10215300402 朱维清 10222140408 谷杰
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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