xref: /leveldb-1.20/util/env_test.cc (revision f3f13973)
1 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 
5 #include "leveldb/env.h"
6 
7 #include "port/port.h"
8 #include "util/testharness.h"
9 
10 namespace leveldb {
11 
12 static const int kDelayMicros = 100000;
13 static const int kReadOnlyFileLimit = 4;
14 static const int kMMapLimit = 4;
15 
16 class EnvTest {
17  private:
18   port::Mutex mu_;
19   std::string events_;
20 
21  public:
22   Env* env_;
EnvTest()23   EnvTest() : env_(Env::Default()) { }
24 };
25 
SetBool(void * ptr)26 static void SetBool(void* ptr) {
27   reinterpret_cast<port::AtomicPointer*>(ptr)->NoBarrier_Store(ptr);
28 }
29 
TEST(EnvTest,RunImmediately)30 TEST(EnvTest, RunImmediately) {
31   port::AtomicPointer called (NULL);
32   env_->Schedule(&SetBool, &called);
33   env_->SleepForMicroseconds(kDelayMicros);
34   ASSERT_TRUE(called.NoBarrier_Load() != NULL);
35 }
36 
TEST(EnvTest,RunMany)37 TEST(EnvTest, RunMany) {
38   port::AtomicPointer last_id (NULL);
39 
40   struct CB {
41     port::AtomicPointer* last_id_ptr;   // Pointer to shared slot
42     uintptr_t id;             // Order# for the execution of this callback
43 
44     CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { }
45 
46     static void Run(void* v) {
47       CB* cb = reinterpret_cast<CB*>(v);
48       void* cur = cb->last_id_ptr->NoBarrier_Load();
49       ASSERT_EQ(cb->id-1, reinterpret_cast<uintptr_t>(cur));
50       cb->last_id_ptr->Release_Store(reinterpret_cast<void*>(cb->id));
51     }
52   };
53 
54   // Schedule in different order than start time
55   CB cb1(&last_id, 1);
56   CB cb2(&last_id, 2);
57   CB cb3(&last_id, 3);
58   CB cb4(&last_id, 4);
59   env_->Schedule(&CB::Run, &cb1);
60   env_->Schedule(&CB::Run, &cb2);
61   env_->Schedule(&CB::Run, &cb3);
62   env_->Schedule(&CB::Run, &cb4);
63 
64   env_->SleepForMicroseconds(kDelayMicros);
65   void* cur = last_id.Acquire_Load();
66   ASSERT_EQ(4, reinterpret_cast<uintptr_t>(cur));
67 }
68 
69 struct State {
70   port::Mutex mu;
71   int val;
72   int num_running;
73 };
74 
ThreadBody(void * arg)75 static void ThreadBody(void* arg) {
76   State* s = reinterpret_cast<State*>(arg);
77   s->mu.Lock();
78   s->val += 1;
79   s->num_running -= 1;
80   s->mu.Unlock();
81 }
82 
TEST(EnvTest,StartThread)83 TEST(EnvTest, StartThread) {
84   State state;
85   state.val = 0;
86   state.num_running = 3;
87   for (int i = 0; i < 3; i++) {
88     env_->StartThread(&ThreadBody, &state);
89   }
90   while (true) {
91     state.mu.Lock();
92     int num = state.num_running;
93     state.mu.Unlock();
94     if (num == 0) {
95       break;
96     }
97     env_->SleepForMicroseconds(kDelayMicros);
98   }
99   ASSERT_EQ(state.val, 3);
100 }
101 
102 }  // namespace leveldb
103 
main(int argc,char ** argv)104 int main(int argc, char** argv) {
105   return leveldb::test::RunAllTests();
106 }
107