services/metrics/tests/xpcshell/test_metrics_storage.js

changeset 0
6474c204b198
     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 +

mercurial