Skip to content

Commit 320b68e

Browse files
committed
More tests.
1 parent 2c3850e commit 320b68e

File tree

2 files changed

+166
-30
lines changed

2 files changed

+166
-30
lines changed

sqlite3/libc/libc_test.go

Lines changed: 163 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
_ "embed"
66
"os"
7+
"strings"
78
"testing"
89

910
"github.com/tetratelabs/wazero"
@@ -209,42 +210,117 @@ func Benchmark_strcspn(b *testing.B) {
209210
}
210211
}
211212

212-
func Test_memchr(t *testing.T) {
213-
for length := range 64 {
214-
for pos := range length + 2 {
215-
for alignment := range 24 {
216-
ptr := (page - 8) + alignment
217-
want := 0
218-
if pos < length {
219-
want = ptr + pos
220-
}
213+
func Test_memcmp(t *testing.T) {
214+
const s1 string = "" +
215+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
216+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
217+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
218+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
219+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
220+
"\x14\xf4\x93\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
221+
"\x94\xf3\x93\x01\x74\x80\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
222+
"\x7f\xf3\x93\x01\x00\x01"
223+
const s2 string = "" +
224+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
225+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
226+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
227+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
228+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
229+
"\xbc\x40\x96\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
230+
"\x94\xf3\x93\x01\x74\x7f\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
231+
"\x80\xf3\x93\x01\x00\x02"
232+
233+
p1 := ptr1
234+
p2 := len(memory) - len(s2)
221235

222-
clear(memory[:2*page])
223-
fill(memory[ptr:ptr+max(pos, length)], 5)
224-
memory[ptr+pos] = 7
225-
226-
got := call(memchr, uint64(ptr), 7, uint64(length))
227-
if uint32(got) != uint32(want) {
228-
t.Errorf("memchr(%d, %d, %d) = %d, want %d",
229-
ptr, 7, uint64(length), uint32(got), uint32(want))
230-
}
236+
clear(memory)
237+
copy(memory[p1:], s1)
238+
copy(memory[p2:], s2)
239+
240+
for i := range len(s1) + 1 {
241+
for j := range len(s1) - i {
242+
want := strings.Compare(s1[i:i+j], s2[i:i+j])
243+
got := call(memcmp, uint64(p1+i), uint64(p2+i), uint64(j))
244+
if sign(int32(got)) != want {
245+
t.Errorf("strcmp(%d, %d, %d) = %d, want %d",
246+
ptr1+i, ptr2+i, j, int32(got), want)
231247
}
232248
}
249+
}
250+
}
233251

234-
clear(memory)
235-
ptr := len(memory) - length
236-
fill(memory[ptr:ptr+length], 5)
237-
memory[len(memory)-1] = 7
252+
func Test_strcmp(t *testing.T) {
253+
const s1 string = "" +
254+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
255+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
256+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
257+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
258+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
259+
"\x14\xf4\x93\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
260+
"\x94\xf3\x93\x01\x74\x80\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
261+
"\x7f\xf3\x93\x01\x00\x01"
262+
const s2 string = "" +
263+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
264+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
265+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
266+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
267+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
268+
"\xbc\x40\x96\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
269+
"\x94\xf3\x93\x01\x74\x7f\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
270+
"\x80\xf3\x93\x01\x00\x02"
271+
272+
p1 := ptr1
273+
p2 := len(memory) - len(s2) - 1
238274

239-
want := len(memory) - 1
240-
if length == 0 {
241-
want = 0
275+
clear(memory)
276+
copy(memory[p1:], s1)
277+
copy(memory[p2:], s2)
278+
279+
for i := range len(s1) + 1 {
280+
want := strings.Compare(term(s1[i:]), term(s2[i:]))
281+
got := call(strcmp, uint64(p1+i), uint64(p2+i))
282+
if sign(int32(got)) != want {
283+
t.Errorf("strcmp(%d, %d) = %d, want %d",
284+
p1+i, ptr2+i, int32(got), want)
242285
}
286+
}
287+
}
243288

244-
got := call(memchr, uint64(ptr), 7, uint64(length))
245-
if uint32(got) != uint32(want) {
246-
t.Errorf("memchr(%d, %d, %d) = %d, want %d",
247-
ptr, 7, uint64(length), uint32(got), uint32(want))
289+
func Test_strncmp(t *testing.T) {
290+
const s1 string = "" +
291+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
292+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
293+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
294+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
295+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
296+
"\x14\xf4\x93\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
297+
"\x94\xf3\x93\x01\x74\x80\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
298+
"\x7f\xf3\x93\x01\x00\x01"
299+
const s2 string = "" +
300+
"\x94\x63\x8f\x01\x74\x63\x8f\x01\x54\x63\x8f\x01\x34\x63\x8f\x01" +
301+
"\xb4\xf2\x93\x01\x94\xf2\x93\x01\x54\xf1\x93\x01\x34\xf1\x93\x01" +
302+
"\x14\xf1\x93\x01\x14\xf2\x93\x01\x34\xf2\x93\x01\x54\xf2\x93\x01" +
303+
"\x74\xf2\x93\x01\x74\xf1\x93\x01\xd4\xf2\x93\x01\x94\xf1\x93\x01" +
304+
"\xb4\xf1\x93\x01\xd4\xf1\x93\x01\xf4\xf1\x93\x01\xf4\xf2\x93\x01" +
305+
"\xbc\x40\x96\x01\xf4\xf3\x93\x01\xd4\xf3\x93\x01\xb4\xf3\x93\x01" +
306+
"\x94\xf3\x93\x01\x74\x7f\x93\x01\x54\xf3\x93\x01\x34\xf3\x93\x01" +
307+
"\x80\xf3\x93\x01\x00\x02"
308+
309+
p1 := ptr1
310+
p2 := len(memory) - len(s2) - 1
311+
312+
clear(memory)
313+
copy(memory[p1:], s1)
314+
copy(memory[p2:], s2)
315+
316+
for i := range len(s1) + 1 {
317+
for j := range len(s1) - i + 1 {
318+
want := strings.Compare(term(s1[i:i+j]), term(s2[i:i+j]))
319+
got := call(strncmp, uint64(p1+i), uint64(p2+i), uint64(j))
320+
if sign(int32(got)) != want {
321+
t.Errorf("strncmp(%d, %d, %d) = %d, want %d",
322+
ptr1+i, ptr2+i, j, int32(got), want)
323+
}
248324
}
249325
}
250326
}
@@ -283,6 +359,46 @@ func Test_strlen(t *testing.T) {
283359
}
284360
}
285361

362+
func Test_memchr(t *testing.T) {
363+
for length := range 64 {
364+
for pos := range length + 2 {
365+
for alignment := range 24 {
366+
ptr := (page - 8) + alignment
367+
want := 0
368+
if pos < length {
369+
want = ptr + pos
370+
}
371+
372+
clear(memory[:2*page])
373+
fill(memory[ptr:ptr+max(pos, length)], 5)
374+
memory[ptr+pos] = 7
375+
376+
got := call(memchr, uint64(ptr), 7, uint64(length))
377+
if uint32(got) != uint32(want) {
378+
t.Errorf("memchr(%d, %d, %d) = %d, want %d",
379+
ptr, 7, uint64(length), uint32(got), uint32(want))
380+
}
381+
}
382+
}
383+
384+
clear(memory)
385+
ptr := len(memory) - length
386+
fill(memory[ptr:ptr+length], 5)
387+
memory[len(memory)-1] = 7
388+
389+
want := len(memory) - 1
390+
if length == 0 {
391+
want = 0
392+
}
393+
394+
got := call(memchr, uint64(ptr), 7, uint64(length))
395+
if uint32(got) != uint32(want) {
396+
t.Errorf("memchr(%d, %d, %d) = %d, want %d",
397+
ptr, 7, uint64(length), uint32(got), uint32(want))
398+
}
399+
}
400+
}
401+
286402
func Test_strchr(t *testing.T) {
287403
for length := range 64 {
288404
for pos := range length + 2 {
@@ -484,3 +600,21 @@ func fill(s []byte, v byte) {
484600
s[i] = v
485601
}
486602
}
603+
604+
func sign(x int32) int {
605+
switch {
606+
case x > 0:
607+
return +1
608+
case x < 0:
609+
return -1
610+
default:
611+
return 0
612+
}
613+
}
614+
615+
func term(s string) string {
616+
if i := strings.IndexByte(s, 0); i >= 0 {
617+
return s[:i]
618+
}
619+
return s
620+
}

sqlite3/libc/string.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ int memcmp(const void *v1, const void *v2, size_t n) {
5656
size_t ctz = __builtin_ctz(~wasm_i8x16_bitmask(cmp));
5757
const unsigned char *u1 = (unsigned char *)w1 + ctz;
5858
const unsigned char *u2 = (unsigned char *)w2 + ctz;
59+
// This may help the compiler if the function is inlined.
60+
__builtin_assume(*u1 - *u2 != 0);
5961
return *u1 - *u2;
6062
}
6163
w1++;
@@ -423,7 +425,7 @@ size_t strcspn(const char *s, const char *c) {
423425
// these are best implemented as
424426
// small wrappers over those functions.
425427

426-
// Simple wrappers from musl:
428+
// Simple wrappers already in musl:
427429
// - mempcpy
428430
// - strcat
429431
// - strdup

0 commit comments

Comments
 (0)