小组成员:谢瑞阳、徐翔宇
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.

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