|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 /* |
|
6 * This file tests the functionality of mozIStorageConnection::executeAsync for |
|
7 * both mozIStorageStatement and mozIStorageAsyncStatement. |
|
8 */ |
|
9 |
|
10 const INTEGER = 1; |
|
11 const TEXT = "this is test text"; |
|
12 const REAL = 3.23; |
|
13 const BLOB = [1, 2]; |
|
14 |
|
15 function test_create_and_add() |
|
16 { |
|
17 getOpenedDatabase().executeSimpleSQL( |
|
18 "CREATE TABLE test (" + |
|
19 "id INTEGER, " + |
|
20 "string TEXT, " + |
|
21 "number REAL, " + |
|
22 "nuller NULL, " + |
|
23 "blober BLOB" + |
|
24 ")" |
|
25 ); |
|
26 |
|
27 let stmts = []; |
|
28 stmts[0] = getOpenedDatabase().createStatement( |
|
29 "INSERT INTO test (id, string, number, nuller, blober) VALUES (?, ?, ?, ?, ?)" |
|
30 ); |
|
31 stmts[0].bindByIndex(0, INTEGER); |
|
32 stmts[0].bindByIndex(1, TEXT); |
|
33 stmts[0].bindByIndex(2, REAL); |
|
34 stmts[0].bindByIndex(3, null); |
|
35 stmts[0].bindBlobByIndex(4, BLOB, BLOB.length); |
|
36 stmts[1] = getOpenedDatabase().createAsyncStatement( |
|
37 "INSERT INTO test (string, number, nuller, blober) VALUES (?, ?, ?, ?)" |
|
38 ); |
|
39 stmts[1].bindByIndex(0, TEXT); |
|
40 stmts[1].bindByIndex(1, REAL); |
|
41 stmts[1].bindByIndex(2, null); |
|
42 stmts[1].bindBlobByIndex(3, BLOB, BLOB.length); |
|
43 |
|
44 getOpenedDatabase().executeAsync(stmts, stmts.length, { |
|
45 handleResult: function(aResultSet) |
|
46 { |
|
47 dump("handleResult("+aResultSet+")\n"); |
|
48 do_throw("unexpected results obtained!"); |
|
49 }, |
|
50 handleError: function(aError) |
|
51 { |
|
52 dump("handleError("+aError.result+")\n"); |
|
53 do_throw("unexpected error!"); |
|
54 }, |
|
55 handleCompletion: function(aReason) |
|
56 { |
|
57 dump("handleCompletion("+aReason+")\n"); |
|
58 do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason); |
|
59 |
|
60 // Check that the result is in the table |
|
61 let stmt = getOpenedDatabase().createStatement( |
|
62 "SELECT string, number, nuller, blober FROM test WHERE id = ?" |
|
63 ); |
|
64 stmt.bindByIndex(0, INTEGER); |
|
65 try { |
|
66 do_check_true(stmt.executeStep()); |
|
67 do_check_eq(TEXT, stmt.getString(0)); |
|
68 do_check_eq(REAL, stmt.getDouble(1)); |
|
69 do_check_true(stmt.getIsNull(2)); |
|
70 let count = { value: 0 }; |
|
71 let blob = { value: null }; |
|
72 stmt.getBlob(3, count, blob); |
|
73 do_check_eq(BLOB.length, count.value); |
|
74 for (let i = 0; i < BLOB.length; i++) |
|
75 do_check_eq(BLOB[i], blob.value[i]); |
|
76 } |
|
77 finally { |
|
78 stmt.finalize(); |
|
79 } |
|
80 |
|
81 // Make sure we have two rows in the table |
|
82 stmt = getOpenedDatabase().createStatement( |
|
83 "SELECT COUNT(1) FROM test" |
|
84 ); |
|
85 try { |
|
86 do_check_true(stmt.executeStep()); |
|
87 do_check_eq(2, stmt.getInt32(0)); |
|
88 } |
|
89 finally { |
|
90 stmt.finalize(); |
|
91 } |
|
92 |
|
93 // Run the next test. |
|
94 run_next_test(); |
|
95 } |
|
96 }); |
|
97 stmts[0].finalize(); |
|
98 stmts[1].finalize(); |
|
99 } |
|
100 |
|
101 function test_multiple_bindings_on_statements() |
|
102 { |
|
103 // This tests to make sure that we pass all the statements multiply bound |
|
104 // parameters when we call executeAsync. |
|
105 const AMOUNT_TO_ADD = 5; |
|
106 const ITERATIONS = 5; |
|
107 |
|
108 let stmts = []; |
|
109 let db = getOpenedDatabase(); |
|
110 let sqlString = "INSERT INTO test (id, string, number, nuller, blober) " + |
|
111 "VALUES (:int, :text, :real, :null, :blob)"; |
|
112 // We run the same statement twice, and should insert 2 * AMOUNT_TO_ADD. |
|
113 for (let i = 0; i < ITERATIONS; i++) { |
|
114 // alternate the type of statement we create |
|
115 if (i % 2) |
|
116 stmts[i] = db.createStatement(sqlString); |
|
117 else |
|
118 stmts[i] = db.createAsyncStatement(sqlString); |
|
119 |
|
120 let params = stmts[i].newBindingParamsArray(); |
|
121 for (let j = 0; j < AMOUNT_TO_ADD; j++) { |
|
122 let bp = params.newBindingParams(); |
|
123 bp.bindByName("int", INTEGER); |
|
124 bp.bindByName("text", TEXT); |
|
125 bp.bindByName("real", REAL); |
|
126 bp.bindByName("null", null); |
|
127 bp.bindBlobByName("blob", BLOB, BLOB.length); |
|
128 params.addParams(bp); |
|
129 } |
|
130 stmts[i].bindParameters(params); |
|
131 } |
|
132 |
|
133 // Get our current number of rows in the table. |
|
134 let currentRows = 0; |
|
135 let countStmt = getOpenedDatabase().createStatement( |
|
136 "SELECT COUNT(1) AS count FROM test" |
|
137 ); |
|
138 try { |
|
139 do_check_true(countStmt.executeStep()); |
|
140 currentRows = countStmt.row.count; |
|
141 } |
|
142 finally { |
|
143 countStmt.reset(); |
|
144 } |
|
145 |
|
146 // Execute asynchronously. |
|
147 getOpenedDatabase().executeAsync(stmts, stmts.length, { |
|
148 handleResult: function(aResultSet) |
|
149 { |
|
150 do_throw("Unexpected call to handleResult!"); |
|
151 }, |
|
152 handleError: function(aError) |
|
153 { |
|
154 print("Error code " + aError.result + " with message '" + |
|
155 aError.message + "' returned."); |
|
156 do_throw("Unexpected error!"); |
|
157 }, |
|
158 handleCompletion: function(aReason) |
|
159 { |
|
160 print("handleCompletion(" + aReason + |
|
161 ") for test_multiple_bindings_on_statements"); |
|
162 do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason); |
|
163 |
|
164 // Check to make sure we added all of our rows. |
|
165 try { |
|
166 do_check_true(countStmt.executeStep()); |
|
167 do_check_eq(currentRows + (ITERATIONS * AMOUNT_TO_ADD), |
|
168 countStmt.row.count); |
|
169 } |
|
170 finally { |
|
171 countStmt.finalize(); |
|
172 } |
|
173 |
|
174 // Run the next test. |
|
175 run_next_test(); |
|
176 } |
|
177 }); |
|
178 stmts.forEach(function(stmt) stmt.finalize()); |
|
179 } |
|
180 |
|
181 function test_asyncClose_does_not_complete_before_statements() |
|
182 { |
|
183 let stmt = createStatement("SELECT * FROM sqlite_master"); |
|
184 let executed = false; |
|
185 stmt.executeAsync({ |
|
186 handleResult: function(aResultSet) |
|
187 { |
|
188 }, |
|
189 handleError: function(aError) |
|
190 { |
|
191 print("Error code " + aError.result + " with message '" + |
|
192 aError.message + "' returned."); |
|
193 do_throw("Unexpected error!"); |
|
194 }, |
|
195 handleCompletion: function(aReason) |
|
196 { |
|
197 print("handleCompletion(" + aReason + |
|
198 ") for test_asyncClose_does_not_complete_before_statements"); |
|
199 do_check_eq(Ci.mozIStorageStatementCallback.REASON_FINISHED, aReason); |
|
200 executed = true; |
|
201 } |
|
202 }); |
|
203 stmt.finalize(); |
|
204 |
|
205 getOpenedDatabase().asyncClose(function() { |
|
206 // Ensure that the statement executed to completion. |
|
207 do_check_true(executed); |
|
208 |
|
209 // Reset gDBConn so that later tests will get a new connection object. |
|
210 gDBConn = null; |
|
211 run_next_test(); |
|
212 }); |
|
213 } |
|
214 |
|
215 function test_asyncClose_does_not_throw_no_callback() |
|
216 { |
|
217 getOpenedDatabase().asyncClose(); |
|
218 |
|
219 // Reset gDBConn so that later tests will get a new connection object. |
|
220 gDBConn = null; |
|
221 run_next_test(); |
|
222 } |
|
223 |
|
224 function test_double_asyncClose_throws() |
|
225 { |
|
226 let conn = getOpenedDatabase(); |
|
227 conn.asyncClose(); |
|
228 try { |
|
229 conn.asyncClose(); |
|
230 do_throw("should have thrown"); |
|
231 // There is a small race condition here, which can cause either of |
|
232 // Cr.NS_ERROR_NOT_INITIALIZED or Cr.NS_ERROR_UNEXPECTED to be thrown. |
|
233 } catch (e if "result" in e && e.result == Cr.NS_ERROR_NOT_INITIALIZED) { |
|
234 do_print("NS_ERROR_NOT_INITIALIZED"); |
|
235 } catch (e if "result" in e && e.result == Cr.NS_ERROR_UNEXPECTED) { |
|
236 do_print("NS_ERROR_UNEXPECTED"); |
|
237 } catch (e) { |
|
238 } |
|
239 |
|
240 // Reset gDBConn so that later tests will get a new connection object. |
|
241 gDBConn = null; |
|
242 run_next_test(); |
|
243 } |
|
244 |
|
245 //////////////////////////////////////////////////////////////////////////////// |
|
246 //// Test Runner |
|
247 |
|
248 [ |
|
249 test_create_and_add, |
|
250 test_multiple_bindings_on_statements, |
|
251 test_asyncClose_does_not_complete_before_statements, |
|
252 test_asyncClose_does_not_throw_no_callback, |
|
253 test_double_asyncClose_throws, |
|
254 ].forEach(add_test); |
|
255 |
|
256 function run_test() |
|
257 { |
|
258 cleanup(); |
|
259 run_next_test(); |
|
260 } |