Complete package for generating ocds structs (with extensions) in golang
This commit is contained in:
1 parent
da726550d4
commit
35974fa070
47 files changed
+9861
-299
No files matched your search
@@ -0,0 +1,151 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// run executes the command tree with args and returns stdout, stderr and the error.
|
||||
func run(t *testing.T, args ...string) (string, string, error) {
|
||||
t.Helper()
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd := NewRootCmd()
|
||||
cmd.SetOut(&stdout)
|
||||
cmd.SetErr(&stderr)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
return stdout.String(), stderr.String(), err
|
||||
}
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
out := filepath.Join(t.TempDir(), "tenders", "ocds_gen.go")
|
||||
if err := os.MkdirAll(filepath.Dir(out), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, stderr, err := run(t, "generate", "-c", "testdata/widgets.json", "-o", out); err != nil {
|
||||
t.Fatalf("generate: %v\n%s", err, stderr)
|
||||
}
|
||||
raw, err := os.ReadFile(out)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// gofmt aligns struct columns, so compare with whitespace collapsed.
|
||||
src := strings.Join(strings.Fields(string(raw)), " ")
|
||||
for _, want := range []string{
|
||||
"package tenders", // derived from the output directory
|
||||
"Date time.Time", // required date-time is not a pointer
|
||||
"ID ID `json:\"id\"`", // ["string","integer"]
|
||||
"Widgets []Widget", // extension field on a core type
|
||||
"Count *int", // extension definition
|
||||
"Releases []Release", // external $ref to the release schema
|
||||
"Widgets (declared)", // header records resolution
|
||||
"Orphan (dependency)",
|
||||
} {
|
||||
if !strings.Contains(src, want) {
|
||||
t.Errorf("generated code is missing %q", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateStdoutNeedsPackage(t *testing.T) {
|
||||
_, _, err := run(t, "generate", "-c", "testdata/core.json", "-o", "-")
|
||||
if err == nil || !strings.Contains(err.Error(), "--package") {
|
||||
t.Fatalf("want --package error, got %v", err)
|
||||
}
|
||||
stdout, _, err := run(t, "generate", "-c", "testdata/core.json", "-o", "-", "-p", "core")
|
||||
if err != nil || !strings.HasPrefix(stdout, "// Code generated") {
|
||||
t.Fatalf("stdout generation failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) {
|
||||
out := filepath.Join(t.TempDir(), "ocds_gen.go")
|
||||
args := []string{"generate", "-q", "-c", "testdata/core.json", "-o", out, "-p", "core"}
|
||||
|
||||
if _, _, err := run(t, append(args, "--check")...); err == nil || !strings.Contains(err.Error(), "does not exist") {
|
||||
t.Fatalf("missing file: want error, got %v", err)
|
||||
}
|
||||
if _, _, err := run(t, args...); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, _, err := run(t, append(args, "--check")...); err != nil {
|
||||
t.Fatalf("fresh file: want no error, got %v", err)
|
||||
}
|
||||
f, _ := os.OpenFile(out, os.O_APPEND|os.O_WRONLY, 0)
|
||||
f.WriteString("// hand edit\n")
|
||||
f.Close()
|
||||
if _, _, err := run(t, append(args, "--check")...); err == nil || !strings.Contains(err.Error(), "out of date") {
|
||||
t.Fatalf("edited file: want out-of-date error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStrict(t *testing.T) {
|
||||
out := filepath.Join(t.TempDir(), "ocds_gen.go")
|
||||
args := []string{"generate", "-c", "testdata/widgets.json", "-o", out, "-p", "x"}
|
||||
|
||||
// Gadget is defined by the Orphan extension but nothing refers to it.
|
||||
_, stderr, err := run(t, args...)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(stderr, "definition Gadget is never referenced") {
|
||||
t.Errorf("want unreachable warning, got stderr:\n%s", stderr)
|
||||
}
|
||||
if _, _, err := run(t, append(args, "--strict")...); err == nil {
|
||||
t.Fatal("--strict: want error")
|
||||
}
|
||||
if _, stderr, _ := run(t, append(args, "-q")...); stderr != "" {
|
||||
t.Errorf("--quiet: want no stderr, got:\n%s", stderr)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveJSON(t *testing.T) {
|
||||
stdout, _, err := run(t, "resolve", "-c", "testdata/widgets.json", "--json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var rows []struct {
|
||||
Name string `json:"name"`
|
||||
Declared bool `json:"declared"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(stdout), &rows); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rows) != 2 || rows[0].Name != "Orphan" || rows[0].Declared || rows[1].Name != "Widgets" || !rows[1].Declared {
|
||||
t.Fatalf("want [Orphan (dependency), Widgets (declared)], got %+v", rows)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSchema(t *testing.T) {
|
||||
stdout, _, err := run(t, "schema", "-q", "-c", "testdata/widgets.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Key order is preserved, and the extension's patch is merged in.
|
||||
if !strings.Contains(stdout, `"widgets"`) || strings.Index(stdout, `"ocid"`) > strings.Index(stdout, `"tender"`) {
|
||||
t.Fatalf("unexpected merged schema:\n%s", stdout)
|
||||
}
|
||||
if _, _, err := run(t, "schema", "--kind", "record", "-c", "testdata/core.json"); err == nil {
|
||||
t.Fatal("--kind record: want error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageFromPath(t *testing.T) {
|
||||
for in, want := range map[string]string{
|
||||
"internal/tenders/ocds_gen.go": "tenders",
|
||||
"profiles/uk/ocds_gen.go": "uk",
|
||||
"pkg/eu-profile/x.go": "euprofile",
|
||||
} {
|
||||
got, err := packageFromPath(in)
|
||||
if err != nil || got != want {
|
||||
t.Errorf("packageFromPath(%q) = %q, %v; want %q", in, got, err, want)
|
||||
}
|
||||
}
|
||||
if _, err := packageFromPath("pkg/func/x.go"); err == nil {
|
||||
t.Error("keyword directory: want error")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user