test: simple llgo tests

This commit is contained in:
Li Jie
2024-06-06 20:54:32 +08:00
parent 6049cf9047
commit 91e1fa6aff
6 changed files with 204 additions and 5 deletions

101
_test/bdwgc.go Normal file
View File

@@ -0,0 +1,101 @@
package main
import (
"unsafe"
"github.com/goplus/llgo/_test/testing"
"github.com/goplus/llgo/c"
"github.com/goplus/llgo/internal/runtime/bdwgc"
)
// ------ Test malloc ------
func TestMalloc(t *testing.T) {
pn := (*int)(bdwgc.Malloc(unsafe.Sizeof(int(0))))
*pn = 1 << 30
c.Printf(c.Str("value: %d, %x, %p, %p\n"), *pn, *pn, pn, &pn)
pl := (*int64)(bdwgc.Realloc(c.Pointer(pn), unsafe.Sizeof(int64(0))))
*pl = 1 << 60
c.Printf(c.Str("value: %lld, %llx, %p, %p\n"), *pl, *pl, pl, &pl)
bdwgc.Free(c.Pointer(pl))
}
// ------ Test finalizer ------
const (
RETURN_VALUE_FREED = 1 << 31
)
var called uint = 0
func setReturnValueFreed(pobj c.Pointer, clientData c.Pointer) {
called |= RETURN_VALUE_FREED
c.Printf(c.Str("called: %x\n"), called)
}
func setLoopValueFreed(pobj c.Pointer, clientData c.Pointer) {
pmask := (*uint)(clientData)
called |= *pmask
c.Printf(c.Str("called: %x\n"), called)
}
func isCalled(mask uint) bool {
return called&mask != 0
}
func returnValue() *int {
pn := bdwgc.Malloc(unsafe.Sizeof(int(0)))
bdwgc.RegisterFinalizer(pn, setReturnValueFreed, nil, nil, nil)
return (*int)(pn)
}
func callFunc() {
pn := returnValue()
*pn = 1 << 30
c.Printf(c.Str("value: %d, %x, %p, %p\n"), *pn, *pn, pn, &pn)
bdwgc.Gcollect()
check(!isCalled(RETURN_VALUE_FREED), c.Str("finalizer should not be called"))
}
func loop() {
for i := 0; i < 5; i++ {
p := bdwgc.Malloc(unsafe.Sizeof(int(0)))
pn := (*int)(p)
*pn = i
c.Printf(c.Str("value: %d, %x, %p, %p\n"), *pn, *pn, pn, &pn)
pflag := (*uint)(c.Malloc(unsafe.Sizeof(uint(0))))
*pflag = 1 << i
bdwgc.RegisterFinalizer(p, setLoopValueFreed, c.Pointer(pflag), nil, nil)
bdwgc.Gcollect()
check(!isCalled(1<<i), c.Str("finalizer should not be called"))
for j := 0; j < i; j++ {
check(isCalled(1<<j), c.Str("finalizers of previous objects should be called"))
}
}
}
// Clear stack to avoid reference
func clearStack() {
p := c.Alloca(128)
c.Memset(p, 0, 128)
}
func check(b bool, msg *c.Char) {
if !b {
c.Printf(c.Str("check failed: %s\n"), msg)
panic("check failed")
}
}
func TestFinalizer(t *testing.T) {
bdwgc.Init()
callFunc()
clearStack()
bdwgc.Gcollect()
check(isCalled(RETURN_VALUE_FREED), c.Str("finalizer should be called"))
loop()
}

31
_test/main.go Normal file
View File

@@ -0,0 +1,31 @@
package main
import (
"github.com/goplus/llgo/_test/testing"
"github.com/goplus/llgo/c"
)
type TestCase struct {
Name string
F func(*testing.T)
}
func main() {
tests := []TestCase{
{"TestMalloc", TestMalloc},
{"TestFinalizer", TestFinalizer},
}
if c.Argc == 1 {
for _, test := range tests {
c.Printf(c.Str("%s\n"), c.AllocaCStr(test.Name))
}
return
}
c.Fprintf(c.Stderr, c.Str("arg: %s\n"), c.Index(c.Argv, 1))
idx := int(c.Atoi(c.Index(c.Argv, 1)))
if idx < 0 || idx >= len(tests) {
c.Printf(c.Str("invalid test index %d"), idx)
panic("invalid test index")
}
tests[idx].F(nil)
}

28
_test/run.sh Normal file
View File

@@ -0,0 +1,28 @@
#!/bin/bash
set -e
testcmd=/tmp/test
llgo build -o $testcmd ./_test
cases=$($testcmd)
total=$(echo "$cases" | wc -l | tr -d ' ')
succ=0
for idx in $(seq 1 $((total))); do
case=$(echo "$cases" | sed -n "${idx}p")
case_id=$(echo "$case" | cut -d',' -f1)
case_name=$(echo "$case" | cut -d',' -f2)
echo "=== Test case: $case_name"
set +e
out=$("$testcmd" "$((idx-1))" 2>&1)
exit_code=$?
set -e
if [ "${exit_code:-0}" -ne 0 ]; then
echo "failed: $out"
else
succ=$((succ+1))
echo "passed"
fi
done
echo "=== Done"
echo "$succ/$total tests passed"
if [ "$total" -ne "$succ" ]; then
exit 1
fi

4
_test/testing/testing.go Normal file
View File

@@ -0,0 +1,4 @@
package testing
type T struct {
}