Files
mesh-catalog/modules/mesh-build-go/buildstep/seatgen/clients_test.go
T

165 lines
7.0 KiB
Go

package seatgen
import (
"os"
"path/filepath"
"strings"
"testing"
)
// ADR 0627 §3's catalog check of a client, ADR 0625 §5's rule for what is hand-written, and module.json's Go package
// artifacts against the tree (ADR 0625 §1, §3): each row writes one tree and names what the checks must say of it.
func TestAClientUsesOnlyItsSeatAndTheRuntime(t *testing.T) {
m, err := Load("testdata/contracts", "example.org/contracts/go", "@example/contracts")
if err != nil {
t.Fatal(err)
}
m.DomainSDK = "example.org/domain/sdk"
files, err := Generate(m)
if err != nil {
t.Fatal(err)
}
const good = `package aregistryclient
import (
"context"
"example.org/contracts/go/seats/aregistry"
"git.novox.be/novox/mesh-sdk/go/keys"
)
func Publish(ctx context.Context) string { _ = keys.EscapeName; return "seat:" + aregistry.Seat + ".publish" }
`
const ts = `,{"name":"ts-aregistry","kind":"package","language":"typescript","paths":["ts/seats/aregistry"]},
{"name":"ts-bregistry","kind":"package","language":"typescript","paths":["ts/seats/bregistry"]}`
artifacts := func(extra string) string {
return `{"build":{"artifacts":[{"name":"go-aregistry","kind":"package","language":"go","paths":["go/seats/aregistry"]},
{"name":"go-bregistry","kind":"package","language":"go","paths":["go/seats/bregistry"]}` + ts + extra + `]}}`
}
clientArtifact := `,{"name":"go-aregistryclient","kind":"package","language":"go","paths":["go/clients/aregistryclient"]}`
for _, c := range []struct {
name string
tree map[string]string
module string
want []string
}{
{"no client: the seats alone", nil, artifacts(""), nil},
{"a client of its own seat over the runtime", map[string]string{
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go/clients/aregistryclient\n",
"go/clients/aregistryclient/client.go": good,
}, artifacts(clientArtifact), nil},
{"a client with no artifact, and an artifact of no module", map[string]string{
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go/clients/aregistryclient\n",
"go/clients/aregistryclient/client.go": good,
}, artifacts(`,{"name":"go-extra","kind":"package","language":"go","paths":["go/extra"]}`),
[]string{"module.json: no Go package artifact go-aregistryclient", "module.json: the Go package artifact go-extra is no seat's"}},
{"a seat's npm package with no artifact, one at another path, and one of no package", nil,
`{"build":{"artifacts":[{"name":"go-aregistry","kind":"package","language":"go","paths":["go/seats/aregistry"]},
{"name":"go-bregistry","kind":"package","language":"go","paths":["go/seats/bregistry"]},
{"name":"ts-aregistry","kind":"package","language":"typescript","paths":["ts"]},
{"name":"ts-onestore","kind":"package","language":"typescript","paths":["ts/seats/onestore"]}]}}`,
[]string{"module.json: no npm package artifact ts-bregistry", "module.json: the artifact ts-aregistry's paths are [ts], not [ts/seats/aregistry]",
"module.json: the npm package artifact ts-onestore is no seat's"}},
{"a client using its own sub-package, which is no other seat's client", map[string]string{
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go/clients/aregistryclient\n",
"go/clients/aregistryclient/client.go": `package aregistryclient
import "example.org/contracts/go/clients/aregistryclient/provider"
var _ = provider.X
`,
}, artifacts(clientArtifact), nil},
{"a client importing its domain's SDK, which another module's is not", map[string]string{
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go/clients/aregistryclient\n",
"go/clients/aregistryclient/client.go": `package aregistryclient
import (
"example.org/domain/sdk/reference"
"example.org/other/sdk/reference"
)
`,
}, artifacts(clientArtifact), []string{`client.go: imports example.org/other/sdk/reference: a client uses only`}},
{"a client of no seat defined whole, and one not a module of its own", map[string]string{
"go/clients/onestoreclient/x.go": "package onestoreclient\n",
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go\n",
}, artifacts(clientArtifact + `,{"name":"go-onestoreclient","kind":"package","language":"go","paths":["go/clients/onestoreclient"]}`),
[]string{"go/clients/aregistryclient/go.mod: not", "go/clients/onestoreclient: the client of no seat defined whole"}},
{"a client using another seat, its client, a module's subject and tool", map[string]string{
"go/clients/aregistryclient/go.mod": "module example.org/contracts/go/clients/aregistryclient\n",
"go/clients/aregistryclient/client.go": `package aregistryclient
import (
"example.org/contracts/go/seats/bregistry"
"example.org/contracts/go/clients/bregistryclient"
"github.com/some/thing"
)
var a, b, c, d, e = bregistry.Seat, bregistryclient.X, thing.Y, "mesh.mod.holder.event.x", "seat:b-registry.publish"
var f = "records.records_search"
`,
}, artifacts(clientArtifact), []string{
`client.go: imports example.org/contracts/go/clients/bregistryclient, another seat's client`,
`client.go: imports example.org/contracts/go/seats/bregistry, not its own seat's contract`,
`client.go: imports github.com/some/thing: a client uses only`,
`client.go: names a module's subject "mesh.mod.holder.event.x"`,
`client.go: names a module's tool "records.records_search"`,
`client.go: names another seat "seat:b-registry.publish"`,
}},
} {
dir := t.TempDir()
write := func(p, s string) {
full := filepath.Join(dir, p)
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(full, []byte(s), 0o644); err != nil {
t.Fatal(err)
}
}
for p, b := range files {
write(p, string(b))
}
for p, s := range c.tree {
write(p, s)
}
write("module.json", c.module)
var got []string
cmp, err := Compare(dir, files)
if err != nil {
t.Fatal(err)
}
got = append(got, cmp...)
for _, check := range []func(string, *Module) ([]string, error){CheckClients, CheckArtifacts} {
more, err := check(dir, m)
if err != nil {
t.Fatalf("%s: %v", c.name, err)
}
got = append(got, more...)
}
if len(got) != len(c.want) {
t.Errorf("%s: said %d problems, want %d:\n%s", c.name, len(got), len(c.want), strings.Join(got, "\n"))
continue
}
for _, w := range c.want {
found := false
for _, g := range got {
found = found || strings.Contains(g, w)
}
if !found {
t.Errorf("%s: no problem says %q:\n%s", c.name, w, strings.Join(got, "\n"))
}
}
}
// A hand-written file outside a client is still out of step (ADR 0625 §5).
dir := t.TempDir()
for p, b := range files {
full := filepath.Join(dir, p)
_ = os.MkdirAll(filepath.Dir(full), 0o755)
_ = os.WriteFile(full, b, 0o644)
}
_ = os.WriteFile(filepath.Join(dir, "go/seats/aregistry/helper.go"), []byte("package aregistry\n"), 0o644)
if out, _ := Compare(dir, files); len(out) != 1 || !strings.Contains(out[0], "helper.go: not written by the generator") {
t.Errorf("a hand-written file beside a contract: %v", out)
}
}