aboutsummaryrefslogtreecommitdiffhomepage
path: root/container
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-20 02:03:18 +0900
committerOphestra <cat@gensokyo.uk>2025-08-20 02:14:39 +0900
commit375acb476d36cac8e122ae8c45628bd8e7e0f0ca (patch)
tree59899fe31c847724ac1a0d4055420a0a751c3ab0 /container
parentc81c9a9d75f179988cf858b85fe2de71bf9c2ff4 (diff)
container/autoroot: check host path equivalence by value
This will never return true otherwise unless the equivalent paths happen to be interned by the caller. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container')
-rw-r--r--container/autoroot.go4
-rw-r--r--container/autoroot_test.go55
-rw-r--r--container/mount_test.go65
3 files changed, 123 insertions, 1 deletions
diff --git a/container/autoroot.go b/container/autoroot.go
index 6145ec6f..640d72d1 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 7e9d1477..77440ace 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 eb904774..4c598b3f 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("is", 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)
+ }
+ })
+ })
+ }
+ })
+}