[M108 Migration][HBBTV] Implement ewk_context_register_jsplugin_mime_types API
[platform/framework/web/chromium-efl.git] / sql / database_options_unittest.cc
1 // Copyright 2022 The Chromium Authors
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/callback_helpers.h"
6 #include "base/files/file_path.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "sql/database.h"
9 #include "sql/sqlite_result_code.h"
10 #include "sql/statement.h"
11 #include "sql/test/scoped_error_expecter.h"
12 #include "sql/test/test_helpers.h"
13 #include "sql/transaction.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "third_party/abseil-cpp/absl/types/optional.h"
16 #include "third_party/sqlite/sqlite3.h"
17
18 namespace sql {
19
20 namespace {
21
22 enum class OpenVariant {
23   kInMemory = 1,
24   kOnDiskExclusiveJournal = 2,
25   kOnDiskNonExclusiveJournal = 3,
26   kOnDiskExclusiveWal = 4,
27 };
28
29 // We use the parameter to run all tests with WAL mode on and off.
30 class DatabaseOptionsTest : public testing::TestWithParam<OpenVariant> {
31  public:
32   DatabaseOptionsTest() = default;
33   ~DatabaseOptionsTest() override = default;
34
35   void SetUp() override {
36     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
37     db_path_ = temp_dir_.GetPath().AppendASCII("database_test.sqlite");
38   }
39
40   OpenVariant open_variant() const { return GetParam(); }
41
42   // The options below interact with all other options. These tests ensure that
43   // all combinations work.
44   bool exclusive_locking() const {
45     return GetParam() != OpenVariant::kOnDiskNonExclusiveJournal;
46   }
47   bool wal_mode() const {
48     return GetParam() == OpenVariant::kOnDiskExclusiveWal;
49   }
50
51   void OpenDatabase(Database& db) {
52     switch (open_variant()) {
53       case OpenVariant::kOnDiskExclusiveJournal:
54         ASSERT_TRUE(db.Open(db_path_));
55         break;
56
57       case OpenVariant::kOnDiskNonExclusiveJournal:
58         ASSERT_TRUE(db.Open(db_path_));
59         break;
60
61       case OpenVariant::kOnDiskExclusiveWal:
62         ASSERT_TRUE(db.Open(db_path_));
63         break;
64
65       case OpenVariant::kInMemory:
66         ASSERT_TRUE(db.OpenInMemory());
67         break;
68     }
69   }
70
71   // Runs a rolled back transaction, followed by a committed transaction.
72   void RunTransactions(Database& db) {
73     {
74       Transaction rolled_back(&db);
75       ASSERT_TRUE(rolled_back.Begin());
76       ASSERT_TRUE(db.Execute("CREATE TABLE rows(id PRIMARY KEY NOT NULL)"));
77       rolled_back.Rollback();
78     }
79     {
80       Transaction committed(&db);
81       ASSERT_TRUE(committed.Begin());
82       ASSERT_TRUE(db.Execute("CREATE TABLE rows(id PRIMARY KEY NOT NULL)"));
83       ASSERT_TRUE(committed.Commit());
84     }
85   }
86
87  protected:
88   base::ScopedTempDir temp_dir_;
89   base::FilePath db_path_;
90 };
91
92 TEST_P(DatabaseOptionsTest, FlushToDisk_FalseByDefault) {
93   DatabaseOptions options = {
94       .exclusive_locking = exclusive_locking(),
95       .wal_mode = wal_mode(),
96   };
97   EXPECT_FALSE(options.flush_to_media) << "Invalid test assumption";
98
99   Database db(options);
100   OpenDatabase(db);
101
102   EXPECT_EQ("0", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"));
103 }
104
105 TEST_P(DatabaseOptionsTest, FlushToDisk_True) {
106   Database db(DatabaseOptions{
107       .exclusive_locking = exclusive_locking(),
108       .wal_mode = wal_mode(),
109       .flush_to_media = true,
110   });
111   OpenDatabase(db);
112
113   EXPECT_EQ("1", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"));
114 }
115
116 TEST_P(DatabaseOptionsTest, FlushToDisk_False_DoesNotCrash) {
117   Database db(DatabaseOptions{
118       .exclusive_locking = exclusive_locking(),
119       .wal_mode = wal_mode(),
120       .flush_to_media = false,
121   });
122   OpenDatabase(db);
123
124   EXPECT_EQ("0", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"))
125       << "Invalid test setup";
126   RunTransactions(db);
127 }
128
129 TEST_P(DatabaseOptionsTest, FlushToDisk_True_DoesNotCrash) {
130   Database db(DatabaseOptions{
131       .exclusive_locking = exclusive_locking(),
132       .wal_mode = wal_mode(),
133       .flush_to_media = true,
134   });
135   OpenDatabase(db);
136
137   EXPECT_EQ("1", sql::test::ExecuteWithResult(&db, "PRAGMA fullfsync"))
138       << "Invalid test setup";
139   RunTransactions(db);
140 }
141
142 TEST_P(DatabaseOptionsTest, PageSize_Default) {
143   static_assert(DatabaseOptions::kDefaultPageSize == 4096,
144                 "The page size numbers in this test file need to change");
145   Database db(DatabaseOptions{
146       .exclusive_locking = exclusive_locking(),
147       .wal_mode = wal_mode(),
148       .page_size = 4096,
149   });
150
151   OpenDatabase(db);
152   EXPECT_EQ("4096", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
153
154   RunTransactions(db);
155   if (open_variant() != OpenVariant::kInMemory) {
156     db.Close();
157     EXPECT_EQ(4096, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
158   }
159 }
160
161 TEST_P(DatabaseOptionsTest, PageSize_Large) {
162   static_assert(DatabaseOptions::kDefaultPageSize < 16384,
163                 "The page size numbers in this test file need to change");
164   Database db(DatabaseOptions{
165       .exclusive_locking = exclusive_locking(),
166       .wal_mode = wal_mode(),
167       .page_size = 16384,
168   });
169
170   OpenDatabase(db);
171   EXPECT_EQ("16384", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
172
173   RunTransactions(db);
174   if (open_variant() != OpenVariant::kInMemory) {
175     db.Close();
176     EXPECT_EQ(16384, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
177   }
178 }
179
180 TEST_P(DatabaseOptionsTest, PageSize_Small) {
181   static_assert(DatabaseOptions::kDefaultPageSize > 1024,
182                 "The page size numbers in this test file need to change");
183   Database db(DatabaseOptions{
184       .exclusive_locking = exclusive_locking(),
185       .wal_mode = wal_mode(),
186       .page_size = 1024,
187   });
188
189   OpenDatabase(db);
190   EXPECT_EQ("1024", sql::test::ExecuteWithResult(&db, "PRAGMA page_size"));
191
192   RunTransactions(db);
193   if (open_variant() != OpenVariant::kInMemory) {
194     db.Close();
195     EXPECT_EQ(1024, sql::test::ReadDatabasePageSize(db_path_).value_or(-1));
196   }
197 }
198
199 TEST_P(DatabaseOptionsTest, CacheSize_Legacy) {
200   Database db(DatabaseOptions{
201       .exclusive_locking = exclusive_locking(),
202       .wal_mode = wal_mode(),
203       .cache_size = 0,
204   });
205   OpenDatabase(db);
206
207   EXPECT_EQ("-2000", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
208 }
209
210 TEST_P(DatabaseOptionsTest, CacheSize_Small) {
211   Database db(DatabaseOptions{
212       .exclusive_locking = exclusive_locking(),
213       .wal_mode = wal_mode(),
214       .cache_size = 16,
215   });
216   OpenDatabase(db);
217   EXPECT_EQ("16", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
218 }
219
220 TEST_P(DatabaseOptionsTest, CacheSize_Large) {
221   Database db(DatabaseOptions{
222       .exclusive_locking = exclusive_locking(),
223       .wal_mode = wal_mode(),
224       .cache_size = 1000,
225   });
226   OpenDatabase(db);
227   EXPECT_EQ("1000", sql::test::ExecuteWithResult(&db, "PRAGMA cache_size"));
228 }
229
230 TEST_P(DatabaseOptionsTest, EnableViewsDiscouraged_FalseByDefault) {
231   DatabaseOptions options = {
232       .exclusive_locking = exclusive_locking(),
233       .wal_mode = wal_mode(),
234   };
235   EXPECT_FALSE(options.enable_views_discouraged) << "Invalid test assumption";
236
237   Database db(options);
238   OpenDatabase(db);
239
240   // sqlite3_db_config() currently only disables querying views. Schema
241   // operations on views are still allowed.
242   ASSERT_TRUE(db.Execute("CREATE VIEW view(id) AS SELECT 1"));
243
244   {
245     sql::test::ScopedErrorExpecter expecter;
246     expecter.ExpectError(SQLITE_ERROR);
247     Statement select_from_view(db.GetUniqueStatement("SELECT id FROM view"));
248     EXPECT_FALSE(select_from_view.is_valid());
249     EXPECT_TRUE(expecter.SawExpectedErrors());
250   }
251
252   // sqlite3_db_config() currently only disables querying views. Schema
253   // operations on views are still allowed.
254   EXPECT_TRUE(db.Execute("DROP VIEW IF EXISTS view"));
255 }
256
257 TEST_P(DatabaseOptionsTest, EnableViewsDiscouraged_True) {
258   Database db(DatabaseOptions{
259       .exclusive_locking = exclusive_locking(),
260       .wal_mode = wal_mode(),
261       .enable_views_discouraged = true,
262   });
263   OpenDatabase(db);
264
265   ASSERT_TRUE(db.Execute("CREATE VIEW view(id) AS SELECT 1"));
266
267   Statement select_from_view(db.GetUniqueStatement("SELECT id FROM view"));
268   ASSERT_TRUE(select_from_view.is_valid());
269   EXPECT_TRUE(select_from_view.Step());
270   EXPECT_EQ(1, select_from_view.ColumnInt64(0));
271
272   EXPECT_TRUE(db.Execute("DROP VIEW IF EXISTS view"));
273 }
274
275 TEST_P(DatabaseOptionsTest, EnableVirtualTablesDiscouraged_FalseByDefault) {
276   DatabaseOptions options = {
277       .exclusive_locking = exclusive_locking(),
278       .wal_mode = wal_mode(),
279   };
280   EXPECT_FALSE(options.enable_virtual_tables_discouraged)
281       << "Invalid test assumption";
282
283   Database db(options);
284   OpenDatabase(db);
285
286   // sqlite3_prepare_v3() currently only disables accessing virtual tables.
287   // Schema operations on virtual tables are still allowed.
288   ASSERT_TRUE(db.Execute(
289       "CREATE VIRTUAL TABLE fts_table USING fts3(data_table, content TEXT)"));
290
291   {
292     sql::test::ScopedErrorExpecter expecter;
293     expecter.ExpectError(SQLITE_ERROR);
294     Statement select_from_vtable(db.GetUniqueStatement(
295         "SELECT content FROM fts_table WHERE content MATCH 'pattern'"));
296     EXPECT_FALSE(select_from_vtable.is_valid());
297     EXPECT_TRUE(expecter.SawExpectedErrors());
298   }
299
300   // sqlite3_prepare_v3() currently only disables accessing virtual tables.
301   // Schema operations on virtual tables are still allowed.
302   EXPECT_TRUE(db.Execute("DROP TABLE IF EXISTS fts_table"));
303 }
304
305 TEST_P(DatabaseOptionsTest, EnableVirtualTablesDiscouraged_True) {
306   Database db(DatabaseOptions{
307       .exclusive_locking = exclusive_locking(),
308       .wal_mode = wal_mode(),
309       .enable_virtual_tables_discouraged = true,
310   });
311   OpenDatabase(db);
312
313   ASSERT_TRUE(db.Execute(
314       "CREATE VIRTUAL TABLE fts_table USING fts3(data_table, content TEXT)"));
315
316   Statement select_from_vtable(db.GetUniqueStatement(
317       "SELECT content FROM fts_table WHERE content MATCH 'pattern'"));
318   ASSERT_TRUE(select_from_vtable.is_valid());
319   EXPECT_FALSE(select_from_vtable.Step());
320
321   EXPECT_TRUE(db.Execute("DROP TABLE IF EXISTS fts_table"));
322 }
323
324 INSTANTIATE_TEST_SUITE_P(
325     ,
326     DatabaseOptionsTest,
327     testing::Values(OpenVariant::kInMemory,
328                     OpenVariant::kOnDiskExclusiveJournal,
329                     OpenVariant::kOnDiskNonExclusiveJournal,
330                     OpenVariant::kOnDiskExclusiveWal));
331
332 }  // namespace
333
334 }  // namespace sql