aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/qmltest/selftests/tst_compare.qml
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/qmltest/selftests/tst_compare.qml')
-rw-r--r--tests/auto/qmltest/selftests/tst_compare.qml1391
1 files changed, 1391 insertions, 0 deletions
diff --git a/tests/auto/qmltest/selftests/tst_compare.qml b/tests/auto/qmltest/selftests/tst_compare.qml
new file mode 100644
index 0000000000..b775b75143
--- /dev/null
+++ b/tests/auto/qmltest/selftests/tst_compare.qml
@@ -0,0 +1,1391 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtTest 1.0
+
+TestCase {
+ name: "SelfTests_compare"
+
+ function test_primitives_and_constants() {
+ compare(qtest_compareInternal(null, null), true, "null");
+ compare(qtest_compareInternal(null, {}), false, "null");
+ compare(qtest_compareInternal(null, undefined), false, "null");
+ compare(qtest_compareInternal(null, 0), false, "null");
+ compare(qtest_compareInternal(null, false), false, "null");
+ compare(qtest_compareInternal(null, ''), false, "null");
+ compare(qtest_compareInternal(null, []), false, "null");
+
+ compare(qtest_compareInternal(undefined, undefined), true, "undefined");
+ compare(qtest_compareInternal(undefined, null), false, "undefined");
+ compare(qtest_compareInternal(undefined, 0), false, "undefined");
+ compare(qtest_compareInternal(undefined, false), false, "undefined");
+ compare(qtest_compareInternal(undefined, {}), false, "undefined");
+ compare(qtest_compareInternal(undefined, []), false, "undefined");
+ compare(qtest_compareInternal(undefined, ""), false, "undefined");
+
+ // Nan usually doest not equal to Nan using the '==' operator.
+ // Only isNaN() is able to do it.
+ compare(qtest_compareInternal(0/0, 0/0), true, "NaN"); // NaN VS NaN
+ compare(qtest_compareInternal(1/0, 2/0), true, "Infinity"); // Infinity VS Infinity
+ compare(qtest_compareInternal(-1/0, 2/0), false, "-Infinity, Infinity"); // -Infinity VS Infinity
+ compare(qtest_compareInternal(-1/0, -2/0), true, "-Infinity, -Infinity"); // -Infinity VS -Infinity
+ compare(qtest_compareInternal(0/0, 1/0), false, "NaN, Infinity"); // Nan VS Infinity
+ compare(qtest_compareInternal(1/0, 0/0), false, "NaN, Infinity"); // Nan VS Infinity
+ compare(qtest_compareInternal(0/0, null), false, "NaN");
+ compare(qtest_compareInternal(0/0, undefined), false, "NaN");
+ compare(qtest_compareInternal(0/0, 0), false, "NaN");
+ compare(qtest_compareInternal(0/0, false), false, "NaN");
+ //compare(qtest_compareInternal(0/0, function () {}), false, "NaN"); // Do we really need that?
+ compare(qtest_compareInternal(1/0, null), false, "NaN, Infinity");
+ compare(qtest_compareInternal(1/0, undefined), false, "NaN, Infinity");
+ compare(qtest_compareInternal(1/0, 0), false, "NaN, Infinity");
+ compare(qtest_compareInternal(1/0, 1), false, "NaN, Infinity");
+ compare(qtest_compareInternal(1/0, false), false, "NaN, Infinity");
+ compare(qtest_compareInternal(1/0, true), false, "NaN, Infinity");
+ //compare(qtest_compareInternal(1/0, function () {}), false, "NaN"); // Do we really need that?
+
+ compare(qtest_compareInternal(0, 0), true, "number");
+ compare(qtest_compareInternal(0, 1), false, "number");
+ compare(qtest_compareInternal(1, 0), false, "number");
+ compare(qtest_compareInternal(1, 1), true, "number");
+ compare(qtest_compareInternal(1.1, 1.1), true, "number");
+ compare(qtest_compareInternal(0.0000005, 0.0000005), true, "number");
+ compare(qtest_compareInternal(0, ''), false, "number");
+ compare(qtest_compareInternal(0, '0'), false, "number");
+ compare(qtest_compareInternal(1, '1'), false, "number");
+ compare(qtest_compareInternal(0, false), false, "number");
+ compare(qtest_compareInternal(1, true), false, "number");
+
+ compare(qtest_compareInternal(true, true), true, "boolean");
+ compare(qtest_compareInternal(true, false), false, "boolean");
+ compare(qtest_compareInternal(false, true), false, "boolean");
+ compare(qtest_compareInternal(false, 0), false, "boolean");
+ compare(qtest_compareInternal(false, null), false, "boolean");
+ compare(qtest_compareInternal(false, undefined), false, "boolean");
+ compare(qtest_compareInternal(true, 1), false, "boolean");
+ compare(qtest_compareInternal(true, null), false, "boolean");
+ compare(qtest_compareInternal(true, undefined), false, "boolean");
+
+ compare(qtest_compareInternal('', ''), true, "string");
+ compare(qtest_compareInternal('a', 'a'), true, "string");
+ compare(qtest_compareInternal("foobar", "foobar"), true, "string");
+ compare(qtest_compareInternal("foobar", "foo"), false, "string");
+ compare(qtest_compareInternal('', 0), false, "string");
+ compare(qtest_compareInternal('', false), false, "string");
+ compare(qtest_compareInternal('', null), false, "string");
+ compare(qtest_compareInternal('', undefined), false, "string");
+
+ // Short annotation VS new annotation
+ compare(qtest_compareInternal(0, new Number()), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Number(), 0), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(1, new Number(1)), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Number(1), 1), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Number(0), 1), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal(0, new Number(1)), false, "short annotation VS new annotation");
+
+ compare(qtest_compareInternal(new String(), ""), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal("", new String()), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new String("My String"), "My String"), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal("My String", new String("My String")), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal("Bad String", new String("My String")), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new String("Bad String"), "My String"), false, "short annotation VS new annotation");
+
+ compare(qtest_compareInternal(false, new Boolean()), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Boolean(), false), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(true, new Boolean(true)), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Boolean(true), true), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(true, new Boolean(1)), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(false, new Boolean(false)), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Boolean(false), false), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(false, new Boolean(0)), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(true, new Boolean(false)), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Boolean(false), true), false, "short annotation VS new annotation");
+
+ compare(qtest_compareInternal(new Object(), {}), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal({}, new Object()), true, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Object(), {a:1}), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal({a:1}, new Object()), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal({a:undefined}, new Object()), false, "short annotation VS new annotation");
+ compare(qtest_compareInternal(new Object(), {a:undefined}), false, "short annotation VS new annotation");
+ }
+
+ function test_objects_basics() {
+ compare(qtest_compareInternal({}, {}), true);
+ compare(qtest_compareInternal({}, null), false);
+ compare(qtest_compareInternal({}, undefined), false);
+ compare(qtest_compareInternal({}, 0), false);
+ compare(qtest_compareInternal({}, false), false);
+
+ // This test is a hard one, it is very important
+ // REASONS:
+ // 1) They are of the same type "object"
+ // 2) [] instanceof Object is true
+ // 3) Their properties are the same (doesn't exists)
+ compare(qtest_compareInternal({}, []), false);
+
+ compare(qtest_compareInternal({a:1}, {a:1}), true);
+ compare(qtest_compareInternal({a:1}, {a:"1"}), false);
+ compare(qtest_compareInternal({a:[]}, {a:[]}), true);
+ compare(qtest_compareInternal({a:{}}, {a:null}), false);
+ compare(qtest_compareInternal({a:1}, {}), false);
+ compare(qtest_compareInternal({}, {a:1}), false);
+
+ // Hard ones
+ compare(qtest_compareInternal({a:undefined}, {}), false);
+ compare(qtest_compareInternal({}, {a:undefined}), false);
+ compare(qtest_compareInternal(
+ {
+ a: [{ bar: undefined }]
+ },
+ {
+ a: [{ bat: undefined }]
+ }
+ ), false);
+ }
+
+ function test_arrays_basics() {
+ compare(qtest_compareInternal([], []), true);
+
+ // May be a hard one, can invoke a crash at execution.
+ // because their types are both "object" but null isn't
+ // like a true object, it doesn't have any property at all.
+ compare(qtest_compareInternal([], null), false);
+
+ compare(qtest_compareInternal([], undefined), false);
+ compare(qtest_compareInternal([], false), false);
+ compare(qtest_compareInternal([], 0), false);
+ compare(qtest_compareInternal([], ""), false);
+
+ // May be a hard one, but less hard
+ // than {} with [] (note the order)
+ compare(qtest_compareInternal([], {}), false);
+
+ compare(qtest_compareInternal([null],[]), false);
+ compare(qtest_compareInternal([undefined],[]), false);
+ compare(qtest_compareInternal([],[null]), false);
+ compare(qtest_compareInternal([],[undefined]), false);
+ compare(qtest_compareInternal([null],[undefined]), false);
+ compare(qtest_compareInternal([[]],[[]]), true);
+ compare(qtest_compareInternal([[],[],[]],[[],[],[]]), true);
+ compare(qtest_compareInternal(
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]),
+ true);
+ compare(qtest_compareInternal(
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // shorter
+ false);
+ compare(qtest_compareInternal(
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
+ [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // deepest element not an array
+ false);
+
+ // same multidimensional
+ compare(qtest_compareInternal(
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,4,[
+ 1,2,[
+ 1,2,3,4,[
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]],
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,4,[
+ 1,2,[
+ 1,2,3,4,[
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]]),
+ true, "Multidimensional");
+
+ // different multidimensional
+ compare(qtest_compareInternal(
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,4,[
+ 1,2,[
+ 1,2,3,4,[
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]],
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,4,[
+ 1,2,[
+ '1',2,3,4,[ // string instead of number
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]]),
+ false, "Multidimensional");
+
+ // different multidimensional
+ compare(qtest_compareInternal(
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,4,[
+ 1,2,[
+ 1,2,3,4,[
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]],
+ [1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,6,7,8,9, [
+ 1,2,3,4,5,[
+ [6,7,8,9, [
+ [
+ 1,2,3,4,[
+ 2,3,[ // missing an element (4)
+ 1,2,[
+ 1,2,3,4,[
+ 1,2,3,4,5,6,7,8,9,[
+ 0
+ ],1,2,3,4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],4,5,6,7,8,9
+ ],5,6,7,8,9
+ ],5,6,7
+ ]
+ ]
+ ]
+ ]
+ ]]]),
+ false, "Multidimensional");
+ }
+
+ function test_date_instances() {
+ // Date, we don't need to test Date.parse() because it returns a number.
+ // Only test the Date instances by setting them a fix date.
+ // The date use is midnight January 1, 1970
+
+ var d1 = new Date();
+ d1.setTime(0); // fix the date
+
+ var d2 = new Date();
+ d2.setTime(0); // fix the date
+
+ var d3 = new Date(); // The very now
+
+ // Anyway their types differs, just in case the code fails in the order in which it deals with date
+ compare(qtest_compareInternal(d1, 0), false); // d1.valueOf() returns 0, but d1 and 0 are different
+ // test same values date and different instances equality
+ compare(qtest_compareInternal(d1, d2), true);
+ // test different date and different instances difference
+ compare(qtest_compareInternal(d1, d3), false);
+
+ // try to fool equiv by adding a valueOf function to an object
+ // that would return the same value of a real date instance.
+ var d4 = new Date();
+ d4.setFullYear(2010);
+ d4.setMonth(1);
+ d4.setDate(1);
+ d4.setHours(1);
+ d4.setMinutes(1);
+ d4.setSeconds(1);
+ d4.setMilliseconds(1);
+ var o4 = {
+ valueOf: function () {
+ return d4.valueOf();
+ }
+ }
+ compare(qtest_compareInternal(d4, o4), false); // o4 isn't an instance of Date
+ }
+
+
+ function test_regexp() {
+ // Must test cases that imply those traps:
+ // var a = /./;
+ // a instanceof Object; // Oops
+ // a instanceof RegExp; // Oops
+ // typeof a === "function"; // Oops, false in IE and Opera, true in FF and Safari ("object")
+
+ // Tests same regex with same modifiers in different order
+ var r = /foo/;
+ var r5 = /foo/gim;
+ var r6 = /foo/gmi;
+ var r7 = /foo/igm;
+ var r8 = /foo/img;
+ var r9 = /foo/mig;
+ var r10 = /foo/mgi;
+ var ri1 = /foo/i;
+ var ri2 = /foo/i;
+ var rm1 = /foo/m;
+ var rm2 = /foo/m;
+ var rg1 = /foo/g;
+ var rg2 = /foo/g;
+
+ compare(qtest_compareInternal(r5, r6), true, "Modifier order");
+ compare(qtest_compareInternal(r5, r7), true, "Modifier order");
+ compare(qtest_compareInternal(r5, r8), true, "Modifier order");
+ compare(qtest_compareInternal(r5, r9), true, "Modifier order");
+ compare(qtest_compareInternal(r5, r10), true, "Modifier order");
+ compare(qtest_compareInternal(r, r5), false, "Modifier");
+
+ compare(qtest_compareInternal(ri1, ri2), true, "Modifier");
+ compare(qtest_compareInternal(r, ri1), false, "Modifier");
+ compare(qtest_compareInternal(ri1, rm1), false, "Modifier");
+ compare(qtest_compareInternal(r, rm1), false, "Modifier");
+ compare(qtest_compareInternal(rm1, ri1), false, "Modifier");
+ compare(qtest_compareInternal(rm1, rm2), true, "Modifier");
+ compare(qtest_compareInternal(rg1, rm1), false, "Modifier");
+ compare(qtest_compareInternal(rm1, rg1), false, "Modifier");
+ compare(qtest_compareInternal(rg1, rg2), true, "Modifier");
+
+ // Different regex, same modifiers
+ var r11 = /[a-z]/gi;
+ var r13 = /[0-9]/gi; // oops! different
+ compare(qtest_compareInternal(r11, r13), false, "Regex pattern");
+
+ var r14 = /0/ig;
+ var r15 = /"0"/ig; // oops! different
+ compare(qtest_compareInternal(r14, r15), false, "Regex pattern");
+
+ var r1 = /[\n\r\u2028\u2029]/g;
+ var r2 = /[\n\r\u2028\u2029]/g;
+ var r3 = /[\n\r\u2028\u2028]/g; // differs from r1
+ var r4 = /[\n\r\u2028\u2029]/; // differs from r1
+
+ compare(qtest_compareInternal(r1, r2), true, "Regex pattern");
+ compare(qtest_compareInternal(r1, r3), false, "Regex pattern");
+ compare(qtest_compareInternal(r1, r4), false, "Regex pattern");
+
+ // More complex regex
+ var regex1 = "^[-_.a-z0-9]+@([-_a-z0-9]+\\.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
+ var regex2 = "^[-_.a-z0-9]+@([-_a-z0-9]+\\.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
+ // regex 3 is different: '.' not escaped
+ var regex3 = "^[-_.a-z0-9]+@([-_a-z0-9]+.)+([A-Za-z][A-Za-z]|[A-Za-z][A-Za-z][A-Za-z])|(([0-9][0-9]?|[0-1][0-9][0-9]|[2][0-4][0-9]|[2][5][0-5]))$";
+
+ var r21 = new RegExp(regex1);
+ var r22 = new RegExp(regex2);
+ var r23 = new RegExp(regex3); // diff from r21, not same pattern
+ var r23a = new RegExp(regex3, "gi"); // diff from r23, not same modifier
+ var r24a = new RegExp(regex3, "ig"); // same as r23a
+
+ compare(qtest_compareInternal(r21, r22), true, "Complex Regex");
+ compare(qtest_compareInternal(r21, r23), false, "Complex Regex");
+ compare(qtest_compareInternal(r23, r23a), false, "Complex Regex");
+ compare(qtest_compareInternal(r23a, r24a), true, "Complex Regex");
+
+ // typeof r1 is "function" in some browsers and "object" in others so we must cover this test
+ var re = / /;
+ compare(qtest_compareInternal(re, function () {}), false, "Regex internal");
+ compare(qtest_compareInternal(re, {}), false, "Regex internal");
+ }
+
+
+ function test_complex_objects() {
+
+ function fn1() {
+ return "fn1";
+ }
+ function fn2() {
+ return "fn2";
+ }
+
+ // Try to invert the order of some properties to make sure it is covered.
+ // It can failed when properties are compared between unsorted arrays.
+ compare(qtest_compareInternal(
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ q: [],
+ p: 1/0,
+ o: 99
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ d: 0,
+ i: true,
+ h: "false"
+ }
+ },
+ e: undefined,
+ g: "",
+ h: "h",
+ f: {},
+ i: []
+ },
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ b: false,
+ a: 3.14159,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ t: undefined,
+ u: 0,
+ s: [1,2,3],
+ v: {
+ w: {
+ x: {
+ z: null,
+ y: "Yahoo!"
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ i: true,
+ h: "false"
+ }
+ },
+ e: undefined,
+ g: "",
+ f: {},
+ h: "h",
+ i: []
+ }
+ ), true);
+
+ compare(qtest_compareInternal(
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ //r: "r", // different: missing a property
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ },
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ }
+ ), false);
+
+ compare(qtest_compareInternal(
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ },
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ //t: undefined, // different: missing a property with an undefined value
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ }
+ ), false);
+
+ compare(qtest_compareInternal(
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ },
+ {
+ a: 1,
+ b: null,
+ c: [{}],
+ d: {
+ a: 3.14159,
+ b: false,
+ c: {
+ d: 0,
+ e: fn1,
+ f: [[[]]],
+ g: {
+ j: {
+ k: {
+ n: {
+ r: "r",
+ s: [1,2,3],
+ t: undefined,
+ u: 0,
+ v: {
+ w: {
+ x: {
+ y: "Yahoo!",
+ z: null
+ }
+ }
+ }
+ },
+ o: 99,
+ p: 1/0,
+ q: {} // different was []
+ },
+ l: undefined,
+ m: null
+ }
+ },
+ h: "false",
+ i: true
+ }
+ },
+ e: undefined,
+ f: {},
+ g: "",
+ h: "h",
+ i: []
+ }
+ ), false);
+
+ var same1 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3]],
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var same2 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3]],
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var diff1 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3,4]], // different: 4 was add to the array
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var diff2 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3]],
+ newprop: undefined, // different: newprop was added
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var diff3 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3]],
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ α" // different: missing last char
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var diff4 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,undefined,{}, [], [1,2,3]], // different: undefined instead of null
+ bar: undefined
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ var diff5 = {
+ a: [
+ "string", null, 0, "1", 1, {
+ prop: null,
+ foo: [1,2,null,{}, [], [1,2,3]],
+ bat: undefined // different: property name not "bar"
+ }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
+ ],
+ unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
+ b: "b",
+ c: fn1
+ };
+
+ compare(qtest_compareInternal(same1, same2), true);
+ compare(qtest_compareInternal(same2, same1), true);
+ compare(qtest_compareInternal(same2, diff1), false);
+ compare(qtest_compareInternal(diff1, same2), false);
+
+ compare(qtest_compareInternal(same1, diff1), false);
+ compare(qtest_compareInternal(same1, diff2), false);
+ compare(qtest_compareInternal(same1, diff3), false);
+ compare(qtest_compareInternal(same1, diff3), false);
+ compare(qtest_compareInternal(same1, diff4), false);
+ compare(qtest_compareInternal(same1, diff5), false);
+ compare(qtest_compareInternal(diff5, diff1), false);
+ }
+
+
+ function test_complex_arrays() {
+
+ function fn() {
+ }
+
+ compare(qtest_compareInternal(
+ [1, 2, 3, true, {}, null, [
+ {
+ a: ["", '1', 0]
+ },
+ 5, 6, 7
+ ], "foo"],
+ [1, 2, 3, true, {}, null, [
+ {
+ a: ["", '1', 0]
+ },
+ 5, 6, 7
+ ], "foo"]),
+ true);
+
+ compare(qtest_compareInternal(
+ [1, 2, 3, true, {}, null, [
+ {
+ a: ["", '1', 0]
+ },
+ 5, 6, 7
+ ], "foo"],
+ [1, 2, 3, true, {}, null, [
+ {
+ b: ["", '1', 0] // not same property name
+ },
+ 5, 6, 7
+ ], "foo"]),
+ false);
+
+ var a = [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn,
+ f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
+ ], [], [[[], "foo", null, {
+ n: 1/0,
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]];
+
+ compare(qtest_compareInternal(a,
+ [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn,
+ f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
+ ], [], [[[], "foo", null, {
+ n: 1/0,
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]]), true);
+
+ compare(qtest_compareInternal(a,
+ [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn,
+ f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[2]]]], "3"], {}, 1/0 // different: [[[[[2]]]]] instead of [[[[[3]]]]]
+ ], [], [[[], "foo", null, {
+ n: 1/0,
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]]), false);
+
+ compare(qtest_compareInternal(a,
+ [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn,
+ f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
+ ], [], [[[], "foo", null, {
+ n: -1/0, // different, -Infinity instead of Infinity
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]]), false);
+
+ compare(qtest_compareInternal(a,
+ [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn,
+ f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
+ ], [], [[[], "foo", { // different: null is missing
+ n: 1/0,
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]]), false);
+
+ compare(qtest_compareInternal(a,
+ [{
+ b: fn,
+ c: false,
+ "do": "reserved word",
+ "for": {
+ ar: [3,5,9,"hey!", [], {
+ ar: [1,[
+ 3,4,6,9, null, [], []
+ ]],
+ e: fn
+ // different: missing property f: undefined
+ }]
+ },
+ e: 0.43445
+ }, 5, "string", 0, fn, false, null, undefined, 0, [
+ 4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
+ ], [], [[[], "foo", null, {
+ n: 1/0,
+ z: {
+ a: [3,4,5,6,"yep!", undefined, undefined],
+ b: {}
+ }
+ }, {}]]]), false);
+ }
+
+
+ function test_prototypal_inheritance() {
+ function Gizmo(id) {
+ this.id = id;
+ }
+
+ function Hoozit(id) {
+ this.id = id;
+ }
+ Hoozit.prototype = new Gizmo();
+
+ var gizmo = new Gizmo("ok");
+ var hoozit = new Hoozit("ok");
+
+ // Try this test many times after test on instances that hold function
+ // to make sure that our code does not mess with last object constructor memoization.
+ compare(qtest_compareInternal(function () {}, function () {}), false);
+
+ // Hoozit inherit from Gizmo
+ // hoozit instanceof Hoozit; // true
+ // hoozit instanceof Gizmo; // true
+ compare(qtest_compareInternal(hoozit, gizmo), true);
+
+ Gizmo.prototype.bar = true; // not a function just in case we skip them
+
+ // Hoozit inherit from Gizmo
+ // They are equivalent
+ compare(qtest_compareInternal(hoozit, gizmo), true);
+
+ // Make sure this is still true !important
+ // The reason for this is that I forgot to reset the last
+ // caller to where it were called from.
+ compare(qtest_compareInternal(function () {}, function () {}), false);
+
+ // Make sure this is still true !important
+ compare(qtest_compareInternal(hoozit, gizmo), true);
+
+ Hoozit.prototype.foo = true; // not a function just in case we skip them
+
+ // Gizmo does not inherit from Hoozit
+ // gizmo instanceof Gizmo; // true
+ // gizmo instanceof Hoozit; // false
+ // They are not equivalent
+ compare(qtest_compareInternal(hoozit, gizmo), false);
+
+ // Make sure this is still true !important
+ compare(qtest_compareInternal(function () {}, function () {}), false);
+ }
+
+
+ function test_instances() {
+ function A() {}
+ var a1 = new A();
+ var a2 = new A();
+
+ function B() {
+ this.fn = function () {};
+ }
+ var b1 = new B();
+ var b2 = new B();
+
+ compare(qtest_compareInternal(a1, a2), true, "Same property, same constructor");
+
+ // b1.fn and b2.fn are functions but they are different references
+ // But we decided to skip function for instances.
+ expectFail("", "Don't know if we want to take over function checking like in QUnit")
+ compare(qtest_compareInternal(b1, b2), true, "Same property, same constructor");
+ compare(qtest_compareInternal(a1, b1), false, "Same properties but different constructor"); // failed
+
+ function Car(year) {
+ var privateVar = 0;
+ this.year = year;
+ this.isOld = function() {
+ return year > 10;
+ };
+ }
+
+ function Human(year) {
+ var privateVar = 1;
+ this.year = year;
+ this.isOld = function() {
+ return year > 80;
+ };
+ }
+
+ var car = new Car(30);
+ var carSame = new Car(30);
+ var carDiff = new Car(10);
+ var human = new Human(30);
+
+ var diff = {
+ year: 30
+ };
+
+ var same = {
+ year: 30,
+ isOld: function () {}
+ };
+
+ compare(qtest_compareInternal(car, car), true);
+ compare(qtest_compareInternal(car, carDiff), false);
+ compare(qtest_compareInternal(car, carSame), true);
+ compare(qtest_compareInternal(car, human), false);
+ }
+
+
+ function test_complex_instances_nesting() {
+ //"Complex Instances Nesting (with function value in literals and/or in nested instances)"
+ function A(fn) {
+ this.a = {};
+ this.fn = fn;
+ this.b = {a: []};
+ this.o = {};
+ this.fn1 = fn;
+ }
+ function B(fn) {
+ this.fn = fn;
+ this.fn1 = function () {};
+ this.a = new A(function () {});
+ }
+
+ function fnOutside() {
+ }
+
+ function C(fn) {
+ function fnInside() {
+ }
+ this.x = 10;
+ this.fn = fn;
+ this.fn1 = function () {};
+ this.fn2 = fnInside;
+ this.fn3 = {
+ a: true,
+ b: fnOutside // ok make reference to a function in all instances scope
+ };
+ this.o1 = {};
+
+ // This function will be ignored.
+ // Even if it is not visible for all instances (e.g. locked in a closures),
+ // it is from a property that makes part of an instance (e.g. from the C constructor)
+ this.b1 = new B(function () {});
+ this.b2 = new B({
+ x: {
+ b2: new B(function() {})
+ }
+ });
+ }
+
+ function D(fn) {
+ function fnInside() {
+ }
+ this.x = 10;
+ this.fn = fn;
+ this.fn1 = function () {};
+ this.fn2 = fnInside;
+ this.fn3 = {
+ a: true,
+ b: fnOutside, // ok make reference to a function in all instances scope
+
+ // This function won't be ingored.
+ // It isn't visible for all C insances
+ // and it is not in a property of an instance. (in an Object instances e.g. the object literal)
+ c: fnInside
+ };
+ this.o1 = {};
+
+ // This function will be ignored.
+ // Even if it is not visible for all instances (e.g. locked in a closures),
+ // it is from a property that makes part of an instance (e.g. from the C constructor)
+ this.b1 = new B(function () {});
+ this.b2 = new B({
+ x: {
+ b2: new B(function() {})
+ }
+ });
+ }
+
+ function E(fn) {
+ function fnInside() {
+ }
+ this.x = 10;
+ this.fn = fn;
+ this.fn1 = function () {};
+ this.fn2 = fnInside;
+ this.fn3 = {
+ a: true,
+ b: fnOutside // ok make reference to a function in all instances scope
+ };
+ this.o1 = {};
+
+ // This function will be ignored.
+ // Even if it is not visible for all instances (e.g. locked in a closures),
+ // it is from a property that makes part of an instance (e.g. from the C constructor)
+ this.b1 = new B(function () {});
+ this.b2 = new B({
+ x: {
+ b1: new B({a: function() {}}),
+ b2: new B(function() {})
+ }
+ });
+ }
+
+
+ var a1 = new A(function () {});
+ var a2 = new A(function () {});
+ expectFail("", "Don't know if we want to take over function checking like in QUnit")
+ compare(qtest_compareInternal(a1, a2), true);
+
+ compare(qtest_compareInternal(a1, a2), true); // different instances
+
+ var b1 = new B(function () {});
+ var b2 = new B(function () {});
+ compare(qtest_compareInternal(a1, a2), true);
+
+ var c1 = new C(function () {});
+ var c2 = new C(function () {});
+ compare(qtest_compareInternal(c1, c2), true);
+
+ var d1 = new D(function () {});
+ var d2 = new D(function () {});
+ compare(qtest_compareInternal(d1, d2), false);
+
+ var e1 = new E(function () {});
+ var e2 = new E(function () {});
+ compare(qtest_compareInternal(e1, e2), false);
+
+ }
+}