1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
package app
import (
"fmt"
"reflect"
"testing"
"hakurei.app/container"
"hakurei.app/container/check"
"hakurei.app/container/fhs"
"hakurei.app/container/stub"
"hakurei.app/hst"
)
func TestEnvPaths(t *testing.T) {
testCases := []struct {
name string
env *EnvPaths
want hst.Paths
wantPanic string
}{
{"nil", nil, hst.Paths{}, "attempting to use an invalid EnvPaths"},
{"zero", new(EnvPaths), hst.Paths{}, "attempting to use an invalid EnvPaths"},
{"nil tempdir", &EnvPaths{
RuntimePath: fhs.AbsTmp,
}, hst.Paths{}, "attempting to use an invalid EnvPaths"},
{"nil runtime", &EnvPaths{
TempDir: fhs.AbsTmp,
}, hst.Paths{
TempDir: fhs.AbsTmp,
SharePath: fhs.AbsTmp.Append("hakurei.3735928559"),
RuntimePath: fhs.AbsTmp.Append("hakurei.3735928559/run/compat"),
RunDirPath: fhs.AbsTmp.Append("hakurei.3735928559/run"),
}, ""},
{"full", &EnvPaths{
TempDir: fhs.AbsTmp,
RuntimePath: fhs.AbsRunUser.Append("1000"),
}, hst.Paths{
TempDir: fhs.AbsTmp,
SharePath: fhs.AbsTmp.Append("hakurei.3735928559"),
RuntimePath: fhs.AbsRunUser.Append("1000"),
RunDirPath: fhs.AbsRunUser.Append("1000/hakurei"),
}, ""},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.wantPanic != "" {
defer func() {
if r := recover(); r != tc.wantPanic {
t.Errorf("Copy: panic = %#v, want %q", r, tc.wantPanic)
}
}()
}
var sc hst.Paths
tc.env.Copy(&sc, 0xdeadbeef)
if !reflect.DeepEqual(&sc, &tc.want) {
t.Errorf("Copy: %#v, want %#v", sc, tc.want)
}
})
}
}
func TestCopyPaths(t *testing.T) {
testCases := []struct {
name string
env map[string]string
tmp string
fatal string
want EnvPaths
}{
{"invalid tempdir", nil, "\x00",
"invalid TMPDIR: path \"\\x00\" is not absolute", EnvPaths{}},
{"empty environment", make(map[string]string), container.Nonexistent,
"", EnvPaths{TempDir: check.MustAbs(container.Nonexistent)}},
{"invalid XDG_RUNTIME_DIR", map[string]string{"XDG_RUNTIME_DIR": "\x00"}, container.Nonexistent,
"", EnvPaths{TempDir: check.MustAbs(container.Nonexistent)}},
{"full", map[string]string{"XDG_RUNTIME_DIR": "/\x00"}, container.Nonexistent,
"", EnvPaths{TempDir: check.MustAbs(container.Nonexistent), RuntimePath: check.MustAbs("/\x00")}},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
if tc.fatal != "" {
defer stub.HandleExit(t)
}
k := copyPathsDispatcher{t: t, env: tc.env, tmp: tc.tmp, expectsFatal: tc.fatal}
got := copyPaths(k)
if tc.fatal != "" {
t.Fatalf("copyPaths: expected fatal %q", tc.fatal)
}
if !reflect.DeepEqual(got, &tc.want) {
t.Errorf("copyPaths: %#v, want %#v", got, &tc.want)
}
})
}
}
// copyPathsDispatcher implements enough of syscallDispatcher for all copyPaths code paths.
type copyPathsDispatcher struct {
env map[string]string
tmp string
// must be checked at the conclusion of the test
expectsFatal string
t *testing.T
panicDispatcher
}
func (k copyPathsDispatcher) tempdir() string { return k.tmp }
func (k copyPathsDispatcher) lookupEnv(key string) (value string, ok bool) {
value, ok = k.env[key]
return
}
func (k copyPathsDispatcher) fatalf(format string, v ...any) {
if k.expectsFatal == "" {
k.t.Fatalf("unexpected call to fatalf: format = %q, v = %#v", format, v)
}
if got := fmt.Sprintf(format, v...); got != k.expectsFatal {
k.t.Fatalf("fatalf: %q, want %q", got, k.expectsFatal)
}
panic(stub.PanicExit)
}
|