1module("equiv");
2
3
4test("Primitive types and constants", function () {
5    equals(QUnit.equiv(null, null), true, "null");
6    equals(QUnit.equiv(null, {}), false, "null");
7    equals(QUnit.equiv(null, undefined), false, "null");
8    equals(QUnit.equiv(null, 0), false, "null");
9    equals(QUnit.equiv(null, false), false, "null");
10    equals(QUnit.equiv(null, ''), false, "null");
11    equals(QUnit.equiv(null, []), false, "null");
12
13    equals(QUnit.equiv(undefined, undefined), true, "undefined");
14    equals(QUnit.equiv(undefined, null), false, "undefined");
15    equals(QUnit.equiv(undefined, 0), false, "undefined");
16    equals(QUnit.equiv(undefined, false), false, "undefined");
17    equals(QUnit.equiv(undefined, {}), false, "undefined");
18    equals(QUnit.equiv(undefined, []), false, "undefined");
19    equals(QUnit.equiv(undefined, ""), false, "undefined");
20
21    // Nan usually doest not equal to Nan using the '==' operator.
22    // Only isNaN() is able to do it.
23    equals(QUnit.equiv(0/0, 0/0), true, "NaN"); // NaN VS NaN
24    equals(QUnit.equiv(1/0, 2/0), true, "Infinity"); // Infinity VS Infinity
25    equals(QUnit.equiv(-1/0, 2/0), false, "-Infinity, Infinity"); // -Infinity VS Infinity
26    equals(QUnit.equiv(-1/0, -2/0), true, "-Infinity, -Infinity"); // -Infinity VS -Infinity
27    equals(QUnit.equiv(0/0, 1/0), false, "NaN, Infinity"); // Nan VS Infinity
28    equals(QUnit.equiv(1/0, 0/0), false, "NaN, Infinity"); // Nan VS Infinity
29    equals(QUnit.equiv(0/0, null), false, "NaN");
30    equals(QUnit.equiv(0/0, undefined), false, "NaN");
31    equals(QUnit.equiv(0/0, 0), false, "NaN");
32    equals(QUnit.equiv(0/0, false), false, "NaN");
33    equals(QUnit.equiv(0/0, function () {}), false, "NaN");
34    equals(QUnit.equiv(1/0, null), false, "NaN, Infinity");
35    equals(QUnit.equiv(1/0, undefined), false, "NaN, Infinity");
36    equals(QUnit.equiv(1/0, 0), false, "NaN, Infinity");
37    equals(QUnit.equiv(1/0, 1), false, "NaN, Infinity");
38    equals(QUnit.equiv(1/0, false), false, "NaN, Infinity");
39    equals(QUnit.equiv(1/0, true), false, "NaN, Infinity");
40    equals(QUnit.equiv(1/0, function () {}), false, "NaN, Infinity");
41
42    equals(QUnit.equiv(0, 0), true, "number");
43    equals(QUnit.equiv(0, 1), false, "number");
44    equals(QUnit.equiv(1, 0), false, "number");
45    equals(QUnit.equiv(1, 1), true, "number");
46    equals(QUnit.equiv(1.1, 1.1), true, "number");
47    equals(QUnit.equiv(0.0000005, 0.0000005), true, "number");
48    equals(QUnit.equiv(0, ''), false, "number");
49    equals(QUnit.equiv(0, '0'), false, "number");
50    equals(QUnit.equiv(1, '1'), false, "number");
51    equals(QUnit.equiv(0, false), false, "number");
52    equals(QUnit.equiv(1, true), false, "number");
53
54    equals(QUnit.equiv(true, true), true, "boolean");
55    equals(QUnit.equiv(true, false), false, "boolean");
56    equals(QUnit.equiv(false, true), false, "boolean");
57    equals(QUnit.equiv(false, 0), false, "boolean");
58    equals(QUnit.equiv(false, null), false, "boolean");
59    equals(QUnit.equiv(false, undefined), false, "boolean");
60    equals(QUnit.equiv(true, 1), false, "boolean");
61    equals(QUnit.equiv(true, null), false, "boolean");
62    equals(QUnit.equiv(true, undefined), false, "boolean");
63
64    equals(QUnit.equiv('', ''), true, "string");
65    equals(QUnit.equiv('a', 'a'), true, "string");
66    equals(QUnit.equiv("foobar", "foobar"), true, "string");
67    equals(QUnit.equiv("foobar", "foo"), false, "string");
68    equals(QUnit.equiv('', 0), false, "string");
69    equals(QUnit.equiv('', false), false, "string");
70    equals(QUnit.equiv('', null), false, "string");
71    equals(QUnit.equiv('', undefined), false, "string");
72
73    // Short annotation VS new annotation
74    equals(QUnit.equiv(0, new Number()), true, "short annotation VS new annotation");
75    equals(QUnit.equiv(new Number(), 0), true, "short annotation VS new annotation");
76    equals(QUnit.equiv(1, new Number(1)), true, "short annotation VS new annotation");
77    equals(QUnit.equiv(new Number(1), 1), true, "short annotation VS new annotation");
78    equals(QUnit.equiv(new Number(0), 1), false, "short annotation VS new annotation");
79    equals(QUnit.equiv(0, new Number(1)), false, "short annotation VS new annotation");
80
81    equals(QUnit.equiv(new String(), ""), true, "short annotation VS new annotation");
82    equals(QUnit.equiv("", new String()), true, "short annotation VS new annotation");
83    equals(QUnit.equiv(new String("My String"), "My String"), true, "short annotation VS new annotation");
84    equals(QUnit.equiv("My String", new String("My String")), true, "short annotation VS new annotation");
85    equals(QUnit.equiv("Bad String", new String("My String")), false, "short annotation VS new annotation");
86    equals(QUnit.equiv(new String("Bad String"), "My String"), false, "short annotation VS new annotation");
87
88    equals(QUnit.equiv(false, new Boolean()), true, "short annotation VS new annotation");
89    equals(QUnit.equiv(new Boolean(), false), true, "short annotation VS new annotation");
90    equals(QUnit.equiv(true, new Boolean(true)), true, "short annotation VS new annotation");
91    equals(QUnit.equiv(new Boolean(true), true), true, "short annotation VS new annotation");
92    equals(QUnit.equiv(true, new Boolean(1)), true, "short annotation VS new annotation");
93    equals(QUnit.equiv(false, new Boolean(false)), true, "short annotation VS new annotation");
94    equals(QUnit.equiv(new Boolean(false), false), true, "short annotation VS new annotation");
95    equals(QUnit.equiv(false, new Boolean(0)), true, "short annotation VS new annotation");
96    equals(QUnit.equiv(true, new Boolean(false)), false, "short annotation VS new annotation");
97    equals(QUnit.equiv(new Boolean(false), true), false, "short annotation VS new annotation");
98
99    equals(QUnit.equiv(new Object(), {}), true, "short annotation VS new annotation");
100    equals(QUnit.equiv({}, new Object()), true, "short annotation VS new annotation");
101    equals(QUnit.equiv(new Object(), {a:1}), false, "short annotation VS new annotation");
102    equals(QUnit.equiv({a:1}, new Object()), false, "short annotation VS new annotation");
103    equals(QUnit.equiv({a:undefined}, new Object()), false, "short annotation VS new annotation");
104    equals(QUnit.equiv(new Object(), {a:undefined}), false, "short annotation VS new annotation");
105});
106
107test("Objects Basics.", function() {
108    equals(QUnit.equiv({}, {}), true);
109    equals(QUnit.equiv({}, null), false);
110    equals(QUnit.equiv({}, undefined), false);
111    equals(QUnit.equiv({}, 0), false);
112    equals(QUnit.equiv({}, false), false);
113
114    // This test is a hard one, it is very important
115    // REASONS:
116    //      1) They are of the same type "object"
117    //      2) [] instanceof Object is true
118    //      3) Their properties are the same (doesn't exists)
119    equals(QUnit.equiv({}, []), false);
120
121    equals(QUnit.equiv({a:1}, {a:1}), true);
122    equals(QUnit.equiv({a:1}, {a:"1"}), false);
123    equals(QUnit.equiv({a:[]}, {a:[]}), true);
124    equals(QUnit.equiv({a:{}}, {a:null}), false);
125    equals(QUnit.equiv({a:1}, {}), false);
126    equals(QUnit.equiv({}, {a:1}), false);
127
128    // Hard ones
129    equals(QUnit.equiv({a:undefined}, {}), false);
130    equals(QUnit.equiv({}, {a:undefined}), false);
131    equals(QUnit.equiv(
132        {
133            a: [{ bar: undefined }]
134        },
135        {
136            a: [{ bat: undefined }]
137        }
138    ), false);
139});
140
141
142test("Arrays Basics.", function() {
143
144    equals(QUnit.equiv([], []), true);
145
146    // May be a hard one, can invoke a crash at execution.
147    // because their types are both "object" but null isn't
148    // like a true object, it doesn't have any property at all.
149    equals(QUnit.equiv([], null), false);
150
151    equals(QUnit.equiv([], undefined), false);
152    equals(QUnit.equiv([], false), false);
153    equals(QUnit.equiv([], 0), false);
154    equals(QUnit.equiv([], ""), false);
155
156    // May be a hard one, but less hard
157    // than {} with [] (note the order)
158    equals(QUnit.equiv([], {}), false);
159
160    equals(QUnit.equiv([null],[]), false);
161    equals(QUnit.equiv([undefined],[]), false);
162    equals(QUnit.equiv([],[null]), false);
163    equals(QUnit.equiv([],[undefined]), false);
164    equals(QUnit.equiv([null],[undefined]), false);
165    equals(QUnit.equiv([[]],[[]]), true);
166    equals(QUnit.equiv([[],[],[]],[[],[],[]]), true);
167    equals(QUnit.equiv(
168                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
169                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]),
170                            true);
171    equals(QUnit.equiv(
172                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
173                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // shorter
174                            false);
175    equals(QUnit.equiv(
176                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]],
177                            [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // deepest element not an array
178                            false);
179
180    // same multidimensional
181    equals(QUnit.equiv(
182                            [1,2,3,4,5,6,7,8,9, [
183                                1,2,3,4,5,6,7,8,9, [
184                                    1,2,3,4,5,[
185                                        [6,7,8,9, [
186                                            [
187                                                1,2,3,4,[
188                                                    2,3,4,[
189                                                        1,2,[
190                                                            1,2,3,4,[
191                                                                1,2,3,4,5,6,7,8,9,[
192                                                                    0
193                                                                ],1,2,3,4,5,6,7,8,9
194                                                            ],5,6,7,8,9
195                                                        ],4,5,6,7,8,9
196                                                    ],5,6,7,8,9
197                                                ],5,6,7
198                                            ]
199                                        ]
200                                    ]
201                                ]
202                            ]]],
203                            [1,2,3,4,5,6,7,8,9, [
204                                1,2,3,4,5,6,7,8,9, [
205                                    1,2,3,4,5,[
206                                        [6,7,8,9, [
207                                            [
208                                                1,2,3,4,[
209                                                    2,3,4,[
210                                                        1,2,[
211                                                            1,2,3,4,[
212                                                                1,2,3,4,5,6,7,8,9,[
213                                                                    0
214                                                                ],1,2,3,4,5,6,7,8,9
215                                                            ],5,6,7,8,9
216                                                        ],4,5,6,7,8,9
217                                                    ],5,6,7,8,9
218                                                ],5,6,7
219                                            ]
220                                        ]
221                                    ]
222                                ]
223                            ]]]),
224                            true, "Multidimensional");
225
226    // different multidimensional
227    equals(QUnit.equiv(
228                            [1,2,3,4,5,6,7,8,9, [
229                                1,2,3,4,5,6,7,8,9, [
230                                    1,2,3,4,5,[
231                                        [6,7,8,9, [
232                                            [
233                                                1,2,3,4,[
234                                                    2,3,4,[
235                                                        1,2,[
236                                                            1,2,3,4,[
237                                                                1,2,3,4,5,6,7,8,9,[
238                                                                    0
239                                                                ],1,2,3,4,5,6,7,8,9
240                                                            ],5,6,7,8,9
241                                                        ],4,5,6,7,8,9
242                                                    ],5,6,7,8,9
243                                                ],5,6,7
244                                            ]
245                                        ]
246                                    ]
247                                ]
248                            ]]],
249                            [1,2,3,4,5,6,7,8,9, [
250                                1,2,3,4,5,6,7,8,9, [
251                                    1,2,3,4,5,[
252                                        [6,7,8,9, [
253                                            [
254                                                1,2,3,4,[
255                                                    2,3,4,[
256                                                        1,2,[
257                                                            '1',2,3,4,[                 // string instead of number
258                                                                1,2,3,4,5,6,7,8,9,[
259                                                                    0
260                                                                ],1,2,3,4,5,6,7,8,9
261                                                            ],5,6,7,8,9
262                                                        ],4,5,6,7,8,9
263                                                    ],5,6,7,8,9
264                                                ],5,6,7
265                                            ]
266                                        ]
267                                    ]
268                                ]
269                            ]]]),
270                            false, "Multidimensional");
271
272    // different multidimensional
273    equals(QUnit.equiv(
274                            [1,2,3,4,5,6,7,8,9, [
275                                1,2,3,4,5,6,7,8,9, [
276                                    1,2,3,4,5,[
277                                        [6,7,8,9, [
278                                            [
279                                                1,2,3,4,[
280                                                    2,3,4,[
281                                                        1,2,[
282                                                            1,2,3,4,[
283                                                                1,2,3,4,5,6,7,8,9,[
284                                                                    0
285                                                                ],1,2,3,4,5,6,7,8,9
286                                                            ],5,6,7,8,9
287                                                        ],4,5,6,7,8,9
288                                                    ],5,6,7,8,9
289                                                ],5,6,7
290                                            ]
291                                        ]
292                                    ]
293                                ]
294                            ]]],
295                            [1,2,3,4,5,6,7,8,9, [
296                                1,2,3,4,5,6,7,8,9, [
297                                    1,2,3,4,5,[
298                                        [6,7,8,9, [
299                                            [
300                                                1,2,3,4,[
301                                                    2,3,[                   // missing an element (4)
302                                                        1,2,[
303                                                            1,2,3,4,[
304                                                                1,2,3,4,5,6,7,8,9,[
305                                                                    0
306                                                                ],1,2,3,4,5,6,7,8,9
307                                                            ],5,6,7,8,9
308                                                        ],4,5,6,7,8,9
309                                                    ],5,6,7,8,9
310                                                ],5,6,7
311                                            ]
312                                        ]
313                                    ]
314                                ]
315                            ]]]),
316                            false, "Multidimensional");
317});
318
319test("Functions.", function() {
320    var f0 = function () {};
321    var f1 = function () {};
322
323    // f2 and f3 have the same code, formatted differently
324    var f2 = function () {var i = 0;};
325    var f3 = function () {
326        var i = 0 // this comment and no semicoma as difference
327    };
328
329    equals(QUnit.equiv(function() {}, function() {}), false, "Anonymous functions"); // exact source code
330    equals(QUnit.equiv(function() {}, function() {return true;}), false, "Anonymous functions");
331
332    equals(QUnit.equiv(f0, f0), true, "Function references"); // same references
333    equals(QUnit.equiv(f0, f1), false, "Function references"); // exact source code, different references
334    equals(QUnit.equiv(f2, f3), false, "Function references"); // equivalent source code, different references
335    equals(QUnit.equiv(f1, f2), false, "Function references"); // different source code, different references
336    equals(QUnit.equiv(function() {}, true), false);
337    equals(QUnit.equiv(function() {}, undefined), false);
338    equals(QUnit.equiv(function() {}, null), false);
339    equals(QUnit.equiv(function() {}, {}), false);
340});
341
342
343test("Date instances.", function() {
344    // Date, we don't need to test Date.parse() because it returns a number.
345    // Only test the Date instances by setting them a fix date.
346    // The date use is midnight January 1, 1970
347
348    var d1 = new Date();
349    d1.setTime(0); // fix the date
350
351    var d2 = new Date();
352    d2.setTime(0); // fix the date
353
354    var d3 = new Date(); // The very now
355
356    // Anyway their types differs, just in case the code fails in the order in which it deals with date
357    equals(QUnit.equiv(d1, 0), false); // d1.valueOf() returns 0, but d1 and 0 are different
358    // test same values date and different instances equality
359    equals(QUnit.equiv(d1, d2), true);
360    // test different date and different instances difference
361    equals(QUnit.equiv(d1, d3), false);
362});
363
364
365test("RegExp.", function() {
366    // Must test cases that imply those traps:
367    // var a = /./;
368    // a instanceof Object;        // Oops
369    // a instanceof RegExp;        // Oops
370    // typeof a === "function";    // Oops, false in IE and Opera, true in FF and Safari ("object")
371
372    // Tests same regex with same modifiers in different order
373    var r = /foo/;
374    var r5 = /foo/gim;
375    var r6 = /foo/gmi;
376    var r7 = /foo/igm;
377    var r8 = /foo/img;
378    var r9 = /foo/mig;
379    var r10 = /foo/mgi;
380    var ri1 = /foo/i;
381    var ri2 = /foo/i;
382    var rm1 = /foo/m;
383    var rm2 = /foo/m;
384    var rg1 = /foo/g;
385    var rg2 = /foo/g;
386
387    equals(QUnit.equiv(r5, r6), true, "Modifier order");
388    equals(QUnit.equiv(r5, r7), true, "Modifier order");
389    equals(QUnit.equiv(r5, r8), true, "Modifier order");
390    equals(QUnit.equiv(r5, r9), true, "Modifier order");
391    equals(QUnit.equiv(r5, r10), true, "Modifier order");
392    equals(QUnit.equiv(r, r5), false, "Modifier");
393
394    equals(QUnit.equiv(ri1, ri2), true, "Modifier");
395    equals(QUnit.equiv(r, ri1), false, "Modifier");
396    equals(QUnit.equiv(ri1, rm1), false, "Modifier");
397    equals(QUnit.equiv(r, rm1), false, "Modifier");
398    equals(QUnit.equiv(rm1, ri1), false, "Modifier");
399    equals(QUnit.equiv(rm1, rm2), true, "Modifier");
400    equals(QUnit.equiv(rg1, rm1), false, "Modifier");
401    equals(QUnit.equiv(rm1, rg1), false, "Modifier");
402    equals(QUnit.equiv(rg1, rg2), true, "Modifier");
403
404    // Different regex, same modifiers
405    var r11 = /[a-z]/gi;
406    var r13 = /[0-9]/gi; // oops! different
407    equals(QUnit.equiv(r11, r13), false, "Regex pattern");
408
409    var r14 = /0/ig;
410    var r15 = /"0"/ig; // oops! different
411    equals(QUnit.equiv(r14, r15), false, "Regex pattern");
412
413    var r1 = /[\n\r\u2028\u2029]/g;
414    var r2 = /[\n\r\u2028\u2029]/g;
415    var r3 = /[\n\r\u2028\u2028]/g; // differs from r1
416    var r4 = /[\n\r\u2028\u2029]/;  // differs from r1
417
418    equals(QUnit.equiv(r1, r2), true, "Regex pattern");
419    equals(QUnit.equiv(r1, r3), false, "Regex pattern");
420    equals(QUnit.equiv(r1, r4), false, "Regex pattern");
421
422    // More complex regex
423    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]))$";
424    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]))$";
425    // regex 3 is different: '.' not escaped
426    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]))$";
427
428    var r21 = new RegExp(regex1);
429    var r22 = new RegExp(regex2);
430    var r23 = new RegExp(regex3); // diff from r21, not same pattern
431    var r23a = new RegExp(regex3, "gi"); // diff from r23, not same modifier
432    var r24a = new RegExp(regex3, "ig"); // same as r23a
433
434    equals(QUnit.equiv(r21, r22), true, "Complex Regex");
435    equals(QUnit.equiv(r21, r23), false, "Complex Regex");
436    equals(QUnit.equiv(r23, r23a), false, "Complex Regex");
437    equals(QUnit.equiv(r23a, r24a), true, "Complex Regex");
438
439    // typeof r1 is "function" in some browsers and "object" in others so we must cover this test
440    var re = / /;
441    equals(QUnit.equiv(re, function () {}), false, "Regex internal");
442    equals(QUnit.equiv(re, {}), false, "Regex internal");
443});
444
445
446test("Complex Objects.", function() {
447
448    function fn1() {
449        return "fn1";
450    }
451    function fn2() {
452        return "fn2";
453    }
454
455    // Try to invert the order of some properties to make sure it is covered.
456    // It can failed when properties are compared between unsorted arrays.
457    equals(QUnit.equiv(
458        {
459            a: 1,
460            b: null,
461            c: [{}],
462            d: {
463                a: 3.14159,
464                b: false,
465                c: {
466                    e: fn1,
467                    f: [[[]]],
468                    g: {
469                        j: {
470                            k: {
471                                n: {
472                                    r: "r",
473                                    s: [1,2,3],
474                                    t: undefined,
475                                    u: 0,
476                                    v: {
477                                        w: {
478                                            x: {
479                                                y: "Yahoo!",
480                                                z: null
481                                            }
482                                        }
483                                    }
484                                },
485                                q: [],
486                                p: 1/0,
487                                o: 99
488                            },
489                            l: undefined,
490                            m: null
491                        }
492                    },
493                    d: 0,
494                    i: true,
495                    h: "false"
496                }
497            },
498            e: undefined,
499            g: "",
500            h: "h",
501            f: {},
502            i: []
503        },
504        {
505            a: 1,
506            b: null,
507            c: [{}],
508            d: {
509                b: false,
510                a: 3.14159,
511                c: {
512                    d: 0,
513                    e: fn1,
514                    f: [[[]]],
515                    g: {
516                        j: {
517                            k: {
518                                n: {
519                                    r: "r",
520                                    t: undefined,
521                                    u: 0,
522                                    s: [1,2,3],
523                                    v: {
524                                        w: {
525                                            x: {
526                                                z: null,
527                                                y: "Yahoo!"
528                                            }
529                                        }
530                                    }
531                                },
532                                o: 99,
533                                p: 1/0,
534                                q: []
535                            },
536                            l: undefined,
537                            m: null
538                        }
539                    },
540                    i: true,
541                    h: "false"
542                }
543            },
544            e: undefined,
545            g: "",
546            f: {},
547            h: "h",
548            i: []
549        }
550    ), true);
551
552    equals(QUnit.equiv(
553        {
554            a: 1,
555            b: null,
556            c: [{}],
557            d: {
558                a: 3.14159,
559                b: false,
560                c: {
561                    d: 0,
562                    e: fn1,
563                    f: [[[]]],
564                    g: {
565                        j: {
566                            k: {
567                                n: {
568                                    //r: "r",   // different: missing a property
569                                    s: [1,2,3],
570                                    t: undefined,
571                                    u: 0,
572                                    v: {
573                                        w: {
574                                            x: {
575                                                y: "Yahoo!",
576                                                z: null
577                                            }
578                                        }
579                                    }
580                                },
581                                o: 99,
582                                p: 1/0,
583                                q: []
584                            },
585                            l: undefined,
586                            m: null
587                        }
588                    },
589                    h: "false",
590                    i: true
591                }
592            },
593            e: undefined,
594            f: {},
595            g: "",
596            h: "h",
597            i: []
598        },
599        {
600            a: 1,
601            b: null,
602            c: [{}],
603            d: {
604                a: 3.14159,
605                b: false,
606                c: {
607                    d: 0,
608                    e: fn1,
609                    f: [[[]]],
610                    g: {
611                        j: {
612                            k: {
613                                n: {
614                                    r: "r",
615                                    s: [1,2,3],
616                                    t: undefined,
617                                    u: 0,
618                                    v: {
619                                        w: {
620                                            x: {
621                                                y: "Yahoo!",
622                                                z: null
623                                            }
624                                        }
625                                    }
626                                },
627                                o: 99,
628                                p: 1/0,
629                                q: []
630                            },
631                            l: undefined,
632                            m: null
633                        }
634                    },
635                    h: "false",
636                    i: true
637                }
638            },
639            e: undefined,
640            f: {},
641            g: "",
642            h: "h",
643            i: []
644        }
645    ), false);
646
647    equals(QUnit.equiv(
648        {
649            a: 1,
650            b: null,
651            c: [{}],
652            d: {
653                a: 3.14159,
654                b: false,
655                c: {
656                    d: 0,
657                    e: fn1,
658                    f: [[[]]],
659                    g: {
660                        j: {
661                            k: {
662                                n: {
663                                    r: "r",
664                                    s: [1,2,3],
665                                    t: undefined,
666                                    u: 0,
667                                    v: {
668                                        w: {
669                                            x: {
670                                                y: "Yahoo!",
671                                                z: null
672                                            }
673                                        }
674                                    }
675                                },
676                                o: 99,
677                                p: 1/0,
678                                q: []
679                            },
680                            l: undefined,
681                            m: null
682                        }
683                    },
684                    h: "false",
685                    i: true
686                }
687            },
688            e: undefined,
689            f: {},
690            g: "",
691            h: "h",
692            i: []
693        },
694        {
695            a: 1,
696            b: null,
697            c: [{}],
698            d: {
699                a: 3.14159,
700                b: false,
701                c: {
702                    d: 0,
703                    e: fn1,
704                    f: [[[]]],
705                    g: {
706                        j: {
707                            k: {
708                                n: {
709                                    r: "r",
710                                    s: [1,2,3],
711                                    //t: undefined,                 // different: missing a property with an undefined value
712                                    u: 0,
713                                    v: {
714                                        w: {
715                                            x: {
716                                                y: "Yahoo!",
717                                                z: null
718                                            }
719                                        }
720                                    }
721                                },
722                                o: 99,
723                                p: 1/0,
724                                q: []
725                            },
726                            l: undefined,
727                            m: null
728                        }
729                    },
730                    h: "false",
731                    i: true
732                }
733            },
734            e: undefined,
735            f: {},
736            g: "",
737            h: "h",
738            i: []
739        }
740    ), false);
741
742    equals(QUnit.equiv(
743        {
744            a: 1,
745            b: null,
746            c: [{}],
747            d: {
748                a: 3.14159,
749                b: false,
750                c: {
751                    d: 0,
752                    e: fn1,
753                    f: [[[]]],
754                    g: {
755                        j: {
756                            k: {
757                                n: {
758                                    r: "r",
759                                    s: [1,2,3],
760                                    t: undefined,
761                                    u: 0,
762                                    v: {
763                                        w: {
764                                            x: {
765                                                y: "Yahoo!",
766                                                z: null
767                                            }
768                                        }
769                                    }
770                                },
771                                o: 99,
772                                p: 1/0,
773                                q: []
774                            },
775                            l: undefined,
776                            m: null
777                        }
778                    },
779                    h: "false",
780                    i: true
781                }
782            },
783            e: undefined,
784            f: {},
785            g: "",
786            h: "h",
787            i: []
788        },
789        {
790            a: 1,
791            b: null,
792            c: [{}],
793            d: {
794                a: 3.14159,
795                b: false,
796                c: {
797                    d: 0,
798                    e: fn1,
799                    f: [[[]]],
800                    g: {
801                        j: {
802                            k: {
803                                n: {
804                                    r: "r",
805                                    s: [1,2,3],
806                                    t: undefined,
807                                    u: 0,
808                                    v: {
809                                        w: {
810                                            x: {
811                                                y: "Yahoo!",
812                                                z: null
813                                            }
814                                        }
815                                    }
816                                },
817                                o: 99,
818                                p: 1/0,
819                                q: {}           // different was []
820                            },
821                            l: undefined,
822                            m: null
823                        }
824                    },
825                    h: "false",
826                    i: true
827                }
828            },
829            e: undefined,
830            f: {},
831            g: "",
832            h: "h",
833            i: []
834        }
835    ), false);
836
837    var same1 = {
838        a: [
839            "string", null, 0, "1", 1, {
840                prop: null,
841                foo: [1,2,null,{}, [], [1,2,3]],
842                bar: undefined
843            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
844        ],
845        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
846        b: "b",
847        c: fn1
848    };
849
850    var same2 = {
851        a: [
852            "string", null, 0, "1", 1, {
853                prop: null,
854                foo: [1,2,null,{}, [], [1,2,3]],
855                bar: undefined
856            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
857        ],
858        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
859        b: "b",
860        c: fn1
861    };
862
863    var diff1 = {
864        a: [
865            "string", null, 0, "1", 1, {
866                prop: null,
867                foo: [1,2,null,{}, [], [1,2,3,4]], // different: 4 was add to the array
868                bar: undefined
869            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
870        ],
871        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
872        b: "b",
873        c: fn1
874    };
875
876    var diff2 = {
877        a: [
878            "string", null, 0, "1", 1, {
879                prop: null,
880                foo: [1,2,null,{}, [], [1,2,3]],
881                newprop: undefined, // different: newprop was added
882                bar: undefined
883            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
884        ],
885        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
886        b: "b",
887        c: fn1
888    };
889
890    var diff3 = {
891        a: [
892            "string", null, 0, "1", 1, {
893                prop: null,
894                foo: [1,2,null,{}, [], [1,2,3]],
895                bar: undefined
896            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ α" // different: missing last char
897        ],
898        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
899        b: "b",
900        c: fn1
901    };
902
903    var diff4 = {
904        a: [
905            "string", null, 0, "1", 1, {
906                prop: null,
907                foo: [1,2,undefined,{}, [], [1,2,3]], // different: undefined instead of null
908                bar: undefined
909            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
910        ],
911        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
912        b: "b",
913        c: fn1
914    };
915
916    var diff5 = {
917        a: [
918            "string", null, 0, "1", 1, {
919                prop: null,
920                foo: [1,2,null,{}, [], [1,2,3]],
921                bat: undefined // different: property name not "bar"
922            }, 3, "Hey!", "Κάνε πάντα γνωρίζουμε ας των, μηχανής επιδιόρθωσης επιδιορθώσεις ώς μια. Κλπ ας"
923        ],
924        unicode: "老 汉语中存在 港澳和海外的华人圈中 贵州 我去了书店 现在尚有争",
925        b: "b",
926        c: fn1
927    };
928
929    equals(QUnit.equiv(same1, same2), true);
930    equals(QUnit.equiv(same2, same1), true);
931    equals(QUnit.equiv(same2, diff1), false);
932    equals(QUnit.equiv(diff1, same2), false);
933
934    equals(QUnit.equiv(same1, diff1), false);
935    equals(QUnit.equiv(same1, diff2), false);
936    equals(QUnit.equiv(same1, diff3), false);
937    equals(QUnit.equiv(same1, diff3), false);
938    equals(QUnit.equiv(same1, diff4), false);
939    equals(QUnit.equiv(same1, diff5), false);
940    equals(QUnit.equiv(diff5, diff1), false);
941});
942
943
944test("Complex Arrays.", function() {
945
946    function fn() {
947    }
948
949    equals(QUnit.equiv(
950                [1, 2, 3, true, {}, null, [
951                    {
952                        a: ["", '1', 0]
953                    },
954                    5, 6, 7
955                ], "foo"],
956                [1, 2, 3, true, {}, null, [
957                    {
958                        a: ["", '1', 0]
959                    },
960                    5, 6, 7
961                ], "foo"]),
962            true);
963
964    equals(QUnit.equiv(
965                [1, 2, 3, true, {}, null, [
966                    {
967                        a: ["", '1', 0]
968                    },
969                    5, 6, 7
970                ], "foo"],
971                [1, 2, 3, true, {}, null, [
972                    {
973                        b: ["", '1', 0]         // not same property name
974                    },
975                    5, 6, 7
976                ], "foo"]),
977            false);
978
979    var a = [{
980        b: fn,
981        c: false,
982        "do": "reserved word",
983        "for": {
984            ar: [3,5,9,"hey!", [], {
985                ar: [1,[
986                    3,4,6,9, null, [], []
987                ]],
988                e: fn,
989                f: undefined
990            }]
991        },
992        e: 0.43445
993    }, 5, "string", 0, fn, false, null, undefined, 0, [
994        4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
995    ], [], [[[], "foo", null, {
996        n: 1/0,
997        z: {
998            a: [3,4,5,6,"yep!", undefined, undefined],
999            b: {}
1000        }
1001    }, {}]]];
1002
1003    equals(QUnit.equiv(a,
1004            [{
1005                b: fn,
1006                c: false,
1007                "do": "reserved word",
1008                "for": {
1009                    ar: [3,5,9,"hey!", [], {
1010                        ar: [1,[
1011                            3,4,6,9, null, [], []
1012                        ]],
1013                        e: fn,
1014                        f: undefined
1015                    }]
1016                },
1017                e: 0.43445
1018            }, 5, "string", 0, fn, false, null, undefined, 0, [
1019                4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1020            ], [], [[[], "foo", null, {
1021                n: 1/0,
1022                z: {
1023                    a: [3,4,5,6,"yep!", undefined, undefined],
1024                    b: {}
1025                }
1026            }, {}]]]), true);
1027
1028    equals(QUnit.equiv(a,
1029            [{
1030                b: fn,
1031                c: false,
1032                "do": "reserved word",
1033                "for": {
1034                    ar: [3,5,9,"hey!", [], {
1035                        ar: [1,[
1036                            3,4,6,9, null, [], []
1037                        ]],
1038                        e: fn,
1039                        f: undefined
1040                    }]
1041                },
1042                e: 0.43445
1043            }, 5, "string", 0, fn, false, null, undefined, 0, [
1044                4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[2]]]], "3"], {}, 1/0    // different: [[[[[2]]]]] instead of [[[[[3]]]]]
1045            ], [], [[[], "foo", null, {
1046                n: 1/0,
1047                z: {
1048                    a: [3,4,5,6,"yep!", undefined, undefined],
1049                    b: {}
1050                }
1051            }, {}]]]), false);
1052
1053    equals(QUnit.equiv(a,
1054            [{
1055                b: fn,
1056                c: false,
1057                "do": "reserved word",
1058                "for": {
1059                    ar: [3,5,9,"hey!", [], {
1060                        ar: [1,[
1061                            3,4,6,9, null, [], []
1062                        ]],
1063                        e: fn,
1064                        f: undefined
1065                    }]
1066                },
1067                e: 0.43445
1068            }, 5, "string", 0, fn, false, null, undefined, 0, [
1069                4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1070            ], [], [[[], "foo", null, {
1071                n: -1/0,                                                                // different, -Infinity instead of Infinity
1072                z: {
1073                    a: [3,4,5,6,"yep!", undefined, undefined],
1074                    b: {}
1075                }
1076            }, {}]]]), false);
1077
1078    equals(QUnit.equiv(a,
1079            [{
1080                b: fn,
1081                c: false,
1082                "do": "reserved word",
1083                "for": {
1084                    ar: [3,5,9,"hey!", [], {
1085                        ar: [1,[
1086                            3,4,6,9, null, [], []
1087                        ]],
1088                        e: fn,
1089                        f: undefined
1090                    }]
1091                },
1092                e: 0.43445
1093            }, 5, "string", 0, fn, false, null, undefined, 0, [
1094                4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1095            ], [], [[[], "foo", {                                                       // different: null is missing
1096                n: 1/0,
1097                z: {
1098                    a: [3,4,5,6,"yep!", undefined, undefined],
1099                    b: {}
1100                }
1101            }, {}]]]), false);
1102
1103    equals(QUnit.equiv(a,
1104            [{
1105                b: fn,
1106                c: false,
1107                "do": "reserved word",
1108                "for": {
1109                    ar: [3,5,9,"hey!", [], {
1110                        ar: [1,[
1111                            3,4,6,9, null, [], []
1112                        ]],
1113                        e: fn
1114                                                                                // different: missing property f: undefined
1115                    }]
1116                },
1117                e: 0.43445
1118            }, 5, "string", 0, fn, false, null, undefined, 0, [
1119                4,5,6,7,8,9,11,22,33,44,55,"66", null, [], [[[[[3]]]], "3"], {}, 1/0
1120            ], [], [[[], "foo", null, {
1121                n: 1/0,
1122                z: {
1123                    a: [3,4,5,6,"yep!", undefined, undefined],
1124                    b: {}
1125                }
1126            }, {}]]]), false);
1127});
1128
1129
1130test("Prototypal inheritance", function() {
1131    function Gizmo(id) {
1132        this.id = id;
1133    }
1134
1135    function Hoozit(id) {
1136        this.id = id;
1137    }
1138    Hoozit.prototype = new Gizmo();
1139
1140    var gizmo = new Gizmo("ok");
1141    var hoozit = new Hoozit("ok");
1142
1143    // Try this test many times after test on instances that hold function
1144    // to make sure that our code does not mess with last object constructor memoization.
1145    equals(QUnit.equiv(function () {}, function () {}), false);
1146
1147    // Hoozit inherit from Gizmo
1148    // hoozit instanceof Hoozit; // true
1149    // hoozit instanceof Gizmo; // true
1150    equals(QUnit.equiv(hoozit, gizmo), true);
1151
1152    Gizmo.prototype.bar = true; // not a function just in case we skip them
1153
1154    // Hoozit inherit from Gizmo
1155    // They are equivalent
1156    equals(QUnit.equiv(hoozit, gizmo), true);
1157
1158    // Make sure this is still true !important
1159    // The reason for this is that I forgot to reset the last
1160    // caller to where it were called from.
1161    equals(QUnit.equiv(function () {}, function () {}), false);
1162
1163    // Make sure this is still true !important
1164    equals(QUnit.equiv(hoozit, gizmo), true);
1165
1166    Hoozit.prototype.foo = true; // not a function just in case we skip them
1167
1168    // Gizmo does not inherit from Hoozit
1169    // gizmo instanceof Gizmo; // true
1170    // gizmo instanceof Hoozit; // false
1171    // They are not equivalent
1172    equals(QUnit.equiv(hoozit, gizmo), false);
1173
1174    // Make sure this is still true !important
1175    equals(QUnit.equiv(function () {}, function () {}), false);
1176});
1177
1178
1179test("Instances", function() {
1180    function A() {}
1181    var a1 = new A();
1182    var a2 = new A();
1183
1184    function B() {
1185        this.fn = function () {};
1186    }
1187    var b1 = new B();
1188    var b2 = new B();
1189
1190    equals(QUnit.equiv(a1, a2), true, "Same property, same constructor");
1191
1192    // b1.fn and b2.fn are functions but they are different references
1193    // But we decided to skip function for instances.
1194    equals(QUnit.equiv(b1, b2), true, "Same property, same constructor");
1195    equals(QUnit.equiv(a1, b1), false, "Same properties but different constructor"); // failed
1196
1197    function Car(year) {
1198        var privateVar = 0;
1199        this.year = year;
1200        this.isOld = function() {
1201            return year > 10;
1202        };
1203    }
1204
1205    function Human(year) {
1206        var privateVar = 1;
1207        this.year = year;
1208        this.isOld = function() {
1209            return year > 80;
1210        };
1211    }
1212
1213    var car = new Car(30);
1214    var carSame = new Car(30);
1215    var carDiff = new Car(10);
1216    var human = new Human(30);
1217
1218    var diff = {
1219        year: 30
1220    };
1221
1222    var same = {
1223        year: 30,
1224        isOld: function () {}
1225    };
1226
1227    equals(QUnit.equiv(car, car), true);
1228    equals(QUnit.equiv(car, carDiff), false);
1229    equals(QUnit.equiv(car, carSame), true);
1230    equals(QUnit.equiv(car, human), false);
1231});
1232
1233
1234test("Complex Instances Nesting (with function value in literals and/or in nested instances)", function() {
1235    function A(fn) {
1236        this.a = {};
1237        this.fn = fn;
1238        this.b = {a: []};
1239        this.o = {};
1240        this.fn1 = fn;
1241    }
1242    function B(fn) {
1243        this.fn = fn;
1244        this.fn1 = function () {};
1245        this.a = new A(function () {});
1246    }
1247
1248    function fnOutside() {
1249    }
1250
1251    function C(fn) {
1252        function fnInside() {
1253        }
1254        this.x = 10;
1255        this.fn = fn;
1256        this.fn1 = function () {};
1257        this.fn2 = fnInside;
1258        this.fn3 = {
1259            a: true,
1260            b: fnOutside // ok make reference to a function in all instances scope
1261        };
1262        this.o1 = {};
1263
1264        // This function will be ignored.
1265        // Even if it is not visible for all instances (e.g. locked in a closures),
1266        // it is from a  property that makes part of an instance (e.g. from the C constructor)
1267        this.b1 = new B(function () {});
1268        this.b2 = new B({
1269            x: {
1270                b2: new B(function() {})
1271            }
1272        });
1273    }
1274
1275    function D(fn) {
1276        function fnInside() {
1277        }
1278        this.x = 10;
1279        this.fn = fn;
1280        this.fn1 = function () {};
1281        this.fn2 = fnInside;
1282        this.fn3 = {
1283            a: true,
1284            b: fnOutside, // ok make reference to a function in all instances scope
1285
1286            // This function won't be ingored.
1287            // It isn't visible for all C insances
1288            // and it is not in a property of an instance. (in an Object instances e.g. the object literal)
1289            c: fnInside
1290        };
1291        this.o1 = {};
1292
1293        // This function will be ignored.
1294        // Even if it is not visible for all instances (e.g. locked in a closures),
1295        // it is from a  property that makes part of an instance (e.g. from the C constructor)
1296        this.b1 = new B(function () {});
1297        this.b2 = new B({
1298            x: {
1299                b2: new B(function() {})
1300            }
1301        });
1302    }
1303
1304    function E(fn) {
1305        function fnInside() {
1306        }
1307        this.x = 10;
1308        this.fn = fn;
1309        this.fn1 = function () {};
1310        this.fn2 = fnInside;
1311        this.fn3 = {
1312            a: true,
1313            b: fnOutside // ok make reference to a function in all instances scope
1314        };
1315        this.o1 = {};
1316
1317        // This function will be ignored.
1318        // Even if it is not visible for all instances (e.g. locked in a closures),
1319        // it is from a  property that makes part of an instance (e.g. from the C constructor)
1320        this.b1 = new B(function () {});
1321        this.b2 = new B({
1322            x: {
1323                b1: new B({a: function() {}}),
1324                b2: new B(function() {})
1325            }
1326        });
1327    }
1328
1329
1330    var a1 = new A(function () {});
1331    var a2 = new A(function () {});
1332    equals(QUnit.equiv(a1, a2), true);
1333
1334    equals(QUnit.equiv(a1, a2), true); // different instances
1335
1336    var b1 = new B(function () {});
1337    var b2 = new B(function () {});
1338    equals(QUnit.equiv(b1, b2), true);
1339
1340    var c1 = new C(function () {});
1341    var c2 = new C(function () {});
1342    equals(QUnit.equiv(c1, c2), true);
1343
1344    var d1 = new D(function () {});
1345    var d2 = new D(function () {});
1346    equals(QUnit.equiv(d1, d2), false);
1347
1348    var e1 = new E(function () {});
1349    var e2 = new E(function () {});
1350    equals(QUnit.equiv(e1, e2), false);
1351
1352});
1353
1354
1355test('object with references to self wont loop', function(){
1356    var circularA = {
1357        abc:null
1358    }, circularB = {
1359        abc:null
1360    };
1361    circularA.abc = circularA;
1362    circularB.abc = circularB;
1363    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
1364
1365    circularA.def = 1;
1366    circularB.def = 1;
1367    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)");
1368
1369    circularA.def = 1;
1370    circularB.def = 0;
1371    equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object (unambigous test)");
1372});
1373
1374test('array with references to self wont loop', function(){
1375    var circularA = [],
1376        circularB = [];
1377    circularA.push(circularA);
1378    circularB.push(circularB);
1379    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
1380
1381    circularA.push( 'abc' );
1382    circularB.push( 'abc' );
1383    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)");
1384
1385    circularA.push( 'hello' );
1386    circularB.push( 'goodbye' );
1387    equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on array (unambigous test)");
1388});
1389
1390test('mixed object/array with references to self wont loop', function(){
1391    var circularA = [{abc:null}],
1392        circularB = [{abc:null}];
1393    circularA[0].abc = circularA;
1394    circularB[0].abc = circularB;
1395
1396    circularA.push(circularA);
1397    circularB.push(circularB);
1398    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
1399
1400    circularA[0].def = 1;
1401    circularB[0].def = 1;
1402    equals(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)");
1403
1404    circularA[0].def = 1;
1405    circularB[0].def = 0;
1406    equals(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object/array (unambigous test)");
1407});
1408
1409test("Test that must be done at the end because they extend some primitive's prototype", function() {
1410    // Try that a function looks like our regular expression.
1411    // This tests if we check that a and b are really both instance of RegExp
1412    Function.prototype.global = true;
1413    Function.prototype.multiline = true;
1414    Function.prototype.ignoreCase = false;
1415    Function.prototype.source = "my regex";
1416    var re = /my regex/gm;
1417    equals(QUnit.equiv(re, function () {}), false, "A function that looks that a regex isn't a regex");
1418    // This test will ensures it works in both ways, and ALSO especially that we can make differences
1419    // between RegExp and Function constructor because typeof on a RegExpt instance is "function"
1420    equals(QUnit.equiv(function () {}, re), false, "Same conversely, but ensures that function and regexp are distinct because their constructor are different");
1421});
1422