memenv_test.cc raw

   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  
   5  #include "helpers/memenv/memenv.h"
   6  
   7  #include <string>
   8  #include <vector>
   9  
  10  #include "db/db_impl.h"
  11  #include "leveldb/db.h"
  12  #include "leveldb/env.h"
  13  #include "util/testharness.h"
  14  
  15  namespace leveldb {
  16  
  17  class MemEnvTest {
  18   public:
  19    MemEnvTest() : env_(NewMemEnv(Env::Default())) {}
  20    ~MemEnvTest() { delete env_; }
  21  
  22    Env* env_;
  23  };
  24  
  25  TEST(MemEnvTest, Basics) {
  26    uint64_t file_size;
  27    WritableFile* writable_file;
  28    std::vector<std::string> children;
  29  
  30    ASSERT_OK(env_->CreateDir("/dir"));
  31  
  32    // Check that the directory is empty.
  33    ASSERT_TRUE(!env_->FileExists("/dir/non_existent"));
  34    ASSERT_TRUE(!env_->GetFileSize("/dir/non_existent", &file_size).ok());
  35    ASSERT_OK(env_->GetChildren("/dir", &children));
  36    ASSERT_EQ(0, children.size());
  37  
  38    // Create a file.
  39    ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file));
  40    ASSERT_OK(env_->GetFileSize("/dir/f", &file_size));
  41    ASSERT_EQ(0, file_size);
  42    delete writable_file;
  43  
  44    // Check that the file exists.
  45    ASSERT_TRUE(env_->FileExists("/dir/f"));
  46    ASSERT_OK(env_->GetFileSize("/dir/f", &file_size));
  47    ASSERT_EQ(0, file_size);
  48    ASSERT_OK(env_->GetChildren("/dir", &children));
  49    ASSERT_EQ(1, children.size());
  50    ASSERT_EQ("f", children[0]);
  51  
  52    // Write to the file.
  53    ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file));
  54    ASSERT_OK(writable_file->Append("abc"));
  55    delete writable_file;
  56  
  57    // Check that append works.
  58    ASSERT_OK(env_->NewAppendableFile("/dir/f", &writable_file));
  59    ASSERT_OK(env_->GetFileSize("/dir/f", &file_size));
  60    ASSERT_EQ(3, file_size);
  61    ASSERT_OK(writable_file->Append("hello"));
  62    delete writable_file;
  63  
  64    // Check for expected size.
  65    ASSERT_OK(env_->GetFileSize("/dir/f", &file_size));
  66    ASSERT_EQ(8, file_size);
  67  
  68    // Check that renaming works.
  69    ASSERT_TRUE(!env_->RenameFile("/dir/non_existent", "/dir/g").ok());
  70    ASSERT_OK(env_->RenameFile("/dir/f", "/dir/g"));
  71    ASSERT_TRUE(!env_->FileExists("/dir/f"));
  72    ASSERT_TRUE(env_->FileExists("/dir/g"));
  73    ASSERT_OK(env_->GetFileSize("/dir/g", &file_size));
  74    ASSERT_EQ(8, file_size);
  75  
  76    // Check that opening non-existent file fails.
  77    SequentialFile* seq_file;
  78    RandomAccessFile* rand_file;
  79    ASSERT_TRUE(!env_->NewSequentialFile("/dir/non_existent", &seq_file).ok());
  80    ASSERT_TRUE(!seq_file);
  81    ASSERT_TRUE(!env_->NewRandomAccessFile("/dir/non_existent", &rand_file).ok());
  82    ASSERT_TRUE(!rand_file);
  83  
  84    // Check that deleting works.
  85    ASSERT_TRUE(!env_->DeleteFile("/dir/non_existent").ok());
  86    ASSERT_OK(env_->DeleteFile("/dir/g"));
  87    ASSERT_TRUE(!env_->FileExists("/dir/g"));
  88    ASSERT_OK(env_->GetChildren("/dir", &children));
  89    ASSERT_EQ(0, children.size());
  90    ASSERT_OK(env_->DeleteDir("/dir"));
  91  }
  92  
  93  TEST(MemEnvTest, ReadWrite) {
  94    WritableFile* writable_file;
  95    SequentialFile* seq_file;
  96    RandomAccessFile* rand_file;
  97    Slice result;
  98    char scratch[100];
  99  
 100    ASSERT_OK(env_->CreateDir("/dir"));
 101  
 102    ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file));
 103    ASSERT_OK(writable_file->Append("hello "));
 104    ASSERT_OK(writable_file->Append("world"));
 105    delete writable_file;
 106  
 107    // Read sequentially.
 108    ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file));
 109    ASSERT_OK(seq_file->Read(5, &result, scratch));  // Read "hello".
 110    ASSERT_EQ(0, result.compare("hello"));
 111    ASSERT_OK(seq_file->Skip(1));
 112    ASSERT_OK(seq_file->Read(1000, &result, scratch));  // Read "world".
 113    ASSERT_EQ(0, result.compare("world"));
 114    ASSERT_OK(seq_file->Read(1000, &result, scratch));  // Try reading past EOF.
 115    ASSERT_EQ(0, result.size());
 116    ASSERT_OK(seq_file->Skip(100));  // Try to skip past end of file.
 117    ASSERT_OK(seq_file->Read(1000, &result, scratch));
 118    ASSERT_EQ(0, result.size());
 119    delete seq_file;
 120  
 121    // Random reads.
 122    ASSERT_OK(env_->NewRandomAccessFile("/dir/f", &rand_file));
 123    ASSERT_OK(rand_file->Read(6, 5, &result, scratch));  // Read "world".
 124    ASSERT_EQ(0, result.compare("world"));
 125    ASSERT_OK(rand_file->Read(0, 5, &result, scratch));  // Read "hello".
 126    ASSERT_EQ(0, result.compare("hello"));
 127    ASSERT_OK(rand_file->Read(10, 100, &result, scratch));  // Read "d".
 128    ASSERT_EQ(0, result.compare("d"));
 129  
 130    // Too high offset.
 131    ASSERT_TRUE(!rand_file->Read(1000, 5, &result, scratch).ok());
 132    delete rand_file;
 133  }
 134  
 135  TEST(MemEnvTest, Locks) {
 136    FileLock* lock;
 137  
 138    // These are no-ops, but we test they return success.
 139    ASSERT_OK(env_->LockFile("some file", &lock));
 140    ASSERT_OK(env_->UnlockFile(lock));
 141  }
 142  
 143  TEST(MemEnvTest, Misc) {
 144    std::string test_dir;
 145    ASSERT_OK(env_->GetTestDirectory(&test_dir));
 146    ASSERT_TRUE(!test_dir.empty());
 147  
 148    WritableFile* writable_file;
 149    ASSERT_OK(env_->NewWritableFile("/a/b", &writable_file));
 150  
 151    // These are no-ops, but we test they return success.
 152    ASSERT_OK(writable_file->Sync());
 153    ASSERT_OK(writable_file->Flush());
 154    ASSERT_OK(writable_file->Close());
 155    delete writable_file;
 156  }
 157  
 158  TEST(MemEnvTest, LargeWrite) {
 159    const size_t kWriteSize = 300 * 1024;
 160    char* scratch = new char[kWriteSize * 2];
 161  
 162    std::string write_data;
 163    for (size_t i = 0; i < kWriteSize; ++i) {
 164      write_data.append(1, static_cast<char>(i));
 165    }
 166  
 167    WritableFile* writable_file;
 168    ASSERT_OK(env_->NewWritableFile("/dir/f", &writable_file));
 169    ASSERT_OK(writable_file->Append("foo"));
 170    ASSERT_OK(writable_file->Append(write_data));
 171    delete writable_file;
 172  
 173    SequentialFile* seq_file;
 174    Slice result;
 175    ASSERT_OK(env_->NewSequentialFile("/dir/f", &seq_file));
 176    ASSERT_OK(seq_file->Read(3, &result, scratch));  // Read "foo".
 177    ASSERT_EQ(0, result.compare("foo"));
 178  
 179    size_t read = 0;
 180    std::string read_data;
 181    while (read < kWriteSize) {
 182      ASSERT_OK(seq_file->Read(kWriteSize - read, &result, scratch));
 183      read_data.append(result.data(), result.size());
 184      read += result.size();
 185    }
 186    ASSERT_TRUE(write_data == read_data);
 187    delete seq_file;
 188    delete[] scratch;
 189  }
 190  
 191  TEST(MemEnvTest, OverwriteOpenFile) {
 192    const char kWrite1Data[] = "Write #1 data";
 193    const size_t kFileDataLen = sizeof(kWrite1Data) - 1;
 194    const std::string kTestFileName = test::TmpDir() + "/leveldb-TestFile.dat";
 195  
 196    ASSERT_OK(WriteStringToFile(env_, kWrite1Data, kTestFileName));
 197  
 198    RandomAccessFile* rand_file;
 199    ASSERT_OK(env_->NewRandomAccessFile(kTestFileName, &rand_file));
 200  
 201    const char kWrite2Data[] = "Write #2 data";
 202    ASSERT_OK(WriteStringToFile(env_, kWrite2Data, kTestFileName));
 203  
 204    // Verify that overwriting an open file will result in the new file data
 205    // being read from files opened before the write.
 206    Slice result;
 207    char scratch[kFileDataLen];
 208    ASSERT_OK(rand_file->Read(0, kFileDataLen, &result, scratch));
 209    ASSERT_EQ(0, result.compare(kWrite2Data));
 210  
 211    delete rand_file;
 212  }
 213  
 214  TEST(MemEnvTest, DBTest) {
 215    Options options;
 216    options.create_if_missing = true;
 217    options.env = env_;
 218    DB* db;
 219  
 220    const Slice keys[] = {Slice("aaa"), Slice("bbb"), Slice("ccc")};
 221    const Slice vals[] = {Slice("foo"), Slice("bar"), Slice("baz")};
 222  
 223    ASSERT_OK(DB::Open(options, "/dir/db", &db));
 224    for (size_t i = 0; i < 3; ++i) {
 225      ASSERT_OK(db->Put(WriteOptions(), keys[i], vals[i]));
 226    }
 227  
 228    for (size_t i = 0; i < 3; ++i) {
 229      std::string res;
 230      ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
 231      ASSERT_TRUE(res == vals[i]);
 232    }
 233  
 234    Iterator* iterator = db->NewIterator(ReadOptions());
 235    iterator->SeekToFirst();
 236    for (size_t i = 0; i < 3; ++i) {
 237      ASSERT_TRUE(iterator->Valid());
 238      ASSERT_TRUE(keys[i] == iterator->key());
 239      ASSERT_TRUE(vals[i] == iterator->value());
 240      iterator->Next();
 241    }
 242    ASSERT_TRUE(!iterator->Valid());
 243    delete iterator;
 244  
 245    DBImpl* dbi = reinterpret_cast<DBImpl*>(db);
 246    ASSERT_OK(dbi->TEST_CompactMemTable());
 247  
 248    for (size_t i = 0; i < 3; ++i) {
 249      std::string res;
 250      ASSERT_OK(db->Get(ReadOptions(), keys[i], &res));
 251      ASSERT_TRUE(res == vals[i]);
 252    }
 253  
 254    delete db;
 255  }
 256  
 257  }  // namespace leveldb
 258  
 259  int main(int argc, char** argv) { return leveldb::test::RunAllTests(); }
 260