wa-lang.org/wazero@v1.0.2/imports/wasi_snapshot_preview1/poll_test.go (about) 1 package wasi_snapshot_preview1 2 3 import ( 4 "testing" 5 6 "wa-lang.org/wazero" 7 internalsys "wa-lang.org/wazero/internal/sys" 8 "wa-lang.org/wazero/internal/testing/require" 9 "wa-lang.org/wazero/internal/wasm" 10 ) 11 12 func Test_pollOneoff(t *testing.T) { 13 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig()) 14 defer r.Close(testCtx) 15 16 mem := []byte{ 17 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata 18 eventTypeClock, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // event type and padding 19 clockIDMonotonic, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // clockID 20 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // timeout (ns) 21 0x01, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // precision (ns) 22 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // flags (relative) 23 '?', // stopped after encoding 24 } 25 26 expectedMem := []byte{ 27 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata 28 byte(ErrnoSuccess), 0x0, // errno is 16 bit 29 eventTypeClock, 0x0, 0x0, 0x0, // 4 bytes for type enum 30 '?', // stopped after encoding 31 } 32 33 in := uint32(0) // past in 34 out := uint32(128) // past in 35 nsubscriptions := uint32(1) 36 resultNevents := uint32(512) // past out 37 38 maskMemory(t, testCtx, mod, 1024) 39 mod.Memory().Write(testCtx, in, mem) 40 41 requireErrno(t, ErrnoSuccess, mod, functionPollOneoff, uint64(in), uint64(out), uint64(nsubscriptions), 42 uint64(resultNevents)) 43 require.Equal(t, ` 44 --> proxy.poll_oneoff(in=0,out=128,nsubscriptions=1,result.nevents=512) 45 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=1,result.nevents=512) 46 <== ESUCCESS 47 <-- (0) 48 `, "\n"+log.String()) 49 50 outMem, ok := mod.Memory().Read(testCtx, out, uint32(len(expectedMem))) 51 require.True(t, ok) 52 require.Equal(t, expectedMem, outMem) 53 54 nevents, ok := mod.Memory().ReadUint32Le(testCtx, resultNevents) 55 require.True(t, ok) 56 require.Equal(t, nsubscriptions, nevents) 57 } 58 59 func Test_pollOneoff_Errors(t *testing.T) { 60 mod, r, log := requireProxyModule(t, wazero.NewModuleConfig()) 61 defer r.Close(testCtx) 62 63 tests := []struct { 64 name string 65 in, out, nsubscriptions, resultNevents uint32 66 mem []byte // at offset in 67 expectedErrno Errno 68 expectedMem []byte // at offset out 69 expectedLog string 70 }{ 71 { 72 name: "in out of range", 73 in: wasm.MemoryPageSize, 74 nsubscriptions: 1, 75 out: 128, // past in 76 resultNevents: 512, // past out 77 expectedErrno: ErrnoFault, 78 expectedLog: ` 79 --> proxy.poll_oneoff(in=65536,out=128,nsubscriptions=1,result.nevents=512) 80 ==> wasi_snapshot_preview1.poll_oneoff(in=65536,out=128,nsubscriptions=1,result.nevents=512) 81 <== EFAULT 82 <-- (21) 83 `, 84 }, 85 { 86 name: "out out of range", 87 out: wasm.MemoryPageSize, 88 resultNevents: 512, // past out 89 nsubscriptions: 1, 90 expectedErrno: ErrnoFault, 91 expectedLog: ` 92 --> proxy.poll_oneoff(in=0,out=65536,nsubscriptions=1,result.nevents=512) 93 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=65536,nsubscriptions=1,result.nevents=512) 94 <== EFAULT 95 <-- (21) 96 `, 97 }, 98 { 99 name: "resultNevents out of range", 100 resultNevents: wasm.MemoryPageSize, 101 nsubscriptions: 1, 102 expectedErrno: ErrnoFault, 103 expectedLog: ` 104 --> proxy.poll_oneoff(in=0,out=0,nsubscriptions=1,result.nevents=65536) 105 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=0,nsubscriptions=1,result.nevents=65536) 106 <== EFAULT 107 <-- (21) 108 `, 109 }, 110 { 111 name: "nsubscriptions zero", 112 out: 128, // past in 113 resultNevents: 512, // past out 114 expectedErrno: ErrnoInval, 115 expectedLog: ` 116 --> proxy.poll_oneoff(in=0,out=128,nsubscriptions=0,result.nevents=512) 117 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=0,result.nevents=512) 118 <== EINVAL 119 <-- (28) 120 `, 121 }, 122 { 123 name: "unsupported eventTypeFdRead", 124 nsubscriptions: 1, 125 mem: []byte{ 126 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata 127 eventTypeFdRead, 0x0, 0x0, 0x0, 128 internalsys.FdStdin, 0x0, 0x0, 0x0, // valid readable FD 129 '?', // stopped after encoding 130 }, 131 expectedErrno: ErrnoSuccess, 132 out: 128, // past in 133 resultNevents: 512, // past out 134 expectedMem: []byte{ 135 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // userdata 136 byte(ErrnoNotsup), 0x0, // errno is 16 bit 137 eventTypeFdRead, 0x0, 0x0, 0x0, // 4 bytes for type enum 138 '?', // stopped after encoding 139 }, 140 expectedLog: ` 141 --> proxy.poll_oneoff(in=0,out=128,nsubscriptions=1,result.nevents=512) 142 ==> wasi_snapshot_preview1.poll_oneoff(in=0,out=128,nsubscriptions=1,result.nevents=512) 143 <== ESUCCESS 144 <-- (0) 145 `, 146 }, 147 } 148 149 for _, tt := range tests { 150 tc := tt 151 t.Run(tc.name, func(t *testing.T) { 152 defer log.Reset() 153 154 maskMemory(t, testCtx, mod, 1024) 155 156 if tc.mem != nil { 157 mod.Memory().Write(testCtx, tc.in, tc.mem) 158 } 159 160 requireErrno(t, tc.expectedErrno, mod, functionPollOneoff, uint64(tc.in), uint64(tc.out), 161 uint64(tc.nsubscriptions), uint64(tc.resultNevents)) 162 require.Equal(t, tc.expectedLog, "\n"+log.String()) 163 164 out, ok := mod.Memory().Read(testCtx, tc.out, uint32(len(tc.expectedMem))) 165 require.True(t, ok) 166 require.Equal(t, tc.expectedMem, out) 167 168 // Events should be written on success regardless of nested failure. 169 if tc.expectedErrno == ErrnoSuccess { 170 nevents, ok := mod.Memory().ReadUint32Le(testCtx, tc.resultNevents) 171 require.True(t, ok) 172 require.Equal(t, uint32(1), nevents) 173 } 174 }) 175 } 176 }