1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/services/metrics/tests/xpcshell/test_metrics_storage.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,839 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + * http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +"use strict"; 1.8 + 1.9 +const {utils: Cu} = Components; 1.10 + 1.11 +Cu.import("resource://gre/modules/Promise.jsm"); 1.12 +Cu.import("resource://gre/modules/Metrics.jsm"); 1.13 +Cu.import("resource://services-common/utils.js"); 1.14 + 1.15 + 1.16 +const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; 1.17 + 1.18 + 1.19 +function run_test() { 1.20 + run_next_test(); 1.21 +} 1.22 + 1.23 +add_test(function test_days_date_conversion() { 1.24 + let toDays = Metrics.dateToDays; 1.25 + let toDate = Metrics.daysToDate; 1.26 + 1.27 + let d = new Date(0); 1.28 + do_check_eq(toDays(d), 0); 1.29 + 1.30 + d = new Date(MILLISECONDS_PER_DAY); 1.31 + do_check_eq(toDays(d), 1); 1.32 + 1.33 + d = new Date(MILLISECONDS_PER_DAY - 1); 1.34 + do_check_eq(toDays(d), 0); 1.35 + 1.36 + d = new Date("1970-12-31T23:59:59.999Z"); 1.37 + do_check_eq(toDays(d), 364); 1.38 + 1.39 + d = new Date("1971-01-01T00:00:00Z"); 1.40 + do_check_eq(toDays(d), 365); 1.41 + 1.42 + d = toDate(0); 1.43 + do_check_eq(d.getTime(), 0); 1.44 + 1.45 + d = toDate(1); 1.46 + do_check_eq(d.getTime(), MILLISECONDS_PER_DAY); 1.47 + 1.48 + d = toDate(365); 1.49 + do_check_eq(d.getUTCFullYear(), 1971); 1.50 + do_check_eq(d.getUTCMonth(), 0); 1.51 + do_check_eq(d.getUTCDate(), 1); 1.52 + do_check_eq(d.getUTCHours(), 0); 1.53 + do_check_eq(d.getUTCMinutes(), 0); 1.54 + do_check_eq(d.getUTCSeconds(), 0); 1.55 + do_check_eq(d.getUTCMilliseconds(), 0); 1.56 + 1.57 + run_next_test(); 1.58 +}); 1.59 + 1.60 +add_task(function test_get_sqlite_backend() { 1.61 + let backend = yield Metrics.Storage("get_sqlite_backend.sqlite"); 1.62 + 1.63 + do_check_neq(backend._connection, null); 1.64 + 1.65 + // Ensure WAL and auto checkpoint are enabled. 1.66 + do_check_neq(backend._enabledWALCheckpointPages, null); 1.67 + let rows = yield backend._connection.execute("PRAGMA journal_mode"); 1.68 + do_check_eq(rows[0].getResultByIndex(0), "wal"); 1.69 + rows = yield backend._connection.execute("PRAGMA wal_autocheckpoint"); 1.70 + do_check_eq(rows[0].getResultByIndex(0), backend._enabledWALCheckpointPages); 1.71 + 1.72 + yield backend.close(); 1.73 + do_check_null(backend._connection); 1.74 +}); 1.75 + 1.76 +add_task(function test_reconnect() { 1.77 + let backend = yield Metrics.Storage("reconnect"); 1.78 + yield backend.close(); 1.79 + 1.80 + let backend2 = yield Metrics.Storage("reconnect"); 1.81 + yield backend2.close(); 1.82 +}); 1.83 + 1.84 +add_task(function test_future_schema_errors() { 1.85 + let backend = yield Metrics.Storage("future_schema_errors"); 1.86 + yield backend._connection.setSchemaVersion(2); 1.87 + yield backend.close(); 1.88 + 1.89 + let backend2; 1.90 + let failed = false; 1.91 + try { 1.92 + backend2 = yield Metrics.Storage("future_schema_errors"); 1.93 + } catch (ex) { 1.94 + failed = true; 1.95 + do_check_true(ex.message.startsWith("Unknown database schema")); 1.96 + } 1.97 + 1.98 + do_check_null(backend2); 1.99 + do_check_true(failed); 1.100 +}); 1.101 + 1.102 +add_task(function test_checkpoint_apis() { 1.103 + let backend = yield Metrics.Storage("checkpoint_apis"); 1.104 + let c = backend._connection; 1.105 + let count = c._statementCounter; 1.106 + 1.107 + yield backend.setAutoCheckpoint(0); 1.108 + do_check_eq(c._statementCounter, count + 1); 1.109 + 1.110 + let rows = yield c.execute("PRAGMA wal_autocheckpoint"); 1.111 + do_check_eq(rows[0].getResultByIndex(0), 0); 1.112 + count = c._statementCounter; 1.113 + 1.114 + yield backend.setAutoCheckpoint(1); 1.115 + do_check_eq(c._statementCounter, count + 1); 1.116 + 1.117 + rows = yield c.execute("PRAGMA wal_autocheckpoint"); 1.118 + do_check_eq(rows[0].getResultByIndex(0), backend._enabledWALCheckpointPages); 1.119 + count = c._statementCounter; 1.120 + 1.121 + yield backend.checkpoint(); 1.122 + do_check_eq(c._statementCounter, count + 1); 1.123 + 1.124 + yield backend.checkpoint(); 1.125 + do_check_eq(c._statementCounter, count + 2); 1.126 + 1.127 + yield backend.close(); 1.128 +}); 1.129 + 1.130 +add_task(function test_measurement_registration() { 1.131 + let backend = yield Metrics.Storage("measurement_registration"); 1.132 + 1.133 + do_check_false(backend.hasProvider("foo")); 1.134 + do_check_false(backend.hasMeasurement("foo", "bar", 1)); 1.135 + 1.136 + let id = yield backend.registerMeasurement("foo", "bar", 1); 1.137 + do_check_eq(id, 1); 1.138 + 1.139 + do_check_true(backend.hasProvider("foo")); 1.140 + do_check_true(backend.hasMeasurement("foo", "bar", 1)); 1.141 + do_check_eq(backend.measurementID("foo", "bar", 1), id); 1.142 + do_check_false(backend.hasMeasurement("foo", "bar", 2)); 1.143 + 1.144 + let id2 = yield backend.registerMeasurement("foo", "bar", 2); 1.145 + do_check_eq(id2, 2); 1.146 + do_check_true(backend.hasMeasurement("foo", "bar", 2)); 1.147 + do_check_eq(backend.measurementID("foo", "bar", 2), id2); 1.148 + 1.149 + yield backend.close(); 1.150 +}); 1.151 + 1.152 +add_task(function test_field_registration_basic() { 1.153 + let backend = yield Metrics.Storage("field_registration_basic"); 1.154 + 1.155 + do_check_false(backend.hasField("foo", "bar", 1, "baz")); 1.156 + 1.157 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.158 + do_check_false(backend.hasField("foo", "bar", 1, "baz")); 1.159 + do_check_false(backend.hasFieldFromMeasurement(mID, "baz")); 1.160 + 1.161 + let bazID = yield backend.registerField(mID, "baz", 1.162 + backend.FIELD_DAILY_COUNTER); 1.163 + do_check_true(backend.hasField("foo", "bar", 1, "baz")); 1.164 + do_check_true(backend.hasFieldFromMeasurement(mID, "baz")); 1.165 + 1.166 + let bar2ID = yield backend.registerMeasurement("foo", "bar2", 1); 1.167 + 1.168 + yield backend.registerField(bar2ID, "baz", 1.169 + backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.170 + 1.171 + do_check_true(backend.hasField("foo", "bar2", 1, "baz")); 1.172 + 1.173 + yield backend.close(); 1.174 +}); 1.175 + 1.176 +// Ensure changes types of fields results in fatal error. 1.177 +add_task(function test_field_registration_changed_type() { 1.178 + let backend = yield Metrics.Storage("field_registration_changed_type"); 1.179 + 1.180 + let mID = yield backend.registerMeasurement("bar", "bar", 1); 1.181 + 1.182 + let id = yield backend.registerField(mID, "baz", 1.183 + backend.FIELD_DAILY_COUNTER); 1.184 + 1.185 + let caught = false; 1.186 + try { 1.187 + yield backend.registerField(mID, "baz", 1.188 + backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.189 + } catch (ex) { 1.190 + caught = true; 1.191 + do_check_true(ex.message.startsWith("Field already defined with different type")); 1.192 + } 1.193 + 1.194 + do_check_true(caught); 1.195 + 1.196 + yield backend.close(); 1.197 +}); 1.198 + 1.199 +add_task(function test_field_registration_repopulation() { 1.200 + let backend = yield Metrics.Storage("field_registration_repopulation"); 1.201 + 1.202 + let mID1 = yield backend.registerMeasurement("foo", "bar", 1); 1.203 + let mID2 = yield backend.registerMeasurement("foo", "bar", 2); 1.204 + let mID3 = yield backend.registerMeasurement("foo", "biz", 1); 1.205 + let mID4 = yield backend.registerMeasurement("baz", "foo", 1); 1.206 + 1.207 + let fID1 = yield backend.registerField(mID1, "foo", backend.FIELD_DAILY_COUNTER); 1.208 + let fID2 = yield backend.registerField(mID1, "bar", backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.209 + let fID3 = yield backend.registerField(mID4, "foo", backend.FIELD_LAST_TEXT); 1.210 + 1.211 + yield backend.close(); 1.212 + 1.213 + backend = yield Metrics.Storage("field_registration_repopulation"); 1.214 + 1.215 + do_check_true(backend.hasProvider("foo")); 1.216 + do_check_true(backend.hasProvider("baz")); 1.217 + do_check_true(backend.hasMeasurement("foo", "bar", 1)); 1.218 + do_check_eq(backend.measurementID("foo", "bar", 1), mID1); 1.219 + do_check_true(backend.hasMeasurement("foo", "bar", 2)); 1.220 + do_check_eq(backend.measurementID("foo", "bar", 2), mID2); 1.221 + do_check_true(backend.hasMeasurement("foo", "biz", 1)); 1.222 + do_check_eq(backend.measurementID("foo", "biz", 1), mID3); 1.223 + do_check_true(backend.hasMeasurement("baz", "foo", 1)); 1.224 + do_check_eq(backend.measurementID("baz", "foo", 1), mID4); 1.225 + 1.226 + do_check_true(backend.hasField("foo", "bar", 1, "foo")); 1.227 + do_check_eq(backend.fieldID("foo", "bar", 1, "foo"), fID1); 1.228 + do_check_true(backend.hasField("foo", "bar", 1, "bar")); 1.229 + do_check_eq(backend.fieldID("foo", "bar", 1, "bar"), fID2); 1.230 + do_check_true(backend.hasField("baz", "foo", 1, "foo")); 1.231 + do_check_eq(backend.fieldID("baz", "foo", 1, "foo"), fID3); 1.232 + 1.233 + yield backend.close(); 1.234 +}); 1.235 + 1.236 +add_task(function test_enqueue_operation_execution_order() { 1.237 + let backend = yield Metrics.Storage("enqueue_operation_execution_order"); 1.238 + 1.239 + let executionCount = 0; 1.240 + 1.241 + let fns = { 1.242 + op1: function () { 1.243 + do_check_eq(executionCount, 1); 1.244 + }, 1.245 + 1.246 + op2: function () { 1.247 + do_check_eq(executionCount, 2); 1.248 + }, 1.249 + 1.250 + op3: function () { 1.251 + do_check_eq(executionCount, 3); 1.252 + }, 1.253 + }; 1.254 + 1.255 + function enqueuedOperation(fn) { 1.256 + let deferred = Promise.defer(); 1.257 + 1.258 + CommonUtils.nextTick(function onNextTick() { 1.259 + executionCount++; 1.260 + fn(); 1.261 + deferred.resolve(); 1.262 + }); 1.263 + 1.264 + return deferred.promise; 1.265 + } 1.266 + 1.267 + let promises = []; 1.268 + for (let i = 1; i <= 3; i++) { 1.269 + let fn = fns["op" + i]; 1.270 + promises.push(backend.enqueueOperation(enqueuedOperation.bind(this, fn))); 1.271 + } 1.272 + 1.273 + for (let promise of promises) { 1.274 + yield promise; 1.275 + } 1.276 + 1.277 + yield backend.close(); 1.278 +}); 1.279 + 1.280 +add_task(function test_enqueue_operation_many() { 1.281 + let backend = yield Metrics.Storage("enqueue_operation_many"); 1.282 + 1.283 + let promises = []; 1.284 + for (let i = 0; i < 100; i++) { 1.285 + promises.push(backend.registerMeasurement("foo", "bar" + i, 1)); 1.286 + } 1.287 + 1.288 + for (let promise of promises) { 1.289 + yield promise; 1.290 + } 1.291 + 1.292 + yield backend.close(); 1.293 +}); 1.294 + 1.295 +// If the operation did not return a promise, everything should still execute. 1.296 +add_task(function test_enqueue_operation_no_return_promise() { 1.297 + let backend = yield Metrics.Storage("enqueue_operation_no_return_promise"); 1.298 + 1.299 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.300 + let fID = yield backend.registerField(mID, "baz", backend.FIELD_DAILY_COUNTER); 1.301 + let now = new Date(); 1.302 + 1.303 + let promises = []; 1.304 + for (let i = 0; i < 10; i++) { 1.305 + promises.push(backend.enqueueOperation(function op() { 1.306 + backend.incrementDailyCounterFromFieldID(fID, now); 1.307 + })); 1.308 + } 1.309 + 1.310 + let deferred = Promise.defer(); 1.311 + 1.312 + let finished = 0; 1.313 + for (let promise of promises) { 1.314 + promise.then( 1.315 + do_throw.bind(this, "Unexpected resolve."), 1.316 + function onError() { 1.317 + finished++; 1.318 + 1.319 + if (finished == promises.length) { 1.320 + backend.getDailyCounterCountFromFieldID(fID, now).then(function onCount(count) { 1.321 + // There should not be a race condition here because storage 1.322 + // serializes all statements. So, for the getDailyCounterCount 1.323 + // query to finish means that all counter update statements must 1.324 + // have completed. 1.325 + do_check_eq(count, promises.length); 1.326 + deferred.resolve(); 1.327 + }); 1.328 + } 1.329 + } 1.330 + ); 1.331 + } 1.332 + 1.333 + yield deferred.promise; 1.334 + yield backend.close(); 1.335 +}); 1.336 + 1.337 +// If an operation throws, subsequent operations should still execute. 1.338 +add_task(function test_enqueue_operation_throw_exception() { 1.339 + let backend = yield Metrics.Storage("enqueue_operation_rejected_promise"); 1.340 + 1.341 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.342 + let fID = yield backend.registerField(mID, "baz", backend.FIELD_DAILY_COUNTER); 1.343 + let now = new Date(); 1.344 + 1.345 + let deferred = Promise.defer(); 1.346 + backend.enqueueOperation(function bad() { 1.347 + throw new Error("I failed."); 1.348 + }).then(do_throw, function onError(error) { 1.349 + do_check_true(error.message.contains("I failed.")); 1.350 + deferred.resolve(); 1.351 + }); 1.352 + 1.353 + let promise = backend.enqueueOperation(function () { 1.354 + return backend.incrementDailyCounterFromFieldID(fID, now); 1.355 + }); 1.356 + 1.357 + yield deferred.promise; 1.358 + yield promise; 1.359 + 1.360 + let count = yield backend.getDailyCounterCountFromFieldID(fID, now); 1.361 + do_check_eq(count, 1); 1.362 + yield backend.close(); 1.363 +}); 1.364 + 1.365 +// If an operation rejects, subsequent operations should still execute. 1.366 +add_task(function test_enqueue_operation_reject_promise() { 1.367 + let backend = yield Metrics.Storage("enqueue_operation_reject_promise"); 1.368 + 1.369 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.370 + let fID = yield backend.registerField(mID, "baz", backend.FIELD_DAILY_COUNTER); 1.371 + let now = new Date(); 1.372 + 1.373 + let deferred = Promise.defer(); 1.374 + backend.enqueueOperation(function reject() { 1.375 + let d = Promise.defer(); 1.376 + 1.377 + CommonUtils.nextTick(function nextTick() { 1.378 + d.reject("I failed."); 1.379 + }); 1.380 + 1.381 + return d.promise; 1.382 + }).then(do_throw, function onError(error) { 1.383 + deferred.resolve(); 1.384 + }); 1.385 + 1.386 + let promise = backend.enqueueOperation(function () { 1.387 + return backend.incrementDailyCounterFromFieldID(fID, now); 1.388 + }); 1.389 + 1.390 + yield deferred.promise; 1.391 + yield promise; 1.392 + 1.393 + let count = yield backend.getDailyCounterCountFromFieldID(fID, now); 1.394 + do_check_eq(count, 1); 1.395 + yield backend.close(); 1.396 +}); 1.397 + 1.398 +add_task(function test_enqueue_transaction() { 1.399 + let backend = yield Metrics.Storage("enqueue_transaction"); 1.400 + 1.401 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.402 + let fID = yield backend.registerField(mID, "baz", backend.FIELD_DAILY_COUNTER); 1.403 + let now = new Date(); 1.404 + 1.405 + yield backend.incrementDailyCounterFromFieldID(fID, now); 1.406 + 1.407 + yield backend.enqueueTransaction(function transaction() { 1.408 + yield backend.incrementDailyCounterFromFieldID(fID, now); 1.409 + }); 1.410 + 1.411 + let count = yield backend.getDailyCounterCountFromFieldID(fID, now); 1.412 + do_check_eq(count, 2); 1.413 + 1.414 + let errored = false; 1.415 + try { 1.416 + yield backend.enqueueTransaction(function aborted() { 1.417 + yield backend.incrementDailyCounterFromFieldID(fID, now); 1.418 + 1.419 + throw new Error("Some error."); 1.420 + }); 1.421 + } catch (ex) { 1.422 + errored = true; 1.423 + } finally { 1.424 + do_check_true(errored); 1.425 + } 1.426 + 1.427 + count = yield backend.getDailyCounterCountFromFieldID(fID, now); 1.428 + do_check_eq(count, 2); 1.429 + 1.430 + yield backend.close(); 1.431 +}); 1.432 + 1.433 +add_task(function test_increment_daily_counter_basic() { 1.434 + let backend = yield Metrics.Storage("increment_daily_counter_basic"); 1.435 + 1.436 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.437 + 1.438 + let fieldID = yield backend.registerField(mID, "baz", 1.439 + backend.FIELD_DAILY_COUNTER); 1.440 + 1.441 + let now = new Date(); 1.442 + yield backend.incrementDailyCounterFromFieldID(fieldID, now); 1.443 + 1.444 + let count = yield backend.getDailyCounterCountFromFieldID(fieldID, now); 1.445 + do_check_eq(count, 1); 1.446 + 1.447 + yield backend.incrementDailyCounterFromFieldID(fieldID, now); 1.448 + count = yield backend.getDailyCounterCountFromFieldID(fieldID, now); 1.449 + do_check_eq(count, 2); 1.450 + 1.451 + yield backend.incrementDailyCounterFromFieldID(fieldID, now, 10); 1.452 + count = yield backend.getDailyCounterCountFromFieldID(fieldID, now); 1.453 + do_check_eq(count, 12); 1.454 + 1.455 + yield backend.close(); 1.456 +}); 1.457 + 1.458 +add_task(function test_increment_daily_counter_multiple_days() { 1.459 + let backend = yield Metrics.Storage("increment_daily_counter_multiple_days"); 1.460 + 1.461 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.462 + let fieldID = yield backend.registerField(mID, "baz", 1.463 + backend.FIELD_DAILY_COUNTER); 1.464 + 1.465 + let days = []; 1.466 + let now = Date.now(); 1.467 + for (let i = 0; i < 100; i++) { 1.468 + days.push(new Date(now - i * MILLISECONDS_PER_DAY)); 1.469 + } 1.470 + 1.471 + for (let day of days) { 1.472 + yield backend.incrementDailyCounterFromFieldID(fieldID, day); 1.473 + } 1.474 + 1.475 + let result = yield backend.getDailyCounterCountsFromFieldID(fieldID); 1.476 + do_check_eq(result.size, 100); 1.477 + for (let day of days) { 1.478 + do_check_true(result.hasDay(day)); 1.479 + do_check_eq(result.getDay(day), 1); 1.480 + } 1.481 + 1.482 + let fields = yield backend.getMeasurementDailyCountersFromMeasurementID(mID); 1.483 + do_check_eq(fields.size, 1); 1.484 + do_check_true(fields.has("baz")); 1.485 + do_check_eq(fields.get("baz").size, 100); 1.486 + 1.487 + for (let day of days) { 1.488 + do_check_true(fields.get("baz").hasDay(day)); 1.489 + do_check_eq(fields.get("baz").getDay(day), 1); 1.490 + } 1.491 + 1.492 + yield backend.close(); 1.493 +}); 1.494 + 1.495 +add_task(function test_last_values() { 1.496 + let backend = yield Metrics.Storage("set_last"); 1.497 + 1.498 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.499 + let numberID = yield backend.registerField(mID, "number", 1.500 + backend.FIELD_LAST_NUMERIC); 1.501 + let textID = yield backend.registerField(mID, "text", 1.502 + backend.FIELD_LAST_TEXT); 1.503 + let now = new Date(); 1.504 + let nowDay = new Date(Math.floor(now.getTime() / MILLISECONDS_PER_DAY) * MILLISECONDS_PER_DAY); 1.505 + 1.506 + yield backend.setLastNumericFromFieldID(numberID, 42, now); 1.507 + yield backend.setLastTextFromFieldID(textID, "hello world", now); 1.508 + 1.509 + let result = yield backend.getLastNumericFromFieldID(numberID); 1.510 + do_check_true(Array.isArray(result)); 1.511 + do_check_eq(result[0].getTime(), nowDay.getTime()); 1.512 + do_check_eq(typeof(result[1]), "number"); 1.513 + do_check_eq(result[1], 42); 1.514 + 1.515 + result = yield backend.getLastTextFromFieldID(textID); 1.516 + do_check_true(Array.isArray(result)); 1.517 + do_check_eq(result[0].getTime(), nowDay.getTime()); 1.518 + do_check_eq(typeof(result[1]), "string"); 1.519 + do_check_eq(result[1], "hello world"); 1.520 + 1.521 + let missingID = yield backend.registerField(mID, "missing", 1.522 + backend.FIELD_LAST_NUMERIC); 1.523 + do_check_null(yield backend.getLastNumericFromFieldID(missingID)); 1.524 + 1.525 + let fields = yield backend.getMeasurementLastValuesFromMeasurementID(mID); 1.526 + do_check_eq(fields.size, 2); 1.527 + do_check_true(fields.has("number")); 1.528 + do_check_true(fields.has("text")); 1.529 + do_check_eq(fields.get("number")[1], 42); 1.530 + do_check_eq(fields.get("text")[1], "hello world"); 1.531 + 1.532 + yield backend.close(); 1.533 +}); 1.534 + 1.535 +add_task(function test_discrete_values_basic() { 1.536 + let backend = yield Metrics.Storage("discrete_values_basic"); 1.537 + 1.538 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.539 + let numericID = yield backend.registerField(mID, "numeric", 1.540 + backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.541 + let textID = yield backend.registerField(mID, "text", 1.542 + backend.FIELD_DAILY_DISCRETE_TEXT); 1.543 + 1.544 + let now = new Date(); 1.545 + let expectedNumeric = []; 1.546 + let expectedText = []; 1.547 + for (let i = 0; i < 100; i++) { 1.548 + expectedNumeric.push(i); 1.549 + expectedText.push("value" + i); 1.550 + yield backend.addDailyDiscreteNumericFromFieldID(numericID, i, now); 1.551 + yield backend.addDailyDiscreteTextFromFieldID(textID, "value" + i, now); 1.552 + } 1.553 + 1.554 + let values = yield backend.getDailyDiscreteNumericFromFieldID(numericID); 1.555 + do_check_eq(values.size, 1); 1.556 + do_check_true(values.hasDay(now)); 1.557 + do_check_true(Array.isArray(values.getDay(now))); 1.558 + do_check_eq(values.getDay(now).length, expectedNumeric.length); 1.559 + 1.560 + for (let i = 0; i < expectedNumeric.length; i++) { 1.561 + do_check_eq(values.getDay(now)[i], expectedNumeric[i]); 1.562 + } 1.563 + 1.564 + values = yield backend.getDailyDiscreteTextFromFieldID(textID); 1.565 + do_check_eq(values.size, 1); 1.566 + do_check_true(values.hasDay(now)); 1.567 + do_check_true(Array.isArray(values.getDay(now))); 1.568 + do_check_eq(values.getDay(now).length, expectedText.length); 1.569 + 1.570 + for (let i = 0; i < expectedText.length; i++) { 1.571 + do_check_eq(values.getDay(now)[i], expectedText[i]); 1.572 + } 1.573 + 1.574 + let fields = yield backend.getMeasurementDailyDiscreteValuesFromMeasurementID(mID); 1.575 + do_check_eq(fields.size, 2); 1.576 + do_check_true(fields.has("numeric")); 1.577 + do_check_true(fields.has("text")); 1.578 + 1.579 + let numeric = fields.get("numeric"); 1.580 + let text = fields.get("text"); 1.581 + do_check_true(numeric.hasDay(now)); 1.582 + do_check_true(text.hasDay(now)); 1.583 + do_check_eq(numeric.getDay(now).length, expectedNumeric.length); 1.584 + do_check_eq(text.getDay(now).length, expectedText.length); 1.585 + 1.586 + for (let i = 0; i < expectedNumeric.length; i++) { 1.587 + do_check_eq(numeric.getDay(now)[i], expectedNumeric[i]); 1.588 + } 1.589 + 1.590 + for (let i = 0; i < expectedText.length; i++) { 1.591 + do_check_eq(text.getDay(now)[i], expectedText[i]); 1.592 + } 1.593 + 1.594 + yield backend.close(); 1.595 +}); 1.596 + 1.597 +add_task(function test_discrete_values_multiple_days() { 1.598 + let backend = yield Metrics.Storage("discrete_values_multiple_days"); 1.599 + 1.600 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.601 + let id = yield backend.registerField(mID, "baz", 1.602 + backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.603 + 1.604 + let now = new Date(); 1.605 + let dates = []; 1.606 + for (let i = 0; i < 50; i++) { 1.607 + let date = new Date(now.getTime() + i * MILLISECONDS_PER_DAY); 1.608 + dates.push(date); 1.609 + 1.610 + yield backend.addDailyDiscreteNumericFromFieldID(id, i, date); 1.611 + } 1.612 + 1.613 + let values = yield backend.getDailyDiscreteNumericFromFieldID(id); 1.614 + do_check_eq(values.size, 50); 1.615 + 1.616 + let i = 0; 1.617 + for (let date of dates) { 1.618 + do_check_true(values.hasDay(date)); 1.619 + do_check_eq(values.getDay(date)[0], i); 1.620 + i++; 1.621 + } 1.622 + 1.623 + let fields = yield backend.getMeasurementDailyDiscreteValuesFromMeasurementID(mID); 1.624 + do_check_eq(fields.size, 1); 1.625 + do_check_true(fields.has("baz")); 1.626 + let baz = fields.get("baz"); 1.627 + do_check_eq(baz.size, 50); 1.628 + i = 0; 1.629 + for (let date of dates) { 1.630 + do_check_true(baz.hasDay(date)); 1.631 + do_check_eq(baz.getDay(date).length, 1); 1.632 + do_check_eq(baz.getDay(date)[0], i); 1.633 + i++; 1.634 + } 1.635 + 1.636 + yield backend.close(); 1.637 +}); 1.638 + 1.639 +add_task(function test_daily_last_values() { 1.640 + let backend = yield Metrics.Storage("daily_last_values"); 1.641 + 1.642 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.643 + let numericID = yield backend.registerField(mID, "numeric", 1.644 + backend.FIELD_DAILY_LAST_NUMERIC); 1.645 + let textID = yield backend.registerField(mID, "text", 1.646 + backend.FIELD_DAILY_LAST_TEXT); 1.647 + 1.648 + let now = new Date(); 1.649 + let yesterday = new Date(now.getTime() - MILLISECONDS_PER_DAY); 1.650 + let dayBefore = new Date(yesterday.getTime() - MILLISECONDS_PER_DAY); 1.651 + 1.652 + yield backend.setDailyLastNumericFromFieldID(numericID, 1, yesterday); 1.653 + yield backend.setDailyLastNumericFromFieldID(numericID, 2, now); 1.654 + yield backend.setDailyLastNumericFromFieldID(numericID, 3, dayBefore); 1.655 + yield backend.setDailyLastTextFromFieldID(textID, "foo", now); 1.656 + yield backend.setDailyLastTextFromFieldID(textID, "bar", yesterday); 1.657 + yield backend.setDailyLastTextFromFieldID(textID, "baz", dayBefore); 1.658 + 1.659 + let days = yield backend.getDailyLastNumericFromFieldID(numericID); 1.660 + do_check_eq(days.size, 3); 1.661 + do_check_eq(days.getDay(yesterday), 1); 1.662 + do_check_eq(days.getDay(now), 2); 1.663 + do_check_eq(days.getDay(dayBefore), 3); 1.664 + 1.665 + days = yield backend.getDailyLastTextFromFieldID(textID); 1.666 + do_check_eq(days.size, 3); 1.667 + do_check_eq(days.getDay(now), "foo"); 1.668 + do_check_eq(days.getDay(yesterday), "bar"); 1.669 + do_check_eq(days.getDay(dayBefore), "baz"); 1.670 + 1.671 + yield backend.setDailyLastNumericFromFieldID(numericID, 4, yesterday); 1.672 + days = yield backend.getDailyLastNumericFromFieldID(numericID); 1.673 + do_check_eq(days.getDay(yesterday), 4); 1.674 + 1.675 + yield backend.setDailyLastTextFromFieldID(textID, "biz", yesterday); 1.676 + days = yield backend.getDailyLastTextFromFieldID(textID); 1.677 + do_check_eq(days.getDay(yesterday), "biz"); 1.678 + 1.679 + days = yield backend.getDailyLastNumericFromFieldID(numericID, yesterday); 1.680 + do_check_eq(days.size, 1); 1.681 + do_check_eq(days.getDay(yesterday), 4); 1.682 + 1.683 + days = yield backend.getDailyLastTextFromFieldID(textID, yesterday); 1.684 + do_check_eq(days.size, 1); 1.685 + do_check_eq(days.getDay(yesterday), "biz"); 1.686 + 1.687 + let fields = yield backend.getMeasurementDailyLastValuesFromMeasurementID(mID); 1.688 + do_check_eq(fields.size, 2); 1.689 + do_check_true(fields.has("numeric")); 1.690 + do_check_true(fields.has("text")); 1.691 + let numeric = fields.get("numeric"); 1.692 + let text = fields.get("text"); 1.693 + do_check_true(numeric.hasDay(yesterday)); 1.694 + do_check_true(numeric.hasDay(dayBefore)); 1.695 + do_check_true(numeric.hasDay(now)); 1.696 + do_check_true(text.hasDay(yesterday)); 1.697 + do_check_true(text.hasDay(dayBefore)); 1.698 + do_check_true(text.hasDay(now)); 1.699 + do_check_eq(numeric.getDay(yesterday), 4); 1.700 + do_check_eq(text.getDay(yesterday), "biz"); 1.701 + 1.702 + yield backend.close(); 1.703 +}); 1.704 + 1.705 +add_task(function test_prune_data_before() { 1.706 + let backend = yield Metrics.Storage("prune_data_before"); 1.707 + 1.708 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.709 + 1.710 + let counterID = yield backend.registerField(mID, "baz", 1.711 + backend.FIELD_DAILY_COUNTER); 1.712 + let text1ID = yield backend.registerField(mID, "one_text_1", 1.713 + backend.FIELD_LAST_TEXT); 1.714 + let text2ID = yield backend.registerField(mID, "one_text_2", 1.715 + backend.FIELD_LAST_TEXT); 1.716 + let numeric1ID = yield backend.registerField(mID, "one_numeric_1", 1.717 + backend.FIELD_LAST_NUMERIC); 1.718 + let numeric2ID = yield backend.registerField(mID, "one_numeric_2", 1.719 + backend.FIELD_LAST_NUMERIC); 1.720 + let text3ID = yield backend.registerField(mID, "daily_last_text_1", 1.721 + backend.FIELD_DAILY_LAST_TEXT); 1.722 + let text4ID = yield backend.registerField(mID, "daily_last_text_2", 1.723 + backend.FIELD_DAILY_LAST_TEXT); 1.724 + let numeric3ID = yield backend.registerField(mID, "daily_last_numeric_1", 1.725 + backend.FIELD_DAILY_LAST_NUMERIC); 1.726 + let numeric4ID = yield backend.registerField(mID, "daily_last_numeric_2", 1.727 + backend.FIELD_DAILY_LAST_NUMERIC); 1.728 + 1.729 + let now = new Date(); 1.730 + let yesterday = new Date(now.getTime() - MILLISECONDS_PER_DAY); 1.731 + let dayBefore = new Date(yesterday.getTime() - MILLISECONDS_PER_DAY); 1.732 + 1.733 + yield backend.incrementDailyCounterFromFieldID(counterID, now); 1.734 + yield backend.incrementDailyCounterFromFieldID(counterID, yesterday); 1.735 + yield backend.incrementDailyCounterFromFieldID(counterID, dayBefore); 1.736 + yield backend.setLastTextFromFieldID(text1ID, "hello", dayBefore); 1.737 + yield backend.setLastTextFromFieldID(text2ID, "world", yesterday); 1.738 + yield backend.setLastNumericFromFieldID(numeric1ID, 42, dayBefore); 1.739 + yield backend.setLastNumericFromFieldID(numeric2ID, 43, yesterday); 1.740 + yield backend.setDailyLastTextFromFieldID(text3ID, "foo", dayBefore); 1.741 + yield backend.setDailyLastTextFromFieldID(text3ID, "bar", yesterday); 1.742 + yield backend.setDailyLastTextFromFieldID(text4ID, "hello", dayBefore); 1.743 + yield backend.setDailyLastTextFromFieldID(text4ID, "world", yesterday); 1.744 + yield backend.setDailyLastNumericFromFieldID(numeric3ID, 40, dayBefore); 1.745 + yield backend.setDailyLastNumericFromFieldID(numeric3ID, 41, yesterday); 1.746 + yield backend.setDailyLastNumericFromFieldID(numeric4ID, 42, dayBefore); 1.747 + yield backend.setDailyLastNumericFromFieldID(numeric4ID, 43, yesterday); 1.748 + 1.749 + let days = yield backend.getDailyCounterCountsFromFieldID(counterID); 1.750 + do_check_eq(days.size, 3); 1.751 + 1.752 + yield backend.pruneDataBefore(yesterday); 1.753 + days = yield backend.getDailyCounterCountsFromFieldID(counterID); 1.754 + do_check_eq(days.size, 2); 1.755 + do_check_false(days.hasDay(dayBefore)); 1.756 + 1.757 + do_check_null(yield backend.getLastTextFromFieldID(text1ID)); 1.758 + do_check_null(yield backend.getLastNumericFromFieldID(numeric1ID)); 1.759 + 1.760 + let result = yield backend.getLastTextFromFieldID(text2ID); 1.761 + do_check_true(Array.isArray(result)); 1.762 + do_check_eq(result[1], "world"); 1.763 + 1.764 + result = yield backend.getLastNumericFromFieldID(numeric2ID); 1.765 + do_check_true(Array.isArray(result)); 1.766 + do_check_eq(result[1], 43); 1.767 + 1.768 + result = yield backend.getDailyLastNumericFromFieldID(numeric3ID); 1.769 + do_check_eq(result.size, 1); 1.770 + do_check_true(result.hasDay(yesterday)); 1.771 + 1.772 + result = yield backend.getDailyLastTextFromFieldID(text3ID); 1.773 + do_check_eq(result.size, 1); 1.774 + do_check_true(result.hasDay(yesterday)); 1.775 + 1.776 + yield backend.close(); 1.777 +}); 1.778 + 1.779 +add_task(function test_provider_state() { 1.780 + let backend = yield Metrics.Storage("provider_state"); 1.781 + 1.782 + yield backend.registerMeasurement("foo", "bar", 1); 1.783 + yield backend.setProviderState("foo", "apple", "orange"); 1.784 + let value = yield backend.getProviderState("foo", "apple"); 1.785 + do_check_eq(value, "orange"); 1.786 + 1.787 + yield backend.setProviderState("foo", "apple", "pear"); 1.788 + value = yield backend.getProviderState("foo", "apple"); 1.789 + do_check_eq(value, "pear"); 1.790 + 1.791 + yield backend.close(); 1.792 +}); 1.793 + 1.794 +add_task(function test_get_measurement_values() { 1.795 + let backend = yield Metrics.Storage("get_measurement_values"); 1.796 + 1.797 + let mID = yield backend.registerMeasurement("foo", "bar", 1); 1.798 + let id1 = yield backend.registerField(mID, "id1", backend.FIELD_DAILY_COUNTER); 1.799 + let id2 = yield backend.registerField(mID, "id2", backend.FIELD_DAILY_DISCRETE_NUMERIC); 1.800 + let id3 = yield backend.registerField(mID, "id3", backend.FIELD_DAILY_DISCRETE_TEXT); 1.801 + let id4 = yield backend.registerField(mID, "id4", backend.FIELD_DAILY_LAST_NUMERIC); 1.802 + let id5 = yield backend.registerField(mID, "id5", backend.FIELD_DAILY_LAST_TEXT); 1.803 + let id6 = yield backend.registerField(mID, "id6", backend.FIELD_LAST_NUMERIC); 1.804 + let id7 = yield backend.registerField(mID, "id7", backend.FIELD_LAST_TEXT); 1.805 + 1.806 + let now = new Date(); 1.807 + let yesterday = new Date(now.getTime() - MILLISECONDS_PER_DAY); 1.808 + 1.809 + yield backend.incrementDailyCounterFromFieldID(id1, now); 1.810 + yield backend.addDailyDiscreteNumericFromFieldID(id2, 3, now); 1.811 + yield backend.addDailyDiscreteNumericFromFieldID(id2, 4, now); 1.812 + yield backend.addDailyDiscreteNumericFromFieldID(id2, 5, yesterday); 1.813 + yield backend.addDailyDiscreteNumericFromFieldID(id2, 6, yesterday); 1.814 + yield backend.addDailyDiscreteTextFromFieldID(id3, "1", now); 1.815 + yield backend.addDailyDiscreteTextFromFieldID(id3, "2", now); 1.816 + yield backend.addDailyDiscreteTextFromFieldID(id3, "3", yesterday); 1.817 + yield backend.addDailyDiscreteTextFromFieldID(id3, "4", yesterday); 1.818 + yield backend.setDailyLastNumericFromFieldID(id4, 1, now); 1.819 + yield backend.setDailyLastNumericFromFieldID(id4, 2, yesterday); 1.820 + yield backend.setDailyLastTextFromFieldID(id5, "foo", now); 1.821 + yield backend.setDailyLastTextFromFieldID(id5, "bar", yesterday); 1.822 + yield backend.setLastNumericFromFieldID(id6, 42, now); 1.823 + yield backend.setLastTextFromFieldID(id7, "foo", now); 1.824 + 1.825 + let fields = yield backend.getMeasurementValues(mID); 1.826 + do_check_eq(Object.keys(fields).length, 2); 1.827 + do_check_true("days" in fields); 1.828 + do_check_true("singular" in fields); 1.829 + do_check_eq(fields.days.size, 2); 1.830 + do_check_true(fields.days.hasDay(now)); 1.831 + do_check_true(fields.days.hasDay(yesterday)); 1.832 + do_check_eq(fields.days.getDay(now).size, 5); 1.833 + do_check_eq(fields.days.getDay(yesterday).size, 4); 1.834 + do_check_eq(fields.days.getDay(now).get("id3")[0], 1); 1.835 + do_check_eq(fields.days.getDay(yesterday).get("id4"), 2); 1.836 + do_check_eq(fields.singular.size, 2); 1.837 + do_check_eq(fields.singular.get("id6")[1], 42); 1.838 + do_check_eq(fields.singular.get("id7")[1], "foo"); 1.839 + 1.840 + yield backend.close(); 1.841 +}); 1.842 +