OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 import simplejson | |
7 import os | |
8 | |
9 import pyauto_functional | |
10 import pyauto | |
11 | |
12 | |
13 class SQLExecutionError(RuntimeError): | |
14 """Represents an error that occurs while executing an SQL statement.""" | |
15 pass | |
16 | |
17 | |
18 class DatabasesTest(pyauto.PyUITest): | |
19 """Test of Web SQL Databases.""" | |
20 | |
21 def __init__(self, methodName='runTest'): | |
22 super(DatabasesTest, self).__init__(methodName) | |
23 # HTML page used for database testing. | |
24 self.TEST_PAGE_URL = self.GetFileURLForDataPath( | |
25 'database', 'database_tester.html') | |
26 | |
27 def _ParseAndCheckResultFromTestPage(self, json): | |
28 """Helper function that parses the message sent from |TEST_PAGE_URL| and | |
29 checks that it succeeded. | |
30 | |
31 Args: | |
32 json: the message, encoded in JSON, that the test page sent to us | |
33 | |
34 Returns: | |
35 dictionary representing the result from the test page, with format: | |
36 { | |
37 'succeeded': boolean | |
38 'errorMsg': optional string | |
39 'returnValue': optional any type | |
40 } | |
41 | |
42 Raises: | |
43 SQLExecutionError if the message contains an error message | |
44 """ | |
45 result_dict = simplejson.loads(json) | |
46 if result_dict['succeeded'] == False: | |
47 raise SQLExecutionError(result_dict['errorMsg']) | |
48 return result_dict | |
49 | |
50 def _CreateTable(self, tab_index=0, windex=0): | |
51 """Creates a table in the database. | |
52 | |
53 This should only be called once per database. This should be called before | |
54 attempting to insert, update, delete, or get the records in the database. | |
55 | |
56 Defaults to first tab in first window. | |
57 | |
58 Args: | |
59 tab_index: index of the tab that will create the database | |
60 windex: index of the window containing the tab that will create the | |
61 database | |
62 """ | |
63 json = self.CallJavascriptFunc('createTable', [], tab_index, windex) | |
64 self._ParseAndCheckResultFromTestPage(json) | |
65 | |
66 def _InsertRecord(self, record, tab_index=0, windex=0): | |
67 """Inserts a record, i.e., a row, into the database. | |
68 | |
69 Defaults to first tab in first window. | |
70 | |
71 Args: | |
72 record: string that will be added as a new row in the database | |
73 tab_index: index of the tab that will insert the record | |
74 windex: index of the window containing the tab that will insert the record | |
75 """ | |
76 json = self.CallJavascriptFunc('insertRecord', [record], tab_index, windex) | |
77 self._ParseAndCheckResultFromTestPage(json) | |
78 | |
79 def _UpdateRecord(self, index, updated_record, tab_index=0, windex=0): | |
80 """Updates a record, i.e., a row, in the database. | |
81 | |
82 Defaults to first tab in first window. | |
83 | |
84 Args: | |
85 index: index of the record to update. Index 0 refers to the oldest item in | |
86 the database | |
87 updated_record: string that will be used to update the row in the database | |
88 tab_index: index of the tab that will update the record | |
89 windex: index of the window containing the tab that will update the record | |
90 """ | |
91 json = self.CallJavascriptFunc( | |
92 'updateRecord', [index, updated_record], tab_index, windex) | |
93 self._ParseAndCheckResultFromTestPage(json) | |
94 | |
95 def _DeleteRecord(self, index, tab_index=0, windex=0): | |
96 """Deletes a record, i.e., a row, from the database. | |
97 | |
98 Defaults to first tab in first window. | |
99 | |
100 Args: | |
101 index: index of the record to be deleted. Index 0 refers to the oldest | |
102 item in the database | |
103 tab_index: index of the tab that will delete the record | |
104 windex: index of the window containing the tab that will delete the record | |
105 """ | |
106 json = self.CallJavascriptFunc('deleteRecord', [index], tab_index, windex) | |
107 self._ParseAndCheckResultFromTestPage(json) | |
108 | |
109 def _GetRecords(self, tab_index=0, windex=0): | |
110 """Returns all the records, i.e., rows, in the database. | |
111 | |
112 The records are ordererd from oldest to newest. | |
113 | |
114 Defaults to first tab in first window. | |
115 | |
116 Returns: | |
117 array of all the records in the database | |
118 | |
119 Args: | |
120 tab_index: index of the tab that will query the database | |
121 windex: index of the window containing the tab that will query the | |
122 database | |
123 """ | |
124 json = self.CallJavascriptFunc('getRecords', [], tab_index, windex) | |
125 return self._ParseAndCheckResultFromTestPage(json)['returnValue'] | |
126 | |
127 def _HasTable(self, tab_index=0, windex=0): | |
128 """Returns whether the page has a table in its database.""" | |
129 try: | |
130 self._GetRecords(tab_index, windex) | |
131 except SQLExecutionError: | |
132 return False | |
133 return True | |
134 | |
135 def testInsertRecord(self): | |
136 """Insert records to the database.""" | |
137 self.NavigateToURL(self.TEST_PAGE_URL) | |
138 self._CreateTable() | |
139 self._InsertRecord('text') | |
140 self.assertEquals(['text'], self._GetRecords()) | |
141 self._InsertRecord('text2') | |
142 self.assertEquals(['text', 'text2'], self._GetRecords()) | |
143 | |
144 def testUpdateRecord(self): | |
145 """Update records in the database.""" | |
146 self.NavigateToURL(self.TEST_PAGE_URL) | |
147 self._CreateTable() | |
148 | |
149 # Update the first record. | |
150 self._InsertRecord('text') | |
151 self._UpdateRecord(0, '0') | |
152 records = self._GetRecords() | |
153 self.assertEquals(1, len(records)) | |
154 self.assertEquals('0', records[0]) | |
155 | |
156 # Update the middle record. | |
157 self._InsertRecord('1') | |
158 self._InsertRecord('2') | |
159 self._UpdateRecord(1, '1000') | |
160 self.assertEquals(['0', '1000', '2'], self._GetRecords()) | |
161 | |
162 def testDeleteRecord(self): | |
163 """Delete records in the database.""" | |
164 self.NavigateToURL(self.TEST_PAGE_URL) | |
165 self._CreateTable() | |
166 | |
167 # Delete the first and only record. | |
168 self._InsertRecord('text') | |
169 self._DeleteRecord(0) | |
170 self.assertFalse(self._GetRecords()) | |
171 | |
172 # Delete the middle record. | |
173 self._InsertRecord('0') | |
174 self._InsertRecord('1') | |
175 self._InsertRecord('2') | |
176 self._DeleteRecord(1) | |
177 self.assertEquals(['0', '2'], self._GetRecords()) | |
178 | |
179 def testDeleteNonexistentRow(self): | |
180 """Attempts to delete a nonexistent row in the table.""" | |
181 self.NavigateToURL(self.TEST_PAGE_URL) | |
182 self._CreateTable() | |
183 self._InsertRecord('text') | |
184 did_throw_exception = False | |
185 try: | |
186 self._DeleteRecord(1) | |
187 except SQLExecutionError: | |
188 did_throw_exception = True | |
189 self.assertTrue(did_throw_exception) | |
190 self.assertEquals(['text'], self._GetRecords()) | |
191 | |
192 def testDatabaseOperations(self): | |
193 """Insert, update, and delete records in the database.""" | |
194 self.NavigateToURL(self.TEST_PAGE_URL) | |
195 self._CreateTable() | |
196 | |
197 for i in range(10): | |
198 self._InsertRecord(str(i)) | |
199 records = self._GetRecords() | |
200 self.assertEqual([str(i) for i in range(10)], records) | |
201 | |
202 for i in range(10): | |
203 self._UpdateRecord(i, str(i * i)) | |
204 records = self._GetRecords() | |
205 self.assertEqual([str(i * i) for i in range(10)], records) | |
206 | |
207 for i in range(10): | |
208 self._DeleteRecord(0) | |
209 self.assertEqual(0, len(self._GetRecords())) | |
210 | |
211 def testReloadActiveTab(self): | |
212 """Create records in the database and verify they persist after reload.""" | |
213 self.NavigateToURL(self.TEST_PAGE_URL) | |
214 self._CreateTable() | |
215 self._InsertRecord('text') | |
216 self.ReloadActiveTab() | |
217 self.assertEquals(['text'], self._GetRecords()) | |
218 | |
219 def testIncognitoCannotReadRegularDatabase(self): | |
220 """Attempt to read a database created in a regular browser from an incognito | |
221 browser. | |
222 """ | |
223 self.NavigateToURL(self.TEST_PAGE_URL) | |
224 self._CreateTable() | |
225 self._InsertRecord('text') | |
226 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) | |
227 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) | |
228 self.assertFalse(self._HasTable(windex=1)) | |
229 self._CreateTable(windex=1) | |
230 self.assertFalse(self._GetRecords(windex=1)) | |
231 | |
232 def testRegularCannotReadIncognitoDatabase(self): | |
233 """Attempt to read a database created in an incognito browser from a regular | |
234 browser. | |
235 """ | |
236 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) | |
237 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) | |
238 self._CreateTable(windex=1) | |
239 self._InsertRecord('text', windex=1) | |
240 | |
241 # Verify a regular browser cannot read the incognito database. | |
242 self.NavigateToURL(self.TEST_PAGE_URL) | |
243 self.assertFalse(self._HasTable()) | |
244 self._CreateTable() | |
245 self.assertFalse(self._GetRecords()) | |
246 | |
247 def testDbModificationPersistInSecondTab(self): | |
248 """Verify DB changes within first tab are present in the second tab.""" | |
249 self.NavigateToURL(self.TEST_PAGE_URL) | |
250 self._CreateTable() | |
251 self._InsertRecord('text') | |
252 self.AppendTab(pyauto.GURL(self.TEST_PAGE_URL)) | |
253 self._UpdateRecord(0, '0', tab_index=0) | |
254 tab1_records = self._GetRecords(tab_index=0) | |
255 tab2_records = self._GetRecords(tab_index=1) | |
256 self.assertEquals(1, len(tab1_records)) | |
257 self.assertEquals('0', tab1_records[0]) | |
258 self.assertEquals(1, len(tab2_records)) | |
259 self.assertEquals(tab1_records[0], tab2_records[0]) | |
260 | |
261 def testIncognitoDatabaseNotPersistent(self): | |
262 """Verify incognito database is removed after incognito window closes.""" | |
263 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) | |
264 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) | |
265 self._CreateTable(windex=1) | |
266 self._InsertRecord('text', windex=1) | |
267 self.CloseBrowserWindow(1) | |
268 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) | |
269 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) | |
270 self.assertFalse(self._HasTable(windex=1)) | |
271 | |
272 def testModificationsPersistAfterRendererCrash(self): | |
273 """Verify database modifications persist after crashing tab.""" | |
274 self.AppendTab(pyauto.GURL('about:blank')) | |
275 self.ActivateTab(0) | |
276 self.NavigateToURL(self.TEST_PAGE_URL) | |
277 self._CreateTable() | |
278 self._InsertRecord('1') | |
279 self.KillRendererProcess( | |
280 self.GetBrowserInfo()['windows'][0]['tabs'][0]['renderer_pid']) | |
281 self.ReloadActiveTab() | |
282 self.assertEqual(['1'], self._GetRecords()) | |
283 | |
284 def testIncognitoDBPersistentAcrossTabs(self): | |
285 """Test to check if database modifications are persistent across tabs | |
286 in incognito window. | |
287 """ | |
288 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) | |
289 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) | |
290 self._CreateTable(windex=1) | |
291 self._InsertRecord('text', windex=1) | |
292 self.AppendTab(pyauto.GURL(self.TEST_PAGE_URL), 1) | |
293 self.assertEquals(['text'], self._GetRecords(1, 1)) | |
294 | |
295 def testDatabasePersistsAfterRelaunch(self): | |
296 """Verify database modifications persist after restarting browser.""" | |
297 self.NavigateToURL(self.TEST_PAGE_URL) | |
298 self._CreateTable() | |
299 self._InsertRecord('text') | |
300 self.RestartBrowser(clear_profile=False) | |
301 self.NavigateToURL(self.TEST_PAGE_URL) | |
302 self.assertEquals(['text'], self._GetRecords()) | |
303 | |
304 if __name__ == '__main__': | |
305 pyauto_functional.Main() | |
OLD | NEW |