text: var assert = require("assert");
  var equal = require(".");
  
  function eq(a, b, opts) {
    var r = equal(a, b, opts);
    if (r.length !== 0) {
      r = r[0];
      var msg = r.reason + " at " + r.path + " " + r.a + " =/= " + r.b;
  
      assert.equal(a, b, msg);
    }
  }
  
  function ne(a, b, opts) {
    var r = equal(a, b, opts);
    assert.ok(r.length !== 0);
  }
  
  /* 1. simple tests */
  
  /* 1.1. positive */
  it("NaN eqs NaN", function() {
    return eq(NaN, NaN);
  });
  it("finite integer n eqs n", function() {
    return eq(1234, 1234);
  });
  it("empty list eqs empty list", function() {
    return eq([], []);
  });
  it("empty obj eqs empty obj", function() {
    return eq({}, {});
  });
  it("number eqs number of same value", function() {
    return eq(123.45678, 123.45678);
  });
  it("regex lit's w same pattern, flags are eq", function() {
    return eq(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/);
  });
  it("pods w same properties are eq", function() {
    return eq(
      {
        a: "b",
        c: "d"
      },
      {
        a: "b",
        c: "d"
      }
    );
  });
  it("pods that only differ wrt prop ord are eq", function() {
    return eq(
      {
        a: "b",
        c: "d"
      },
      {
        c: "d",
        a: "b"
      }
    );
  });
  
  /* 1.2. negative */
  it("obj doesn't eq list", function() {
    return ne({}, []);
  });
  it("obj in a list doesn't eq list in list", function() {
    return ne([{}], [[]]);
  });
  it("integer n doesn't eq rpr n", function() {
    return ne(1234, "1234");
  });
  it("integer n doesn't eq n + 1", function() {
    return ne(1234, 1235);
  });
  it("empty list doesn't eq false", function() {
    return ne([], false);
  });
  it("list w an integer doesn't eq one w rpr n", function() {
    return ne([3], ["3"]);
  });
  it("regex lit's w diff. patterns, same flags aren't eq", function() {
    return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]x/);
  });
  it("regex lit's w same patterns, diff. flags aren't eq", function() {
    return ne(/^abc[a-zA-Z]/, /^abc[a-zA-Z]/i);
  });
  it("number obj not eqs primitive number of same value", function() {
    return ne(5, new Number(5));
  });
  it("string obj not eqs primitive string of same value", function() {
    return ne("helo", new String("helo"));
  });
  it("(1) bool obj not eqs primitive bool of same value", function() {
    return ne(false, new Boolean(false));
  });
  it("(2) bool obj not eqs primitive bool of same value", function() {
    return ne(true, new Boolean(true));
  });
  it("number obj eqs the same valued number object", function() {
    return eq(new Number(5), new Number(5));
  });
  
  /* 2. complex tests */
  it("obj w undef member not eqs other obj w/out same member", function() {
    var d, e;
    d = {
      x: void 0
    };
    e = {};
    return ne(d, e);
  });
  it("fn1: functions w same source are eq", function() {
    var d, e;
    d = function(a, b, c) {
      return a * b * c;
    };
    e = function(a, b, c) {
      return a * b * c;
    };
    return eq(d, e);
  });
  it("fn2: functions w diff source aren't eq", function() {
    var d, e;
    d = function(a, b, c) {
      return a * b * c;
    };
    e = function(a, b, s) {
      return a * b * s;
    };
    return ne(d, e);
  });
  it("fn3: equal functions w equal props are eq", function() {
    var d, e;
    d = function() {
      return null;
    };
    d.foo = {
      some: "meaningless",
      properties: "here"
    };
    e = function() {
      return null;
    };
    e.foo = {
      some: "meaningless",
      properties: "here"
    };
    return eq(d, e);
  });
  it("fn4: equal functions w unequal props aren't eq", function() {
    var d, e;
    d = function() {
      return null;
    };
    d.foo = {
      some: "meaningless",
      properties: "here"
    };
    e = function() {
      return null;
    };
    e.foo = {
      some: "meaningless",
      properties: "here!!!"
    };
    return ne(d, e);
  });
  it("list w named member eqs other list w same member", function() {
    var d, e;
    d = ["foo", null, 3];
    d["extra"] = 42;
    e = ["foo", null, 3];
    e["extra"] = 42;
    return eq(d, e);
  });
  it("list w named member doesn't eq list w same member, other value", function() {
    var d, e;
    d = ["foo", null, 3];
    d["extra"] = 42;
    e = ["foo", null, 3];
    e["extra"] = 108;
    return ne(d, e);
  });
  it("date eqs other date pointing to same time", function() {
    var d, e;
    d = new Date("1995-12-17T03:24:00");
    e = new Date("1995-12-17T03:24:00");
    return eq(d, e);
  });
  it("date does not eq other date pointing to other time", function() {
    var d, e;
    d = new Date("1995-12-17T03:24:00");
    e = new Date("1995-12-17T03:24:01");
    return ne(d, e);
  });
  it("str obj w props eq same str, same props", function() {
    var d, e;
    d = new String("helo test");
    d["abc"] = 42;
    e = new String("helo test");
    e["abc"] = 42;
    return eq(d, e);
  });
  it("str obj w props not eq same str, other props", function() {
    var d, e;
    d = new String("helo test");
    d["abc"] = 42;
    e = new String("helo test");
    e["def"] = 42;
    return ne(d, e);
  });
  it("str obj w props eq same str, same props (circ)", function() {
    var c, d, e;
    c = ["a list"];
    c.push(c);
    d = new String("helo test");
    d["abc"] = c;
    e = new String("helo test");
    e["abc"] = c;
    return eq(d, e);
  });
  it("str obj w props not eq same str, other props (circ)", function() {
    var c, d, e;
    c = ["a list"];
    c.push(c);
    d = new String("helo test");
    d["abc"] = c;
    e = new String("helo test");
    e["def"] = c;
    return ne(d, e);
  });
  /*it("(1) circ arrays w similar layout, same values aren't eq", function() {
    var d, e;
    d = [1, 2, 3];
    d.push(d);
    e = [1, 2, 3];
    e.push(d);
    return ne(d, e);
  });*/
  it("(2) circ arrays w same layout, same values are eq", function() {
    var d, e;
    d = [1, 2, 3];
    d.push(d);
    e = [1, 2, 3];
    e.push(e);
    return eq(d, e);
  });
  it("(fkling1) arrays w eq subarrays are eq", function() {
    var a, b, bar, foo;
    a = [1, 2, 3];
    b = [1, 2, 3];
    foo = [a, a];
    bar = [b, b];
    return eq(foo, bar);
  });
  /*it("(fkling2) arrays w eq subarrays but diff distribution aren't eq"] = function() {
    var a, b, bar, foo;
    a = [1, 2, 3];
    b = [1, 2, 3];
    foo = [a, a];
    bar = [a, b];
    return ne(foo, bar);
  };*/
  
  /* joshwilsdon's test (https://github.com/joyent/node/issues/7161) */
  it("joshwilsdon", function() {
    var count, d1, d2, errors, idx1, idx2, v1, v2, _i, _j, _len, _ref;
    d1 = [
      NaN,
      void 0,
      null,
      true,
      false,
      Infinity,
      0,
      1,
      "a",
      "b",
      {
        a: 1
      },
      {
        a: "a"
      },
      [
        {
          a: 1
        }
      ],
      [
        {
          a: true
        }
      ],
      {
        a: 1,
        b: 2
      },
      [1, 2],
      [1, 2, 3],
      {
        a: "1"
      },
      {
        a: "1",
        b: "2"
      }
    ];
    d2 = [
      NaN,
      void 0,
      null,
      true,
      false,
      Infinity,
      0,
      1,
      "a",
      "b",
      {
        a: 1
      },
      {
        a: "a"
      },
      [
        {
          a: 1
        }
      ],
      [
        {
          a: true
        }
      ],
      {
        a: 1,
        b: 2
      },
      [1, 2],
      [1, 2, 3],
      {
        a: "1"
      },
      {
        a: "1",
        b: "2"
      }
    ];
    errors = [];
    count = 0;
    for (idx1 = _i = 0, _len = d1.length; _i < _len; idx1 = ++_i) {
      v1 = d1[idx1];
      for (idx2 = _j = idx1, _ref = d2.length; idx1 <= _ref ? _j < _ref : _j > _ref; idx2 = idx1 <= _ref ? ++_j : --_j) {
        count += 1;
        v2 = d2[idx2];
        if (idx1 === idx2) {
          if (!eq(v1, v2)) {
            //errors.push("eq " + (rpr(v1)) + ", " + (rpr(v2)));
          }
        } else {
          if (!ne(v1, v2)) {
            //errors.push("ne " + (rpr(v1)) + ", " + (rpr(v2)));
          }
        }
      }
    }
    return [count, errors];
  });
  it("node buffer", function() {
    eq(new Buffer("abc"), new Buffer("abc"));
    ne(new Buffer("abc"), new Buffer("abc1"));
    ne(new Buffer("abd"), new Buffer("abc"));
  });
  it("RegExp with props", function() {
    var re1 = /a/;
    re1.lastIndex = 3;
    ne(re1, /a/);
  });
  it("Date with props", function() {
    var now = Date.now();
  
    var d1 = new Date(now);
    var d2 = new Date(now);
  
    d1.a = 10;
  
    ne(d1, d2);
  });
  it("Check object prototypes", function() {
    var nbRoot = {
      toString: function() {
        return this.first + " " + this.last;
      }
    };
  
    function nameBuilder(first, last) {
      this.first = first;
      this.last = last;
      return this;
    }
    nameBuilder.prototype = nbRoot;
  
    function nameBuilder2(first, last) {
      this.first = first;
      this.last = last;
      return this;
    }
    nameBuilder2.prototype = nbRoot;
  
    var nb1 = new nameBuilder("Ryan", "Dahl");
    var nb2 = new nameBuilder2("Ryan", "Dahl");
  
    eq(nb1, nb2);
  
    nameBuilder2.prototype = Object;
    nb2 = new nameBuilder2("Ryan", "Dahl");
  
    ne(nb1, nb2);
  });
  
  if (typeof Uint8Array !== "undefined") {
    it("typed arrays and array buffer", function() {
      var arr1 = new Uint8Array([21, 31]);
      var arr2 = new Uint8Array([21, 31]);
  
      eq(arr1, arr2);
  
      eq(arr1.buffer, arr2.buffer);
    });
  }
  
  if (typeof Set !== "undefined") {
    it("es6 sets", function() {
      var s1 = new Set([1, 2, 3]);
      var s2 = new Set([1, 2, 3]);
      var s3 = new Set(["a", "b", "c"]);
      var s4 = new Set([]);
  
      eq(s1, s2);
      ne(s1, s3);
      ne(s1, s4);
  
      var k1 = { a: 1 };
  
      var s5 = new Set([k1, k1, k1]);
      var s6 = new Set([k1, k1, k1]);
  
      ne(s1, s5);
      eq(s5, s6);
      eq(s6, s5);
    });
  }
  
  if (typeof Map !== "undefined") {
    it("es6 maps", function() {
      var m1 = new Map([[1, 1], [2, 2], [3, 3]]);
      var m2 = new Map([[1, 1], [2, 2], [3, 3]]);
      var m3 = new Map([[1, 2], [2, 3], [3, 4]]);
  
      eq(m1, m1);
      eq(m1, m2);
      ne(m3, m2);
  
      var key_a10 = { a: 10 };
      var key_a11 = { a: 11 };
      var key_a12 = { a: 12 };
      var key_a13 = { a: 13 };
      var m4 = new Map([[key_a10, 2], [key_a11, 2], [key_a12, 2]]);
      var m5 = new Map([[key_a11, 2], [key_a12, 2], [key_a13, 2]]);
      var m6 = new Map([[key_a11, 2], [key_a12, 2], [key_a13, 2]]);
  
      ne(m4, m5);
      eq(m5, m6);
  
      var m7 = new Map([[{}, 1], [{}, 2]]);
      var m8 = new Map([[{}, 2], [{}, 3]]);
      var m9 = new Map([[{}, 2], [{}, 3]]);
  
      ne(m7, m8);
      ne(m9, m8);
    });
  }
  if (typeof WeakSet !== "undefined") {
    it("es WeakMap, WeakSet", function() {
      var a = new WeakSet();
      var b = new WeakSet();
      eq(a, b);
    });
  }
  
  it("should treat -0 and +0 as not equal when param not passed", function() {
    eq(-0, +0);
  
    ne(-0, +0, { plusZeroAndMinusZeroEqual: false });
  });
  
  if (typeof Symbol !== "undefined") {
    it("should work with Symbols", function() {
      ne([Symbol()], [Symbol()]);
      eq([Symbol.for("a")], [Symbol.for("a")]);
      ne(Symbol(), Symbol());
      ne(Symbol("abc"), Symbol("abc"));
      eq(Symbol.for("a"), Symbol.for("a"));
      ne(Symbol.for("a"), Symbol.for("b"));
    });
  }
  
  if (typeof Buffer !== "undefined") {
    it("should support node Buffer", function() {
      var b1 = new Buffer("abc", "utf8");
      var b2 = new Buffer("abc", "utf8");
      var b3 = new Buffer("acc", "utf8");
  
      eq(b1, b2);
      ne(b1, b3);
    });
  }
  it("should not assume object with only the same properties are equal", function() {
    var F = function(a, b) {
      this.a = a;
      this.b = b;
    };
  
    var f = new F(19, 11);
    var f1 = { a: 19, b: 11 };
    ne(f, f1);
    eq(f, f1, { checkProtoEql: false });
  });
  