- Add backtest analysis results migration (000002) - Update backtest proto definitions and generated code - Extend backtest domain types and engine - Add parser map for backtest analysis - Update storage layer with backtest analysis queries and keys - Add client contract tests and generated code - Add m-backtest-analysis-surface task documentation
107 lines
3 KiB
Go
107 lines
3 KiB
Go
package postgres
|
|
|
|
import (
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestMigrationsAreEmbeddedInOrder(t *testing.T) {
|
|
entries, err := migrationsFS.ReadDir("migrations")
|
|
if err != nil {
|
|
t.Fatalf("failed to read migrations directory: %v", err)
|
|
}
|
|
|
|
var upFiles []string
|
|
var downFiles []string
|
|
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
continue
|
|
}
|
|
name := entry.Name()
|
|
if strings.HasSuffix(name, ".up.sql") {
|
|
upFiles = append(upFiles, name)
|
|
} else if strings.HasSuffix(name, ".down.sql") {
|
|
downFiles = append(downFiles, name)
|
|
}
|
|
}
|
|
|
|
if len(upFiles) == 0 {
|
|
t.Error("expected at least one up migration file, found none")
|
|
}
|
|
if len(downFiles) == 0 {
|
|
t.Error("expected at least one down migration file, found none")
|
|
}
|
|
|
|
if len(upFiles) != len(downFiles) {
|
|
t.Errorf("mismatched migration count: %d up files, %d down files", len(upFiles), len(downFiles))
|
|
}
|
|
|
|
// Verify up and down files match and are in numerical order
|
|
for i := 0; i < len(upFiles); i++ {
|
|
up := upFiles[i]
|
|
partsUp := strings.Split(up, "_")
|
|
if len(partsUp) < 2 {
|
|
t.Errorf("invalid up migration file name: %s", up)
|
|
continue
|
|
}
|
|
versionUp, err := strconv.ParseInt(partsUp[0], 10, 64)
|
|
if err != nil {
|
|
t.Errorf("failed to parse up version from %s: %v", up, err)
|
|
}
|
|
|
|
if versionUp != int64(i+1) {
|
|
t.Errorf("expected version %d for file %s, got %d", i+1, up, versionUp)
|
|
}
|
|
|
|
// Find corresponding down file
|
|
var foundDown bool
|
|
for _, down := range downFiles {
|
|
if strings.Split(down, "_")[0] == partsUp[0] {
|
|
foundDown = true
|
|
break
|
|
}
|
|
}
|
|
if !foundDown {
|
|
t.Errorf("missing corresponding down migration for: %s", up)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMigrationStatementsAreNamed(t *testing.T) {
|
|
// Check if migrate.go FS variable is populated
|
|
entries, err := migrationsFS.ReadDir("migrations")
|
|
if err != nil {
|
|
t.Fatalf("failed to read migrations: %v", err)
|
|
}
|
|
if len(entries) == 0 {
|
|
t.Error("migrations FS has no entries")
|
|
}
|
|
}
|
|
|
|
func TestAnalysisResultColumnsAddedInVersionedMigration(t *testing.T) {
|
|
// The analysis result columns must arrive through the v2 migration so databases
|
|
// already at version 1 receive them, rather than being edited into 000001.
|
|
content, err := migrationsFS.ReadFile("migrations/000002_backtest_analysis_results.up.sql")
|
|
if err != nil {
|
|
t.Fatalf("failed to read 000002 up migration: %v", err)
|
|
}
|
|
up := string(content)
|
|
for _, column := range []string{"total_return", "trade_count", "equity_curve"} {
|
|
if !strings.Contains(up, column) {
|
|
t.Errorf("000002 up migration missing column %q", column)
|
|
}
|
|
}
|
|
|
|
// The originally applied 000001 migration must not carry the analysis columns.
|
|
backbone, err := migrationsFS.ReadFile("migrations/000001_worker_backbone.up.sql")
|
|
if err != nil {
|
|
t.Fatalf("failed to read 000001 up migration: %v", err)
|
|
}
|
|
for _, column := range []string{"total_return", "trade_count", "equity_curve"} {
|
|
if strings.Contains(string(backbone), column) {
|
|
t.Errorf("000001 up migration should not contain analysis column %q", column)
|
|
}
|
|
}
|
|
}
|