App list: The line under folder headings has a fixed margin.
[chromium-blink-merge.git] / third_party / leveldatabase / env_chromium_unittest.cc
blobcaac7a6b1356eba3c7dc2df61ef90ab24a0ff635
1 // Copyright (c) 2013 The Chromium 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.
5 #include "base/file_util.h"
6 #include "base/files/file.h"
7 #include "base/files/file_enumerator.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/test/test_suite.h"
11 #include "third_party/leveldatabase/env_chromium_stdio.h"
12 #if defined(OS_WIN)
13 #include "third_party/leveldatabase/env_chromium_win.h"
14 #endif
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/leveldatabase/env_idb.h"
17 #include "third_party/leveldatabase/src/include/leveldb/db.h"
19 #define FPL FILE_PATH_LITERAL
21 using leveldb::DB;
22 using leveldb::Env;
23 using leveldb::IDBEnv;
24 using leveldb::Options;
25 using leveldb::ReadOptions;
26 using leveldb::Slice;
27 using leveldb::Status;
28 using leveldb::WritableFile;
29 using leveldb::WriteOptions;
30 using leveldb_env::ChromiumEnvStdio;
31 #if defined(OS_WIN)
32 using leveldb_env::ChromiumEnvWin;
33 #endif
34 using leveldb_env::MethodID;
36 TEST(ErrorEncoding, OnlyAMethod) {
37 const MethodID in_method = leveldb_env::kSequentialFileRead;
38 const Status s = MakeIOError("Somefile.txt", "message", in_method);
39 MethodID method;
40 int error = -75;
41 EXPECT_EQ(leveldb_env::METHOD_ONLY,
42 ParseMethodAndError(s.ToString().c_str(), &method, &error));
43 EXPECT_EQ(in_method, method);
44 EXPECT_EQ(-75, error);
47 TEST(ErrorEncoding, FileError) {
48 const MethodID in_method = leveldb_env::kWritableFileClose;
49 const base::File::Error fe = base::File::FILE_ERROR_INVALID_OPERATION;
50 const Status s = MakeIOError("Somefile.txt", "message", in_method, fe);
51 MethodID method;
52 int error;
53 EXPECT_EQ(leveldb_env::METHOD_AND_PFE,
54 ParseMethodAndError(s.ToString().c_str(), &method, &error));
55 EXPECT_EQ(in_method, method);
56 EXPECT_EQ(fe, error);
59 TEST(ErrorEncoding, Errno) {
60 const MethodID in_method = leveldb_env::kWritableFileFlush;
61 const int some_errno = ENOENT;
62 const Status s =
63 MakeIOError("Somefile.txt", "message", in_method, some_errno);
64 MethodID method;
65 int error;
66 EXPECT_EQ(leveldb_env::METHOD_AND_ERRNO,
67 ParseMethodAndError(s.ToString().c_str(), &method, &error));
68 EXPECT_EQ(in_method, method);
69 EXPECT_EQ(some_errno, error);
72 #if defined(OS_WIN)
73 TEST(ErrorEncoding, ErrnoWin32) {
74 const MethodID in_method = leveldb_env::kWritableFileFlush;
75 const DWORD some_errno = ERROR_FILE_NOT_FOUND;
76 const Status s =
77 MakeIOErrorWin("Somefile.txt", "message", in_method, some_errno);
78 MethodID method;
79 int error;
80 EXPECT_EQ(leveldb_env::METHOD_AND_ERRNO,
81 ParseMethodAndError(s.ToString().c_str(), &method, &error));
82 EXPECT_EQ(in_method, method);
83 EXPECT_EQ(some_errno, error);
85 #endif
87 TEST(ErrorEncoding, NoEncodedMessage) {
88 Status s = Status::IOError("Some message", "from leveldb itself");
89 MethodID method = leveldb_env::kRandomAccessFileRead;
90 int error = 4;
91 EXPECT_EQ(leveldb_env::NONE,
92 ParseMethodAndError(s.ToString().c_str(), &method, &error));
93 EXPECT_EQ(leveldb_env::kRandomAccessFileRead, method);
94 EXPECT_EQ(4, error);
97 template <typename T>
98 class MyEnv : public T {
99 public:
100 MyEnv() : directory_syncs_(0) {}
101 int directory_syncs() { return directory_syncs_; }
103 protected:
104 virtual void DidSyncDir(const std::string& fname) {
105 ++directory_syncs_;
106 leveldb_env::ChromiumEnv::DidSyncDir(fname);
109 private:
110 int directory_syncs_;
113 template <typename T>
114 class ChromiumEnvMultiPlatformTests : public ::testing::Test {
115 public:
118 #if defined(OS_WIN)
119 typedef ::testing::Types<ChromiumEnvStdio, ChromiumEnvWin>
120 ChromiumEnvMultiPlatformTestsTypes;
121 #else
122 typedef ::testing::Types<ChromiumEnvStdio> ChromiumEnvMultiPlatformTestsTypes;
123 #endif
124 TYPED_TEST_CASE(ChromiumEnvMultiPlatformTests,
125 ChromiumEnvMultiPlatformTestsTypes);
127 TYPED_TEST(ChromiumEnvMultiPlatformTests, DirectorySyncing) {
128 MyEnv<TypeParam> env;
130 base::ScopedTempDir dir;
131 ASSERT_TRUE(dir.CreateUniqueTempDir());
132 base::FilePath dir_path = dir.path();
133 std::string some_data = "some data";
134 Slice data = some_data;
136 std::string manifest_file_name = leveldb_env::FilePathToString(
137 dir_path.Append(FILE_PATH_LITERAL("MANIFEST-001")));
138 WritableFile* manifest_file_ptr;
139 Status s = env.NewWritableFile(manifest_file_name, &manifest_file_ptr);
140 EXPECT_TRUE(s.ok());
141 scoped_ptr<WritableFile> manifest_file(manifest_file_ptr);
142 manifest_file->Append(data);
143 EXPECT_EQ(0, env.directory_syncs());
144 manifest_file->Append(data);
145 EXPECT_EQ(0, env.directory_syncs());
147 std::string sst_file_name = leveldb_env::FilePathToString(
148 dir_path.Append(FILE_PATH_LITERAL("000003.sst")));
149 WritableFile* sst_file_ptr;
150 s = env.NewWritableFile(sst_file_name, &sst_file_ptr);
151 EXPECT_TRUE(s.ok());
152 scoped_ptr<WritableFile> sst_file(sst_file_ptr);
153 sst_file->Append(data);
154 EXPECT_EQ(0, env.directory_syncs());
156 manifest_file->Append(data);
157 EXPECT_EQ(1, env.directory_syncs());
158 manifest_file->Append(data);
159 EXPECT_EQ(1, env.directory_syncs());
162 int CountFilesWithExtension(const base::FilePath& dir,
163 const base::FilePath::StringType& extension) {
164 int matching_files = 0;
165 base::FileEnumerator dir_reader(
166 dir, false, base::FileEnumerator::FILES);
167 for (base::FilePath fname = dir_reader.Next(); !fname.empty();
168 fname = dir_reader.Next()) {
169 if (fname.MatchesExtension(extension))
170 matching_files++;
172 return matching_files;
175 bool GetFirstLDBFile(const base::FilePath& dir, base::FilePath* ldb_file) {
176 base::FileEnumerator dir_reader(
177 dir, false, base::FileEnumerator::FILES);
178 for (base::FilePath fname = dir_reader.Next(); !fname.empty();
179 fname = dir_reader.Next()) {
180 if (fname.MatchesExtension(FPL(".ldb"))) {
181 *ldb_file = fname;
182 return true;
185 return false;
188 TEST(ChromiumEnv, BackupTables) {
189 Options options;
190 options.create_if_missing = true;
191 options.env = IDBEnv();
193 base::ScopedTempDir scoped_temp_dir;
194 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
195 base::FilePath dir = scoped_temp_dir.path();
197 DB* db;
198 Status status = DB::Open(options, dir.AsUTF8Unsafe(), &db);
199 EXPECT_TRUE(status.ok()) << status.ToString();
200 status = db->Put(WriteOptions(), "key", "value");
201 EXPECT_TRUE(status.ok()) << status.ToString();
202 Slice a = "a";
203 Slice z = "z";
204 db->CompactRange(&a, &z);
205 int ldb_files = CountFilesWithExtension(dir, FPL(".ldb"));
206 int bak_files = CountFilesWithExtension(dir, FPL(".bak"));
207 EXPECT_GT(ldb_files, 0);
208 EXPECT_EQ(ldb_files, bak_files);
209 base::FilePath ldb_file;
210 EXPECT_TRUE(GetFirstLDBFile(dir, &ldb_file));
211 delete db;
212 EXPECT_TRUE(base::DeleteFile(ldb_file, false));
213 EXPECT_EQ(ldb_files - 1, CountFilesWithExtension(dir, FPL(".ldb")));
215 // The ldb file deleted above should be restored in Open.
216 status = leveldb::DB::Open(options, dir.AsUTF8Unsafe(), &db);
217 EXPECT_TRUE(status.ok()) << status.ToString();
218 std::string value;
219 status = db->Get(ReadOptions(), "key", &value);
220 EXPECT_TRUE(status.ok()) << status.ToString();
221 EXPECT_EQ("value", value);
222 delete db;
224 // Ensure that deleting an ldb file also deletes its backup.
225 int orig_ldb_files = CountFilesWithExtension(dir, FPL(".ldb"));
226 EXPECT_GT(ldb_files, 0);
227 EXPECT_EQ(ldb_files, bak_files);
228 EXPECT_TRUE(GetFirstLDBFile(dir, &ldb_file));
229 options.env->DeleteFile(ldb_file.AsUTF8Unsafe());
230 ldb_files = CountFilesWithExtension(dir, FPL(".ldb"));
231 bak_files = CountFilesWithExtension(dir, FPL(".bak"));
232 EXPECT_EQ(orig_ldb_files - 1, ldb_files);
233 EXPECT_EQ(bak_files, ldb_files);
236 TEST(ChromiumEnv, GetChildrenEmptyDir) {
237 base::ScopedTempDir scoped_temp_dir;
238 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
239 base::FilePath dir = scoped_temp_dir.path();
241 Env* env = IDBEnv();
242 std::vector<std::string> result;
243 leveldb::Status status = env->GetChildren(dir.AsUTF8Unsafe(), &result);
244 EXPECT_TRUE(status.ok());
245 EXPECT_EQ(0U, result.size());
248 TEST(ChromiumEnv, GetChildrenPriorResults) {
249 base::ScopedTempDir scoped_temp_dir;
250 ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
251 base::FilePath dir = scoped_temp_dir.path();
253 base::FilePath new_file_dir = dir.Append(FPL("tmp_file"));
254 FILE* f = fopen(new_file_dir.AsUTF8Unsafe().c_str(), "w");
255 if (f) {
256 fputs("Temp file contents", f);
257 fclose(f);
260 Env* env = IDBEnv();
261 std::vector<std::string> result;
262 leveldb::Status status = env->GetChildren(dir.AsUTF8Unsafe(), &result);
263 EXPECT_TRUE(status.ok());
264 EXPECT_EQ(1U, result.size());
266 // And a second time should also return one result
267 status = env->GetChildren(dir.AsUTF8Unsafe(), &result);
268 EXPECT_TRUE(status.ok());
269 EXPECT_EQ(1U, result.size());
272 int main(int argc, char** argv) { return base::TestSuite(argc, argv).Run(); }