aboutsummaryrefslogtreecommitdiffhomepage
path: root/container/initplace_test.go
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-08-21 21:59:07 +0900
committerOphestra <cat@gensokyo.uk>2025-08-22 19:27:31 +0900
commit09d284498109b847da0da1e2c5f883268a7f2d46 (patch)
tree3784dee4b4e4ec97a95cb222c70d05463ae640ef /container/initplace_test.go
parentd500d6e55917e12a3f98b39cf0d29b6c96de9667 (diff)
container/init: wrap syscall helper functions
This allows tests to stub all kernel behaviour, enabling measurement of all function call arguments and error injection. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'container/initplace_test.go')
-rw-r--r--container/initplace_test.go109
1 files changed, 89 insertions, 20 deletions
diff --git a/container/initplace_test.go b/container/initplace_test.go
index db3d955c..02c37336 100644
--- a/container/initplace_test.go
+++ b/container/initplace_test.go
@@ -1,25 +1,94 @@
package container
-import "testing"
+import (
+ "os"
+ "testing"
+)
func TestTmpfileOp(t *testing.T) {
+ const sampleDataString = `chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`
+ var (
+ samplePath = MustAbs("/etc/passwd")
+ sampleData = []byte(sampleDataString)
+ )
+
+ checkOpBehaviour(t, []opBehaviourTestCase{
+ {"createTemp", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), errUnique},
+ }, wrapErrSelf(errUnique)},
+
+ {"Write", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, writeErrOsFile{errUnique}, nil},
+ }, wrapErrSuffix(errUnique, "cannot write to intermediate file:")},
+
+ {"Close", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, errUnique), nil},
+ }, wrapErrSuffix(errUnique, "cannot close intermediate file:")},
+
+ {"ensureFile", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil},
+ {"ensureFile", expectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, errUnique},
+ }, errUnique},
+
+ {"bindMount", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil},
+ {"ensureFile", expectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil},
+ {"bindMount", expectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, errUnique},
+ }, errUnique},
+
+ {"remove", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil},
+ {"ensureFile", expectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil},
+ {"bindMount", expectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil},
+ {"remove", expectArgs{"tmp.32768"}, nil, errUnique},
+ }, wrapErrSelf(errUnique)},
+
+ {"success", &Params{ParentPerm: 0700}, &TmpfileOp{
+ Path: samplePath,
+ Data: sampleData,
+ }, nil, nil, []kexpect{
+ {"createTemp", expectArgs{"/", "tmp.*"}, newCheckedFile(t, "tmp.32768", sampleDataString, nil), nil},
+ {"ensureFile", expectArgs{"/sysroot/etc/passwd", os.FileMode(0444), os.FileMode(0700)}, nil, nil},
+ {"bindMount", expectArgs{"tmp.32768", "/sysroot/etc/passwd", uintptr(0x5), false}, nil, nil},
+ {"remove", expectArgs{"tmp.32768"}, nil, nil},
+ }, nil},
+ })
+
checkOpsValid(t, []opValidTestCase{
{"nil", (*TmpfileOp)(nil), false},
{"zero", new(TmpfileOp), false},
- {"valid", &TmpfileOp{Path: MustAbs("/etc/passwd")}, true},
+ {"valid", &TmpfileOp{Path: samplePath}, true},
})
checkOpsBuilder(t, []opsBuilderTestCase{
- {"noref", new(Ops).Place(MustAbs("/etc/passwd"), []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`)), Ops{
+ {"noref", new(Ops).Place(samplePath, sampleData), Ops{
&TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
},
}},
- {"ref", new(Ops).PlaceP(MustAbs("/etc/passwd"), new(*[]byte)), Ops{
+ {"ref", new(Ops).PlaceP(samplePath, new(*[]byte)), Ops{
&TmpfileOp{
- Path: MustAbs("/etc/passwd"),
+ Path: samplePath,
Data: []byte{},
},
}},
@@ -30,33 +99,33 @@ func TestTmpfileOp(t *testing.T) {
{"differs path", &TmpfileOp{
Path: MustAbs("/etc/group"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Data: sampleData,
}, &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
}, false},
{"differs data", &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh` + "\x00"),
+ Path: samplePath,
+ Data: append(sampleData, 0),
}, &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
}, false},
{"equals", &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
}, &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
}, true},
})
checkOpMeta(t, []opMetaTestCase{
{"passwd", &TmpfileOp{
- Path: MustAbs("/etc/passwd"),
- Data: []byte(`chronos:x:65534:65534:Hakurei:/var/empty:/bin/zsh`),
+ Path: samplePath,
+ Data: sampleData,
}, "placing", `tmpfile "/etc/passwd" (49 bytes)`},
})
}