作者: 韩晨旭 10225101440 李畅 10225102463
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.

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