267 lines
6.3 KiB
Go
267 lines
6.3 KiB
Go
//go:build !llgo
|
|
// +build !llgo
|
|
|
|
package build
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/goplus/llgo/internal/mockable"
|
|
)
|
|
|
|
func mockRun(args []string, cfg *Config) {
|
|
const maxAttempts = 3
|
|
var lastErr error
|
|
var lastPanic interface{}
|
|
for attempt := 0; attempt < maxAttempts; attempt++ {
|
|
mockable.EnableMock()
|
|
func() {
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
if r != "exit" {
|
|
lastPanic = r
|
|
} else {
|
|
exitCode := mockable.ExitCode()
|
|
if (exitCode != 0) != false {
|
|
lastPanic = fmt.Errorf("got exit code %d", exitCode)
|
|
}
|
|
}
|
|
}
|
|
}()
|
|
file, _ := os.CreateTemp("", "llgo-*")
|
|
cfg.OutFile = file.Name()
|
|
file.Close()
|
|
defer os.Remove(cfg.OutFile)
|
|
_, err := Do(args, cfg)
|
|
if err == nil {
|
|
return // Success, return immediately from the inner function
|
|
}
|
|
lastErr = err
|
|
}()
|
|
|
|
if lastPanic == nil && lastErr == nil {
|
|
return // Success, return from mockRun
|
|
}
|
|
// Continue to next attempt if this one failed
|
|
}
|
|
// If we get here, all attempts failed
|
|
if lastPanic != nil {
|
|
panic(lastPanic)
|
|
}
|
|
panic(fmt.Errorf("all %d attempts failed, last error: %v", maxAttempts, lastErr))
|
|
}
|
|
|
|
func TestRun(t *testing.T) {
|
|
mockRun([]string{"../../cl/_testgo/print"}, &Config{Mode: ModeRun})
|
|
}
|
|
|
|
func TestTest(t *testing.T) {
|
|
// FIXME(zzy): with builtin package test in a llgo test ./... will cause duplicate symbol error
|
|
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeTest})
|
|
}
|
|
|
|
func TestExtest(t *testing.T) {
|
|
originalStdout := os.Stdout
|
|
defer func() { os.Stdout = originalStdout }()
|
|
|
|
r, w, err := os.Pipe()
|
|
if err != nil {
|
|
t.Fatalf("os.Pipe failed: %v", err)
|
|
}
|
|
os.Stdout = w
|
|
outputChan := make(chan string)
|
|
go func() {
|
|
var data bytes.Buffer
|
|
io.Copy(&data, r)
|
|
outputChan <- data.String()
|
|
}()
|
|
|
|
mockRun([]string{"../../cl/_testgo/runextest/..."}, &Config{Mode: ModeTest})
|
|
|
|
w.Close()
|
|
got := <-outputChan
|
|
expected := "PASS\nPASS\nPASS\nPASS\n"
|
|
if got != expected {
|
|
t.Errorf("Expected output %q, but got %q", expected, got)
|
|
}
|
|
}
|
|
|
|
func TestCmpTest(t *testing.T) {
|
|
mockRun([]string{"../../cl/_testgo/runtest"}, &Config{Mode: ModeCmpTest})
|
|
}
|
|
|
|
func TestGenerateOutputFilenames(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
outFile string
|
|
binPath string
|
|
appExt string
|
|
binExt string
|
|
pkgName string
|
|
mode Mode
|
|
isMultiplePkgs bool
|
|
wantAppSuffix string
|
|
wantOrgAppDiff bool // true if orgApp should be different from app
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "empty outFile, single package",
|
|
outFile: "",
|
|
binPath: "/usr/local/bin",
|
|
appExt: "",
|
|
binExt: "",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "/usr/local/bin/hello",
|
|
wantOrgAppDiff: false,
|
|
},
|
|
{
|
|
name: "empty outFile with appExt",
|
|
outFile: "",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: "",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "/usr/local/bin/hello.exe",
|
|
wantOrgAppDiff: false,
|
|
},
|
|
{
|
|
name: "outFile without binExt",
|
|
outFile: "myapp",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: "",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "myapp.exe",
|
|
wantOrgAppDiff: false,
|
|
},
|
|
{
|
|
name: "outFile with existing extension, no binExt",
|
|
outFile: "myapp.exe",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: "",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "myapp.exe",
|
|
wantOrgAppDiff: false,
|
|
},
|
|
{
|
|
name: "outFile with binExt, different from existing extension",
|
|
outFile: "myapp",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: ".bin",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "myapp.bin",
|
|
wantOrgAppDiff: true,
|
|
},
|
|
{
|
|
name: "outFile already ends with binExt",
|
|
outFile: "t.bin",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: ".bin",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "t.bin",
|
|
wantOrgAppDiff: true,
|
|
},
|
|
{
|
|
name: "outFile with full path already ends with binExt",
|
|
outFile: "/path/to/t.bin",
|
|
binPath: "/usr/local/bin",
|
|
appExt: ".exe",
|
|
binExt: ".bin",
|
|
pkgName: "hello",
|
|
mode: ModeBuild,
|
|
isMultiplePkgs: false,
|
|
wantAppSuffix: "/path/to/t.bin",
|
|
wantOrgAppDiff: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
app, orgApp, err := generateOutputFilenames(
|
|
tt.outFile,
|
|
tt.binPath,
|
|
tt.appExt,
|
|
tt.binExt,
|
|
tt.pkgName,
|
|
tt.mode,
|
|
tt.isMultiplePkgs,
|
|
)
|
|
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("generateOutputFilenames() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
|
|
if tt.wantAppSuffix != "" {
|
|
if app != tt.wantAppSuffix {
|
|
t.Errorf("generateOutputFilenames() app = %v, want %v", app, tt.wantAppSuffix)
|
|
}
|
|
}
|
|
|
|
if tt.wantOrgAppDiff {
|
|
if app == orgApp {
|
|
t.Errorf("generateOutputFilenames() orgApp should be different from app, but both are %v", app)
|
|
}
|
|
// Clean up temp file
|
|
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
|
os.Remove(orgApp)
|
|
}
|
|
} else {
|
|
if app != orgApp {
|
|
t.Errorf("generateOutputFilenames() orgApp = %v, want %v (same as app)", orgApp, app)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGenerateOutputFilenames_EdgeCases(t *testing.T) {
|
|
// Test case where outFile has same extension as binExt
|
|
app, orgApp, err := generateOutputFilenames(
|
|
"firmware.bin",
|
|
"/usr/local/bin",
|
|
".exe",
|
|
".bin",
|
|
"esp32app",
|
|
ModeBuild,
|
|
false,
|
|
)
|
|
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
if app != "firmware.bin" {
|
|
t.Errorf("Expected app to be 'firmware.bin', got '%s'", app)
|
|
}
|
|
|
|
if app == orgApp {
|
|
t.Errorf("Expected orgApp to be different from app when binExt is present, but both are '%s'", app)
|
|
}
|
|
|
|
// Clean up temp file
|
|
if orgApp != "" && strings.Contains(orgApp, "llgo-") {
|
|
os.Remove(orgApp)
|
|
}
|
|
}
|