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)
|
|||
|
}
|
|||
|
}
|