package host import ( "context" "os" "testing" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/instancectl" ) func TestPlan14UnitDispatch(t *testing.T) { b, in, shape := plan14UnitBindingFixture(t, "console.service", "", "") configured := map[string]claimUnitShape{in.Host: shape} d := claimUnitDispatch{bindings: b, shapes: func() (map[string]claimUnitShape, error) { return configured, nil }} if _, err := d.forStart(t.Context(), in.Host); err == nil { t.Fatal("configured unit without retained binding fell through") } if _, err := b.establish(t.Context(), in.Host); err != nil { t.Fatal(err) } unit, group, err := d.Placement(in.Host) if err != nil || unit != shape.Unit || group != instancectl.BoundClaimUnitControlGroup(in.Host, shape.Unit) { t.Fatal(unit, group, err) } unit, group, err = d.Placement("sibling.example") if err != nil || unit != instancectl.UnitName(instancectl.RoleRun, "sibling.example") || group != instancectl.ClaimUnitControlGroup("sibling.example") { t.Fatal(unit, group, err) } delete(configured, in.Host) if _, err := d.forStart(t.Context(), in.Host); err == nil { t.Fatal("removed configuration allowed start") } unit, _, err = d.Placement(in.Host) if err != nil || unit != shape.Unit { t.Fatal("cleanup lost retained placement", unit, err) } configured[in.Host] = shape changed := in changed.Stamp++ b.installation = func(context.Context, string) (hostguard.RootInstallation, error) { return changed, nil } if _, err := d.forStart(t.Context(), in.Host); err == nil { t.Fatal("successor inherited placement") } b.state.Write(in.Host+".json", []byte("broken")) if _, _, err := d.Placement(in.Host); err == nil { t.Fatal("corruption fell through") } d.shapes = func() (map[string]claimUnitShape, error) { return nil, os.ErrPermission } if _, _, err := d.Placement("sibling.example"); err != nil { t.Fatal("unreadable named configuration blocked ordinary cleanup", err) } } func TestPlan14BackingUnitRegistryShape(t *testing.T) { b, in, s := plan14UnitBindingFixture(t, "carlos-app@shop.example.service", "unit", "") if _, err := b.establish(t.Context(), in.Host); err != nil { t.Fatal(err) } r := s.route() if r.Unit != "" { t.Fatal("canonical backing route invents a named unit", r.Unit) } if _, err := b.check(t.Context(), in.Host, &r); err != nil { t.Fatal(err) } r.Unit = s.Unit if _, err := b.check(t.Context(), in.Host, &r); err == nil { t.Fatal("accepted backing-to-named shape change") } } func TestPlan14UnitBindingRetainedOwnership(t *testing.T) { b, in, shape := plan14UnitBindingFixture(t, "console.service", "", "") if _, err := b.establish(t.Context(), in.Host); err != nil { t.Fatal(err) } other := in other.Host, other.Record = "sibling.example", "apps/bab/shop/instances/sibling.example.json" shape.Host = other.Host b.installation = func(context.Context, string) (hostguard.RootInstallation, error) { return other, nil } b.canonical = func(context.Context, string) (claimUnitShape, error) { return shape, nil } if _, err := b.establish(t.Context(), other.Host); err == nil { t.Fatal("root config reassigned a retained unit to a sibling") } if _, err := b.read(other.Host); !os.IsNotExist(err) { t.Fatal("created conflicting owner", err) } }