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