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

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