Save errno for logging before potentially overwriting it.
[chromium-blink-merge.git] / content / browser / database_browsertest.cc
blob305d8ff94c0e1864300f051d7df2836aa9d46734
1 // Copyright (c) 2012 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/strings/string_number_conversions.h"
6 #include "base/strings/utf_string_conversions.h"
7 #include "content/public/browser/browser_context.h"
8 #include "content/public/browser/download_manager.h"
9 #include "content/public/browser/notification_service.h"
10 #include "content/public/browser/notification_types.h"
11 #include "content/public/browser/web_contents.h"
12 #include "content/public/test/browser_test_utils.h"
13 #include "content/public/test/test_utils.h"
14 #include "content/shell/shell.h"
15 #include "content/test/content_browser_test.h"
16 #include "content/test/content_browser_test_utils.h"
17 #include "content/test/net/url_request_mock_http_job.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 namespace content {
22 class DatabaseTest : public ContentBrowserTest {
23 public:
24 DatabaseTest() {}
26 void RunScriptAndCheckResult(Shell* shell,
27 const std::string& script,
28 const std::string& result) {
29 std::string data;
30 ASSERT_TRUE(ExecuteScriptAndExtractString(
31 shell->web_contents(),
32 script,
33 &data));
34 ASSERT_EQ(data, result);
37 void Navigate(Shell* shell) {
38 NavigateToURL(shell, GetTestUrl("", "simple_database.html"));
41 void CreateTable(Shell* shell) {
42 RunScriptAndCheckResult(shell, "createTable()", "done");
45 void InsertRecord(Shell* shell, const std::string& data) {
46 RunScriptAndCheckResult(shell, "insertRecord('" + data + "')", "done");
49 void UpdateRecord(Shell* shell, int index, const std::string& data) {
50 RunScriptAndCheckResult(
51 shell,
52 "updateRecord(" + base::IntToString(index) + ", '" + data + "')",
53 "done");
56 void DeleteRecord(Shell* shell, int index) {
57 RunScriptAndCheckResult(
58 shell, "deleteRecord(" + base::IntToString(index) + ")", "done");
61 void CompareRecords(Shell* shell, const std::string& expected) {
62 RunScriptAndCheckResult(shell, "getRecords()", expected);
65 bool HasTable(Shell* shell) {
66 std::string data;
67 CHECK(ExecuteScriptAndExtractString(
68 shell->web_contents(),
69 "getRecords()",
70 &data));
71 return data != "getRecords error: [object SQLError]";
75 // Insert records to the database.
76 IN_PROC_BROWSER_TEST_F(DatabaseTest, InsertRecord) {
77 Navigate(shell());
78 CreateTable(shell());
79 InsertRecord(shell(), "text");
80 CompareRecords(shell(), "text");
81 InsertRecord(shell(), "text2");
82 CompareRecords(shell(), "text, text2");
85 // Update records in the database.
86 IN_PROC_BROWSER_TEST_F(DatabaseTest, UpdateRecord) {
87 Navigate(shell());
88 CreateTable(shell());
89 InsertRecord(shell(), "text");
90 UpdateRecord(shell(), 0, "0");
91 CompareRecords(shell(), "0");
93 InsertRecord(shell(), "1");
94 InsertRecord(shell(), "2");
95 UpdateRecord(shell(), 1, "1000");
96 CompareRecords(shell(), "0, 1000, 2");
99 // Delete records in the database.
100 IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteRecord) {
101 Navigate(shell());
102 CreateTable(shell());
103 InsertRecord(shell(), "text");
104 DeleteRecord(shell(), 0);
105 CompareRecords(shell(), std::string());
107 InsertRecord(shell(), "0");
108 InsertRecord(shell(), "1");
109 InsertRecord(shell(), "2");
110 DeleteRecord(shell(), 1);
111 CompareRecords(shell(), "0, 2");
114 // Attempts to delete a nonexistent row in the table.
115 IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteNonexistentRow) {
116 Navigate(shell());
117 CreateTable(shell());
118 InsertRecord(shell(), "text");
120 RunScriptAndCheckResult(
121 shell(), "deleteRecord(1)", "could not find row with index: 1");
123 CompareRecords(shell(), "text");
126 // Insert, update, and delete records in the database.
127 IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabaseOperations) {
128 Navigate(shell());
129 CreateTable(shell());
131 std::string expected;
132 for (int i = 0; i < 10; ++i) {
133 std::string item = base::IntToString(i);
134 InsertRecord(shell(), item);
135 if (!expected.empty())
136 expected += ", ";
137 expected += item;
139 CompareRecords(shell(), expected);
141 expected.clear();
142 for (int i = 0; i < 10; ++i) {
143 std::string item = base::IntToString(i * i);
144 UpdateRecord(shell(), i, item);
145 if (!expected.empty())
146 expected += ", ";
147 expected += item;
149 CompareRecords(shell(), expected);
151 for (int i = 0; i < 10; ++i)
152 DeleteRecord(shell(), 0);
154 CompareRecords(shell(), std::string());
156 RunScriptAndCheckResult(
157 shell(), "deleteRecord(1)", "could not find row with index: 1");
159 CompareRecords(shell(), std::string());
162 // Create records in the database and verify they persist after reload.
163 IN_PROC_BROWSER_TEST_F(DatabaseTest, ReloadPage) {
164 Navigate(shell());
165 CreateTable(shell());
166 InsertRecord(shell(), "text");
168 WindowedNotificationObserver load_stop_observer(
169 NOTIFICATION_LOAD_STOP,
170 NotificationService::AllSources());
171 shell()->Reload();
172 load_stop_observer.Wait();
174 CompareRecords(shell(), "text");
177 // Attempt to read a database created in a regular browser from an off the
178 // record browser.
179 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordCannotReadRegularDatabase) {
180 Navigate(shell());
181 CreateTable(shell());
182 InsertRecord(shell(), "text");
184 Shell* otr = CreateOffTheRecordBrowser();
185 Navigate(otr);
186 ASSERT_FALSE(HasTable(otr));
188 CreateTable(otr);
189 CompareRecords(otr, std::string());
192 // Attempt to read a database created in an off the record browser from a
193 // regular browser.
194 IN_PROC_BROWSER_TEST_F(DatabaseTest, RegularCannotReadOffTheRecordDatabase) {
195 Shell* otr = CreateOffTheRecordBrowser();
196 Navigate(otr);
197 CreateTable(otr);
198 InsertRecord(otr, "text");
200 Navigate(shell());
201 ASSERT_FALSE(HasTable(shell()));
202 CreateTable(shell());
203 CompareRecords(shell(), std::string());
206 // Verify DB changes within first window are present in the second window.
207 IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationPersistInSecondTab) {
208 Navigate(shell());
209 CreateTable(shell());
210 InsertRecord(shell(), "text");
212 Shell* shell2 = CreateBrowser();
213 Navigate(shell2);
214 UpdateRecord(shell2, 0, "0");
216 CompareRecords(shell(), "0");
217 CompareRecords(shell2, "0");
220 // Verify database modifications persist after restarting browser.
221 IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_DatabasePersistsAfterRelaunch) {
222 Navigate(shell());
223 CreateTable(shell());
224 InsertRecord(shell(), "text");
227 IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabasePersistsAfterRelaunch) {
228 Navigate(shell());
229 CompareRecords(shell(), "text");
232 // Verify OTR database is removed after OTR window closes.
233 IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_OffTheRecordDatabaseNotPersistent) {
234 Shell* otr = CreateOffTheRecordBrowser();
235 Navigate(otr);
236 CreateTable(otr);
237 InsertRecord(otr, "text");
240 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDatabaseNotPersistent) {
241 Shell* otr = CreateOffTheRecordBrowser();
242 Navigate(otr);
243 ASSERT_FALSE(HasTable(otr));
246 // Verify database modifications persist after crashing window.
247 IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationsPersistAfterRendererCrash) {
248 Navigate(shell());
249 CreateTable(shell());
250 InsertRecord(shell(), "1");
252 CrashTab(shell()->web_contents());
253 Navigate(shell());
254 CompareRecords(shell(), "1");
257 // Test to check if database modifications are persistent across windows in
258 // off the record window.
259 IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDBPersistentAcrossWindows) {
260 Shell* otr1 = CreateOffTheRecordBrowser();
261 Navigate(otr1);
262 CreateTable(otr1);
263 InsertRecord(otr1, "text");
265 Shell* otr2 = CreateOffTheRecordBrowser();
266 Navigate(otr2);
267 CompareRecords(otr2, "text");
270 } // namespace content