chromium/third_party/blink/web_tests/storage/indexeddb/resources/cursor-prev-no-duplicate.js

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

description("Test IndexedDB behavior when iterating backwards with and without NO_DUPLICATE");

indexedDBTest(prepareDatabase, populateStore);
function prepareDatabase()
{
    db = event.target.result;
    store = evalAndLog("store = db.createObjectStore('store')");
    evalAndLog("store.createIndex('index', 'sorted')");
}

function populateStore()
{
    debug("");
    debug("populating store...");
    evalAndLog("trans = db.transaction('store', 'readwrite', {durability: 'relaxed'})");
    evalAndLog("store = trans.objectStore('store');");
    trans.onerror = unexpectedErrorCallback;
    trans.onabort = unexpectedAbortCallback;

    evalAndLog("store.put({sorted: 3, value: 111}, 1)");
    evalAndLog("store.put({sorted: 2, value: 222}, 2)");
    evalAndLog("store.put({sorted: 1, value: 333}, 3)");
    evalAndLog("store.put({sorted: 10, value: 444}, 17)");
    evalAndLog("store.put({sorted: 10, value: 555}, 16)");
    evalAndLog("store.put({sorted: 10, value: 666}, 15)");
    trans.oncomplete = testFarRangeCursor_closed;
}


function testFarRangeCursor_closed()
{
    debug("");
    debug("testFarRangeCursor: upper bound is well out of range, results always the same, whether open or closed");

    runTest(makeOpenCursor("store", 7, false, "'prev'"),
            { expectedValue: 333, expectedKey: 3},
            testFarRangeCursor_open);
}

function testFarRangeCursor_open()
{
    runTest(makeOpenCursor("store", 7, true, "'prev'"),
            { expectedValue: 333, expectedKey: 3},
            testFarRangeCursor_indexClosed);
}

function testFarRangeCursor_indexClosed()
{
    // here '7' refers to the 'sorted' value
    runTest(makeOpenCursor("index", 7, false, "'prev'"),
            { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1},
            testFarRangeCursor_indexOpen);
}
function testFarRangeCursor_indexOpen()
{
    runTest(makeOpenCursor("index", 7, true, "'prev'"),
            { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1},
            testFarRangeCursor_indexKeyOpen);
}

function testFarRangeCursor_indexKeyOpen()
{
    // here '7' refers to the sorted value
    runTest(makeOpenKeyCursor("index", 7, false, "'prev'"),
            { expectedKey: 3, expectedPrimaryKey: 1},
            testFarRangeCursor_indexKeyClosed);
}

function testFarRangeCursor_indexKeyClosed()
{
    runTest(makeOpenKeyCursor("index", 7, true, "'prev'"),
            { expectedKey: 3, expectedPrimaryKey: 1},
            testBoundaryCursor_closed);
}

function testBoundaryCursor_closed()
{
    runTest(makeOpenCursor("store", 3, false, "'prev'"),
            { expectedValue: 333, expectedKey: 3},
            testBoundaryCursor_open);
};

function testBoundaryCursor_open()
{
    runTest(makeOpenCursor("store", 3, true, "'prev'"),
            { expectedValue: 222, expectedKey: 2},
            testBoundaryCursor_indexClosed);
}

function testBoundaryCursor_indexClosed()
{
    // by index sort order, we should return them in a different order
    runTest(makeOpenCursor("index", 3, false, "'prev'"),
            { expectedValue: 111, expectedKey: 3, expectedPrimaryKey: 1},
            testBoundaryCursor_indexOpen);
}

function testBoundaryCursor_indexOpen()
{
    runTest(makeOpenCursor("index", 3, true, "'prev'"),
            { expectedValue: 222, expectedKey: 2, expectedPrimaryKey: 2},
            testBoundaryCursor_indexKeyClosed);
}

function testBoundaryCursor_indexKeyClosed()
{

    // now the value doesn't matter, just the primary key
    runTest(makeOpenKeyCursor("index", 3, false, "'prev'"),
            { expectedKey: 3, expectedPrimaryKey: 1},
            testBoundaryCursor_indexKeyOpen);
}

function testBoundaryCursor_indexKeyOpen()
{
    runTest(makeOpenKeyCursor("index", 3, true, "'prev'"),
            { expectedKey: 2, expectedPrimaryKey: 2},
            testNoDuplicate_closed);
}

function testNoDuplicate_closed()
{
    debug("testNoDuplicate: there are 3 values, but we should return always the first one");

    // PREV_NO_DUPLICATE doesn't really affect non-indexed
    // cursors, but we should make sure we get the right one
    // anyway
    runTest(makeOpenCursor("store", 15, false, "'prevunique'"),
            { expectedValue: 666, expectedKey: 15, expectedPrimaryKey: 15 },
            testNoDuplicate_open);
}

function testNoDuplicate_open()
{
    // still three values, but now the index says we should return the
    // second one
    runTest(makeOpenCursor("index", 15, false, "'prevunique'"),
            { expectedValue: 666, expectedKey: 10, expectedPrimaryKey: 15},
            testNoDuplicate_indexKeyClosed);
}


function testNoDuplicate_indexKeyClosed()
{
    // same behavior as above, without a value
    runTest(makeOpenKeyCursor("index", 15, false, "'prevunique'"),
            { expectedKey: 10, expectedPrimaryKey: 15},
            finishJSTest);
}


function makeOpenCursor(obj, upperBound, open, direction)
{
    return obj + ".openCursor(IDBKeyRange.upperBound(" + upperBound + ", " +
        open + "), " +
            direction + ")";
}

function makeOpenKeyCursor(obj, upperBound, open, direction)
{
    return obj + ".openKeyCursor(IDBKeyRange.upperBound(" + upperBound + ", " +
        open + "), " +
            direction + ")";
}

function runTest(openCursor, expectation, callback)
{
    trans = db.transaction('store', 'readonly', {durability: 'relaxed'});

    // expose these for code in openCursor
    store = trans.objectStore('store');
    index = store.index('index');
    trans.onerror = unexpectedErrorCallback;
    trans.onabort = unexpectedAbortCallback;
    trans.oncomplete = function() {
        debug("DONE");
        debug("");
        callback();
    };

    storeReq = evalAndLog("storeReq = " + openCursor);
    storeReq.onsuccess = function() {
        cursor = event.target.result;
        if (cursor === null) {
            testFailed("null cursor");
            return;
        }

        shouldBe("cursor.key", JSON.stringify(expectation.expectedKey));
        if ("value" in cursor) {
            shouldBe("cursor.value.value", JSON.stringify(expectation.expectedValue));
        } else if ("expectedValue" in expectation)
            testFailed("Test broken: shouldn't have expectedValue");

        if ("expectedPrimaryKey" in expectation) {
            shouldBe("cursor.primaryKey", JSON.stringify(expectation.expectedPrimaryKey));
        }
    };
}