Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / leveldatabase / env_chromium_unittest.cc
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.
4
5 #include "base/files/file.h"
6 #include "base/files/file_enumerator.h"
7 #include "base/files/file_path.h"
8 #include "base/files/file_util.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"
18
19 #define FPL FILE_PATH_LITERAL
20
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;
35
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);
45 }
46
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);
57 }
58
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);
70 }
71
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);
84 }
85 #endif
86
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);
95 }
96
97 template <typename T>
98 class MyEnv : public T {
99  public:
100   MyEnv() : directory_syncs_(0) {}
101   int directory_syncs() { return directory_syncs_; }
102
103  protected:
104   virtual void DidSyncDir(const std::string& fname) {
105     ++directory_syncs_;
106     leveldb_env::ChromiumEnv::DidSyncDir(fname);
107   }
108
109  private:
110   int directory_syncs_;
111 };
112
113 template <typename T>
114 class ChromiumEnvMultiPlatformTests : public ::testing::Test {
115  public:
116 };
117
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);
126
127 TYPED_TEST(ChromiumEnvMultiPlatformTests, DirectorySyncing) {
128   MyEnv<TypeParam> env;
129
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;
135
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());
146
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());
155
156   manifest_file->Append(data);
157   EXPECT_EQ(1, env.directory_syncs());
158   manifest_file->Append(data);
159   EXPECT_EQ(1, env.directory_syncs());
160 }
161
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++;
171   }
172   return matching_files;
173 }
174
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;
183     }
184   }
185   return false;
186 }
187
188 TEST(ChromiumEnv, BackupTables) {
189   Options options;
190   options.create_if_missing = true;
191   options.env = IDBEnv();
192
193   base::ScopedTempDir scoped_temp_dir;
194   ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
195   base::FilePath dir = scoped_temp_dir.path();
196
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")));
214
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;
223
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);
234 }
235
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();
240
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());
246 }
247
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();
252
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);
258   }
259
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());
265
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());
270 }
271
272 int main(int argc, char** argv) { return base::TestSuite(argc, argv).Run(); }