OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 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 os.path.join('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 testInsertRecord(self): |
| 128 """Insert records to the database.""" |
| 129 self.NavigateToURL(self.TEST_PAGE_URL) |
| 130 self._CreateTable() |
| 131 self._InsertRecord('text') |
| 132 self.assertEquals(['text'], self._GetRecords()) |
| 133 self._InsertRecord('text2') |
| 134 self.assertEquals(['text', 'text2'], self._GetRecords()) |
| 135 |
| 136 def testUpdateRecord(self): |
| 137 """Update records in the database.""" |
| 138 self.NavigateToURL(self.TEST_PAGE_URL) |
| 139 self._CreateTable() |
| 140 |
| 141 # Update the first record. |
| 142 self._InsertRecord('text') |
| 143 self._UpdateRecord(0, '0') |
| 144 records = self._GetRecords() |
| 145 self.assertEquals(1, len(records)) |
| 146 self.assertEquals('0', records[0]) |
| 147 |
| 148 # Update the middle record. |
| 149 self._InsertRecord('1') |
| 150 self._InsertRecord('2') |
| 151 self._UpdateRecord(1, '1000') |
| 152 self.assertEquals(['0', '1000', '2'], self._GetRecords()) |
| 153 |
| 154 def testDeleteRecord(self): |
| 155 """Delete records in the database.""" |
| 156 self.NavigateToURL(self.TEST_PAGE_URL) |
| 157 self._CreateTable() |
| 158 |
| 159 # Delete the first and only record. |
| 160 self._InsertRecord('text') |
| 161 self._DeleteRecord(0) |
| 162 self.assertFalse(self._GetRecords()) |
| 163 |
| 164 # Delete the middle record. |
| 165 self._InsertRecord('0') |
| 166 self._InsertRecord('1') |
| 167 self._InsertRecord('2') |
| 168 self._DeleteRecord(1) |
| 169 self.assertEquals(['0', '2'], self._GetRecords()) |
| 170 |
| 171 def testDeleteNonexistentRow(self): |
| 172 """Attempts to delete a nonexistent row in the table.""" |
| 173 self.NavigateToURL(self.TEST_PAGE_URL) |
| 174 self._CreateTable() |
| 175 self._InsertRecord('text') |
| 176 did_throw_exception = False |
| 177 try: |
| 178 self._DeleteRecord(1) |
| 179 except: |
| 180 did_throw_exception = True |
| 181 self.assertTrue(did_throw_exception) |
| 182 self.assertEquals(['text'], self._GetRecords()) |
| 183 |
| 184 def testDatabaseOperations(self): |
| 185 """Insert, update, and delete records in the database.""" |
| 186 self.NavigateToURL(self.TEST_PAGE_URL) |
| 187 self._CreateTable() |
| 188 |
| 189 for i in range(10): |
| 190 self._InsertRecord(str(i)) |
| 191 records = self._GetRecords() |
| 192 self.assertEqual([str(i) for i in range(10)], records) |
| 193 |
| 194 for i in range(10): |
| 195 self._UpdateRecord(i, str(i * i)) |
| 196 records = self._GetRecords() |
| 197 self.assertEqual([str(i * i) for i in range(10)], records) |
| 198 |
| 199 for i in range(10): |
| 200 self._DeleteRecord(0) |
| 201 self.assertEqual(0, len(self._GetRecords())) |
| 202 |
| 203 def testReloadActiveTab(self): |
| 204 """Create records in the database and verify they persist after reload.""" |
| 205 self.NavigateToURL(self.TEST_PAGE_URL) |
| 206 self._CreateTable() |
| 207 self._InsertRecord('text') |
| 208 self.ReloadActiveTab() |
| 209 self.assertEquals(['text'], self._GetRecords()) |
| 210 |
| 211 def testIncognitoCannotReadRegularDatabase(self): |
| 212 """Attempt to read a database created in a regular browser from an incognito |
| 213 browser. |
| 214 """ |
| 215 self.NavigateToURL(self.TEST_PAGE_URL) |
| 216 self._CreateTable() |
| 217 self._InsertRecord('text') |
| 218 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) |
| 219 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) |
| 220 can_read_regular_database = False |
| 221 try: |
| 222 # |_GetRecords| should throw an error because the table does not exist. |
| 223 if len(self._GetRecords(windex=1)) == 1: |
| 224 can_read_regular_database = True |
| 225 except SQLExecutionError: |
| 226 pass |
| 227 self.assertFalse(can_read_regular_database) |
| 228 self._CreateTable(windex=1) |
| 229 self.assertEqual(0, len(self._GetRecords(windex=1))) |
| 230 |
| 231 def testRegularCannotReadIncognitoDatabase(self): |
| 232 """Attempt to read a database created in an incognito browser from a regular |
| 233 browser. |
| 234 """ |
| 235 self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW) |
| 236 self.NavigateToURL(self.TEST_PAGE_URL, 1, 0) |
| 237 self._CreateTable(windex=1) |
| 238 self._InsertRecord('text', windex=1) |
| 239 |
| 240 # Verify a regular browser cannot read the incognito database. |
| 241 self.NavigateToURL(self.TEST_PAGE_URL) |
| 242 can_read_incognito_database = False |
| 243 try: |
| 244 # |_GetRecords| should throw an error because the table does not exist. |
| 245 if len(self._GetRecords()) == 1: |
| 246 can_read_incognito_database = True |
| 247 except SQLExecutionError: |
| 248 pass |
| 249 self.assertFalse(can_read_incognito_database) |
| 250 |
| 251 |
| 252 if __name__ == '__main__': |
| 253 pyauto_functional.Main() |
OLD | NEW |