-
Notifications
You must be signed in to change notification settings - Fork 909
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
129 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
//go:build tinygo.wasm | ||
// +build tinygo.wasm | ||
|
||
package runtime_wasi | ||
|
||
import ( | ||
"reflect" | ||
"runtime" | ||
"strconv" | ||
"testing" | ||
"unsafe" | ||
) | ||
|
||
//export malloc | ||
func libc_malloc(size uintptr) unsafe.Pointer | ||
|
||
//export free | ||
func libc_free(ptr unsafe.Pointer) | ||
|
||
//export calloc | ||
func libc_calloc(nmemb, size uintptr) unsafe.Pointer | ||
|
||
//export realloc | ||
func libc_realloc(ptr unsafe.Pointer, size uintptr) unsafe.Pointer | ||
|
||
func getFilledBuffer_malloc() uintptr { | ||
ptr := libc_malloc(5) | ||
fillPanda(ptr) | ||
return uintptr(ptr) | ||
} | ||
|
||
func getFilledBuffer_calloc() uintptr { | ||
ptr := libc_calloc(2, 5) | ||
fillPanda(ptr) | ||
*(*byte)(unsafe.Add(ptr, 5)) = 'b' | ||
*(*byte)(unsafe.Add(ptr, 6)) = 'e' | ||
*(*byte)(unsafe.Add(ptr, 7)) = 'a' | ||
*(*byte)(unsafe.Add(ptr, 8)) = 'r' | ||
*(*byte)(unsafe.Add(ptr, 9)) = 's' | ||
return uintptr(ptr) | ||
} | ||
|
||
func getFilledBuffer_realloc() uintptr { | ||
origPtr := getFilledBuffer_malloc() | ||
ptr := libc_realloc(unsafe.Pointer(origPtr), 9) | ||
*(*byte)(unsafe.Add(ptr, 5)) = 'b' | ||
*(*byte)(unsafe.Add(ptr, 6)) = 'e' | ||
*(*byte)(unsafe.Add(ptr, 7)) = 'a' | ||
*(*byte)(unsafe.Add(ptr, 8)) = 'r' | ||
return uintptr(ptr) | ||
} | ||
|
||
func getFilledBuffer_reallocNil() uintptr { | ||
ptr := libc_realloc(nil, 5) | ||
fillPanda(ptr) | ||
return uintptr(ptr) | ||
} | ||
|
||
func fillPanda(ptr unsafe.Pointer) { | ||
*(*byte)(unsafe.Add(ptr, 0)) = 'p' | ||
*(*byte)(unsafe.Add(ptr, 1)) = 'a' | ||
*(*byte)(unsafe.Add(ptr, 2)) = 'n' | ||
*(*byte)(unsafe.Add(ptr, 3)) = 'd' | ||
*(*byte)(unsafe.Add(ptr, 4)) = 'a' | ||
} | ||
|
||
func checkFilledBuffer(t *testing.T, ptr uintptr, content string) { | ||
t.Helper() | ||
buf := *(*string)(unsafe.Pointer(&reflect.StringHeader{ | ||
Data: ptr, | ||
Len: uintptr(len(content)), | ||
})) | ||
if buf != content { | ||
t.Errorf("expected %q, got %q", content, buf) | ||
} | ||
} | ||
|
||
func TestMallocFree(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
getBuffer func() uintptr | ||
content string | ||
}{ | ||
{ | ||
name: "malloc", | ||
getBuffer: getFilledBuffer_malloc, | ||
content: "panda", | ||
}, | ||
{ | ||
name: "calloc", | ||
getBuffer: getFilledBuffer_calloc, | ||
content: "pandabears", | ||
}, | ||
{ | ||
name: "realloc", | ||
getBuffer: getFilledBuffer_realloc, | ||
content: "pandabear", | ||
}, | ||
{ | ||
name: "realloc nil", | ||
getBuffer: getFilledBuffer_reallocNil, | ||
content: "panda", | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
tt := tc | ||
t.Run(tt.name, func(t *testing.T) { | ||
bufPtr := tt.getBuffer() | ||
// Don't use defer to free the buffer as it seems to cause the GC to track it. | ||
|
||
// Churn GC, the pointer should still be valid until free is called. | ||
for i := 0; i < 1000; i++ { | ||
a := "hello" + strconv.Itoa(i) | ||
// Some conditional logic to ensure optimization doesn't remove the loop completely. | ||
if len(a) < 0 { | ||
break | ||
} | ||
runtime.GC() | ||
} | ||
|
||
checkFilledBuffer(t, bufPtr, tt.content) | ||
|
||
libc_free(unsafe.Pointer(bufPtr)) | ||
}) | ||
} | ||
} |