xref: /aosp_15_r20/external/leveldb/util/env_test.cc (revision 9507f98c5f32dee4b5f9e4a38cd499f3ff5c4490)
1*9507f98cSAndroid Build Coastguard Worker // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2*9507f98cSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*9507f98cSAndroid Build Coastguard Worker // found in the LICENSE file. See the AUTHORS file for names of contributors.
4*9507f98cSAndroid Build Coastguard Worker 
5*9507f98cSAndroid Build Coastguard Worker #include "leveldb/env.h"
6*9507f98cSAndroid Build Coastguard Worker 
7*9507f98cSAndroid Build Coastguard Worker #include <algorithm>
8*9507f98cSAndroid Build Coastguard Worker 
9*9507f98cSAndroid Build Coastguard Worker #include "gtest/gtest.h"
10*9507f98cSAndroid Build Coastguard Worker #include "port/port.h"
11*9507f98cSAndroid Build Coastguard Worker #include "port/thread_annotations.h"
12*9507f98cSAndroid Build Coastguard Worker #include "util/mutexlock.h"
13*9507f98cSAndroid Build Coastguard Worker #include "util/testutil.h"
14*9507f98cSAndroid Build Coastguard Worker 
15*9507f98cSAndroid Build Coastguard Worker namespace leveldb {
16*9507f98cSAndroid Build Coastguard Worker 
17*9507f98cSAndroid Build Coastguard Worker static const int kDelayMicros = 100000;
18*9507f98cSAndroid Build Coastguard Worker 
19*9507f98cSAndroid Build Coastguard Worker class EnvTest : public testing::Test {
20*9507f98cSAndroid Build Coastguard Worker  public:
EnvTest()21*9507f98cSAndroid Build Coastguard Worker   EnvTest() : env_(Env::Default()) {}
22*9507f98cSAndroid Build Coastguard Worker 
23*9507f98cSAndroid Build Coastguard Worker   Env* env_;
24*9507f98cSAndroid Build Coastguard Worker };
25*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,ReadWrite)26*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, ReadWrite) {
27*9507f98cSAndroid Build Coastguard Worker   Random rnd(test::RandomSeed());
28*9507f98cSAndroid Build Coastguard Worker 
29*9507f98cSAndroid Build Coastguard Worker   // Get file to use for testing.
30*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
31*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
32*9507f98cSAndroid Build Coastguard Worker   std::string test_file_name = test_dir + "/open_on_read.txt";
33*9507f98cSAndroid Build Coastguard Worker   WritableFile* writable_file;
34*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewWritableFile(test_file_name, &writable_file));
35*9507f98cSAndroid Build Coastguard Worker 
36*9507f98cSAndroid Build Coastguard Worker   // Fill a file with data generated via a sequence of randomly sized writes.
37*9507f98cSAndroid Build Coastguard Worker   static const size_t kDataSize = 10 * 1048576;
38*9507f98cSAndroid Build Coastguard Worker   std::string data;
39*9507f98cSAndroid Build Coastguard Worker   while (data.size() < kDataSize) {
40*9507f98cSAndroid Build Coastguard Worker     int len = rnd.Skewed(18);  // Up to 2^18 - 1, but typically much smaller
41*9507f98cSAndroid Build Coastguard Worker     std::string r;
42*9507f98cSAndroid Build Coastguard Worker     test::RandomString(&rnd, len, &r);
43*9507f98cSAndroid Build Coastguard Worker     ASSERT_LEVELDB_OK(writable_file->Append(r));
44*9507f98cSAndroid Build Coastguard Worker     data += r;
45*9507f98cSAndroid Build Coastguard Worker     if (rnd.OneIn(10)) {
46*9507f98cSAndroid Build Coastguard Worker       ASSERT_LEVELDB_OK(writable_file->Flush());
47*9507f98cSAndroid Build Coastguard Worker     }
48*9507f98cSAndroid Build Coastguard Worker   }
49*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Sync());
50*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Close());
51*9507f98cSAndroid Build Coastguard Worker   delete writable_file;
52*9507f98cSAndroid Build Coastguard Worker 
53*9507f98cSAndroid Build Coastguard Worker   // Read all data using a sequence of randomly sized reads.
54*9507f98cSAndroid Build Coastguard Worker   SequentialFile* sequential_file;
55*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewSequentialFile(test_file_name, &sequential_file));
56*9507f98cSAndroid Build Coastguard Worker   std::string read_result;
57*9507f98cSAndroid Build Coastguard Worker   std::string scratch;
58*9507f98cSAndroid Build Coastguard Worker   while (read_result.size() < data.size()) {
59*9507f98cSAndroid Build Coastguard Worker     int len = std::min<int>(rnd.Skewed(18), data.size() - read_result.size());
60*9507f98cSAndroid Build Coastguard Worker     scratch.resize(std::max(len, 1));  // at least 1 so &scratch[0] is legal
61*9507f98cSAndroid Build Coastguard Worker     Slice read;
62*9507f98cSAndroid Build Coastguard Worker     ASSERT_LEVELDB_OK(sequential_file->Read(len, &read, &scratch[0]));
63*9507f98cSAndroid Build Coastguard Worker     if (len > 0) {
64*9507f98cSAndroid Build Coastguard Worker       ASSERT_GT(read.size(), 0);
65*9507f98cSAndroid Build Coastguard Worker     }
66*9507f98cSAndroid Build Coastguard Worker     ASSERT_LE(read.size(), len);
67*9507f98cSAndroid Build Coastguard Worker     read_result.append(read.data(), read.size());
68*9507f98cSAndroid Build Coastguard Worker   }
69*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(read_result, data);
70*9507f98cSAndroid Build Coastguard Worker   delete sequential_file;
71*9507f98cSAndroid Build Coastguard Worker }
72*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,RunImmediately)73*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, RunImmediately) {
74*9507f98cSAndroid Build Coastguard Worker   struct RunState {
75*9507f98cSAndroid Build Coastguard Worker     port::Mutex mu;
76*9507f98cSAndroid Build Coastguard Worker     port::CondVar cvar{&mu};
77*9507f98cSAndroid Build Coastguard Worker     bool called = false;
78*9507f98cSAndroid Build Coastguard Worker 
79*9507f98cSAndroid Build Coastguard Worker     static void Run(void* arg) {
80*9507f98cSAndroid Build Coastguard Worker       RunState* state = reinterpret_cast<RunState*>(arg);
81*9507f98cSAndroid Build Coastguard Worker       MutexLock l(&state->mu);
82*9507f98cSAndroid Build Coastguard Worker       ASSERT_EQ(state->called, false);
83*9507f98cSAndroid Build Coastguard Worker       state->called = true;
84*9507f98cSAndroid Build Coastguard Worker       state->cvar.Signal();
85*9507f98cSAndroid Build Coastguard Worker     }
86*9507f98cSAndroid Build Coastguard Worker   };
87*9507f98cSAndroid Build Coastguard Worker 
88*9507f98cSAndroid Build Coastguard Worker   RunState state;
89*9507f98cSAndroid Build Coastguard Worker   env_->Schedule(&RunState::Run, &state);
90*9507f98cSAndroid Build Coastguard Worker 
91*9507f98cSAndroid Build Coastguard Worker   MutexLock l(&state.mu);
92*9507f98cSAndroid Build Coastguard Worker   while (!state.called) {
93*9507f98cSAndroid Build Coastguard Worker     state.cvar.Wait();
94*9507f98cSAndroid Build Coastguard Worker   }
95*9507f98cSAndroid Build Coastguard Worker }
96*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,RunMany)97*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, RunMany) {
98*9507f98cSAndroid Build Coastguard Worker   struct RunState {
99*9507f98cSAndroid Build Coastguard Worker     port::Mutex mu;
100*9507f98cSAndroid Build Coastguard Worker     port::CondVar cvar{&mu};
101*9507f98cSAndroid Build Coastguard Worker     int last_id = 0;
102*9507f98cSAndroid Build Coastguard Worker   };
103*9507f98cSAndroid Build Coastguard Worker 
104*9507f98cSAndroid Build Coastguard Worker   struct Callback {
105*9507f98cSAndroid Build Coastguard Worker     RunState* state_;  // Pointer to shared state.
106*9507f98cSAndroid Build Coastguard Worker     const int id_;  // Order# for the execution of this callback.
107*9507f98cSAndroid Build Coastguard Worker 
108*9507f98cSAndroid Build Coastguard Worker     Callback(RunState* s, int id) : state_(s), id_(id) {}
109*9507f98cSAndroid Build Coastguard Worker 
110*9507f98cSAndroid Build Coastguard Worker     static void Run(void* arg) {
111*9507f98cSAndroid Build Coastguard Worker       Callback* callback = reinterpret_cast<Callback*>(arg);
112*9507f98cSAndroid Build Coastguard Worker       RunState* state = callback->state_;
113*9507f98cSAndroid Build Coastguard Worker 
114*9507f98cSAndroid Build Coastguard Worker       MutexLock l(&state->mu);
115*9507f98cSAndroid Build Coastguard Worker       ASSERT_EQ(state->last_id, callback->id_ - 1);
116*9507f98cSAndroid Build Coastguard Worker       state->last_id = callback->id_;
117*9507f98cSAndroid Build Coastguard Worker       state->cvar.Signal();
118*9507f98cSAndroid Build Coastguard Worker     }
119*9507f98cSAndroid Build Coastguard Worker   };
120*9507f98cSAndroid Build Coastguard Worker 
121*9507f98cSAndroid Build Coastguard Worker   RunState state;
122*9507f98cSAndroid Build Coastguard Worker   Callback callback1(&state, 1);
123*9507f98cSAndroid Build Coastguard Worker   Callback callback2(&state, 2);
124*9507f98cSAndroid Build Coastguard Worker   Callback callback3(&state, 3);
125*9507f98cSAndroid Build Coastguard Worker   Callback callback4(&state, 4);
126*9507f98cSAndroid Build Coastguard Worker   env_->Schedule(&Callback::Run, &callback1);
127*9507f98cSAndroid Build Coastguard Worker   env_->Schedule(&Callback::Run, &callback2);
128*9507f98cSAndroid Build Coastguard Worker   env_->Schedule(&Callback::Run, &callback3);
129*9507f98cSAndroid Build Coastguard Worker   env_->Schedule(&Callback::Run, &callback4);
130*9507f98cSAndroid Build Coastguard Worker 
131*9507f98cSAndroid Build Coastguard Worker   MutexLock l(&state.mu);
132*9507f98cSAndroid Build Coastguard Worker   while (state.last_id != 4) {
133*9507f98cSAndroid Build Coastguard Worker     state.cvar.Wait();
134*9507f98cSAndroid Build Coastguard Worker   }
135*9507f98cSAndroid Build Coastguard Worker }
136*9507f98cSAndroid Build Coastguard Worker 
137*9507f98cSAndroid Build Coastguard Worker struct State {
138*9507f98cSAndroid Build Coastguard Worker   port::Mutex mu;
139*9507f98cSAndroid Build Coastguard Worker   port::CondVar cvar{&mu};
140*9507f98cSAndroid Build Coastguard Worker 
141*9507f98cSAndroid Build Coastguard Worker   int val GUARDED_BY(mu);
142*9507f98cSAndroid Build Coastguard Worker   int num_running GUARDED_BY(mu);
143*9507f98cSAndroid Build Coastguard Worker 
Stateleveldb::State144*9507f98cSAndroid Build Coastguard Worker   State(int val, int num_running) : val(val), num_running(num_running) {}
145*9507f98cSAndroid Build Coastguard Worker };
146*9507f98cSAndroid Build Coastguard Worker 
ThreadBody(void * arg)147*9507f98cSAndroid Build Coastguard Worker static void ThreadBody(void* arg) {
148*9507f98cSAndroid Build Coastguard Worker   State* s = reinterpret_cast<State*>(arg);
149*9507f98cSAndroid Build Coastguard Worker   s->mu.Lock();
150*9507f98cSAndroid Build Coastguard Worker   s->val += 1;
151*9507f98cSAndroid Build Coastguard Worker   s->num_running -= 1;
152*9507f98cSAndroid Build Coastguard Worker   s->cvar.Signal();
153*9507f98cSAndroid Build Coastguard Worker   s->mu.Unlock();
154*9507f98cSAndroid Build Coastguard Worker }
155*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,StartThread)156*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, StartThread) {
157*9507f98cSAndroid Build Coastguard Worker   State state(0, 3);
158*9507f98cSAndroid Build Coastguard Worker   for (int i = 0; i < 3; i++) {
159*9507f98cSAndroid Build Coastguard Worker     env_->StartThread(&ThreadBody, &state);
160*9507f98cSAndroid Build Coastguard Worker   }
161*9507f98cSAndroid Build Coastguard Worker 
162*9507f98cSAndroid Build Coastguard Worker   MutexLock l(&state.mu);
163*9507f98cSAndroid Build Coastguard Worker   while (state.num_running != 0) {
164*9507f98cSAndroid Build Coastguard Worker     state.cvar.Wait();
165*9507f98cSAndroid Build Coastguard Worker   }
166*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(state.val, 3);
167*9507f98cSAndroid Build Coastguard Worker }
168*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,TestOpenNonExistentFile)169*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, TestOpenNonExistentFile) {
170*9507f98cSAndroid Build Coastguard Worker   // Write some test data to a single file that will be opened |n| times.
171*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
172*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
173*9507f98cSAndroid Build Coastguard Worker 
174*9507f98cSAndroid Build Coastguard Worker   std::string non_existent_file = test_dir + "/non_existent_file";
175*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(!env_->FileExists(non_existent_file));
176*9507f98cSAndroid Build Coastguard Worker 
177*9507f98cSAndroid Build Coastguard Worker   RandomAccessFile* random_access_file;
178*9507f98cSAndroid Build Coastguard Worker   Status status =
179*9507f98cSAndroid Build Coastguard Worker       env_->NewRandomAccessFile(non_existent_file, &random_access_file);
180*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(status.IsNotFound());
181*9507f98cSAndroid Build Coastguard Worker 
182*9507f98cSAndroid Build Coastguard Worker   SequentialFile* sequential_file;
183*9507f98cSAndroid Build Coastguard Worker   status = env_->NewSequentialFile(non_existent_file, &sequential_file);
184*9507f98cSAndroid Build Coastguard Worker   ASSERT_TRUE(status.IsNotFound());
185*9507f98cSAndroid Build Coastguard Worker }
186*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,ReopenWritableFile)187*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, ReopenWritableFile) {
188*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
189*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
190*9507f98cSAndroid Build Coastguard Worker   std::string test_file_name = test_dir + "/reopen_writable_file.txt";
191*9507f98cSAndroid Build Coastguard Worker   env_->RemoveFile(test_file_name);
192*9507f98cSAndroid Build Coastguard Worker 
193*9507f98cSAndroid Build Coastguard Worker   WritableFile* writable_file;
194*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewWritableFile(test_file_name, &writable_file));
195*9507f98cSAndroid Build Coastguard Worker   std::string data("hello world!");
196*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Append(data));
197*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Close());
198*9507f98cSAndroid Build Coastguard Worker   delete writable_file;
199*9507f98cSAndroid Build Coastguard Worker 
200*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewWritableFile(test_file_name, &writable_file));
201*9507f98cSAndroid Build Coastguard Worker   data = "42";
202*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Append(data));
203*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(writable_file->Close());
204*9507f98cSAndroid Build Coastguard Worker   delete writable_file;
205*9507f98cSAndroid Build Coastguard Worker 
206*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(ReadFileToString(env_, test_file_name, &data));
207*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(std::string("42"), data);
208*9507f98cSAndroid Build Coastguard Worker   env_->RemoveFile(test_file_name);
209*9507f98cSAndroid Build Coastguard Worker }
210*9507f98cSAndroid Build Coastguard Worker 
TEST_F(EnvTest,ReopenAppendableFile)211*9507f98cSAndroid Build Coastguard Worker TEST_F(EnvTest, ReopenAppendableFile) {
212*9507f98cSAndroid Build Coastguard Worker   std::string test_dir;
213*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
214*9507f98cSAndroid Build Coastguard Worker   std::string test_file_name = test_dir + "/reopen_appendable_file.txt";
215*9507f98cSAndroid Build Coastguard Worker   env_->RemoveFile(test_file_name);
216*9507f98cSAndroid Build Coastguard Worker 
217*9507f98cSAndroid Build Coastguard Worker   WritableFile* appendable_file;
218*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
219*9507f98cSAndroid Build Coastguard Worker   std::string data("hello world!");
220*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(appendable_file->Append(data));
221*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(appendable_file->Close());
222*9507f98cSAndroid Build Coastguard Worker   delete appendable_file;
223*9507f98cSAndroid Build Coastguard Worker 
224*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
225*9507f98cSAndroid Build Coastguard Worker   data = "42";
226*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(appendable_file->Append(data));
227*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(appendable_file->Close());
228*9507f98cSAndroid Build Coastguard Worker   delete appendable_file;
229*9507f98cSAndroid Build Coastguard Worker 
230*9507f98cSAndroid Build Coastguard Worker   ASSERT_LEVELDB_OK(ReadFileToString(env_, test_file_name, &data));
231*9507f98cSAndroid Build Coastguard Worker   ASSERT_EQ(std::string("hello world!42"), data);
232*9507f98cSAndroid Build Coastguard Worker   env_->RemoveFile(test_file_name);
233*9507f98cSAndroid Build Coastguard Worker }
234*9507f98cSAndroid Build Coastguard Worker 
235*9507f98cSAndroid Build Coastguard Worker }  // namespace leveldb
236*9507f98cSAndroid Build Coastguard Worker 
237