ydn.db
Version:
Javascript database library for IndexedDB, WebDatabase (WebSQL) and WebStorage (localStorage) storage mechanisms supporting version migration, advanced query and transaction workflow.
545 lines (441 loc) • 14 kB
JavaScript
goog.require('goog.debug.Console');
goog.require('goog.testing.jsunit');
goog.require('ydn.db');
goog.require('ydn.debug');
goog.require('ydn.db.core.Storage');
var reachedFinalContinuation, schema, objs;
var store_name = 't1';
var db_name = 'test_index_2';
var setUp = function () {
// ydn.debug.log('ydn.db', 'finest');
// ydn.db.core.req.SimpleStore.DEBUG = true;
// ydn.db.con.simple.Store.DEBUG = true;
// ydn.db.con.WebSql.DEBUG = true;
// ydn.db.crud.req.WebSql.DEBUG = true;
//ydn.db.core.req.WebSql.DEBUG = true;
//ydn.db.core.req.WebsqlCursor.DEBUG = true;
//ydn.db.Cursor.DEBUG = true;
reachedFinalContinuation = false;
};
var tearDown = function() {
assertTrue('The final continuation was not reached', reachedFinalContinuation);
};
var load_default_cnt = 0;
var load_default = function(cb) {
var db_name = 'test-default' + (load_default_cnt++);
var indexSchema = new ydn.db.schema.Index('value', ydn.db.schema.DataType.TEXT, true);
var typeIndex = new ydn.db.schema.Index('type', ydn.db.schema.DataType.TEXT, false);
var store_schema = new ydn.db.schema.Store(store_name, 'id', false,
ydn.db.schema.DataType.INTEGER, [indexSchema, typeIndex]);
schema = new ydn.db.schema.Database(undefined, [store_schema]);
var db = new ydn.db.core.Storage(db_name, schema, options);
objs = [
{id: -3, value: 'ba', type: 'a', remark: 'test ' + Math.random()},
{id: 0, value: 'a2', type: 'a', remark: 'test ' + Math.random()},
{id: 1, value: 'b', type: 'b', remark: 'test ' + Math.random()},
{id: 3, value: 'b1', type: 'b', remark: 'test ' + Math.random()},
{id: 10, value: 'c', type: 'c', remark: 'test ' + Math.random()},
{id: 11, value: 'a3', type: 'c', remark: 'test ' + Math.random()},
{id: 20, value: 'ca', type: 'c', remark: 'test ' + Math.random()}
];
db.clear(store_name);
db.put(store_name, objs).addCallback(function (value) {
console.log(db + ' ready.');
cb(db);
});
return objs;
};
var test_values_index_resume = function () {
var done;
var result1, result2;
waitForCondition(
// Condition
function() {
return done;
},
// Continuation
function() {
assertArrayEquals('first iteration', [objs[4], objs[5]], result1);
assertArrayEquals('second iteration', [objs[6]], result2);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
load_default(function(db) {
var q1 = ydn.db.IndexValueIterator.where(store_name, 'type', '=', 'c');
db.values(q1, 2).addBoth(function(value) {
result1 = value;
});
db.values(q1, 2).addBoth(function(value) {
result2 = value;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_values_index_resume_reverse = function () {
var done;
var result1, result2;
waitForCondition(
// Condition
function() {
return done;
},
// Continuation
function() {
assertArrayEquals('first iteration', [objs[6], objs[5]], result1);
assertArrayEquals('second iteration', [objs[4]], result2);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
load_default(function(db) {
var q1 = ydn.db.IndexValueIterator.where(store_name, 'type', '=', 'c');
q1 = q1.reverse();
db.values(q1, 2).addBoth(function(value) {
result1 = value;
});
db.values(q1, 2).addBoth(function(value) {
result2 = value;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_list_index_rev = function () {
var done, result, objs;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertEquals('length', objs.length, result.length);
assertArrayEquals(objs, result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
var q = new ydn.db.IndexValueIterator(store_name, 'value', null, true);
objs = load_default(function (db) {
db.values(q).addBoth(function (value) {
//console.log(db + ' fetch value: ' + JSON.stringify(value));
//console.log(db.explain(q));
result = value;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
goog.array.sort(objs, function(a, b) {
return - goog.array.defaultCompare(a.value, b.value);
});
};
var test_count_by_index_iterator = function () {
var done, result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertEquals('result', 2, result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
var range = ydn.db.KeyRange.only('a');
var iter = new ydn.db.IndexIterator(store_name, 'type', range);
load_default(function (db) {
db.count(iter).addBoth(function (x) {
result = x;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_date_index = function() {
var db_name = 'test_date_index';
var store_name = 's1';
var schema = {
stores: [{
name: store_name,
keyPath: 'id',
type: 'INTEGER',
indexes: [{
name: 'updated',
type: 'DATE'
}]
}]
};
var db = new ydn.db.core.Storage(db_name, schema, options);
var objs = [
{id: 1, value: Math.random(), updated: new Date( "2013-04-11T13:14:00.000Z")},
{id: 2, value: Math.random(), updated: new Date( "2013-04-11T13:15:00.000Z")},
{id: 3, value: Math.random(), updated: new Date( "2013-04-11T13:16:00.000Z")}
];
db.clear(store_name);
db.put(store_name, objs).addCallback(function (value) {
console.log(db + ' ready.');
});
var done, result, reverse_result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertArrayEquals('ascending values', objs, result);
assertArrayEquals('descending values', [objs[2], objs[1], objs[0]], reverse_result);
reachedFinalContinuation = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
},
100, // interval
1000); // maxTimeout
db.values(store_name, 'updated', null, 10, 0).addBoth(function (x) {
result = x;
});
db.values(store_name, 'updated', null, 10, 0, true).addBoth(function (x) {
reverse_result = x;
done = true;
});
};
var test_remove_by_index_key_range = function() {
var hasEventFired = false;
var countValue;
waitForCondition(
// Condition
function() { return hasEventFired; },
// Continuation
function() {
assertEquals('2 b', 2, countValue);
// Remember, the state of this boolean will be tested in tearDown().
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
var range = ydn.db.KeyRange.bound('b', 'c', false, true);
load_default(function (db) {
db.remove(store_name, 'type', range).addBoth(function (value) {
countValue = value;
hasEventFired = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_count_by_iterator = function () {
var done, result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertEquals('result', 3, result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
//var range = ydn.db.KeyRange.bound(1, 10);
//var iter = new ydn.db.KeyIterator(store_name, range);
var iter = ydn.db.KeyIterator.where(store_name, '>=', 1, '<=', 10);
load_default(function (db) {
db.count(iter).addBoth(function (x) {
result = x;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_list_by_index = function () {
var done, result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertArrayEquals('result', objs.slice(0, 2), result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
var range = ydn.db.KeyRange.only('a');
load_default(function (db) {
db.values(store_name, 'type', range, undefined, undefined).addBoth(function (x) {
result = x;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_values = function() {
var db_name = 'test_values-2';
var db;
var df = new goog.async.Deferred();
var schema_1 = {
stores: [
{
name: 'sii',
keyPath: 'id',
type: 'NUMERIC',
indexes: [
{name: 'name', type: 'TEXT'},
{name: 'value', type: 'NUMERIC'},
{name: 'tags', type: 'TEXT', multiEntry: true}
]
}
]
};
var objs = [
{test: 't' + Math.random(), value: 0, id: 0, name: 'a', tags: ['a', 'b']},
{test: 't' + Math.random(), value: 2, id: 1, name: 'b', tags: ['x']},
{test: 't' + Math.random(), value: 4, id: 2, name: 'ba', tags: ['z']},
{test: 't' + Math.random(), value: 6, id: 3, name: 'bc', tags: ['a', 'd', 'c']},
{test: 't' + Math.random(), value: 8, id: 4, name: 'bd', tags: ['e', 'c']},
{test: 't' + Math.random(), value: 10, id: 5, name: 'c', tags: ['b']},
{test: 't' + Math.random(), value: 12, id: 6, name: 'c', tags: ['a']}
];
// persist store data.
// we don't want to share this database connection and test database connection.
(function() {
var _db = new ydn.db.core.Storage(db_name, schema_1, options);
_db.clear('sii');
_db.put('sii', objs);
_db.count('sii').addBoth(function() {
df.callback(); // this ensure all transactions are completed
});
_db.close();
})();
var done, result1, result2, result3, result4, result5, result6, result7, result8;
waitForCondition(
function() {
return done;
},
function() {
assertArrayEquals('closed bound', objs.slice(1, 4), result1);
assertArrayEquals('closed bound reverse', objs.slice(1, 4).reverse(), result2);
assertArrayEquals('closed bound limit', objs.slice(1, 2), result3);
assertArrayEquals('closed bound reverse limit', objs.slice(3, 4), result4);
assertArrayEquals('lowerBound', objs.slice(2), result5);
assertArrayEquals('open lowerBound', objs.slice(3), result6);
assertArrayEquals('upperBound', objs.slice(0, 3), result7);
assertArrayEquals('open upperBound', objs.slice(0, 2), result8);
reachedFinalContinuation = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
},
100, // interval
1000); // maxTimeout
df.addBoth(function() {
db = new ydn.db.core.Storage(db_name, schema_1, options);
var key_range = ydn.db.KeyRange.bound(1, 3);
var q = new ydn.db.ValueIterator('sii', key_range);
db.values(q).addBoth(function (x) {
result1 = x;
});
key_range = ydn.db.KeyRange.bound(1, 3);
q = new ydn.db.ValueIterator('sii', key_range, true);
db.values(q).addBoth(function (x) {
result2 = x;
});
key_range = ydn.db.KeyRange.bound(1, 3);
q = new ydn.db.ValueIterator('sii', key_range);
db.values(q, 1).addBoth(function (x) {
result3 = x;
});
key_range = ydn.db.KeyRange.bound(1, 3);
q = new ydn.db.ValueIterator('sii', key_range, true);
db.values(q, 1).addBoth(function (x) {
result4 = x;
});
key_range = ydn.db.KeyRange.lowerBound(2);
q = new ydn.db.ValueIterator('sii', key_range);
db.values(q).addBoth(function (x) {
result5 = x;
});
key_range = ydn.db.KeyRange.lowerBound(2, true);
q = new ydn.db.ValueIterator('sii', key_range);
db.values(q).addBoth(function (x) {
result6 = x;
});
key_range = ydn.db.KeyRange.upperBound(2);
q = new ydn.db.ValueIterator('sii', key_range);
db.values(q).addBoth(function (x) {
result7 = x;
});
key_range = ydn.db.KeyRange.upperBound(2, true);
q = new ydn.db.ValueIterator('sii', key_range);
db.values(q).addBoth(function (x) {
result8 = x;
done = true;
});
});
};
var test_values_store_reverse = function () {
var done;
var result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertEquals('length', objs.length, result.length);
assertArrayEquals(objs.reverse(), result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
var q = new ydn.db.Iterator(store_name, undefined, null, true);
load_default(function (db) {
db.values(q).addBoth(function (value) {
//console.log(db + ' fetch value: ' + JSON.stringify(value));
result = value;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var test_values_store_range = function () {
var done;
var result;
waitForCondition(
// Condition
function () {
return done;
},
// Continuation
function () {
assertArrayEquals('result', objs.slice(2, 5), result);
reachedFinalContinuation = true;
},
100, // interval
1000); // maxTimeout
load_default(function (db) {
db.values(store_name, ydn.db.KeyRange.bound(1, 10)).addBoth(function (value) {
//console.log(db + ' fetch value: ' + JSON.stringify(value));
result = value;
done = true;
ydn.db.deleteDatabase(db.getName(), db.getType());
db.close();
});
});
};
var testCase = new goog.testing.ContinuationTestCase();
testCase.autoDiscoverTests();
G_testRunner.initialize(testCase);