Skip to content

main (test): run tests on AVR #2458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ jobs:
qemu-user \
gcc-avr \
avr-libc \
simavr \
ninja-build
- name: Install Go
uses: actions/setup-go@v2
Expand Down Expand Up @@ -213,6 +214,7 @@ jobs:
- name: Build wasi-libc
if: steps.cache-wasi-libc.outputs.cache-hit != 'true'
run: make wasi-libc
- run: make gen-device -j4
- name: Test TinyGo
run: make ASSERT=1 test
- name: Build TinyGo
Expand All @@ -227,6 +229,5 @@ jobs:
sudo tar -C /usr/local -xf xtensa-esp32-elf-gcc8_2_0-esp-2020r2-linux-amd64.tar.gz
sudo ln -s /usr/local/xtensa-esp32-elf/bin/xtensa-esp32-elf-ld /usr/local/bin/xtensa-esp32-elf-ld
rm xtensa-esp32-elf-gcc8_2_0-esp-2020r2-linux-amd64.tar.gz
- run: make gen-device -j4
- run: make smoketest
- run: make wasmtest
103 changes: 96 additions & 7 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main
import (
"bufio"
"bytes"
"errors"
"flag"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -72,6 +73,7 @@ func TestCompiler(t *testing.T) {
}

t.Run("Host", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("", sema), tests, t)
})

Expand Down Expand Up @@ -127,34 +129,107 @@ func TestCompiler(t *testing.T) {
}

t.Run("EmulatedCortexM3", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("cortex-m-qemu", sema), tests, t)
})

t.Run("EmulatedRISCV", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("riscv-qemu", sema), tests, t)
})

t.Run("AVR", func(t *testing.T) {
// LLVM backend crash:
// LIBCLANG FATAL ERROR: Cannot select: t3: i16 = JumpTable<0>
// This bug is non-deterministic, and only happens when run concurrently with non-AVR tests.
Copy link
Member

@aykevl aykevl Jan 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh. Yeah that's bad. I hope we can fix this (after this PR is merged, in LLVM probably).

// For this reason, we do not t.Parallel() here.

var avrTests []string
for _, t := range tests {
switch t {
case "atomic.go":
// Not supported due to unaligned atomic accesses.

case "reflect.go":
// Reflect tests do not work due to type code issues.

case "gc.go":
// Does not pass due to high mark false positive rate.

case "json.go", "stdlib.go", "testing.go":
// Breaks interp.

case "map.go":
// Reflect size calculation crashes.

case "binop.go":
// Interface comparison results are inverted.

case "channel.go":
// Freezes after recv from closed channel.

case "float.go", "math.go", "print.go":
// Stuck in runtime.printfloat64.

case "goroutines.go":
// The main() never runs.

case "interface.go":
// Several comparison tests fail.

case "cgo/":
// CGo does not work on AVR.

default:
avrTests = append(avrTests, t)
}
}
opts := optionsFromTarget("atmega1284p", sema)
opts.Scheduler = "tasks"
runPlatTests(opts, avrTests, t)
})

if runtime.GOOS == "linux" {
t.Run("X86Linux", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromOSARCH("linux/386", sema), tests, t)
})
t.Run("ARMLinux", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromOSARCH("linux/arm/6", sema), tests, t)
})
t.Run("ARM64Linux", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromOSARCH("linux/arm64", sema), tests, t)
})
t.Run("WebAssembly", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasm", sema), tests, t)
})
t.Run("WASI", func(t *testing.T) {
t.Parallel()
runPlatTests(optionsFromTarget("wasi", sema), tests, t)
})
}
}

func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
t.Parallel()
// Check if the emulator is installed.
spec, err := compileopts.LoadTarget(&options)
if err != nil {
t.Fatal("failed to load target spec:", err)
}
if len(spec.Emulator) != 0 {
_, err := exec.LookPath(spec.Emulator[0])
if err != nil {
if errors.Is(err, exec.ErrNotFound) {
t.Skipf("emulator not installed: %q", spec.Emulator[0])
}

t.Errorf("searching for emulator: %v", err)
return
}
}

for _, name := range tests {
name := name // redefine to avoid race condition
Expand All @@ -163,10 +238,12 @@ func runPlatTests(options compileopts.Options, tests []string, t *testing.T) {
runTest(name, options, t, nil, nil)
})
}
t.Run("env.go", func(t *testing.T) {
t.Parallel()
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
})
if len(spec.Emulator) == 0 || spec.Emulator[0] != "simavr" {
t.Run("env.go", func(t *testing.T) {
t.Parallel()
runTest("env.go", options, t, []string{"first", "second"}, []string{"ENV1=VALUE1", "ENV2=VALUE2"})
})
}
if options.Target == "wasi" || options.Target == "wasm" {
t.Run("alias.go-scheduler-none", func(t *testing.T) {
t.Parallel()
Expand Down Expand Up @@ -319,8 +396,13 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
runComplete := make(chan struct{})
ranTooLong := false
stdout := &bytes.Buffer{}
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
if len(spec.Emulator) != 0 && spec.Emulator[0] == "simavr" {
cmd.Stdout = os.Stderr
cmd.Stderr = stdout
} else {
cmd.Stdout = stdout
cmd.Stderr = os.Stderr
}
err = cmd.Start()
if err != nil {
t.Fatal("failed to start:", err)
Expand Down Expand Up @@ -357,6 +439,13 @@ func runTestWithConfig(name string, t *testing.T, options compileopts.Options, c
actual := bytes.Replace(stdout.Bytes(), []byte{'\r', '\n'}, []byte{'\n'}, -1)
expected = bytes.Replace(expected, []byte{'\r', '\n'}, []byte{'\n'}, -1) // for Windows

if len(spec.Emulator) != 0 && spec.Emulator[0] == "simavr" {
// Strip simavr log formatting.
actual = bytes.Replace(actual, []byte{0x1b, '[', '3', '2', 'm'}, nil, -1)
actual = bytes.Replace(actual, []byte{0x1b, '[', '0', 'm'}, nil, -1)
actual = bytes.Replace(actual, []byte{'.', '.', '\n'}, []byte{'\n'}, -1)
}

// Check whether the command ran successfully.
fail := false
if err != nil {
Expand Down
6 changes: 5 additions & 1 deletion src/runtime/runtime_avr.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build avr
// +build avr

package runtime
Expand Down Expand Up @@ -111,7 +112,10 @@ func exit(code int) {
}

func abort() {
// Disable interrupts and go to sleep.
// This can never be awoken except for reset, and is recogized as termination by simavr.
avr.Asm("cli")
for {
sleepWDT(WDT_PERIOD_2S)
avr.Asm("sleep")
}
}