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.

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