chromium/third_party/blink/web_tests/storage/indexeddb/resources/cursor-key-order.js

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

description("Test IndexedDB keys ordering and readback from cursors.");

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

self.keys = [
    "-Infinity",
    "-Number.MAX_VALUE",
    "-1",
    "-Number.MIN_VALUE",
    "0",
    "Number.MIN_VALUE",
    "1",
    "Number.MAX_VALUE",
    "Infinity",

    "new Date(0)",
    "new Date(1000)",
    "new Date(1317399931023)",

    "''",
    "'\x00'",
    "'a'",
    "'aa'",
    "'b'",
    "'ba'",

    "'\xA2'", // U+00A2 CENT SIGN
    "'\u6C34'", // U+6C34 CJK UNIFIED IDEOGRAPH (water)
    "'\uD834\uDD1E'", // U+1D11E MUSICAL SYMBOL G-CLEF (UTF-16 surrogate pair)
    "'\uFFFD'", // U+FFFD REPLACEMENT CHARACTER

    "[]",

    "[-Infinity]",
    "[-Number.MAX_VALUE]",
    "[-1]",
    "[-Number.MIN_VALUE]",
    "[0]",
    "[Number.MIN_VALUE]",
    "[1]",
    "[Number.MAX_VALUE]",
    "[Infinity]",

    "[new Date(0)]",
    "[new Date(1000)]",
    "[new Date(1317399931023)]",

    "['']",
    "['\x00']",
    "['a']",
    "['aa']",
    "['b']",
    "['ba']",

    "['\xA2']", // U+00A2 CENT SIGN
    "['\u6C34']", // U+6C34 CJK UNIFIED IDEOGRAPH (water)
    "['\uD834\uDD1E']", // U+1D11E MUSICAL SYMBOL G-CLEF (UTF-16 surrogate pair)
    "['\uFFFD']", // U+FFFD REPLACEMENT CHARACTER

    "[[]]",

    "[[], []]",
    "[[], [], []]",

    "[[[]]]",
    "[[[[]]]]"
];

function compare(a, b)
{
    if (typeof a !== typeof b) {
        return false;
    }

    switch (typeof a) {
        case 'undefined': // Not valid keys, but compare anyway.
        case 'boolean': // Not valid keys, but compare anyway.
        case 'string':
            return a === b;
        case 'number':
            if (a === b) {
                return (a !== 0) || (1 / a === 1 / b); // 0 isn't -0
            } else {
                return a !== a && b !== b; // NaN is NaN
            }
        case 'object':
            if (a instanceof Date && b instanceof Date) {
                return +a === +b;
            } else if (a instanceof Array && b instanceof Array) {
                if (a.length !== b.length) {
                    return false;
                }
                for (var i = 0; i < a.length; i++) {
                    if (!compare(a[i], b[i])) {
                        return false;
                    }
                }
                return true;
            }
            // For the purposes of this test, other objects don't count
            return false;
        default:
            return false;
    }
}

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;
    var count = 0;
    keys.forEach(function(key) {
        evalAndLog("store.put(" + (count++) + ", " + key + ")");
    });
    trans.oncomplete = checkStore;
}

function checkStore()
{
    debug("");
    debug("iterating cursor...");
    evalAndLog("trans = db.transaction('store', 'readonly', {durability: 'relaxed'})");
    evalAndLog("store = trans.objectStore('store');");
    trans.onerror = unexpectedErrorCallback;
    trans.onabort = unexpectedAbortCallback;
    evalAndLog("count = 0");
    curreq = evalAndLog("curreq = store.openCursor()");
    curreq.onerror = unexpectedErrorCallback;
    curreq.onsuccess = function() {
        if (curreq.result) {
            evalAndLog("cursor = curreq.result");
            shouldBeTrue("compare(cursor.key, " + keys[count] + ")");
            evalAndLog("getreq = store.get(cursor.key)");
            getreq.onerror = unexpectedErrorCallback;
            getreq.onsuccess = function() {
                shouldBe("getreq.result", "count++");
                cursor.continue();
            };
        } else {
            shouldBe("count", "keys.length");
            finishUp();
        }
    };
}

function finishUp()
{
    testKeyCompare();
    finishJSTest();
}

function testKeyCompare()
{
    debug("");
    debug("validate compare function");
    var cases = [
        "undefined",
        "true",
        "false",
        "0",
        "-0",
        "123",
        "Infinity",
        "-Infinity",
        "NaN",
        "''",
        "'abc'",
        "'xyz'",
        "new Date(0)",
        "new Date(1e3)",
        "new Date(1e9)",
        "[]",
        "[123]",
        "['abc']",
        "[123, 'abc']",
        "['abc', 123]",
        "[[]]",
        "[[123]]",
        "[['abc']]",
        "[[123], 'abc']",
        "[[123], 123]"
    ];

    for (var i = 0; i < cases.length; ++i) {
        for (var j = 0; j < cases.length; ++j) {
            if (i === j) {
                shouldBeTrue("compare(" + cases[i] + ", " + cases[j] + ")");
            } else {
                shouldBeFalse("compare(" + cases[i] + ", " + cases[j] + ")");
            }
        }
    }
}