#!/usr/bin/ruby

# Equality and comparison tests for arrays that contain cyclic references.

var x = [1,2,3]
var y = [1,2,3]

x[3] = x
y[3] = x

assert_eq(x == y, true)
assert_eq(y == x, true)

assert_eq(x <=> y, 0)
assert_eq(y <=> x, 0)

y[0] = 42

assert_eq(x == y, false)
assert_eq(y == x, false)
assert_eq(x <=> y, -1)
assert_eq(y <=> x, 1)

y[0] = 0

assert_eq(x == y, false)
assert_eq(y == x, false)
assert_eq(x <=> y, 1)
assert_eq(y <=> x, -1)

x[0] = 0

assert_eq(x == y, true)
assert_eq(x <=> y, 0)
assert_eq(y <=> x, 0)

x[1] = y
y[1] = y

assert_eq(x == y, true)
assert_eq(x <=> y, 0)
assert_eq(y <=> x, 0)

x[2] = x

assert_eq(x == y, false)
assert_ne(x <=> y, 0)

y[2] = x

assert_eq(x == y, true)
assert_eq(x <=> y, 0)
assert_eq(y <=> x, 0)

do {
    var x = Hash(a => 1, b => 2)
    x{:c} = x

    var z = Hash(a => 1, b => 2)
    z{:c} = z

    assert_eq(x, x)
    assert_eq(z, z)
    assert_ne(z, x)
    assert_ne(x, z)

    assert_eq(x <=> x, 0)
    assert_eq(z <=> z, 0)

    assert_ne(z <=> x, 0)
    assert_ne(x <=> z, 0)

    assert_eq(x <=> x{:c}, 0)
    assert_eq(z{:c} <=> z, 0)

    assert_ne(z{:c} <=> x, 0)
    assert_ne(x <=> z{:c}, 0)

    assert_eq(z{:c}, z)
    assert_eq(x, x{:c})

    assert_ne(x{:c}, z)

    assert_ne(x.values, z.values)
    assert_ne(x.values <=> z.values, 0)

    assert_eq(x.values, x{:c}.values)
    assert_eq(x.values <=> x{:c}.values, 0)

    assert_ne(x.values.sort <=> z.values.sort, 0)
    assert_ne(x.values.sort.flip <=> z.values.sort.flip, 0)

    assert_eq(x.values.sort <=> x{:c}.values.sort, 0)
    assert_eq(x.values.sort.flip <=> x{:c}.values.sort.flip, 0)

    assert_eq(x.values.sort <=> x.values.sort.flip, -1)
    assert_eq(x.values.sort.flip <=> x.values.sort, 1)

    assert_ne(x, Hash(a => 1, b => 2))
    assert_ne(Hash(a => 1, b => 2), x)
}

do {
    var x = [1,2,3]
    x[1] = x

    var y = [1,2,3]
    y[1] = y

    assert_eq(x, x)
    assert_ne(x, y)
    assert_ne(y, x)

    assert_eq(x <=> x, 0)
    assert_ne(y <=> x, 0)
    assert_ne(x <=> y, 0)

    assert_eq(x <=> x[1], 0)
    assert_eq(y[1] <=> y, 0)

    assert_eq(x[1], x)
    assert_eq(y, y[1])

    assert_ne(y[1], x)
    assert_ne(y, x[1])

    assert_ne(x, [1,2,3])
    assert_ne([1,2,3], y)
}

do {
    var p = Pair(1, 2)
    p.second = p

    var q = Pair(1, 2)
    q.second = q

    assert_ne(p, q)
    assert_eq(q, q)
    assert_eq(p, p)

    assert_eq(p, p.second)
    assert_eq(q.second, q)

    assert_ne(p, q.second)
    assert_ne(q.second, p)
}

say "** Test passed!"