202 lines
4.8 KiB
Go
202 lines
4.8 KiB
Go
package goja
|
||
|
||
import (
|
||
"hash/maphash"
|
||
"math"
|
||
"math/big"
|
||
"strconv"
|
||
"testing"
|
||
)
|
||
|
||
func testMapHashVal(v1, v2 Value, expected bool, t *testing.T) {
|
||
var h maphash.Hash
|
||
actual := v1.hash(&h) == v2.hash(&h)
|
||
if actual != expected {
|
||
t.Fatalf("testMapHashVal failed for %v, %v", v1, v2)
|
||
}
|
||
}
|
||
|
||
func TestMapHash(t *testing.T) {
|
||
testMapHashVal(_NaN, _NaN, true, t)
|
||
testMapHashVal(valueTrue, valueFalse, false, t)
|
||
testMapHashVal(valueTrue, valueTrue, true, t)
|
||
testMapHashVal(intToValue(0), _negativeZero, true, t)
|
||
testMapHashVal(asciiString("Test"), asciiString("Test"), true, t)
|
||
testMapHashVal(newStringValue("Тест"), newStringValue("Тест"), true, t)
|
||
testMapHashVal(floatToValue(1.2345), floatToValue(1.2345), true, t)
|
||
testMapHashVal(SymIterator, SymToStringTag, false, t)
|
||
testMapHashVal(SymIterator, SymIterator, true, t)
|
||
testMapHashVal((*valueBigInt)(big.NewInt(1)), (*valueBigInt)(big.NewInt(-1)), false, t)
|
||
testMapHashVal((*valueBigInt)(big.NewInt(1)), (*valueBigInt)(big.NewInt(1)), true, t)
|
||
|
||
// The following tests introduce indeterministic behaviour
|
||
//testMapHashVal(asciiString("Test"), asciiString("Test1"), false, t)
|
||
//testMapHashVal(newStringValue("Тест"), asciiString("Test"), false, t)
|
||
//testMapHashVal(newStringValue("Тест"), newStringValue("Тест1"), false, t)
|
||
}
|
||
|
||
func TestOrderedMap(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
for i := int64(0); i < 50; i++ {
|
||
m.set(intToValue(i), asciiString(strconv.FormatInt(i, 10)))
|
||
}
|
||
if m.size != 50 {
|
||
t.Fatalf("Unexpected size: %d", m.size)
|
||
}
|
||
|
||
for i := int64(0); i < 50; i++ {
|
||
expected := asciiString(strconv.FormatInt(i, 10))
|
||
actual := m.get(intToValue(i))
|
||
if !expected.SameAs(actual) {
|
||
t.Fatalf("Wrong value for %d", i)
|
||
}
|
||
}
|
||
|
||
for i := int64(0); i < 50; i += 2 {
|
||
if !m.remove(intToValue(i)) {
|
||
t.Fatalf("remove(%d) return false", i)
|
||
}
|
||
}
|
||
if m.size != 25 {
|
||
t.Fatalf("Unexpected size: %d", m.size)
|
||
}
|
||
|
||
iter := m.newIter()
|
||
count := 0
|
||
for {
|
||
entry := iter.next()
|
||
if entry == nil {
|
||
break
|
||
}
|
||
m.remove(entry.key)
|
||
count++
|
||
}
|
||
|
||
if count != 25 {
|
||
t.Fatalf("Unexpected iter count: %d", count)
|
||
}
|
||
|
||
if m.size != 0 {
|
||
t.Fatalf("Unexpected size: %d", m.size)
|
||
}
|
||
}
|
||
|
||
func TestOrderedMapCollision(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
n1 := uint64(123456789)
|
||
n2 := math.Float64frombits(n1)
|
||
n1Key := intToValue(int64(n1))
|
||
n2Key := floatToValue(n2)
|
||
m.set(n1Key, asciiString("n1"))
|
||
m.set(n2Key, asciiString("n2"))
|
||
if m.size == len(m.hashTable) {
|
||
t.Fatal("Expected a collision but there wasn't one")
|
||
}
|
||
if n2Val := m.get(n2Key); !asciiString("n2").SameAs(n2Val) {
|
||
t.Fatalf("unexpected n2Val: %v", n2Val)
|
||
}
|
||
if n1Val := m.get(n1Key); !asciiString("n1").SameAs(n1Val) {
|
||
t.Fatalf("unexpected nVal: %v", n1Val)
|
||
}
|
||
|
||
if !m.remove(n1Key) {
|
||
t.Fatal("removing n1Key returned false")
|
||
}
|
||
if n2Val := m.get(n2Key); !asciiString("n2").SameAs(n2Val) {
|
||
t.Fatalf("2: unexpected n2Val: %v", n2Val)
|
||
}
|
||
}
|
||
|
||
func TestOrderedMapIter(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
iter := m.newIter()
|
||
ent := iter.next()
|
||
if ent != nil {
|
||
t.Fatal("entry should be nil")
|
||
}
|
||
iter1 := m.newIter()
|
||
m.set(intToValue(1), valueTrue)
|
||
ent = iter.next()
|
||
if ent != nil {
|
||
t.Fatal("2: entry should be nil")
|
||
}
|
||
ent = iter1.next()
|
||
if ent == nil {
|
||
t.Fatal("entry is nil")
|
||
}
|
||
if !intToValue(1).SameAs(ent.key) {
|
||
t.Fatal("unexpected key")
|
||
}
|
||
if !valueTrue.SameAs(ent.value) {
|
||
t.Fatal("unexpected value")
|
||
}
|
||
}
|
||
|
||
func TestOrderedMapIterVisitAfterReAdd(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
one := intToValue(1)
|
||
two := intToValue(2)
|
||
|
||
m.set(one, valueTrue)
|
||
m.set(two, valueTrue)
|
||
iter := m.newIter()
|
||
entry := iter.next()
|
||
if !one.SameAs(entry.key) {
|
||
t.Fatalf("1: unexpected key: %v", entry.key)
|
||
}
|
||
if !m.remove(one) {
|
||
t.Fatal("remove returned false")
|
||
}
|
||
entry = iter.next()
|
||
if !two.SameAs(entry.key) {
|
||
t.Fatalf("2: unexpected key: %v", entry.key)
|
||
}
|
||
m.set(one, valueTrue)
|
||
entry = iter.next()
|
||
if entry == nil {
|
||
t.Fatal("entry is nil")
|
||
}
|
||
if !one.SameAs(entry.key) {
|
||
t.Fatalf("3: unexpected key: %v", entry.key)
|
||
}
|
||
}
|
||
|
||
func TestOrderedMapIterAddAfterClear(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
one := intToValue(1)
|
||
m.set(one, valueTrue)
|
||
iter := m.newIter()
|
||
iter.next()
|
||
m.clear()
|
||
m.set(one, valueTrue)
|
||
entry := iter.next()
|
||
if entry == nil {
|
||
t.Fatal("entry is nil")
|
||
}
|
||
if entry.key != one {
|
||
t.Fatalf("unexpected key: %v", entry.key)
|
||
}
|
||
entry = iter.next()
|
||
if entry != nil {
|
||
t.Fatalf("entry is not nil: %v", entry)
|
||
}
|
||
}
|
||
|
||
func TestOrderedMapIterDeleteCurrent(t *testing.T) {
|
||
m := newOrderedMap(&maphash.Hash{})
|
||
one := intToValue(1)
|
||
two := intToValue(2)
|
||
iter := m.newIter()
|
||
m.set(one, valueTrue)
|
||
m.set(two, valueTrue)
|
||
entry := iter.next()
|
||
if entry.key != one {
|
||
t.Fatalf("unexpected key: %v", entry.key)
|
||
}
|
||
m.remove(one)
|
||
entry = iter.next()
|
||
if entry.key != two {
|
||
t.Fatalf("2: unexpected key: %v", entry.key)
|
||
}
|
||
}
|