作者: 谢瑞阳 10225101483 徐翔宇 10225101535
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.

174 lines
4.7 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 "port/port.h"
  6. #include "util/testharness.h"
  7. #include "util/testutil.h"
  8. namespace leveldb {
  9. static const int kDelayMicros = 100000;
  10. static const int kReadOnlyFileLimit = 4;
  11. static const int kMMapLimit = 4;
  12. class EnvTest {
  13. private:
  14. port::Mutex mu_;
  15. std::string events_;
  16. public:
  17. Env* env_;
  18. EnvTest() : env_(Env::Default()) { }
  19. };
  20. static void SetBool(void* ptr) {
  21. reinterpret_cast<port::AtomicPointer*>(ptr)->NoBarrier_Store(ptr);
  22. }
  23. TEST(EnvTest, ReadWrite) {
  24. Random rnd(test::RandomSeed());
  25. // Get file to use for testing.
  26. std::string test_dir;
  27. ASSERT_OK(env_->GetTestDirectory(&test_dir));
  28. std::string test_file_name = test_dir + "/open_on_read.txt";
  29. WritableFile* wfile_tmp;
  30. ASSERT_OK(env_->NewWritableFile(test_file_name, &wfile_tmp));
  31. std::unique_ptr<WritableFile> wfile(wfile_tmp);
  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(wfile->Append(r));
  40. data += r;
  41. if (rnd.OneIn(10)) {
  42. ASSERT_OK(wfile->Flush());
  43. }
  44. }
  45. ASSERT_OK(wfile->Sync());
  46. ASSERT_OK(wfile->Close());
  47. wfile.reset();
  48. // Read all data using a sequence of randomly sized reads.
  49. SequentialFile* rfile_tmp;
  50. ASSERT_OK(env_->NewSequentialFile(test_file_name, &rfile_tmp));
  51. std::unique_ptr<SequentialFile> rfile(rfile_tmp);
  52. std::string read_result;
  53. std::string scratch;
  54. while (read_result.size() < data.size()) {
  55. int len = std::min<int>(rnd.Skewed(18), data.size() - read_result.size());
  56. scratch.resize(std::max(len, 1)); // at least 1 so &scratch[0] is legal
  57. Slice read;
  58. ASSERT_OK(rfile->Read(len, &read, &scratch[0]));
  59. if (len > 0) {
  60. ASSERT_GT(read.size(), 0);
  61. }
  62. ASSERT_LE(read.size(), len);
  63. read_result.append(read.data(), read.size());
  64. }
  65. ASSERT_EQ(read_result, data);
  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. } // namespace leveldb
  144. int main(int argc, char** argv) {
  145. return leveldb::test::RunAllTests();
  146. }