367 lines
8.9 KiB
Go
367 lines
8.9 KiB
Go
//go:build !llgo
|
|
// +build !llgo
|
|
|
|
package build
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/goplus/llgo/internal/crosscompile"
|
|
"github.com/goplus/llgo/internal/flash"
|
|
)
|
|
|
|
func TestBuildOutFmtsWithTarget(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
conf *Config
|
|
pkgName string
|
|
crossCompile crosscompile.Export
|
|
wantOut string // use empty string to indicate temp file
|
|
wantBin string
|
|
wantHex string
|
|
wantImg string
|
|
wantUf2 string
|
|
wantZip string
|
|
}{
|
|
{
|
|
name: "build with -o",
|
|
conf: &Config{
|
|
Mode: ModeBuild,
|
|
OutFile: "myapp",
|
|
AppExt: "",
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "",
|
|
},
|
|
wantOut: "myapp",
|
|
},
|
|
{
|
|
name: "build hex format",
|
|
conf: &Config{
|
|
Mode: ModeBuild,
|
|
Target: "esp32",
|
|
AppExt: ".elf",
|
|
OutFmts: OutFmts{Hex: true},
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "esp32", // This will auto-set Bin: true
|
|
},
|
|
wantOut: "hello.elf",
|
|
wantBin: "hello.bin", // Now expected due to esp32 BinaryFormat
|
|
wantHex: "hello.hex",
|
|
},
|
|
{
|
|
name: "emulator mode with bin format",
|
|
conf: &Config{
|
|
Mode: ModeRun,
|
|
Target: "esp32",
|
|
AppExt: ".elf",
|
|
Emulator: true,
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "esp32",
|
|
Emulator: "qemu-system-xtensa -machine esp32 -kernel {bin}",
|
|
},
|
|
wantBin: ".bin", // Should be temp file with .bin extension
|
|
},
|
|
{
|
|
name: "flash command with hex format",
|
|
conf: &Config{
|
|
Mode: ModeInstall,
|
|
Target: "esp32",
|
|
AppExt: ".elf",
|
|
Emulator: false,
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "esp32", // This will auto-set Bin: true
|
|
Device: flash.Device{
|
|
Flash: flash.Flash{
|
|
Method: "command",
|
|
Command: "esptool.py --chip esp32 write_flash 0x10000 {hex}",
|
|
},
|
|
},
|
|
},
|
|
wantBin: ".bin", // Expected due to esp32 BinaryFormat
|
|
wantHex: ".hex", // Should be temp file with .hex extension
|
|
},
|
|
{
|
|
name: "multiple formats specified",
|
|
conf: &Config{
|
|
Mode: ModeBuild,
|
|
Target: "esp32",
|
|
AppExt: ".elf",
|
|
OutFmts: OutFmts{
|
|
Bin: true,
|
|
Hex: true,
|
|
Img: true,
|
|
Uf2: true,
|
|
},
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "esp32",
|
|
},
|
|
wantOut: "hello.elf",
|
|
wantBin: "hello.bin",
|
|
wantHex: "hello.hex",
|
|
wantImg: "hello.img",
|
|
wantUf2: "hello.uf2",
|
|
wantZip: "", // Not specified
|
|
},
|
|
{
|
|
name: "no formats specified",
|
|
conf: &Config{
|
|
Mode: ModeBuild,
|
|
Target: "esp32",
|
|
AppExt: ".elf",
|
|
OutFmts: OutFmts{}, // No formats specified
|
|
},
|
|
pkgName: "hello",
|
|
crossCompile: crosscompile.Export{
|
|
BinaryFormat: "esp32",
|
|
},
|
|
wantOut: "hello.elf",
|
|
wantBin: "", // No bin file should be generated
|
|
wantHex: "", // No hex file should be generated
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
// Determine if multi-package (mock single package for simplicity)
|
|
multiPkg := false
|
|
|
|
result, err := buildOutFmts(tt.pkgName, tt.conf, multiPkg, &tt.crossCompile)
|
|
if err != nil {
|
|
t.Errorf("buildOutFmts() error = %v", err)
|
|
return
|
|
}
|
|
|
|
// Check base output path
|
|
if tt.wantOut != "" {
|
|
if result.Out != tt.wantOut {
|
|
t.Errorf("buildOutFmts().Out = %v, want %v", result.Out, tt.wantOut)
|
|
}
|
|
} else {
|
|
// Should be a temp file
|
|
if result.Out == "" || !strings.Contains(result.Out, tt.pkgName) {
|
|
t.Errorf("buildOutFmts().Out should be temp file containing %v, got %v", tt.pkgName, result.Out)
|
|
}
|
|
}
|
|
|
|
// Check format-specific paths
|
|
checkFormatPath := func(actual, expected, formatName string) {
|
|
if expected == "" {
|
|
// Empty means no file should be generated
|
|
if actual != "" {
|
|
t.Errorf("buildOutFmts().%s = %v, want empty (no file generated)", formatName, actual)
|
|
}
|
|
} else if strings.HasPrefix(expected, ".") && !strings.Contains(expected[1:], ".") {
|
|
// ".xxx" means temp file with .xxx extension
|
|
if actual == "" {
|
|
t.Errorf("buildOutFmts().%s = empty, want temp file with %s extension", formatName, expected)
|
|
} else if !strings.HasSuffix(actual, expected) || !strings.Contains(actual, tt.pkgName) {
|
|
t.Errorf("buildOutFmts().%s should be temp file with %s extension containing %v, got %v", formatName, expected, tt.pkgName, actual)
|
|
}
|
|
} else {
|
|
// "aaa.xxx" means exact file name
|
|
if actual != expected {
|
|
t.Errorf("buildOutFmts().%s = %v, want %v", formatName, actual, expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
checkFormatPath(result.Bin, tt.wantBin, "Bin")
|
|
checkFormatPath(result.Hex, tt.wantHex, "Hex")
|
|
checkFormatPath(result.Img, tt.wantImg, "Img")
|
|
checkFormatPath(result.Uf2, tt.wantUf2, "Uf2")
|
|
checkFormatPath(result.Zip, tt.wantZip, "Zip")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildOutFmtsNativeTarget(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
mode Mode
|
|
multiPkg bool
|
|
outFile string
|
|
binPath string
|
|
appExt string
|
|
goos string
|
|
pkgName string
|
|
wantOut string
|
|
}{
|
|
// ModeBuild scenarios
|
|
{
|
|
name: "build single pkg no outfile macos",
|
|
mode: ModeBuild,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
appExt: "",
|
|
goos: "darwin",
|
|
pkgName: "hello",
|
|
wantOut: "hello",
|
|
},
|
|
{
|
|
name: "build single pkg no outfile linux",
|
|
mode: ModeBuild,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "hello",
|
|
},
|
|
{
|
|
name: "build single pkg no outfile windows",
|
|
mode: ModeBuild,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
appExt: ".exe",
|
|
goos: "windows",
|
|
pkgName: "hello",
|
|
wantOut: "hello.exe",
|
|
},
|
|
{
|
|
name: "build single pkg with outfile",
|
|
mode: ModeBuild,
|
|
multiPkg: false,
|
|
outFile: "myapp",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "myapp",
|
|
},
|
|
{
|
|
name: "build single pkg with outfile and ext",
|
|
mode: ModeBuild,
|
|
multiPkg: false,
|
|
outFile: "myapp.exe",
|
|
appExt: ".exe",
|
|
goos: "windows",
|
|
pkgName: "hello",
|
|
wantOut: "myapp.exe",
|
|
},
|
|
{
|
|
name: "build multi pkg",
|
|
mode: ModeBuild,
|
|
multiPkg: true,
|
|
outFile: "",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "", // Should be temp file
|
|
},
|
|
// ModeInstall scenarios
|
|
{
|
|
name: "install single pkg macos",
|
|
mode: ModeInstall,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
binPath: "/go/bin",
|
|
appExt: "",
|
|
goos: "darwin",
|
|
pkgName: "hello",
|
|
wantOut: "/go/bin/hello",
|
|
},
|
|
{
|
|
name: "install single pkg windows",
|
|
mode: ModeInstall,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
binPath: "C:/go/bin", // Use forward slashes for cross-platform compatibility
|
|
appExt: ".exe",
|
|
goos: "windows",
|
|
pkgName: "hello",
|
|
wantOut: "C:/go/bin/hello.exe",
|
|
},
|
|
{
|
|
name: "install multi pkg",
|
|
mode: ModeInstall,
|
|
multiPkg: true,
|
|
outFile: "",
|
|
binPath: "/go/bin",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "/go/bin/hello",
|
|
},
|
|
// Other modes should use temp files
|
|
{
|
|
name: "run mode",
|
|
mode: ModeRun,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "", // Should be temp file
|
|
},
|
|
{
|
|
name: "test mode",
|
|
mode: ModeTest,
|
|
multiPkg: false,
|
|
outFile: "",
|
|
appExt: "",
|
|
goos: "linux",
|
|
pkgName: "hello",
|
|
wantOut: "", // Should be temp file
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
conf := &Config{
|
|
Mode: tt.mode,
|
|
OutFile: tt.outFile,
|
|
BinPath: tt.binPath,
|
|
AppExt: tt.appExt,
|
|
Target: "", // Native target
|
|
}
|
|
|
|
crossCompile := &crosscompile.Export{}
|
|
|
|
result, err := buildOutFmts(tt.pkgName, conf, tt.multiPkg, crossCompile)
|
|
if err != nil {
|
|
t.Errorf("buildOutFmts() error = %v", err)
|
|
return
|
|
}
|
|
|
|
// Check base output path
|
|
if tt.wantOut != "" {
|
|
if result.Out != tt.wantOut {
|
|
t.Errorf("buildOutFmts().Out = %v, want %v", result.Out, tt.wantOut)
|
|
}
|
|
} else {
|
|
// Should be a temp file
|
|
if result.Out == "" || !strings.Contains(result.Out, tt.pkgName) {
|
|
t.Errorf("buildOutFmts().Out should be temp file containing %v, got %v", tt.pkgName, result.Out)
|
|
}
|
|
}
|
|
|
|
// For native targets, no format files should be generated
|
|
if result.Bin != "" {
|
|
t.Errorf("buildOutFmts().Bin = %v, want empty for native target", result.Bin)
|
|
}
|
|
if result.Hex != "" {
|
|
t.Errorf("buildOutFmts().Hex = %v, want empty for native target", result.Hex)
|
|
}
|
|
if result.Img != "" {
|
|
t.Errorf("buildOutFmts().Img = %v, want empty for native target", result.Img)
|
|
}
|
|
if result.Uf2 != "" {
|
|
t.Errorf("buildOutFmts().Uf2 = %v, want empty for native target", result.Uf2)
|
|
}
|
|
if result.Zip != "" {
|
|
t.Errorf("buildOutFmts().Zip = %v, want empty for native target", result.Zip)
|
|
}
|
|
})
|
|
}
|
|
}
|