Add Google's LevelDB support
[novacoin.git] / src / leveldb / util / env_test.cc
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
14 class EnvPosixTest {
15  private:
16   port::Mutex mu_;
17   std::string events_;
18
19  public:
20   Env* env_;
21   EnvPosixTest() : env_(Env::Default()) { }
22 };
23
24 static void SetBool(void* ptr) {
25   reinterpret_cast<port::AtomicPointer*>(ptr)->NoBarrier_Store(ptr);
26 }
27
28 TEST(EnvPosixTest, RunImmediately) {
29   port::AtomicPointer called (NULL);
30   env_->Schedule(&SetBool, &called);
31   Env::Default()->SleepForMicroseconds(kDelayMicros);
32   ASSERT_TRUE(called.NoBarrier_Load() != NULL);
33 }
34
35 TEST(EnvPosixTest, RunMany) {
36   port::AtomicPointer last_id (NULL);
37
38   struct CB {
39     port::AtomicPointer* last_id_ptr;   // Pointer to shared slot
40     uintptr_t id;             // Order# for the execution of this callback
41
42     CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { }
43
44     static void Run(void* v) {
45       CB* cb = reinterpret_cast<CB*>(v);
46       void* cur = cb->last_id_ptr->NoBarrier_Load();
47       ASSERT_EQ(cb->id-1, reinterpret_cast<uintptr_t>(cur));
48       cb->last_id_ptr->Release_Store(reinterpret_cast<void*>(cb->id));
49     }
50   };
51
52   // Schedule in different order than start time
53   CB cb1(&last_id, 1);
54   CB cb2(&last_id, 2);
55   CB cb3(&last_id, 3);
56   CB cb4(&last_id, 4);
57   env_->Schedule(&CB::Run, &cb1);
58   env_->Schedule(&CB::Run, &cb2);
59   env_->Schedule(&CB::Run, &cb3);
60   env_->Schedule(&CB::Run, &cb4);
61
62   Env::Default()->SleepForMicroseconds(kDelayMicros);
63   void* cur = last_id.Acquire_Load();
64   ASSERT_EQ(4, reinterpret_cast<uintptr_t>(cur));
65 }
66
67 struct State {
68   port::Mutex mu;
69   int val;
70   int num_running;
71 };
72
73 static void ThreadBody(void* arg) {
74   State* s = reinterpret_cast<State*>(arg);
75   s->mu.Lock();
76   s->val += 1;
77   s->num_running -= 1;
78   s->mu.Unlock();
79 }
80
81 TEST(EnvPosixTest, StartThread) {
82   State state;
83   state.val = 0;
84   state.num_running = 3;
85   for (int i = 0; i < 3; i++) {
86     env_->StartThread(&ThreadBody, &state);
87   }
88   while (true) {
89     state.mu.Lock();
90     int num = state.num_running;
91     state.mu.Unlock();
92     if (num == 0) {
93       break;
94     }
95     Env::Default()->SleepForMicroseconds(kDelayMicros);
96   }
97   ASSERT_EQ(state.val, 3);
98 }
99
100 }  // namespace leveldb
101
102 int main(int argc, char** argv) {
103   return leveldb::test::RunAllTests();
104 }