diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-07-02 21:31:29 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-07-02 21:31:29 +0900 |
| commit | eec021cc4b4eb42bc9c8311755826828bfba1996 (patch) | |
| tree | 5dfe107c31ee525b13af275f8261982e916c331a /vfs/unfold_test.go | |
| parent | a1d98823f8d17b49b432508d071b62ccd426f1ce (diff) | |
hakurei: move container helpers toplevel
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'vfs/unfold_test.go')
| -rw-r--r-- | vfs/unfold_test.go | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/vfs/unfold_test.go b/vfs/unfold_test.go new file mode 100644 index 00000000..59e52041 --- /dev/null +++ b/vfs/unfold_test.go @@ -0,0 +1,93 @@ +package vfs_test + +import ( + "errors" + "reflect" + "slices" + "strings" + "syscall" + "testing" + + "git.gensokyo.uk/security/hakurei/vfs" +) + +func TestUnfold(t *testing.T) { + testCases := []struct { + name string + sample string + target string + wantErr error + + want *vfs.MountInfoNode + wantCollectF func(n *vfs.MountInfoNode) []*vfs.MountInfoNode + wantCollectN []string + }{ + { + "no match", + sampleMountinfoBase, + "/mnt", + syscall.ESTALE, nil, nil, nil, + }, + { + "cover", + `33 1 0:33 / / rw,relatime shared:1 - tmpfs impure rw,size=16777216k,mode=755 +37 33 0:32 / /proc rw,nosuid,nodev,noexec,relatime shared:41 - proc proc rw +551 33 0:121 / /mnt rw,relatime shared:666 - tmpfs tmpfs rw +595 551 0:123 / /mnt rw,relatime shared:990 - tmpfs tmpfs rw +611 595 0:142 / /mnt/etc rw,relatime shared:1112 - tmpfs tmpfs rw +625 644 0:142 /passwd /mnt/etc/passwd rw,relatime shared:1112 - tmpfs tmpfs rw +641 625 0:33 /etc/passwd /mnt/etc/passwd rw,relatime shared:1 - tmpfs impure rw,size=16777216k,mode=755 +644 611 0:33 /etc/passwd /mnt/etc/passwd rw,relatime shared:1 - tmpfs impure rw,size=16777216k,mode=755 +`, "/mnt", nil, + mn(595, 551, 0, 123, "/", "/mnt", "rw,relatime", o("shared:990"), "tmpfs", "tmpfs", "rw", false, + mn(611, 595, 0, 142, "/", "/mnt/etc", "rw,relatime", o("shared:1112"), "tmpfs", "tmpfs", "rw", false, + mn(644, 611, 0, 33, "/etc/passwd", "/mnt/etc/passwd", "rw,relatime", o("shared:1"), "tmpfs", "impure", "rw,size=16777216k,mode=755", true, + mn(625, 644, 0, 142, "/passwd", "/mnt/etc/passwd", "rw,relatime", o("shared:1112"), "tmpfs", "tmpfs", "rw", true, + mn(641, 625, 0, 33, "/etc/passwd", "/mnt/etc/passwd", "rw,relatime", o("shared:1"), "tmpfs", "impure", "rw,size=16777216k,mode=755", false, + nil, nil), nil), nil), nil), nil), func(n *vfs.MountInfoNode) []*vfs.MountInfoNode { + return []*vfs.MountInfoNode{n, n.FirstChild, n.FirstChild.FirstChild.FirstChild.FirstChild} + }, []string{"/mnt", "/mnt/etc", "/mnt/etc/passwd"}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + d := vfs.NewMountInfoDecoder(strings.NewReader(tc.sample)) + got, err := d.Unfold(tc.target) + + if !errors.Is(err, tc.wantErr) { + t.Errorf("Unfold: error = %v, wantErr %v", + err, tc.wantErr) + } + + if !reflect.DeepEqual(got, tc.want) { + t.Errorf("Unfold:\ngot %s\nwant %s", + mustMarshal(got), mustMarshal(tc.want)) + } + + if err == nil && tc.wantCollectF != nil { + t.Run("collective", func(t *testing.T) { + wantCollect := tc.wantCollectF(got) + gotCollect := slices.Collect(got.Collective()) + if !reflect.DeepEqual(gotCollect, wantCollect) { + t.Errorf("Collective: \ngot %#v\nwant %#v", + gotCollect, wantCollect) + } + t.Run("target", func(t *testing.T) { + gotCollectN := slices.Collect[string](func(yield func(v string) bool) { + for _, cur := range gotCollect { + if !yield(cur.Clean) { + return + } + } + }) + if !reflect.DeepEqual(gotCollectN, tc.wantCollectN) { + t.Errorf("Collective: got %q, want %q", + gotCollectN, tc.wantCollectN) + } + }) + }) + } + }) + } +} |
