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:]...)...) } }) } }