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