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