database_browsertest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// found in the LICENSE file.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/browser_context.h"
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/download_manager.h"
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/notification_service.h"
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/notification_types.h"
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/browser/web_contents.h"
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/test/browser_test_utils.h"
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/public/test/test_utils.h"
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/shell/shell.h"
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/test/content_browser_test.h"
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/test/content_browser_test_utils.h"
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "content/test/net/url_request_mock_http_job.h"
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace content {
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class DatabaseTest : public ContentBrowserTest {
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) public:
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  DatabaseTest() {}
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  void RunScriptAndCheckResult(Shell* shell,
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                               const std::string& script,
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                               const std::string& result) {
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    std::string data;
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_TRUE(ExecuteScriptAndExtractString(
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        shell->web_contents(),
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        script,
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        &data));
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_EQ(data, result);
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  void Navigate(Shell* shell) {
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NavigateToURL(shell, GetTestUrl("", "simple_database.html"));
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  void CreateTable(Shell* shell) {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RunScriptAndCheckResult(shell, "createTable()", "done");
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)  }
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
45  void InsertRecord(Shell* shell, const std::string& data) {
46    RunScriptAndCheckResult(shell, "insertRecord('" + data + "')", "done");
47  }
48
49  void UpdateRecord(Shell* shell, int index, const std::string& data) {
50    RunScriptAndCheckResult(
51        shell,
52        "updateRecord(" + base::IntToString(index) + ", '" + data + "')",
53        "done");
54  }
55
56  void DeleteRecord(Shell* shell, int index) {
57    RunScriptAndCheckResult(
58        shell, "deleteRecord(" + base::IntToString(index) + ")", "done");
59  }
60
61  void CompareRecords(Shell* shell, const std::string& expected) {
62    RunScriptAndCheckResult(shell, "getRecords()", expected);
63  }
64
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]";
72  }
73};
74
75// Insert records to the database.
76IN_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");
83}
84
85// Update records in the database.
86IN_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");
92
93  InsertRecord(shell(), "1");
94  InsertRecord(shell(), "2");
95  UpdateRecord(shell(), 1, "1000");
96  CompareRecords(shell(), "0, 1000, 2");
97}
98
99// Delete records in the database.
100IN_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());
106
107  InsertRecord(shell(), "0");
108  InsertRecord(shell(), "1");
109  InsertRecord(shell(), "2");
110  DeleteRecord(shell(), 1);
111  CompareRecords(shell(), "0, 2");
112}
113
114// Attempts to delete a nonexistent row in the table.
115IN_PROC_BROWSER_TEST_F(DatabaseTest, DeleteNonexistentRow) {
116  Navigate(shell());
117  CreateTable(shell());
118  InsertRecord(shell(), "text");
119
120  RunScriptAndCheckResult(
121      shell(), "deleteRecord(1)", "could not find row with index: 1");
122
123  CompareRecords(shell(), "text");
124}
125
126// Insert, update, and delete records in the database.
127IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabaseOperations) {
128  Navigate(shell());
129  CreateTable(shell());
130
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;
138  }
139  CompareRecords(shell(), expected);
140
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;
148  }
149  CompareRecords(shell(), expected);
150
151  for (int i = 0; i < 10; ++i)
152    DeleteRecord(shell(), 0);
153
154  CompareRecords(shell(), std::string());
155
156  RunScriptAndCheckResult(
157      shell(), "deleteRecord(1)", "could not find row with index: 1");
158
159  CompareRecords(shell(), std::string());
160}
161
162// Create records in the database and verify they persist after reload.
163IN_PROC_BROWSER_TEST_F(DatabaseTest, ReloadPage) {
164  Navigate(shell());
165  CreateTable(shell());
166  InsertRecord(shell(), "text");
167
168  WindowedNotificationObserver load_stop_observer(
169      NOTIFICATION_LOAD_STOP,
170      NotificationService::AllSources());
171  shell()->Reload();
172  load_stop_observer.Wait();
173
174  CompareRecords(shell(), "text");
175}
176
177// Attempt to read a database created in a regular browser from an off the
178// record browser.
179IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordCannotReadRegularDatabase) {
180  Navigate(shell());
181  CreateTable(shell());
182  InsertRecord(shell(), "text");
183
184  Shell* otr = CreateOffTheRecordBrowser();
185  Navigate(otr);
186  ASSERT_FALSE(HasTable(otr));
187
188  CreateTable(otr);
189  CompareRecords(otr, std::string());
190}
191
192// Attempt to read a database created in an off the record browser from a
193// regular browser.
194IN_PROC_BROWSER_TEST_F(DatabaseTest, RegularCannotReadOffTheRecordDatabase) {
195  Shell* otr = CreateOffTheRecordBrowser();
196  Navigate(otr);
197  CreateTable(otr);
198  InsertRecord(otr, "text");
199
200  Navigate(shell());
201  ASSERT_FALSE(HasTable(shell()));
202  CreateTable(shell());
203  CompareRecords(shell(), std::string());
204}
205
206// Verify DB changes within first window are present in the second window.
207IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationPersistInSecondTab) {
208  Navigate(shell());
209  CreateTable(shell());
210  InsertRecord(shell(), "text");
211
212  Shell* shell2 = CreateBrowser();
213  Navigate(shell2);
214  UpdateRecord(shell2, 0, "0");
215
216  CompareRecords(shell(), "0");
217  CompareRecords(shell2, "0");
218}
219
220// Verify database modifications persist after restarting browser.
221IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_DatabasePersistsAfterRelaunch) {
222  Navigate(shell());
223  CreateTable(shell());
224  InsertRecord(shell(), "text");
225}
226
227IN_PROC_BROWSER_TEST_F(DatabaseTest, DatabasePersistsAfterRelaunch) {
228  Navigate(shell());
229  CompareRecords(shell(), "text");
230}
231
232// Verify OTR database is removed after OTR window closes.
233IN_PROC_BROWSER_TEST_F(DatabaseTest, PRE_OffTheRecordDatabaseNotPersistent) {
234  Shell* otr = CreateOffTheRecordBrowser();
235  Navigate(otr);
236  CreateTable(otr);
237  InsertRecord(otr, "text");
238}
239
240IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDatabaseNotPersistent) {
241  Shell* otr = CreateOffTheRecordBrowser();
242  Navigate(otr);
243  ASSERT_FALSE(HasTable(otr));
244}
245
246// Verify database modifications persist after crashing window.
247IN_PROC_BROWSER_TEST_F(DatabaseTest, ModificationsPersistAfterRendererCrash) {
248  Navigate(shell());
249  CreateTable(shell());
250  InsertRecord(shell(), "1");
251
252  CrashTab(shell()->web_contents());
253  Navigate(shell());
254  CompareRecords(shell(), "1");
255}
256
257// Test to check if database modifications are persistent across windows in
258// off the record window.
259IN_PROC_BROWSER_TEST_F(DatabaseTest, OffTheRecordDBPersistentAcrossWindows) {
260  Shell* otr1 = CreateOffTheRecordBrowser();
261  Navigate(otr1);
262  CreateTable(otr1);
263  InsertRecord(otr1, "text");
264
265  Shell* otr2 = CreateOffTheRecordBrowser();
266  Navigate(otr2);
267  CompareRecords(otr2, "text");
268}
269
270}  // namespace content
271