Files
akvorado/common/helpers/intern/intern_test.go
Vincent Bernat e2f1df9add tests: replace godebug by go-cmp for structure diffs
go-cmp is stricter and allow to catch more problems. Moreover, the
output is a bit nicer.
2025-08-23 16:03:09 +02:00

176 lines
4.1 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package intern
import (
"testing"
"akvorado/common/helpers"
"github.com/google/go-cmp/cmp/cmpopts"
)
type likeInt int
func (i likeInt) Equal(j likeInt) bool { return i == j }
func (i likeInt) Hash() uint64 { return uint64(i) % 10 }
func TestPut(t *testing.T) {
p := NewPool[likeInt]()
a := p.Put(likeInt(10))
b := p.Put(likeInt(10))
c := p.Put(likeInt(11))
d := p.Put(likeInt(12))
if a != b {
t.Error("got two references for Put(10)")
}
if a == c || a == d || c == d {
t.Error("got same reference for Put(10)/Put(11)/Put(12)")
}
if p.Get(a) != likeInt(10) {
t.Errorf("Get(Put(10)) == %d != 10", p.Get(a))
}
if p.Get(c) != likeInt(11) {
t.Errorf("Get(Put(11)) == %d != 10", p.Get(c))
}
if p.Get(d) != likeInt(12) {
t.Errorf("Get(Put(12)) == %d != 10", p.Get(d))
}
}
func TestRef(t *testing.T) {
p := NewPool[likeInt]()
a := p.Put(likeInt(10))
b, bOK := p.Ref(likeInt(10))
c, cOK := p.Ref(likeInt(20))
if a != b {
t.Error("got two references for Put/Ref(10)")
}
if !bOK {
t.Error("didn't get a ref for Ref(10)")
}
if cOK {
t.Error("got a ref for Ref(20)")
}
if c != 0 {
t.Error("got a value for Ref(20)")
}
}
func TestPutCollision(t *testing.T) {
p := NewPool[likeInt]()
a := p.Put(likeInt(10))
b := p.Put(likeInt(20))
c := p.Put(likeInt(11))
d := p.Put(likeInt(21))
if a == b || a == c || a == d || b == c || b == d || c == d {
t.Error("got same reference for two different values")
}
}
func TestTake(t *testing.T) {
p := NewPool[likeInt]()
diffOpt := cmpopts.EquateComparable(internValue[likeInt]{})
val1 := likeInt(10)
ref1 := p.Put(val1)
val2 := likeInt(10)
ref2 := p.Put(val2)
val3 := likeInt(12)
ref3 := p.Put(val3)
val4 := likeInt(22) // collision
ref4 := p.Put(val4)
val5 := likeInt(32)
ref5 := p.Put(val5)
expectedValues := []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 1, next: 3},
{value: 22, refCount: 1, previous: 2, next: 4},
{value: 32, refCount: 1, previous: 3},
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
p.Take(ref4)
expectedValues = []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 1, next: 4},
{value: 22, refCount: 0, previous: 2, next: 4}, // free
{value: 32, refCount: 1, previous: 2},
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
ref6 := p.Put(likeInt(42))
if ref6 != ref4 {
t.Fatal("p.Put() did not reuse free slot")
}
expectedValues = []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 1, next: 4},
{value: 42, refCount: 1, previous: 4},
{value: 32, refCount: 1, previous: 2, next: 3},
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
p.Take(ref3)
expectedValues = []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 0, next: 4}, // free
{value: 42, refCount: 1, previous: 4},
{value: 32, refCount: 1, next: 3},
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
p.Take(ref5)
expectedValues = []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 0, next: 4}, // free
{value: 42, refCount: 1},
{value: 32, refCount: 0, next: 3}, // free
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
p.Take(ref6)
expectedValues = []internValue[likeInt]{
{},
{value: 10, refCount: 2},
{value: 12, refCount: 0, next: 4}, // free
{value: 42, refCount: 0}, // free
{value: 32, refCount: 0, next: 3}, // free
}
if diff := helpers.Diff(p.values, expectedValues, diffOpt); diff != "" {
t.Fatalf("p.values (-got, +want):\n%s", diff)
}
p.Take(ref1)
p.Take(ref2)
diff := p.Len()
if diff != 0 {
t.Fatalf("Take() didn't free everything (%d remaining)", diff)
}
}