diff --git a/container/autoroot.go b/container/autoroot.go index 6145ec6..640d72d 100644 --- a/container/autoroot.go +++ b/container/autoroot.go @@ -73,7 +73,9 @@ func (r *AutoRootOp) apply(state *setupState) error { func (r *AutoRootOp) Is(op Op) bool { vr, ok := op.(*AutoRootOp) return ok && ((r == nil && vr == nil) || (r != nil && vr != nil && - r.Host == vr.Host && r.Prefix == vr.Prefix && r.Flags == vr.Flags)) + r.Host != nil && vr.Host != nil && + r.Host.String() == vr.Host.String() && + r.Prefix == vr.Prefix && r.Flags == vr.Flags)) } func (*AutoRootOp) prefix() string { return "setting up" } func (r *AutoRootOp) String() string { diff --git a/container/autoroot_test.go b/container/autoroot_test.go index 7e9d147..77440ac 100644 --- a/container/autoroot_test.go +++ b/container/autoroot_test.go @@ -2,6 +2,61 @@ package container import "testing" +func TestAutoRootOp(t *testing.T) { + checkOpsBuilder(t, []opsBuilderTestCase{ + {"pd", new(Ops).Root(MustAbs("/"), "048090b6ed8f9ebb10e275ff5d8c0659", BindWritable), Ops{ + &AutoRootOp{ + Host: MustAbs("/"), + Prefix: "048090b6ed8f9ebb10e275ff5d8c0659", + Flags: BindWritable, + }, + }}, + }) + + checkOpIs(t, []opIsTestCase{ + {"zero", new(AutoRootOp), new(AutoRootOp), false}, + + {"internal ne", &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + }, &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + resolved: []Op{new(BindMountOp)}, + }, true}, + + {"differs", &AutoRootOp{ + Host: MustAbs("/"), + Prefix: "\x00", + Flags: BindWritable, + }, &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + }, false}, + + {"equals", &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + }, &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + }, true}, + }) + + checkOpMeta(t, []opMetaTestCase{ + {"root", &AutoRootOp{ + Host: MustAbs("/"), + Prefix: ":3", + Flags: BindWritable, + }, "setting up", `auto root "/" prefix :3 flags 0x2`}, + }) +} + func TestIsAutoRootBindable(t *testing.T) { testCases := []struct { name string diff --git a/container/mount_test.go b/container/mount_test.go index eb90477..a400d69 100644 --- a/container/mount_test.go +++ b/container/mount_test.go @@ -2,6 +2,7 @@ package container import ( "os" + "slices" "testing" ) @@ -47,3 +48,67 @@ func TestEscapeOverlayDataSegment(t *testing.T) { }) } } + +type opsBuilderTestCase struct { + name string + ops *Ops + want Ops +} + +func checkOpsBuilder(t *testing.T, testCases []opsBuilderTestCase) { + t.Run("build", func(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if !slices.EqualFunc(*tc.ops, tc.want, func(op Op, v Op) bool { return op.Is(v) }) { + t.Errorf("Ops: %#v, want %#v", tc.ops, tc.want) + } + }) + } + }) +} + +type opIsTestCase struct { + name string + op, v Op + want bool +} + +func checkOpIs(t *testing.T, testCases []opIsTestCase) { + t.Run("meta", func(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if got := tc.op.Is(tc.v); got != tc.want { + t.Errorf("Is: %v, want %v", got, tc.want) + } + }) + } + }) +} + +type opMetaTestCase struct { + name string + op Op + + wantPrefix string + wantString string +} + +func checkOpMeta(t *testing.T, testCases []opMetaTestCase) { + t.Run("meta", func(t *testing.T) { + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + t.Run("prefix", func(t *testing.T) { + if got := tc.op.prefix(); got != tc.wantPrefix { + t.Errorf("prefix: %q, want %q", got, tc.wantPrefix) + } + }) + + t.Run("string", func(t *testing.T) { + if got := tc.op.String(); got != tc.wantString { + t.Errorf("String: %s, want %s", got, tc.wantString) + } + }) + }) + } + }) +}