173 lines
3.6 KiB
Go
173 lines
3.6 KiB
Go
package pfile
|
|
|
|
import (
|
|
"errors"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func (al allocList) Assert(t *testing.T, state map[[2]uint64][]uint64) {
|
|
t.Helper()
|
|
|
|
if len(al) != len(state) {
|
|
t.Fatalf("Expected %d items, but found %d.", len(state), len(al))
|
|
}
|
|
|
|
for key, expected := range state {
|
|
val, ok := al[key]
|
|
if !ok {
|
|
t.Fatalf("Expected to find key %v.", key)
|
|
}
|
|
if !reflect.DeepEqual(val, expected) {
|
|
t.Fatalf("For %v, expected %v but got %v.", key, expected, val)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (al *allocList) With(collectionID, itemID uint64, pages ...uint64) *allocList {
|
|
al.Store(collectionID, itemID, pages)
|
|
return al
|
|
}
|
|
|
|
func (al *allocList) Equals(rhs *allocList) bool {
|
|
|
|
if len(*rhs) != len(*al) {
|
|
return false
|
|
}
|
|
|
|
for key, val := range *rhs {
|
|
actual := (*al)[key]
|
|
if !reflect.DeepEqual(val, actual) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestAllocList(t *testing.T) {
|
|
const (
|
|
CREATE = "CREATE"
|
|
PUSH = "PUSH"
|
|
STORE = "STORE"
|
|
REMOVE = "REMOVE"
|
|
)
|
|
|
|
type TestCase struct {
|
|
Name string
|
|
Action string
|
|
Key [2]uint64
|
|
Page uint64
|
|
Pages []uint64 // For STORE command.
|
|
Expected *allocList
|
|
ExpectedLen int
|
|
}
|
|
|
|
testCases := []TestCase{{
|
|
Name: "Create something",
|
|
Action: CREATE,
|
|
Key: [2]uint64{1, 1},
|
|
Page: 1,
|
|
Expected: newAllocList().With(1, 1, 1),
|
|
ExpectedLen: 1,
|
|
}, {
|
|
Name: "Push onto something",
|
|
Action: PUSH,
|
|
Key: [2]uint64{1, 1},
|
|
Page: 2,
|
|
Expected: newAllocList().With(1, 1, 1, 2),
|
|
ExpectedLen: 1,
|
|
}, {
|
|
Name: "Push onto something again",
|
|
Action: PUSH,
|
|
Key: [2]uint64{1, 1},
|
|
Page: 3,
|
|
Expected: newAllocList().With(1, 1, 1, 2, 3),
|
|
ExpectedLen: 1,
|
|
}, {
|
|
Name: "Store something",
|
|
Action: STORE,
|
|
Key: [2]uint64{2, 2},
|
|
Pages: []uint64{4, 5, 6},
|
|
Expected: newAllocList().With(1, 1, 1, 2, 3).With(2, 2, 4, 5, 6),
|
|
ExpectedLen: 2,
|
|
}, {
|
|
Name: "Remove something",
|
|
Action: REMOVE,
|
|
Key: [2]uint64{1, 1},
|
|
Expected: newAllocList().With(2, 2, 4, 5, 6),
|
|
ExpectedLen: 1,
|
|
}}
|
|
|
|
al := newAllocList()
|
|
|
|
for _, tc := range testCases {
|
|
switch tc.Action {
|
|
case CREATE:
|
|
al.Create(tc.Key[0], tc.Key[1], tc.Page)
|
|
|
|
case PUSH:
|
|
al.Push(tc.Key[0], tc.Key[1], tc.Page)
|
|
|
|
case STORE:
|
|
al.Store(tc.Key[0], tc.Key[1], tc.Pages)
|
|
|
|
case REMOVE:
|
|
al.Remove(tc.Key[0], tc.Key[1])
|
|
|
|
default:
|
|
t.Fatalf("Unknown action: %s", tc.Action)
|
|
}
|
|
|
|
if !al.Equals(tc.Expected) {
|
|
t.Fatal(tc.Name, al, tc.Expected)
|
|
}
|
|
|
|
if al.Len() != tc.ExpectedLen {
|
|
t.Fatal(tc.Name, al.Len(), tc.ExpectedLen)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAllocListIterate_eachError(t *testing.T) {
|
|
al := newAllocList().With(1, 1, 2, 3, 4, 5)
|
|
myErr := errors.New("xxx")
|
|
err := al.Iterate(func(collectionID, itemID uint64, pageIDs []uint64) error {
|
|
return myErr
|
|
})
|
|
if err != myErr {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAllocListIterate(t *testing.T) {
|
|
al := newAllocList().With(1, 1, 2, 3, 4, 5).With(2, 2, 6, 7)
|
|
expected := map[uint64][]uint64{
|
|
1: {2, 3, 4, 5},
|
|
2: {6, 7},
|
|
}
|
|
|
|
err := al.Iterate(func(collectionID, itemID uint64, pageIDs []uint64) error {
|
|
e, ok := expected[collectionID]
|
|
if !ok {
|
|
t.Fatalf("Not found: %d", collectionID)
|
|
}
|
|
if !reflect.DeepEqual(e, pageIDs) {
|
|
t.Fatalf("%v != %v", pageIDs, e)
|
|
}
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAllocListPushNoHead(t *testing.T) {
|
|
al := newAllocList().With(1, 1, 2, 3, 4, 5).With(2, 2, 6, 7)
|
|
if !al.Push(1, 1, 8) {
|
|
t.Fatal("Failed to push onto head page")
|
|
}
|
|
if al.Push(1, 2, 9) {
|
|
t.Fatal("Pushed with no head.")
|
|
}
|
|
}
|