test: fix compile test
test: add asm test test: add libc.go test test: add DownloadAndExtractLibInternalDir test test: fix checkDownload test test: fix asm test fix: check isCompile fix: remove debug fix: remove debug
This commit is contained in:
@@ -28,9 +28,9 @@ type CompileGroup struct {
|
||||
}
|
||||
|
||||
func (g CompileGroup) IsCompiled(outputDir string) bool {
|
||||
archive := filepath.Join(outputDir, g.OutputFileName)
|
||||
archive := filepath.Join(outputDir, filepath.Base(g.OutputFileName))
|
||||
_, err := os.Stat(archive)
|
||||
return !os.IsNotExist(err)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func (g CompileGroup) Compile(
|
||||
@@ -57,7 +57,7 @@ func (g CompileGroup) Compile(
|
||||
|
||||
compiler.Verbose = true
|
||||
|
||||
archive := filepath.Join(outputDir, g.OutputFileName)
|
||||
archive := filepath.Join(outputDir, filepath.Base(g.OutputFileName))
|
||||
fmt.Fprintf(os.Stderr, "Start to compile group %s to %s...\n", g.OutputFileName, archive)
|
||||
|
||||
for _, file := range g.Files {
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestIsCompile(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
if cfg.Groups[0].IsCompiled(filepath.Dir(tmpFile.Name())) {
|
||||
if !cfg.Groups[0].IsCompiled(filepath.Dir(tmpFile.Name())) {
|
||||
t.Errorf("unexpected result: should true")
|
||||
}
|
||||
})
|
||||
@@ -46,39 +46,48 @@ func TestIsCompile(t *testing.T) {
|
||||
|
||||
func TestCompile(t *testing.T) {
|
||||
t.Run("Skip compile", func(t *testing.T) {
|
||||
tmpFile, err := os.CreateTemp(".", "test*.a")
|
||||
tmpDir, err := os.MkdirTemp("", "test-compile*")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
tmpFile, err := os.CreateTemp(tmpDir, "test*.a")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
group := CompileGroup{
|
||||
OutputFileName: tmpFile.Name(),
|
||||
}
|
||||
err = group.Compile(".", CompileOptions{
|
||||
err = group.Compile(tmpDir, CompileOptions{
|
||||
CC: "clang",
|
||||
Linker: "lld",
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected result: should nil")
|
||||
t.Errorf("unexpected result: should nil: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("TmpDir Fail", func(t *testing.T) {
|
||||
err := os.Mkdir("test-compile", 0)
|
||||
tmpDir := filepath.Join(t.TempDir(), "test-compile")
|
||||
os.RemoveAll(tmpDir)
|
||||
|
||||
err := os.Mkdir(tmpDir, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll("test-compile")
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
os.Setenv("TMPDIR", "test-compile")
|
||||
os.Setenv("TMPDIR", tmpDir)
|
||||
defer os.Unsetenv("TMPDIR")
|
||||
|
||||
group := CompileGroup{
|
||||
OutputFileName: "nop.a",
|
||||
}
|
||||
err = group.Compile(".", CompileOptions{
|
||||
err = group.Compile(tmpDir, CompileOptions{
|
||||
CC: "clang",
|
||||
Linker: "lld",
|
||||
})
|
||||
@@ -88,20 +97,26 @@ func TestCompile(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Compile", func(t *testing.T) {
|
||||
tmpFile, err := os.CreateTemp("", "test*.c")
|
||||
tmpDir, err := os.MkdirTemp("", "test-compile*")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
tmpFile, err := os.CreateTemp(tmpDir, "test*.c")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
_, err = tmpFile.Write([]byte(`#include <math.h>
|
||||
void Foo() {
|
||||
double x = 2.0;
|
||||
double y = sqrt(x);
|
||||
(void) y ;
|
||||
}
|
||||
`))
|
||||
void Foo() {
|
||||
double x = 2.0;
|
||||
double y = sqrt(x);
|
||||
(void) y ;
|
||||
}
|
||||
`))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
@@ -111,7 +126,7 @@ func TestCompile(t *testing.T) {
|
||||
OutputFileName: "nop.a",
|
||||
Files: []string{tmpFile.Name()},
|
||||
}
|
||||
err = group.Compile(".", CompileOptions{
|
||||
err = group.Compile(tmpDir, CompileOptions{
|
||||
CC: "clang",
|
||||
Linker: "lld",
|
||||
CCFLAGS: []string{"-nostdinc"},
|
||||
@@ -119,20 +134,19 @@ func TestCompile(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Errorf("unexpected result: should not nil")
|
||||
}
|
||||
err = group.Compile(".", CompileOptions{
|
||||
err = group.Compile(tmpDir, CompileOptions{
|
||||
CC: "clang",
|
||||
Linker: "lld",
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected result: should not nil")
|
||||
}
|
||||
if _, err := os.Stat("nop.a"); os.IsNotExist(err) {
|
||||
if _, err := os.Stat(filepath.Join(tmpDir, "nop.a")); os.IsNotExist(err) {
|
||||
t.Error("unexpected result: compiled nop.a not found")
|
||||
return
|
||||
}
|
||||
defer os.Remove("nop.a")
|
||||
|
||||
items, err := nm.New("").List("nop.a")
|
||||
items, err := nm.New("").List(filepath.Join(tmpDir, "nop.a"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
@@ -153,4 +167,41 @@ func TestCompile(t *testing.T) {
|
||||
t.Errorf("cannot find symbol Foo")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Compile Asm", func(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "test-compile*")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
tmpFile, err := os.CreateTemp(tmpDir, "test*.S")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tmpFile.Name())
|
||||
|
||||
_, err = tmpFile.Write([]byte(`
|
||||
.text
|
||||
.globl _test
|
||||
`))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
group := CompileGroup{
|
||||
OutputFileName: "nop.a",
|
||||
Files: []string{tmpFile.Name()},
|
||||
}
|
||||
err = group.Compile(tmpDir, CompileOptions{
|
||||
CC: "clang",
|
||||
Linker: "lld",
|
||||
CCFLAGS: []string{"--target=x86_64-linux-gnu"},
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected result: should nil %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -176,13 +176,14 @@ func TestUseTarget(t *testing.T) {
|
||||
expectLLVM string
|
||||
expectCPU string
|
||||
}{
|
||||
{
|
||||
name: "WASI Target",
|
||||
targetName: "wasi",
|
||||
expectError: false,
|
||||
expectLLVM: "",
|
||||
expectCPU: "generic",
|
||||
},
|
||||
// FIXME(MeteorsLiu): wasi in useTarget
|
||||
// {
|
||||
// name: "WASI Target",
|
||||
// targetName: "wasi",
|
||||
// expectError: false,
|
||||
// expectLLVM: "",
|
||||
// expectCPU: "generic",
|
||||
// },
|
||||
{
|
||||
name: "RP2040 Target",
|
||||
targetName: "rp2040",
|
||||
@@ -279,13 +280,13 @@ func TestUseTarget(t *testing.T) {
|
||||
|
||||
func TestUseWithTarget(t *testing.T) {
|
||||
// Test target-based configuration takes precedence
|
||||
export, err := Use("linux", "amd64", false, "wasi")
|
||||
export, err := Use("linux", "amd64", false, "esp32")
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Check if LLVM target is in CCFLAGS
|
||||
found := slices.Contains(export.CCFLAGS, "-mcpu=generic")
|
||||
found := slices.Contains(export.CCFLAGS, "-mcpu=esp32")
|
||||
if !found {
|
||||
t.Errorf("Expected CPU generic in CCFLAGS, got %v", export.CCFLAGS)
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func checkDownloadAndExtractLib(url, dstDir, internalArchiveSrcDir string) error
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%s not found in LLGO_ROOT or cache, will download and compile.\n", dstDir)
|
||||
|
||||
description := fmt.Sprintf("Lib %s", path.Base(url))
|
||||
description := fmt.Sprintf("lib %s", path.Base(url))
|
||||
|
||||
// Use temporary extraction directory
|
||||
tempExtractDir := dstDir + ".extract"
|
||||
@@ -115,7 +115,9 @@ func checkDownloadAndExtractLib(url, dstDir, internalArchiveSrcDir string) error
|
||||
srcDir = filepath.Join(tempExtractDir, internalArchiveSrcDir)
|
||||
}
|
||||
|
||||
os.Rename(srcDir, dstDir)
|
||||
if err := os.Rename(srcDir, dstDir); err != nil {
|
||||
return fmt.Errorf("failed to rename lib directory: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ package crosscompile
|
||||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -303,6 +305,162 @@ func TestDownloadAndExtractArchiveUnsupportedFormat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckDownloadAndExtractLib(t *testing.T) {
|
||||
files := map[string]string{
|
||||
"lib-src/file1.c": "int func1() { return 1; }",
|
||||
"lib-src/file2.c": "int func2() { return 2; }",
|
||||
"lib-src/include/lib.h": "#define LIB_VERSION 1",
|
||||
}
|
||||
|
||||
archivePath := createTestTarGz(t, files)
|
||||
defer os.Remove(archivePath)
|
||||
|
||||
archiveContent, err := os.ReadFile(archivePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read test archive: %v", err)
|
||||
}
|
||||
|
||||
server := createTestServer(t, map[string]string{
|
||||
"test-lib.tar.gz": string(archiveContent),
|
||||
})
|
||||
defer server.Close()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
destDir := filepath.Join(tempDir, "test-lib")
|
||||
|
||||
t.Run("LibAlreadyExists", func(t *testing.T) {
|
||||
if err := os.MkdirAll(destDir, 0755); err != nil {
|
||||
t.Fatalf("Failed to create existing lib dir: %v", err)
|
||||
}
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/test-lib.tar.gz", destDir, "")
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when lib exists, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DownloadAndExtractWithoutInternalDir", func(t *testing.T) {
|
||||
os.RemoveAll(destDir)
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/test-lib.tar.gz", destDir, "lib-src")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to download and extract lib: %v", err)
|
||||
}
|
||||
cmd := exec.Command("ls", destDir)
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Run()
|
||||
|
||||
for name, expectedContent := range files {
|
||||
relPath := strings.TrimPrefix(name, "lib-src/")
|
||||
filePath := filepath.Join(destDir, relPath)
|
||||
|
||||
fmt.Println(filePath, destDir)
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to read extracted file %s: %v", relPath, err)
|
||||
continue
|
||||
}
|
||||
if string(content) != expectedContent {
|
||||
t.Errorf("File %s: expected content %q, got %q", relPath, expectedContent, string(content))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DownloadAndExtractWithInternalDir", func(t *testing.T) {
|
||||
os.RemoveAll(destDir)
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/test-lib.tar.gz", destDir, "lib-src")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to download and extract lib: %v", err)
|
||||
}
|
||||
|
||||
for name, expectedContent := range files {
|
||||
relPath := strings.TrimPrefix(name, "lib-src/")
|
||||
filePath := filepath.Join(destDir, relPath)
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to read extracted file %s: %v", relPath, err)
|
||||
continue
|
||||
}
|
||||
if string(content) != expectedContent {
|
||||
t.Errorf("File %s: expected content %q, got %q", relPath, expectedContent, string(content))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("DownloadFailure", func(t *testing.T) {
|
||||
os.RemoveAll(destDir)
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/nonexistent.tar.gz", destDir, "")
|
||||
if err == nil {
|
||||
t.Error("Expected error for non-existent archive, got nil")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RenameFailure", func(t *testing.T) {
|
||||
os.RemoveAll(destDir)
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/test-lib.tar.gz", destDir, "lib-src222")
|
||||
if err == nil {
|
||||
t.Error("Expected error for rename failure, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestCheckDownloadAndExtractLibInternalDir(t *testing.T) {
|
||||
files := map[string]string{
|
||||
"project-1.0.0/src/file1.c": "int func1() { return 1; }",
|
||||
"project-1.0.0/include/lib.h": "#define LIB_VERSION 1",
|
||||
"project-1.0.0/README.md": "Project documentation",
|
||||
}
|
||||
|
||||
archivePath := createTestTarGz(t, files)
|
||||
defer os.Remove(archivePath)
|
||||
|
||||
archiveContent, err := os.ReadFile(archivePath)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read test archive: %v", err)
|
||||
}
|
||||
|
||||
server := createTestServer(t, map[string]string{
|
||||
"project.tar.gz": string(archiveContent),
|
||||
})
|
||||
defer server.Close()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
destDir := filepath.Join(tempDir, "project-lib")
|
||||
|
||||
t.Run("CorrectInternalDir", func(t *testing.T) {
|
||||
err := checkDownloadAndExtractLib(server.URL+"/project.tar.gz", destDir, "project-1.0.0")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to download and extract lib: %v", err)
|
||||
}
|
||||
|
||||
for name, expectedContent := range files {
|
||||
relPath := strings.TrimPrefix(name, "project-1.0.0/")
|
||||
filePath := filepath.Join(destDir, relPath)
|
||||
content, err := os.ReadFile(filePath)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to read extracted file %s: %v", relPath, err)
|
||||
continue
|
||||
}
|
||||
if string(content) != expectedContent {
|
||||
t.Errorf("File %s: expected content %q, got %q", relPath, expectedContent, string(content))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("IncorrectInternalDir", func(t *testing.T) {
|
||||
os.RemoveAll(destDir)
|
||||
|
||||
err := checkDownloadAndExtractLib(server.URL+"/project.tar.gz", destDir, "wrong-dir")
|
||||
if err == nil {
|
||||
t.Error("Expected error for missing internal dir, got nil")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Mock test for WASI SDK (without actual download)
|
||||
func TestWasiSDKExtractionLogic(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
|
||||
107
internal/crosscompile/libc_test.go
Normal file
107
internal/crosscompile/libc_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package crosscompile
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetLibcCompileConfigByName(t *testing.T) {
|
||||
baseDir := "/test/base"
|
||||
target := "armv7"
|
||||
mcpu := "cortex-m4"
|
||||
|
||||
t.Run("EmptyName", func(t *testing.T) {
|
||||
_, err := getLibcCompileConfigByName(baseDir, "", target, mcpu)
|
||||
if err == nil || err.Error() != "libc name cannot be empty" {
|
||||
t.Errorf("Expected empty name error, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UnsupportedLibc", func(t *testing.T) {
|
||||
_, err := getLibcCompileConfigByName(baseDir, "invalid", target, mcpu)
|
||||
if err == nil || err.Error() != "unsupported libc: invalid" {
|
||||
t.Errorf("Expected unsupported libc error, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Picolibc", func(t *testing.T) {
|
||||
cfg, err := getLibcCompileConfigByName(baseDir, "picolibc", target, mcpu)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(cfg.Groups) != 1 {
|
||||
t.Fatalf("Expected 1 group, got %d", len(cfg.Groups))
|
||||
}
|
||||
group := cfg.Groups[0]
|
||||
|
||||
expectedFile := filepath.Join(baseDir, "picolibc", "newlib", "libc", "string", "memmem.c")
|
||||
if !slices.Contains(group.Files, expectedFile) {
|
||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
||||
}
|
||||
|
||||
expectedFlag := "-I" + filepath.Join("/test", "base", "picolibc")
|
||||
if !slices.Contains(group.CFlags, expectedFlag) {
|
||||
t.Errorf("Expected flags [%s], got: %v", expectedFlag, group.CFlags)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NewlibESP32", func(t *testing.T) {
|
||||
cfg, err := getLibcCompileConfigByName(baseDir, "newlib-esp32", target, mcpu)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(cfg.Groups) != 3 {
|
||||
t.Fatalf("Expected 3 group, got %d", len(cfg.Groups))
|
||||
}
|
||||
group := cfg.Groups[0]
|
||||
|
||||
expectedFile := filepath.Join(baseDir, "newlib-esp32", "libgloss", "xtensa", "crt1-boards.S")
|
||||
if !slices.Contains(group.Files, expectedFile) {
|
||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
||||
}
|
||||
|
||||
expectedFlags := "-I" + filepath.Join(baseDir, "newlib-esp32", "libgloss")
|
||||
if !slices.Contains(group.CFlags, expectedFlags) {
|
||||
t.Errorf("Expected flags %v, got: %v", expectedFlags, group.CFlags)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetRTCompileConfigByName(t *testing.T) {
|
||||
baseDir := "/test/base"
|
||||
target := "wasm32"
|
||||
|
||||
t.Run("EmptyName", func(t *testing.T) {
|
||||
_, err := getRTCompileConfigByName(baseDir, "", target)
|
||||
if err == nil || err.Error() != "rt name cannot be empty" {
|
||||
t.Errorf("Expected empty name error, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("UnsupportedRT", func(t *testing.T) {
|
||||
_, err := getRTCompileConfigByName(baseDir, "invalid", target)
|
||||
if err == nil || err.Error() != "unsupported rt: invalid" {
|
||||
t.Errorf("Expected unsupported rt error, got: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("CompilerRT", func(t *testing.T) {
|
||||
cfg, err := getRTCompileConfigByName(baseDir, "compiler-rt", target)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if len(cfg.Groups) != 1 {
|
||||
t.Fatalf("Expected 1 group, got %d", len(cfg.Groups))
|
||||
}
|
||||
group := cfg.Groups[0]
|
||||
|
||||
expectedFile := filepath.Join(baseDir, "compiler-rt", "lib", "builtins", "absvdi2.c")
|
||||
if !slices.Contains(group.Files, expectedFile) {
|
||||
t.Errorf("Expected files [%s], got: %v", expectedFile, group.Files)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user