Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions internal/generator/e2e_combinations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ func TestE2E_Combinations(t *testing.T) {
{"operations.go", "params.Either", "a union-typed parameter"},
{"errors.go", "func (e *ProblemResponse) Error() string", "a typed error wrapper"},
{"errors.go", "e.Detail.Detail", "a message field found by its conventional name"},
{"errors.go", "func parseFailureResponse", "a second error shape in one package"},
{"errors.go", "func parseListAlertsResponse422Error", "an error body with no name of its own"},
{"types.go", "Name string `json:\"name\"`", "a property two allOf entries declare, required by one"},
} {
if !containsCollapsed(byName[want.file], want.decl) {
Expand All @@ -99,3 +101,52 @@ func TestE2E_Combinations(t *testing.T) {
func containsCollapsed(haystack, needle string) bool {
return strings.Contains(strings.Join(strings.Fields(haystack), " "), strings.Join(strings.Fields(needle), " "))
}

// TestGenerationIsDeterministic generates one spec twice and compares the bytes.
// Generated clients are committed and reviewed, so output that shifts between
// runs shows up as churn in a diff nobody made, and the usual cause is a map
// iterated somewhere on the way out.
func TestGenerationIsDeterministic(t *testing.T) {
specPath := filepath.Join(projectRoot(), "testdata", "combinations.yaml")

generate := func() map[string]string {
t.Helper()
result, err := parser.Parse(specPath, parser.Config{})
if err != nil {
t.Fatalf("Parse: %v", err)
}
pkg, err := analyzer.New(result.Model).Analyze("combinations")
if err != nil {
t.Fatalf("Analyze: %v", err)
}
gen, err := New(pkg)
if err != nil {
t.Fatalf("New: %v", err)
}
files, err := gen.Generate()
if err != nil {
t.Fatalf("Generate: %v", err)
}
out := make(map[string]string, len(files))
for _, f := range files {
out[f.Name] = string(f.Content)
}
return out
}

first, second := generate(), generate()

if len(first) != len(second) {
t.Fatalf("file counts differ: %d and %d", len(first), len(second))
}
for name, content := range first {
other, ok := second[name]
if !ok {
t.Errorf("%s was generated once and not the other time", name)
continue
}
if content != other {
t.Errorf("%s differs between two runs of the same spec", name)
}
}
}
14 changes: 14 additions & 0 deletions testdata/combinations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ paths:
content:
application/json:
schema: { type: array, items: { $ref: "#/components/schemas/Alert" } }
"422":
description: An error body with no name of its own.
content:
application/json:
schema: { type: array, items: { type: string } }
default:
description: A second named error shape, so the package holds more than one.
content:
application/json: { schema: { $ref: "#/components/schemas/Failure" } }
/reports:
get:
operationId: listReports
Expand Down Expand Up @@ -213,6 +222,11 @@ components:
"^x-": { type: string }
refined: { $ref: "#/components/schemas/Refined" }
required: [id]
Failure:
type: object
properties:
code: { type: integer }
message: { type: string }
Problem:
type: object
properties:
Expand Down