feat: implement lseq for golang
This commit is contained in:
parent
3eef15ba0b
commit
8104c24016
7 changed files with 575 additions and 0 deletions
124
conformance-tests/runners/golang/main_test.go
Normal file
124
conformance-tests/runners/golang/main_test.go
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"peoplesgrocers.com/code/oss/lseq/golang"
|
||||
)
|
||||
|
||||
type Operation struct {
|
||||
Before *int `json:"before,omitempty"`
|
||||
After *int `json:"after,omitempty"`
|
||||
Expected string `json:"expected"`
|
||||
}
|
||||
|
||||
type Scenario struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Seed int `json:"seed"`
|
||||
Init []string `json:"init"`
|
||||
RNG []float64 `json:"rng"`
|
||||
Operations []Operation `json:"operations"`
|
||||
}
|
||||
|
||||
func createMockRandom(values []float64) func() float64 {
|
||||
index := 0
|
||||
return func() float64 {
|
||||
if index >= len(values) {
|
||||
panic("ran out of random values")
|
||||
}
|
||||
v := values[index]
|
||||
index++
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func TestConformance(t *testing.T) {
|
||||
testDataDir := "../../genfiles"
|
||||
entries, err := os.ReadDir(testDataDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read test data directory: %v", err)
|
||||
}
|
||||
|
||||
var files []string
|
||||
for _, entry := range entries {
|
||||
if strings.HasSuffix(entry.Name(), ".scenario.json") {
|
||||
files = append(files, entry.Name())
|
||||
}
|
||||
}
|
||||
sort.Strings(files)
|
||||
|
||||
for _, file := range files {
|
||||
filePath := filepath.Join(testDataDir, file)
|
||||
data, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read %s: %v", file, err)
|
||||
}
|
||||
|
||||
var scenario Scenario
|
||||
if err := json.Unmarshal(data, &scenario); err != nil {
|
||||
t.Fatalf("Failed to parse %s: %v", file, err)
|
||||
}
|
||||
|
||||
t.Run(scenario.Name, func(t *testing.T) {
|
||||
mockRandom := createMockRandom(scenario.RNG)
|
||||
l := lseq.NewLSEQ(mockRandom)
|
||||
state := make([]string, len(scenario.Init))
|
||||
copy(state, scenario.Init)
|
||||
|
||||
for i, op := range scenario.Operations {
|
||||
var beforeKey, afterKey *string
|
||||
var insertIdx int
|
||||
|
||||
if op.Before != nil {
|
||||
// Insert before index X
|
||||
idx := *op.Before
|
||||
if idx < 0 {
|
||||
idx = len(state) + idx
|
||||
}
|
||||
if idx > 0 {
|
||||
beforeKey = &state[idx-1]
|
||||
}
|
||||
if idx < len(state) {
|
||||
afterKey = &state[idx]
|
||||
}
|
||||
insertIdx = idx
|
||||
} else if op.After != nil {
|
||||
// Insert after index X
|
||||
idx := *op.After
|
||||
if idx < 0 {
|
||||
idx = len(state) + idx
|
||||
}
|
||||
if idx >= 0 && idx < len(state) {
|
||||
beforeKey = &state[idx]
|
||||
}
|
||||
if idx+1 < len(state) {
|
||||
afterKey = &state[idx+1]
|
||||
}
|
||||
insertIdx = idx + 1
|
||||
} else {
|
||||
// Neither specified - insert at end
|
||||
if len(state) > 0 {
|
||||
beforeKey = &state[len(state)-1]
|
||||
}
|
||||
insertIdx = len(state)
|
||||
}
|
||||
|
||||
result := l.Alloc(beforeKey, afterKey)
|
||||
|
||||
if result != op.Expected {
|
||||
t.Errorf("op %d: alloc(%v, %v) = %q, want %q",
|
||||
i, beforeKey, afterKey, result, op.Expected)
|
||||
}
|
||||
|
||||
// Insert result into state
|
||||
state = append(state[:insertIdx], append([]string{result}, state[insertIdx:]...)...)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue