116 lines
4.0 KiB
Go
116 lines
4.0 KiB
Go
package seatgen
|
|
|
|
import (
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
re "regexp"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestAStateHasItsNamesKeyFormsAndStrictValues is ADR 0634 §6's generator check for `states`: a seat's states give a
|
|
// constant per local name, per key form a builder, a parser and a strict reader of the value, and the fixtures of
|
|
// `state:` decode into those types. The generated seat package is written out and run with `go vet` and `go test`, so
|
|
// what the generator writes is compiled, not only read.
|
|
func TestAStateHasItsNamesKeyFormsAndStrictValues(t *testing.T) {
|
|
m, err := Load("testdata/contracts", "example.org/contracts/go", "@example/contracts")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
files, err := Generate(m)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
src := string(files["go/seats/aregistry/contract.go"])
|
|
for _, want := range []string{
|
|
"func AsksByAskerIDKey(asker, id string) string", "func ParseAsksByAskerIDKey(key string) (string, string, bool)",
|
|
"func DecodeAsksByAskerIDValue(raw []byte)", "type AsksByAskerIDValue struct",
|
|
"func AsksByAskerIDDoneKey(", "func AsksByDefaultsKey() string",
|
|
"func LocalNameBySeenIDOfAskKey(idOfAsk string) string",
|
|
} {
|
|
if !strings.Contains(src, want) {
|
|
t.Errorf("the seat's package lacks %q:\n%s", want, src)
|
|
}
|
|
}
|
|
for _, c := range []string{`StateAsks\s+= "asks"`, `StateLocalName\s+= "local-name"`} {
|
|
if !re.MustCompile(c).MatchString(src) {
|
|
t.Errorf("the seat's package lacks a constant %s", c)
|
|
}
|
|
}
|
|
if strings.Contains(src, "Record") {
|
|
t.Errorf("the seat's package still names a record:\n%s", src)
|
|
}
|
|
ts := string(files["ts/seats/aregistry/src/index.ts"])
|
|
for _, want := range []string{"export const states = {", "export function asksByAskerIDKey(asker: string, id: string): string",
|
|
"export function parseAsksByAskerIDKey(key: string)", "export interface AsksByAskerIDValue"} {
|
|
if !strings.Contains(ts, want) {
|
|
t.Errorf("the seat's npm package lacks %q:\n%s", want, ts)
|
|
}
|
|
}
|
|
|
|
dir := t.TempDir()
|
|
for p, b := range files {
|
|
if !strings.HasPrefix(p, "go/seats/aregistry/") {
|
|
continue
|
|
}
|
|
dst := filepath.Join(dir, strings.TrimPrefix(p, "go/seats/aregistry/"))
|
|
if err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(dst, b, 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
extra := `package aregistry
|
|
|
|
import "testing"
|
|
|
|
func TestKeysAndValues(t *testing.T) {
|
|
if k := AsksByAskerIDKey("a", "7"); k != "a.7" {
|
|
t.Fatal(k)
|
|
}
|
|
if a, id, ok := ParseAsksByAskerIDKey("a.7"); !ok || a != "a" || id != "7" {
|
|
t.Fatal(a, id, ok)
|
|
}
|
|
for _, bad := range []string{"", "a", ".7", "a.", "a.7.done"} {
|
|
if bad == "a.7.done" {
|
|
continue // the id takes the rest: another form is told apart by its own parser
|
|
}
|
|
if _, _, ok := ParseAsksByAskerIDKey(bad); ok {
|
|
t.Errorf("%q parsed", bad)
|
|
}
|
|
}
|
|
if a, id, ok := ParseAsksByAskerIDDoneKey("a.7.done"); !ok || a != "a" || id != "7" {
|
|
t.Fatal(a, id, ok)
|
|
}
|
|
if _, _, ok := ParseAsksByAskerIDDoneKey("a.7"); ok {
|
|
t.Error("a key without its literal parsed")
|
|
}
|
|
if !ParseAsksByDefaultsKey("defaults") || ParseAsksByDefaultsKey("defaultsx") {
|
|
t.Error("a literal key")
|
|
}
|
|
if _, err := DecodeAsksByAskerIDValue([]byte(` + "`" + `{"state":"open","extra":1}` + "`" + `)); err == nil {
|
|
t.Error("a field the type does not know was taken")
|
|
}
|
|
if _, err := DecodeAsksByAskerIDValue([]byte(` + "`" + `{"state":"open"} {}` + "`" + `)); err == nil {
|
|
t.Error("text after the value was taken")
|
|
}
|
|
if v, err := DecodeAsksByAskerIDValue([]byte(` + "`" + `{"state":"open","since":3}` + "`" + `)); err != nil || v.State != "open" {
|
|
t.Error(v, err)
|
|
}
|
|
}
|
|
`
|
|
if err := os.WriteFile(filepath.Join(dir, "extra_test.go"), []byte(extra), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, args := range [][]string{{"vet", "./..."}, {"test", "./..."}} {
|
|
cmd := exec.Command("go", args...)
|
|
cmd.Dir = dir
|
|
cmd.Env = append(os.Environ(), "GOWORK=off", "GOFLAGS=-mod=mod")
|
|
if out, err := cmd.CombinedOutput(); err != nil {
|
|
t.Fatalf("go %s on the generated package: %v\n%s", strings.Join(args, " "), err, out)
|
|
}
|
|
}
|
|
}
|