1 package sys
2
3 import (
4 "bytes"
5 "testing"
6 "time"
7
8 experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
9 "github.com/tetratelabs/wazero/internal/fstest"
10 "github.com/tetratelabs/wazero/internal/platform"
11 "github.com/tetratelabs/wazero/internal/sysfs"
12 "github.com/tetratelabs/wazero/internal/testing/require"
13 "github.com/tetratelabs/wazero/sys"
14 )
15
16 func TestContext_WalltimeNanos(t *testing.T) {
17 sysCtx := DefaultContext(nil)
18
19 require.Equal(t, int64(1640995200000000000), sysCtx.WalltimeNanos())
20 }
21
22 func TestDefaultSysContext(t *testing.T) {
23 testFS := &sysfs.AdaptFS{FS: fstest.FS}
24
25 sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, []experimentalsys.FS{testFS}, []string{"/"}, nil)
26 require.NoError(t, err)
27
28 require.Nil(t, sysCtx.Args())
29 require.Zero(t, sysCtx.ArgsSize())
30 require.Nil(t, sysCtx.Environ())
31 require.Zero(t, sysCtx.EnvironSize())
32
33
34 sec, _ := sysCtx.Walltime()
35 require.Equal(t, platform.FakeEpochNanos/time.Second.Nanoseconds(), sec)
36 require.Equal(t, sys.ClockResolution(1_000), sysCtx.WalltimeResolution())
37 require.Zero(t, sysCtx.Nanotime())
38 require.Equal(t, sys.ClockResolution(1), sysCtx.NanotimeResolution())
39 require.Equal(t, platform.FakeNanosleep, sysCtx.nanosleep)
40 require.Equal(t, platform.NewFakeRandSource(), sysCtx.RandSource())
41
42 expected := FileTable{}
43 noopStdin, _ := stdinFileEntry(nil)
44 expected.Insert(noopStdin)
45 noopStdout, _ := stdioWriterFileEntry("stdout", nil)
46 expected.Insert(noopStdout)
47 noopStderr, _ := stdioWriterFileEntry("stderr", nil)
48 expected.Insert(noopStderr)
49 expected.Insert(&FileEntry{
50 IsPreopen: true,
51 Name: "/",
52 FS: testFS,
53 File: &lazyDir{fs: testFS},
54 })
55 require.Equal(t, expected, sysCtx.FS().openedFiles)
56 }
57
58 func TestNewContext_Args(t *testing.T) {
59 tests := []struct {
60 name string
61 args [][]byte
62 maxSize uint32
63 expectedSize uint32
64 expectedErr string
65 }{
66 {
67 name: "ok",
68 maxSize: 10,
69 args: [][]byte{[]byte("a"), []byte("bc")},
70 expectedSize: 5,
71 },
72 {
73 name: "exceeds max count",
74 maxSize: 1,
75 args: [][]byte{[]byte("a"), []byte("bc")},
76 expectedErr: "args invalid: exceeds maximum count",
77 },
78 {
79 name: "exceeds max size",
80 maxSize: 4,
81 args: [][]byte{[]byte("a"), []byte("bc")},
82 expectedErr: "args invalid: exceeds maximum size",
83 },
84 {
85 name: "null character",
86 maxSize: 10,
87 args: [][]byte{[]byte("a"), {'b', 0}},
88 expectedErr: "args invalid: contains NUL character",
89 },
90 }
91
92 for _, tt := range tests {
93 tc := tt
94
95 t.Run(tc.name, func(t *testing.T) {
96 sysCtx, err := NewContext(tc.maxSize, tc.args, nil, bytes.NewReader(make([]byte, 0)), nil, nil, nil, nil, 0, nil, 0, nil, nil, nil, nil, nil)
97 if tc.expectedErr == "" {
98 require.Nil(t, err)
99 require.Equal(t, tc.args, sysCtx.Args())
100 require.Equal(t, tc.expectedSize, sysCtx.ArgsSize())
101 } else {
102 require.EqualError(t, err, tc.expectedErr)
103 }
104 })
105 }
106 }
107
108 func TestNewContext_Environ(t *testing.T) {
109 tests := []struct {
110 name string
111 environ [][]byte
112 maxSize uint32
113 expectedSize uint32
114 expectedErr string
115 }{
116 {
117 name: "ok",
118 maxSize: 10,
119 environ: [][]byte{[]byte("a=b"), []byte("c=de")},
120 expectedSize: 9,
121 },
122 {
123 name: "exceeds max count",
124 maxSize: 1,
125 environ: [][]byte{[]byte("a=b"), []byte("c=de")},
126 expectedErr: "environ invalid: exceeds maximum count",
127 },
128 {
129 name: "exceeds max size",
130 maxSize: 4,
131 environ: [][]byte{[]byte("a=b"), []byte("c=de")},
132 expectedErr: "environ invalid: exceeds maximum size",
133 },
134 {
135 name: "null character",
136 maxSize: 10,
137 environ: [][]byte{[]byte("a=b"), append([]byte("c=d"), 0)},
138 expectedErr: "environ invalid: contains NUL character",
139 },
140 }
141
142 for _, tt := range tests {
143 tc := tt
144
145 t.Run(tc.name, func(t *testing.T) {
146 sysCtx, err := NewContext(tc.maxSize, nil, tc.environ, bytes.NewReader(make([]byte, 0)), nil, nil, nil, nil, 0, nil, 0, nil, nil, nil, nil, nil)
147 if tc.expectedErr == "" {
148 require.Nil(t, err)
149 require.Equal(t, tc.environ, sysCtx.Environ())
150 require.Equal(t, tc.expectedSize, sysCtx.EnvironSize())
151 } else {
152 require.EqualError(t, err, tc.expectedErr)
153 }
154 })
155 }
156 }
157
158 func TestNewContext_Walltime(t *testing.T) {
159 tests := []struct {
160 name string
161 time sys.Walltime
162 resolution sys.ClockResolution
163 expectedErr string
164 }{
165 {
166 name: "ok",
167 time: platform.NewFakeWalltime(),
168 resolution: 3,
169 },
170 {
171 name: "invalid resolution",
172 time: platform.NewFakeWalltime(),
173 resolution: 0,
174 expectedErr: "invalid Walltime resolution: 0",
175 },
176 }
177
178 for _, tt := range tests {
179 tc := tt
180
181 t.Run(tc.name, func(t *testing.T) {
182 sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, tc.time, tc.resolution, nil, 0, nil, nil, nil, nil, nil)
183 if tc.expectedErr == "" {
184 require.Nil(t, err)
185 require.Equal(t, tc.time, sysCtx.walltime)
186 require.Equal(t, tc.resolution, sysCtx.WalltimeResolution())
187 } else {
188 require.EqualError(t, err, tc.expectedErr)
189 }
190 })
191 }
192 }
193
194 func TestNewContext_Nanotime(t *testing.T) {
195 tests := []struct {
196 name string
197 time sys.Nanotime
198 resolution sys.ClockResolution
199 expectedErr string
200 }{
201 {
202 name: "ok",
203 time: platform.NewFakeNanotime(),
204 resolution: 3,
205 },
206 {
207 name: "invalid resolution",
208 time: platform.NewFakeNanotime(),
209 resolution: 0,
210 expectedErr: "invalid Nanotime resolution: 0",
211 },
212 }
213
214 for _, tt := range tests {
215 tc := tt
216
217 t.Run(tc.name, func(t *testing.T) {
218 sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, tc.time, tc.resolution, nil, nil, nil, nil, nil)
219 if tc.expectedErr == "" {
220 require.Nil(t, err)
221 require.Equal(t, tc.time, sysCtx.nanotime)
222 require.Equal(t, tc.resolution, sysCtx.NanotimeResolution())
223 } else {
224 require.EqualError(t, err, tc.expectedErr)
225 }
226 })
227 }
228 }
229
230 func Test_clockResolutionInvalid(t *testing.T) {
231 tests := []struct {
232 name string
233 resolution sys.ClockResolution
234 expected bool
235 }{
236 {
237 name: "ok",
238 resolution: 1,
239 },
240 {
241 name: "zero",
242 resolution: 0,
243 expected: true,
244 },
245 {
246 name: "too big",
247 resolution: sys.ClockResolution(time.Hour.Nanoseconds() * 2),
248 expected: true,
249 },
250 }
251
252 for _, tt := range tests {
253 tc := tt
254
255 t.Run(tc.name, func(t *testing.T) {
256 require.Equal(t, tc.expected, clockResolutionInvalid(tc.resolution))
257 })
258 }
259 }
260
261 func TestNewContext_Nanosleep(t *testing.T) {
262 var aNs sys.Nanosleep = func(int64) {}
263 sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, aNs, nil, nil, nil, nil)
264 require.Nil(t, err)
265 require.Equal(t, aNs, sysCtx.nanosleep)
266 }
267
268 func TestNewContext_Osyield(t *testing.T) {
269 var oy sys.Osyield = func() {}
270 sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, oy, nil, nil, nil)
271 require.Nil(t, err)
272 require.Equal(t, oy, sysCtx.osyield)
273 }
274
View as plain text