test: support non-host tests
For example, for running tests with -target=wasm or -target=cortex-m-qemu. It looks at the output to determine whether tests were successful in the absence of a status code.
Этот коммит содержится в:
родитель
1096596b69
коммит
b713001313
6 изменённых файлов: 72 добавлений и 14 удалений
54
main.go
54
main.go
|
@ -128,22 +128,50 @@ func Test(pkgName string, options *compileopts.Options) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
return builder.Build(pkgName, ".elf", config, func(result builder.BuildResult) error {
|
||||||
cmd := exec.Command(result.Binary)
|
if len(config.Target.Emulator) == 0 {
|
||||||
cmd.Stdout = os.Stdout
|
// Run directly.
|
||||||
cmd.Stderr = os.Stderr
|
cmd := exec.Command(result.Binary)
|
||||||
cmd.Dir = result.MainDir
|
cmd.Stdout = os.Stdout
|
||||||
err := cmd.Run()
|
cmd.Stderr = os.Stderr
|
||||||
if err != nil {
|
cmd.Dir = result.MainDir
|
||||||
// Propagate the exit code
|
err := cmd.Run()
|
||||||
if err, ok := err.(*exec.ExitError); ok {
|
if err != nil {
|
||||||
if status, ok := err.Sys().(syscall.WaitStatus); ok {
|
// Propagate the exit code
|
||||||
os.Exit(status.ExitStatus())
|
if err, ok := err.(*exec.ExitError); ok {
|
||||||
|
if status, ok := err.Sys().(syscall.WaitStatus); ok {
|
||||||
|
os.Exit(status.ExitStatus())
|
||||||
|
}
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
return &commandError{"failed to run compiled binary", result.Binary, err}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// Run in an emulator.
|
||||||
|
args := append(config.Target.Emulator[1:], result.Binary)
|
||||||
|
cmd := exec.Command(config.Target.Emulator[0], args...)
|
||||||
|
buf := &bytes.Buffer{}
|
||||||
|
w := io.MultiWriter(os.Stdout, buf)
|
||||||
|
cmd.Stdout = w
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
if err, ok := err.(*exec.ExitError); !ok || !err.Exited() {
|
||||||
|
// Workaround for QEMU which always exits with an error.
|
||||||
|
return &commandError{"failed to run emulator with", result.Binary, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testOutput := string(buf.Bytes())
|
||||||
|
if testOutput == "PASS\n" || strings.HasSuffix(testOutput, "\nPASS\n") {
|
||||||
|
// Test passed.
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
// Test failed, either by ending with the word "FAIL" or with a
|
||||||
|
// panic of some sort.
|
||||||
|
os.Exit(1)
|
||||||
|
return nil // unreachable
|
||||||
}
|
}
|
||||||
return &commandError{"failed to run compiled binary", result.Binary, err}
|
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,4 +39,9 @@ func libc_free(ptr unsafe.Pointer) {
|
||||||
free(ptr)
|
free(ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:linkname syscall_Exit syscall.Exit
|
||||||
|
func syscall_Exit(code int) {
|
||||||
|
abort()
|
||||||
|
}
|
||||||
|
|
||||||
const baremetal = true
|
const baremetal = true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// +build cortexm,!nxp
|
// +build cortexm,!nxp,!qemu
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@ func postinit() {}
|
||||||
func main() {
|
func main() {
|
||||||
preinit()
|
preinit()
|
||||||
run()
|
run()
|
||||||
|
|
||||||
|
// Signal successful exit.
|
||||||
arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingApplicationExit)
|
arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingApplicationExit)
|
||||||
abort()
|
abort()
|
||||||
}
|
}
|
||||||
|
@ -54,3 +56,13 @@ func putchar(c byte) {
|
||||||
func waitForEvents() {
|
func waitForEvents() {
|
||||||
arm.Asm("wfe")
|
arm.Asm("wfe")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func abort() {
|
||||||
|
// Signal an abnormal exit.
|
||||||
|
arm.SemihostingCall(arm.SemihostingReportException, arm.SemihostingRunTimeErrorUnknown)
|
||||||
|
|
||||||
|
// Lock up forever (should be unreachable).
|
||||||
|
for {
|
||||||
|
arm.Asm("wfi")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -195,6 +195,8 @@ func (m *M) Run() int {
|
||||||
if failures > 0 {
|
if failures > 0 {
|
||||||
fmt.Printf("exit status %d\n", failures)
|
fmt.Printf("exit status %d\n", failures)
|
||||||
fmt.Println("FAIL")
|
fmt.Println("FAIL")
|
||||||
|
} else {
|
||||||
|
fmt.Println("PASS")
|
||||||
}
|
}
|
||||||
return failures
|
return failures
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,6 +289,17 @@
|
||||||
setTimeout(this._inst.exports.go_scheduler, timeout);
|
setTimeout(this._inst.exports.go_scheduler, timeout);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// func Exit(code int)
|
||||||
|
"syscall.Exit": (code) => {
|
||||||
|
if (global.process) {
|
||||||
|
// Node.js
|
||||||
|
process.exit(code);
|
||||||
|
} else {
|
||||||
|
// Can't exit in a browser.
|
||||||
|
throw 'trying to exit with code ' + code;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// func finalizeRef(v ref)
|
// func finalizeRef(v ref)
|
||||||
"syscall/js.finalizeRef": (sp) => {
|
"syscall/js.finalizeRef": (sp) => {
|
||||||
// Note: TinyGo does not support finalizers so this should never be
|
// Note: TinyGo does not support finalizers so this should never be
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче