Skip to content

Commit 204e70b

Browse files
committed
tests: sdl parity
1 parent 01f2e37 commit 204e70b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+4180
-17
lines changed

.github/workflows/tests.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,23 @@ jobs:
5454
with:
5555
files: ./ts/coverage
5656
token: ${{ secrets.CODECOV_TOKEN }}
57+
sdl-parity:
58+
runs-on: ubuntu-latest
59+
steps:
60+
- uses: actions/checkout@v4
61+
- run: git fetch --prune --unshallow
62+
- name: Setup env
63+
uses: HatsuneMiku3939/direnv-action@v1
64+
- run: |
65+
toolchain=$(./script/tools.sh gotoolchain | sed 's/go*//')
66+
echo "GOVERSION=${toolchain}" >> $GITHUB_ENV
67+
- name: Setup Node.js
68+
uses: actions/setup-node@v4
69+
with:
70+
node-version: 22.14.0
71+
cache: npm
72+
cache-dependency-path: ts/package-lock.json
73+
- uses: actions/setup-go@v5
74+
with:
75+
go-version: "${{ env.GOVERSION }}"
76+
- run: make test-sdl-parity

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ coverage.txt
2424
dev.env
2525

2626
.editorconfig
27+
28+
# test/build artifacts
29+
output
30+
31+
# coverage output files
32+
coverage-go-cli.txt
33+
coverage-go-sdl.txt
34+
coverage-go.txt
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
9+
"pkg.akt.dev/go/sdl"
10+
)
11+
12+
func main() {
13+
fixturesRoot := "../../../testdata/sdl"
14+
versions := []string{"v2.0", "v2.1"}
15+
16+
for _, version := range versions {
17+
versionDir := filepath.Join(fixturesRoot, version)
18+
19+
if _, err := os.Stat(versionDir); os.IsNotExist(err) {
20+
continue
21+
}
22+
23+
entries, err := os.ReadDir(versionDir)
24+
if err != nil {
25+
fmt.Printf("Error reading %s: %v\n", versionDir, err)
26+
continue
27+
}
28+
29+
for _, entry := range entries {
30+
if !entry.IsDir() {
31+
continue
32+
}
33+
34+
fixtureDir := filepath.Join(versionDir, entry.Name())
35+
inputPath := filepath.Join(fixtureDir, "input.yaml")
36+
37+
if _, err := os.Stat(inputPath); os.IsNotExist(err) {
38+
continue
39+
}
40+
41+
fmt.Printf("Processing %s...\n", inputPath)
42+
43+
obj, err := sdl.ReadFile(inputPath)
44+
if err != nil {
45+
fmt.Printf(" ❌ Error: %v\n", err)
46+
continue
47+
}
48+
49+
manifest, err := obj.Manifest()
50+
if err != nil {
51+
fmt.Printf(" ❌ Manifest error: %v\n", err)
52+
continue
53+
}
54+
manifestJSON, err := json.MarshalIndent(manifest, "", " ")
55+
if err != nil {
56+
fmt.Printf(" ❌ JSON marshal error: %v\n", err)
57+
continue
58+
}
59+
manifestPath := filepath.Join(fixtureDir, "manifest.json")
60+
if err := os.WriteFile(manifestPath, manifestJSON, 0644); err != nil {
61+
fmt.Printf(" ❌ Write error: %v\n", err)
62+
continue
63+
}
64+
fmt.Printf(" ✓ Generated %s\n", manifestPath)
65+
66+
groups, err := obj.DeploymentGroups()
67+
if err != nil {
68+
fmt.Printf(" ❌ Groups error: %v\n", err)
69+
continue
70+
}
71+
groupsJSON, err := json.MarshalIndent(groups, "", " ")
72+
if err != nil {
73+
fmt.Printf(" ❌ JSON marshal error: %v\n", err)
74+
continue
75+
}
76+
groupsPath := filepath.Join(fixtureDir, "groups.json")
77+
if err := os.WriteFile(groupsPath, groupsJSON, 0644); err != nil {
78+
fmt.Printf(" ❌ Write error: %v\n", err)
79+
continue
80+
}
81+
fmt.Printf(" ✓ Generated %s\n", groupsPath)
82+
}
83+
}
84+
85+
fmt.Println("\n✅ Fixture generation complete!")
86+
}
87+

go/sdl/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/blang/semver/v4 v4.0.0
1010
github.com/cosmos/cosmos-sdk v0.53.3
1111
github.com/stretchr/testify v1.10.0
12+
github.com/xeipuuv/gojsonschema v1.2.0
1213
gopkg.in/yaml.v3 v3.0.1
1314
pkg.akt.dev/go v0.1.1
1415
)
@@ -162,6 +163,8 @@ require (
162163
github.com/tidwall/btree v1.7.0 // indirect
163164
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
164165
github.com/x448/float16 v0.8.4 // indirect
166+
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
167+
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
165168
github.com/zondax/hid v0.9.2 // indirect
166169
github.com/zondax/ledger-go v0.14.3 // indirect
167170
go.etcd.io/bbolt v1.4.0 // indirect

go/sdl/go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,12 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
670670
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
671671
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
672672
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
673+
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
674+
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
675+
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
676+
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
677+
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
678+
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
673679
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
674680
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
675681
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

go/sdl/groupBuilder_v2.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,13 @@ func (sdl *v2) buildGroups() error {
102102

103103
if len(svc.Params.Storage) > 0 {
104104
params.Storage = make([]manifest.StorageParams, 0, len(svc.Params.Storage))
105-
for volName, volParams := range svc.Params.Storage {
105+
storageNames := make([]string, 0, len(svc.Params.Storage))
106+
for volName := range svc.Params.Storage {
107+
storageNames = append(storageNames, volName)
108+
}
109+
sort.Strings(storageNames)
110+
for _, volName := range storageNames {
111+
volParams := svc.Params.Storage[volName]
106112
params.Storage = append(params.Storage, manifest.StorageParams{
107113
Name: volName,
108114
Mount: volParams.Mount,

go/sdl/groupBuilder_v2_1.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,13 @@ func (sdl *v2_1) buildGroups() error {
112112

113113
if len(svc.Params.Storage) > 0 {
114114
params.Storage = make([]manifest.StorageParams, 0, len(svc.Params.Storage))
115-
for volName, volParams := range svc.Params.Storage {
115+
storageNames := make([]string, 0, len(svc.Params.Storage))
116+
for volName := range svc.Params.Storage {
117+
storageNames = append(storageNames, volName)
118+
}
119+
sort.Strings(storageNames)
120+
for _, volName := range storageNames {
121+
volParams := svc.Params.Storage[volName]
116122
params.Storage = append(params.Storage, manifest.StorageParams{
117123
Name: volName,
118124
Mount: volParams.Mount,

go/sdl/parity_test.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package sdl
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
"path/filepath"
7+
"testing"
8+
9+
"github.com/stretchr/testify/require"
10+
"github.com/xeipuuv/gojsonschema"
11+
"gopkg.in/yaml.v3"
12+
)
13+
14+
const fixturesRoot = "../../testdata/sdl"
15+
const schemasRoot = "../../specs/sdl"
16+
17+
func validateAgainstSchema(t *testing.T, name string, data []byte, schemaPath string) {
18+
t.Helper()
19+
20+
schemaBytes, err := os.ReadFile(schemaPath)
21+
if err != nil {
22+
t.Fatalf("Schema file %s not found: %v", schemaPath, err)
23+
}
24+
25+
var schemaJSON map[string]any
26+
err = yaml.Unmarshal(schemaBytes, &schemaJSON)
27+
require.NoError(t, err, "Failed to parse YAML schema")
28+
29+
jsonBytes, err := json.Marshal(schemaJSON)
30+
require.NoError(t, err, "Failed to convert schema to JSON")
31+
32+
schemaLoader := gojsonschema.NewSchemaLoader()
33+
schema, err := schemaLoader.Compile(gojsonschema.NewBytesLoader(jsonBytes))
34+
require.NoError(t, err, "Failed to compile schema")
35+
36+
result, err := schema.Validate(gojsonschema.NewBytesLoader(data))
37+
require.NoError(t, err, "Failed to validate against schema")
38+
39+
if !result.Valid() {
40+
var errors []string
41+
for _, desc := range result.Errors() {
42+
errors = append(errors, desc.String())
43+
}
44+
require.Failf(t, "%s validation failed", name, "Errors: %v", errors)
45+
}
46+
}
47+
48+
func TestParityV2_0(t *testing.T) {
49+
testParity(t, "v2.0")
50+
}
51+
52+
func TestParityV2_1(t *testing.T) {
53+
testParity(t, "v2.1")
54+
}
55+
56+
func testParity(t *testing.T, version string) {
57+
fixturesDir := filepath.Join(fixturesRoot, version)
58+
59+
entries, err := os.ReadDir(fixturesDir)
60+
if os.IsNotExist(err) {
61+
t.Fatalf("Fixtures directory %s does not exist", fixturesDir)
62+
}
63+
require.NoError(t, err)
64+
65+
for _, entry := range entries {
66+
if !entry.IsDir() {
67+
continue
68+
}
69+
70+
fixtureName := entry.Name()
71+
fixtureDir := filepath.Join(fixturesDir, fixtureName)
72+
inputPath := filepath.Join(fixtureDir, "input.yaml")
73+
manifestPath := filepath.Join(fixtureDir, "manifest.json")
74+
groupsPath := filepath.Join(fixtureDir, "groups.json")
75+
76+
if _, err := os.Stat(manifestPath); os.IsNotExist(err) {
77+
t.Fatalf("manifest.json not generated for %s (run: make generate-sdl-fixtures)", fixtureName)
78+
}
79+
80+
if _, err := os.Stat(groupsPath); os.IsNotExist(err) {
81+
t.Fatalf("groups.json not generated for %s (run: make generate-sdl-fixtures)", fixtureName)
82+
}
83+
84+
t.Run(fixtureName, func(t *testing.T) {
85+
sdl, err := ReadFile(inputPath)
86+
require.NoError(t, err)
87+
88+
expectedManifestBytes, err := os.ReadFile(manifestPath)
89+
require.NoError(t, err, "Failed to read expected manifest.json")
90+
91+
expectedGroupsBytes, err := os.ReadFile(groupsPath)
92+
require.NoError(t, err, "Failed to read expected groups.json")
93+
94+
manifest, err := sdl.Manifest()
95+
require.NoError(t, err)
96+
97+
actualManifestBytes, err := json.Marshal(manifest)
98+
require.NoError(t, err)
99+
100+
var expectedManifest, actualManifest any
101+
require.NoError(t, json.Unmarshal(expectedManifestBytes, &expectedManifest))
102+
require.NoError(t, json.Unmarshal(actualManifestBytes, &actualManifest))
103+
require.Equal(t, expectedManifest, actualManifest, "Manifest does not match expected output")
104+
105+
validateAgainstSchema(t, "manifest", actualManifestBytes, schemasRoot+"/manifest.schema.yaml")
106+
107+
groups, err := sdl.DeploymentGroups()
108+
require.NoError(t, err)
109+
110+
actualGroupsBytes, err := json.Marshal(groups)
111+
require.NoError(t, err)
112+
113+
var expectedGroups, actualGroups any
114+
require.NoError(t, json.Unmarshal(expectedGroupsBytes, &expectedGroups))
115+
require.NoError(t, json.Unmarshal(actualGroupsBytes, &actualGroups))
116+
require.Equal(t, expectedGroups, actualGroups, "Groups does not match expected output")
117+
118+
validateAgainstSchema(t, "groups", actualGroupsBytes, schemasRoot+"/groups.schema.yaml")
119+
})
120+
}
121+
}
122+
123+
func TestInvalidSDLsRejected(t *testing.T) {
124+
invalidDir := filepath.Join(fixturesRoot, "invalid")
125+
126+
entries, err := os.ReadDir(invalidDir)
127+
if os.IsNotExist(err) {
128+
t.Skip("Invalid fixtures directory does not exist yet")
129+
return
130+
}
131+
require.NoError(t, err)
132+
133+
for _, entry := range entries {
134+
if entry.IsDir() {
135+
continue
136+
}
137+
138+
fixturePath := filepath.Join(invalidDir, entry.Name())
139+
t.Run(entry.Name(), func(t *testing.T) {
140+
_, err := ReadFile(fixturePath)
141+
require.Error(t, err)
142+
})
143+
}
144+
}

make/test.mk

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,17 @@ test-coverage-go: export GO111MODULE := $(GO111MODULE)
4747
test-coverage-go: export GOWORK := $(GOWORK)
4848
test-coverage-go:
4949
@$(TOOLS) gocoverage "$(GO_MODULES)" "$(test_go_flags)" "$(GO_TEST_DIRS)"
50+
51+
.PHONY: generate-sdl-fixtures
52+
generate-sdl-fixtures: ## Generate SDL test fixtures (manifest.json and groups.json from input.yaml files)
53+
@echo "Generating SDL fixtures..."
54+
@cd go/sdl && go run ./cmd/generate-sdl-fixtures
55+
56+
.PHONY: test-sdl-parity
57+
test-sdl-parity: generate-sdl-fixtures $(AKASH_TS_NODE_MODULES) ## Run SDL parity tests for Go and TypeScript. Note: YAML schemas are manually maintained and validated by parity tests.
58+
@echo "Running Go SDL parity tests..."
59+
@cd go/sdl && go test -v -run "TestParity|TestInvalidSDLsRejected"
60+
@echo ""
61+
@echo "Running TypeScript SDL parity tests..."
62+
@echo " (includes: v2.0 fixtures, v2.1 fixtures, and invalid SDL rejection)"
63+
@cd ts && npm test -- --testPathPattern=parity.spec.ts

0 commit comments

Comments
 (0)