1 package wasi_snapshot_preview1_test
2
3 import (
4 _ "embed"
5 "testing"
6
7 "github.com/tetratelabs/wazero"
8 "github.com/tetratelabs/wazero/internal/testing/require"
9 "github.com/tetratelabs/wazero/internal/wasip1"
10 )
11
12 func Test_clockResGet(t *testing.T) {
13 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
14 defer r.Close(testCtx)
15
16 expectedMemoryMicro := []byte{
17 '?',
18 0xe8, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
19 '?',
20 }
21
22 expectedMemoryNano := []byte{
23 '?',
24 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
25 '?',
26 }
27
28 tests := []struct {
29 name string
30 clockID uint32
31 expectedMemory []byte
32 expectedLog string
33 }{
34 {
35 name: "Realtime",
36 clockID: wasip1.ClockIDRealtime,
37 expectedMemory: expectedMemoryMicro,
38 expectedLog: `
39 ==> wasi_snapshot_preview1.clock_res_get(id=realtime)
40 <== (resolution=1000,errno=ESUCCESS)
41 `,
42 },
43 {
44 name: "Monotonic",
45 clockID: wasip1.ClockIDMonotonic,
46 expectedMemory: expectedMemoryNano,
47 expectedLog: `
48 ==> wasi_snapshot_preview1.clock_res_get(id=monotonic)
49 <== (resolution=1,errno=ESUCCESS)
50 `,
51 },
52 }
53
54 for _, tt := range tests {
55 tc := tt
56
57 t.Run(tc.name, func(t *testing.T) {
58 defer log.Reset()
59
60 resultResolution := 16
61 maskMemory(t, mod, resultResolution+len(tc.expectedMemory))
62
63 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ClockResGetName, uint64(tc.clockID), uint64(resultResolution))
64 require.Equal(t, tc.expectedLog, "\n"+log.String())
65
66 actual, ok := mod.Memory().Read(uint32(resultResolution-1), uint32(len(tc.expectedMemory)))
67 require.True(t, ok)
68 require.Equal(t, tc.expectedMemory, actual)
69 })
70 }
71 }
72
73 func Test_clockResGet_Unsupported(t *testing.T) {
74 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
75 defer r.Close(testCtx)
76
77 tests := []struct {
78 name string
79 clockID uint32
80 expectedErrno wasip1.Errno
81 expectedLog string
82 }{
83 {
84 name: "process cputime",
85 clockID: 2,
86 expectedErrno: wasip1.ErrnoInval,
87 expectedLog: `
88 ==> wasi_snapshot_preview1.clock_res_get(id=2)
89 <== (resolution=,errno=EINVAL)
90 `,
91 },
92 {
93 name: "thread cputime",
94 clockID: 3,
95 expectedErrno: wasip1.ErrnoInval,
96 expectedLog: `
97 ==> wasi_snapshot_preview1.clock_res_get(id=3)
98 <== (resolution=,errno=EINVAL)
99 `,
100 },
101 {
102 name: "undefined",
103 clockID: 100,
104 expectedErrno: wasip1.ErrnoInval,
105 expectedLog: `
106 ==> wasi_snapshot_preview1.clock_res_get(id=100)
107 <== (resolution=,errno=EINVAL)
108 `,
109 },
110 }
111 for _, tt := range tests {
112 tc := tt
113
114 t.Run(tc.name, func(t *testing.T) {
115 defer log.Reset()
116
117 resultResolution := 16
118 requireErrnoResult(t, tc.expectedErrno, mod, wasip1.ClockResGetName, uint64(tc.clockID), uint64(resultResolution))
119 require.Equal(t, tc.expectedLog, "\n"+log.String())
120 })
121 }
122 }
123
124 func Test_clockTimeGet(t *testing.T) {
125 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
126 defer r.Close(testCtx)
127
128 tests := []struct {
129 name string
130 clockID uint32
131 expectedMemory []byte
132 expectedLog string
133 }{
134 {
135 name: "Realtime",
136 clockID: wasip1.ClockIDRealtime,
137 expectedMemory: []byte{
138 '?',
139 0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16,
140 '?',
141 },
142 expectedLog: `
143 ==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
144 <== (timestamp=1640995200000000000,errno=ESUCCESS)
145 `,
146 },
147 {
148 name: "Monotonic",
149 clockID: wasip1.ClockIDMonotonic,
150 expectedMemory: []byte{
151 '?',
152 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
153 '?',
154 },
155 expectedLog: `
156 ==> wasi_snapshot_preview1.clock_time_get(id=monotonic,precision=0)
157 <== (timestamp=0,errno=ESUCCESS)
158 `,
159 },
160 }
161
162 for _, tt := range tests {
163 tc := tt
164 t.Run(tc.name, func(t *testing.T) {
165 defer log.Reset()
166
167 resultTimestamp := 16
168 maskMemory(t, mod, resultTimestamp+len(tc.expectedMemory))
169
170 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ClockTimeGetName, uint64(tc.clockID), 0 , uint64(resultTimestamp))
171 require.Equal(t, tc.expectedLog, "\n"+log.String())
172
173 actual, ok := mod.Memory().Read(uint32(resultTimestamp-1), uint32(len(tc.expectedMemory)))
174 require.True(t, ok)
175 require.Equal(t, tc.expectedMemory, actual)
176 })
177 }
178 }
179
180
181 func Test_clockTimeGet_monotonic(t *testing.T) {
182 mod, r, _ := requireProxyModule(t, wazero.NewModuleConfig().
183
184 WithSysNanotime())
185 defer r.Close(testCtx)
186
187 getMonotonicTime := func() uint64 {
188 const offset uint32 = 0
189 requireErrnoResult(t, wasip1.ErrnoSuccess, mod, wasip1.ClockTimeGetName, uint64(wasip1.ClockIDMonotonic),
190 0 , uint64(offset))
191 timestamp, ok := mod.Memory().ReadUint64Le(offset)
192 require.True(t, ok)
193 return timestamp
194 }
195
196 t1 := getMonotonicTime()
197 t2 := getMonotonicTime()
198 t3 := getMonotonicTime()
199 t4 := getMonotonicTime()
200
201 require.True(t, t1 < t2)
202 require.True(t, t2 < t3)
203 require.True(t, t3 < t4)
204 }
205
206 func Test_clockTimeGet_Unsupported(t *testing.T) {
207 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
208 defer r.Close(testCtx)
209
210 tests := []struct {
211 name string
212 clockID uint32
213 expectedErrno wasip1.Errno
214 expectedLog string
215 }{
216 {
217 name: "process cputime",
218 clockID: 2,
219 expectedErrno: wasip1.ErrnoInval,
220 expectedLog: `
221 ==> wasi_snapshot_preview1.clock_time_get(id=2,precision=0)
222 <== (timestamp=,errno=EINVAL)
223 `,
224 },
225 {
226 name: "thread cputime",
227 clockID: 3,
228 expectedErrno: wasip1.ErrnoInval,
229 expectedLog: `
230 ==> wasi_snapshot_preview1.clock_time_get(id=3,precision=0)
231 <== (timestamp=,errno=EINVAL)
232 `,
233 },
234 {
235 name: "undefined",
236 clockID: 100,
237 expectedErrno: wasip1.ErrnoInval,
238 expectedLog: `
239 ==> wasi_snapshot_preview1.clock_time_get(id=100,precision=0)
240 <== (timestamp=,errno=EINVAL)
241 `,
242 },
243 }
244
245 for _, tt := range tests {
246 tc := tt
247
248 t.Run(tc.name, func(t *testing.T) {
249 defer log.Reset()
250
251 resultTimestamp := 16
252 requireErrnoResult(t, tc.expectedErrno, mod, wasip1.ClockTimeGetName, uint64(tc.clockID), uint64(0) , uint64(resultTimestamp))
253 require.Equal(t, tc.expectedLog, "\n"+log.String())
254 })
255 }
256 }
257
258 func Test_clockTimeGet_Errors(t *testing.T) {
259 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig())
260 defer r.Close(testCtx)
261
262 memorySize := mod.Memory().Size()
263
264 tests := []struct {
265 name string
266 resultTimestamp, argvLen uint32
267 expectedLog string
268 }{
269 {
270 name: "resultTimestamp OOM",
271 resultTimestamp: memorySize,
272 expectedLog: `
273 ==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
274 <== (timestamp=,errno=EFAULT)
275 `,
276 },
277 {
278 name: "resultTimestamp exceeds the maximum valid address by 1",
279 resultTimestamp: memorySize - 4 + 1,
280 expectedLog: `
281 ==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
282 <== (timestamp=,errno=EFAULT)
283 `,
284 },
285 }
286
287 for _, tt := range tests {
288 tc := tt
289
290 t.Run(tc.name, func(t *testing.T) {
291 defer log.Reset()
292
293 requireErrnoResult(t, wasip1.ErrnoFault, mod, wasip1.ClockTimeGetName, uint64(0) , uint64(0) , uint64(tc.resultTimestamp))
294 require.Equal(t, tc.expectedLog, "\n"+log.String())
295 })
296 }
297 }
298
View as plain text