diff --git a/internal/system/shapes_test.go b/internal/system/shapes_test.go new file mode 100644 index 0000000..2305929 --- /dev/null +++ b/internal/system/shapes_test.go @@ -0,0 +1,31 @@ +package system + +import ( + "testing" + + "github.com/novox/mesh-host/internal/declaration" +) + +// Every shape in the vocabulary is implemented by a host that claims to do everything. +// +// **Added because adding a shape and forgetting this was silent here and loud there.** The +// `network` shape parsed, validated, applied and removed, and a full host still refused every +// declaration containing one — correctly, because it does not do half a declaration. The count +// test above passed throughout: it checks what the language has, not what a host can do. +func TestAFullHostImplementsEveryShapeTheLanguageHas(t *testing.T) { + does := map[declaration.Type]bool{} + for _, s := range All() { + if s.Name() != "arch" { + continue + } + for _, shape := range s.Shapes() { + does[shape] = true + } + } + for _, shape := range declaration.Vocabulary() { + if !does[shape] { + t.Errorf("the language has %q and a full host cannot apply it, so every declaration "+ + "carrying one is refused whole", shape) + } + } +} diff --git a/internal/system/system.go b/internal/system/system.go index 1d5daff..9508982 100644 --- a/internal/system/system.go +++ b/internal/system/system.go @@ -166,6 +166,9 @@ func everyShape() []declaration.Type { declaration.TypeDirectory, declaration.TypeFile, declaration.TypeService, declaration.TypePackage, declaration.TypeContainer, declaration.TypeAction, declaration.TypeUser, declaration.TypeArchive, + // A network needs the same runtime a container does, so a host that can run one can make + // the other. Not in portableShapes for exactly that reason. + declaration.TypeNetwork, } }