You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

237 lines
6.5 KiB

  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. #include "leveldb/env.h"
  5. #include <algorithm>
  6. #include "port/port.h"
  7. #include "port/thread_annotations.h"
  8. #include "util/mutexlock.h"
  9. #include "util/testharness.h"
  10. #include "util/testutil.h"
  11. namespace leveldb {
  12. static const int kDelayMicros = 100000;
  13. class EnvTest {
  14. public:
  15. EnvTest() : env_(Env::Default()) {}
  16. Env* env_;
  17. };
  18. TEST(EnvTest, ReadWrite) {
  19. Random rnd(test::RandomSeed());
  20. // Get file to use for testing.
  21. std::string test_dir;
  22. ASSERT_OK(env_->GetTestDirectory(&test_dir));
  23. std::string test_file_name = test_dir + "/open_on_read.txt";
  24. WritableFile* writable_file;
  25. ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
  26. // Fill a file with data generated via a sequence of randomly sized writes.
  27. static const size_t kDataSize = 10 * 1048576;
  28. std::string data;
  29. while (data.size() < kDataSize) {
  30. int len = rnd.Skewed(18); // Up to 2^18 - 1, but typically much smaller
  31. std::string r;
  32. test::RandomString(&rnd, len, &r);
  33. ASSERT_OK(writable_file->Append(r));
  34. data += r;
  35. if (rnd.OneIn(10)) {
  36. ASSERT_OK(writable_file->Flush());
  37. }
  38. }
  39. ASSERT_OK(writable_file->Sync());
  40. ASSERT_OK(writable_file->Close());
  41. delete writable_file;
  42. // Read all data using a sequence of randomly sized reads.
  43. SequentialFile* sequential_file;
  44. ASSERT_OK(env_->NewSequentialFile(test_file_name, &sequential_file));
  45. std::string read_result;
  46. std::string scratch;
  47. while (read_result.size() < data.size()) {
  48. int len = std::min<int>(rnd.Skewed(18), data.size() - read_result.size());
  49. scratch.resize(std::max(len, 1)); // at least 1 so &scratch[0] is legal
  50. Slice read;
  51. ASSERT_OK(sequential_file->Read(len, &read, &scratch[0]));
  52. if (len > 0) {
  53. ASSERT_GT(read.size(), 0);
  54. }
  55. ASSERT_LE(read.size(), len);
  56. read_result.append(read.data(), read.size());
  57. }
  58. ASSERT_EQ(read_result, data);
  59. delete sequential_file;
  60. }
  61. TEST(EnvTest, RunImmediately) {
  62. struct RunState {
  63. port::Mutex mu;
  64. port::CondVar cvar{&mu};
  65. bool called = false;
  66. static void Run(void* arg) {
  67. RunState* state = reinterpret_cast<RunState*>(arg);
  68. MutexLock l(&state->mu);
  69. ASSERT_EQ(state->called, false);
  70. state->called = true;
  71. state->cvar.Signal();
  72. }
  73. };
  74. RunState state;
  75. env_->Schedule(&RunState::Run, &state);
  76. MutexLock l(&state.mu);
  77. while (!state.called) {
  78. state.cvar.Wait();
  79. }
  80. }
  81. TEST(EnvTest, RunMany) {
  82. struct RunState {
  83. port::Mutex mu;
  84. port::CondVar cvar{&mu};
  85. int last_id = 0;
  86. };
  87. struct Callback {
  88. RunState* state_; // Pointer to shared state.
  89. const int id_; // Order# for the execution of this callback.
  90. Callback(RunState* s, int id) : state_(s), id_(id) {}
  91. static void Run(void* arg) {
  92. Callback* callback = reinterpret_cast<Callback*>(arg);
  93. RunState* state = callback->state_;
  94. MutexLock l(&state->mu);
  95. ASSERT_EQ(state->last_id, callback->id_ - 1);
  96. state->last_id = callback->id_;
  97. state->cvar.Signal();
  98. }
  99. };
  100. RunState state;
  101. Callback callback1(&state, 1);
  102. Callback callback2(&state, 2);
  103. Callback callback3(&state, 3);
  104. Callback callback4(&state, 4);
  105. env_->Schedule(&Callback::Run, &callback1);
  106. env_->Schedule(&Callback::Run, &callback2);
  107. env_->Schedule(&Callback::Run, &callback3);
  108. env_->Schedule(&Callback::Run, &callback4);
  109. MutexLock l(&state.mu);
  110. while (state.last_id != 4) {
  111. state.cvar.Wait();
  112. }
  113. }
  114. struct State {
  115. port::Mutex mu;
  116. port::CondVar cvar{&mu};
  117. int val GUARDED_BY(mu);
  118. int num_running GUARDED_BY(mu);
  119. State(int val, int num_running) : val(val), num_running(num_running) {}
  120. };
  121. static void ThreadBody(void* arg) {
  122. State* s = reinterpret_cast<State*>(arg);
  123. s->mu.Lock();
  124. s->val += 1;
  125. s->num_running -= 1;
  126. s->cvar.Signal();
  127. s->mu.Unlock();
  128. }
  129. TEST(EnvTest, StartThread) {
  130. State state(0, 3);
  131. for (int i = 0; i < 3; i++) {
  132. env_->StartThread(&ThreadBody, &state);
  133. }
  134. MutexLock l(&state.mu);
  135. while (state.num_running != 0) {
  136. state.cvar.Wait();
  137. }
  138. ASSERT_EQ(state.val, 3);
  139. }
  140. TEST(EnvTest, TestOpenNonExistentFile) {
  141. // Write some test data to a single file that will be opened |n| times.
  142. std::string test_dir;
  143. ASSERT_OK(env_->GetTestDirectory(&test_dir));
  144. std::string non_existent_file = test_dir + "/non_existent_file";
  145. ASSERT_TRUE(!env_->FileExists(non_existent_file));
  146. RandomAccessFile* random_access_file;
  147. Status status =
  148. env_->NewRandomAccessFile(non_existent_file, &random_access_file);
  149. ASSERT_TRUE(status.IsNotFound());
  150. SequentialFile* sequential_file;
  151. status = env_->NewSequentialFile(non_existent_file, &sequential_file);
  152. ASSERT_TRUE(status.IsNotFound());
  153. }
  154. TEST(EnvTest, ReopenWritableFile) {
  155. std::string test_dir;
  156. ASSERT_OK(env_->GetTestDirectory(&test_dir));
  157. std::string test_file_name = test_dir + "/reopen_writable_file.txt";
  158. env_->DeleteFile(test_file_name);
  159. WritableFile* writable_file;
  160. ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
  161. std::string data("hello world!");
  162. ASSERT_OK(writable_file->Append(data));
  163. ASSERT_OK(writable_file->Close());
  164. delete writable_file;
  165. ASSERT_OK(env_->NewWritableFile(test_file_name, &writable_file));
  166. data = "42";
  167. ASSERT_OK(writable_file->Append(data));
  168. ASSERT_OK(writable_file->Close());
  169. delete writable_file;
  170. ASSERT_OK(ReadFileToString(env_, test_file_name, &data));
  171. ASSERT_EQ(std::string("42"), data);
  172. env_->DeleteFile(test_file_name);
  173. }
  174. TEST(EnvTest, ReopenAppendableFile) {
  175. std::string test_dir;
  176. ASSERT_OK(env_->GetTestDirectory(&test_dir));
  177. std::string test_file_name = test_dir + "/reopen_appendable_file.txt";
  178. env_->DeleteFile(test_file_name);
  179. WritableFile* appendable_file;
  180. ASSERT_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
  181. std::string data("hello world!");
  182. ASSERT_OK(appendable_file->Append(data));
  183. ASSERT_OK(appendable_file->Close());
  184. delete appendable_file;
  185. ASSERT_OK(env_->NewAppendableFile(test_file_name, &appendable_file));
  186. data = "42";
  187. ASSERT_OK(appendable_file->Append(data));
  188. ASSERT_OK(appendable_file->Close());
  189. delete appendable_file;
  190. ASSERT_OK(ReadFileToString(env_, test_file_name, &data));
  191. ASSERT_EQ(std::string("hello world!42"), data);
  192. env_->DeleteFile(test_file_name);
  193. }
  194. } // namespace leveldb
  195. int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }