chromium/third_party/blink/web_tests/storage/indexeddb/resources/index-multientry.js

if (this.importScripts) {
    importScripts('../../../resources/js-test.js');
    importScripts('shared.js');
}

description("Test features of IndexedDB's multiEntry indices.");

indexedDBTest(prepareDatabase, addData);
function prepareDatabase()
{
    db = event.target.result;

    store = evalAndLog("store = db.createObjectStore('store')");
    evalAndLog("store.createIndex('index', 'x', {multiEntry: true})");

    store2 = evalAndLog("store2 = db.createObjectStore('store-unique')");
    evalAndLog("store2.createIndex('index-unique', 'x', {multiEntry: true, unique: true})");
}

function addData()
{
    debug("");
    debug("Populating stores (and indexes)");
    transaction = evalAndLog("transaction = db.transaction(['store'], 'readwrite')");
    transaction.onabort = unexpectedAbortCallback;
    transaction.oncomplete = function() { verifyIndexes('index', verifyUniqueConstraint); };

    debug("First try some keys that aren't what we're expecting");
    request = evalAndLog("transaction.objectStore('store').put({x: [7, 8, 9], y: 'a'}, 'foo')");
    request.onerror = unexpectedErrorCallback;
    debug("Now overwrite them with what we're expecting");
    request = evalAndLog("transaction.objectStore('store').put({x: [1, 2, 3], y: 'a'}, 'foo')");
    request.onerror = unexpectedErrorCallback;
    request = evalAndLog("transaction.objectStore('store').put({x: [4, 5, 6], y: 'b'}, 'bar')");
    request.onerror = unexpectedErrorCallback;
    request = evalAndLog("transaction.objectStore('store').put({x: [7, 7, 8, 7], y: 'c'}, 'baz')");
    request.onerror = unexpectedErrorCallback;
    request = evalAndLog("transaction.objectStore('store').put({x: [null, 9, 9], y: 'd'}, 'bloop')");
    request.onerror = unexpectedErrorCallback;
}

function verifyIndexes(indexName, callback)
{
    debug("");
    debug("Verifying index: " + indexName);
    transaction = evalAndLog("transaction = db.transaction(['store'], 'readonly')");
    transaction.onabort = unexpectedAbortCallback;
    transaction.oncomplete = function() { verifyCount(callback); };

    expected = [
        { key: 1, primaryKey: 'foo', y: 'a' },
        { key: 2, primaryKey: 'foo', y: 'a' },
        { key: 3, primaryKey: 'foo', y: 'a' },
        { key: 4, primaryKey: 'bar', y: 'b' },
        { key: 5, primaryKey: 'bar', y: 'b' },
        { key: 6, primaryKey: 'bar', y: 'b' },
        { key: 7, primaryKey: 'baz', y: 'c' },
        { key: 8, primaryKey: 'baz', y: 'c' },
        { key: 9, primaryKey: 'bloop', y: 'd' },
    ];

    var request = evalAndLog("transaction.objectStore('store').index('" + indexName + "').openCursor()");
    request.onerror = unexpectedErrorCallback;
    request.onsuccess = function(event) {
        cursor = evalAndLog("cursor = event.target.result");
        if (cursor) {
            ex = expected.shift();
            shouldBeNonNull("ex");
            shouldBe("cursor.key", String(ex.key));
            shouldBeEqualToString("cursor.primaryKey", ex.primaryKey);
            shouldBeEqualToString("cursor.value.y", ex.y);
            evalAndLog("cursor.continue()");
        } else {
            shouldBe("expected.length", "0");
        }
    };
}

function verifyUniqueConstraint()
{
    debug("");
    debug("Verifying unique constraint on multiEntry index");
    transaction = evalAndLog("transaction = db.transaction(['store-unique'], 'readwrite')");
    transaction.onabort = function () {
        debug("Transaction aborted as expected");
        createIndexOnStoreWithData();
    };
    transaction.oncomplete = unexpectedCompleteCallback;

    request = evalAndLog("transaction.objectStore('store-unique').put({x: [1, 2, 3], y: 'a'}, 'foo')");
    request.onerror = unexpectedErrorCallback;
    request.onsuccess = function() {
        debug("success!");
        debug("Replace an existing record - this should work");
        request = evalAndLog("transaction.objectStore('store-unique').put({x: [1, 2, 7], y: 'a'}, 'foo')");
        request.onerror = unexpectedErrorCallback;
        request.onsuccess = function() {
            debug("success!");
            debug("This should fail the uniqueness constraint on the index, and fail:");
            request = evalAndLog("transaction.objectStore('store-unique').put({x: [5, 2], y: 'c'}, 'should fail')");
            request.onsuccess = unexpectedSuccessCallback;
            request.onerror = function() {
                shouldBeUndefined("request.result");
                shouldBeNonNull("request.error");
                debug("Request failed, as expected (" + request.error.name + ")");
            };
        };
    };
}

function verifyCount(callback) {
    evalAndLog("transaction = db.transaction(['store'])");

    transaction.onabort = unexpectedAbortCallback;
    transaction.oncomplete = callback;

    index = evalAndLog("transaction.objectStore('store').index('index')");
    request = evalAndLog("index.count()");
    request.onsuccess = function(event) {

        shouldBe("event.target.result", "9");

        request = evalAndLog("index.count(7)");
        request.onsuccess = function(event) {
            shouldBe("event.target.result", "1");
        };
    };

}

function createIndexOnStoreWithData()
{
    debug("");
    debug("Create an index on a populated store");
    evalAndLog("db.close()");

    request = evalAndLog("indexedDB.open(dbname, 2)");
    request.onerror = unexpectedErrorCallback;
    request.onupgradeneeded = function() {
        evalAndLog("db = event.target.result");
        evalAndLog("trans = event.target.transaction");
        trans.onabort = unexpectedAbortCallback;

        store = evalAndLog("store = trans.objectStore('store')");
        evalAndLog("store.createIndex('index-new', 'x', {multiEntry: true})");
    };
    request.onsuccess = function() { verifyIndexes('index-new', finishJSTest); };
}