mirror of
https://github.com/sliverarmory/reflektor
synced 2026-08-25 09:14:48 +00:00
155 lines
5.4 KiB
Go
155 lines
5.4 KiB
Go
package reflektor_test
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type recursiveSharedLibraries struct {
|
|
root string
|
|
middle string
|
|
leaf string
|
|
}
|
|
|
|
func TestBuildRecursiveCSharedLibraryMatrix(t *testing.T) {
|
|
requireCommand(t, "zig")
|
|
requireCommand(t, "file")
|
|
requireCommand(t, "nm")
|
|
requireCommand(t, "objdump")
|
|
|
|
outDir := t.TempDir()
|
|
for _, target := range sharedLibTargets {
|
|
target := target
|
|
t.Run(fmt.Sprintf("%s-%s", target.goos, target.goarch), func(t *testing.T) {
|
|
graphDir := filepath.Join(outDir, target.goos+"-"+target.goarch)
|
|
if err := os.MkdirAll(graphDir, 0o755); err != nil {
|
|
t.Fatalf("create recursive fixture directory: %v", err)
|
|
}
|
|
libraries := buildRecursiveSharedLibs(t, graphDir, target.goos, target.goarch)
|
|
for _, path := range []string{libraries.leaf, libraries.middle, libraries.root} {
|
|
info, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Fatalf("stat %s: %v", path, err)
|
|
}
|
|
if info.Size() == 0 {
|
|
t.Fatalf("empty recursive fixture: %s", path)
|
|
}
|
|
if fileOut := runCmd(t, "file", path); !strings.Contains(fileOut, target.fileProbe) {
|
|
t.Fatalf("unexpected architecture probe for %s: want substring %q, got %q", path, target.fileProbe, fileOut)
|
|
}
|
|
}
|
|
|
|
switch target.goos {
|
|
case "windows":
|
|
if out := runCmd(t, "objdump", "-p", libraries.root); !strings.Contains(out, "StartW") || !strings.Contains(strings.ToLower(out), "libreflektor_middle.dll") {
|
|
t.Fatalf("recursive Windows root is missing StartW or middle import:\n%s", out)
|
|
}
|
|
case "darwin":
|
|
if out := runCmd(t, "nm", libraries.root); !strings.Contains(out, "_StartW") {
|
|
t.Fatalf("recursive Darwin root is missing _StartW:\n%s", out)
|
|
}
|
|
default:
|
|
if out := runCmd(t, "objdump", "-p", libraries.root); !strings.Contains(out, "libreflektor_middle.so") {
|
|
t.Fatalf("recursive Linux root is missing middle DT_NEEDED entry:\n%s", out)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func buildRecursiveSharedLibs(t *testing.T, outDir string, goos string, goarch string) recursiveSharedLibraries {
|
|
t.Helper()
|
|
|
|
target, ok := zigTargetFor(goos, goarch)
|
|
if !ok {
|
|
t.Fatalf("unsupported recursive shared-library target %s/%s", goos, goarch)
|
|
}
|
|
|
|
ext, err := sharedLibExt(goos)
|
|
if err != nil {
|
|
t.Fatalf("recursive shared-library extension: %v", err)
|
|
}
|
|
leaf := filepath.Join(outDir, "libreflektor_leaf."+ext)
|
|
middle := filepath.Join(outDir, "libreflektor_middle."+ext)
|
|
root := filepath.Join(outDir, "reflektor_recursive_root."+ext)
|
|
|
|
common := []string{"cc", "-target", target, "-O2", "-g0"}
|
|
switch goos {
|
|
case "darwin":
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-dynamiclib", "-fPIC",
|
|
"-Wl,-install_name,@rpath/libreflektor_leaf.dylib",
|
|
"-o", leaf, filepath.Join("testdata", "c", "recursive_leaf.c"),
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-dynamiclib", "-fPIC",
|
|
"-Wl,-install_name,@rpath/libreflektor_middle.dylib",
|
|
"-Wl,-rpath,@loader_path",
|
|
"-o", middle, filepath.Join("testdata", "c", "recursive_middle.c"),
|
|
"-L" + outDir, "-lreflektor_leaf",
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-dynamiclib", "-fPIC",
|
|
"-Wl,-rpath,@loader_path",
|
|
"-o", root, filepath.Join("testdata", "c", "recursive_root.c"),
|
|
"-L" + outDir, "-lreflektor_middle",
|
|
})
|
|
case "linux":
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-fPIC", "-Wl,-z,now", "-Wl,-z,defs",
|
|
"-Wl,-soname,libreflektor_leaf.so",
|
|
"-o", leaf, filepath.Join("testdata", "c", "recursive_leaf.c"),
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-fPIC", "-Wl,-z,now", "-Wl,-z,defs",
|
|
"-Wl,-soname,libreflektor_middle.so",
|
|
"-Wl,--enable-new-dtags", "-Wl,-rpath,$ORIGIN",
|
|
"-o", middle, filepath.Join("testdata", "c", "recursive_middle.c"),
|
|
"-L" + outDir, "-Wl,--no-as-needed", "-lreflektor_leaf",
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-fPIC", "-Wl,-z,now", "-Wl,-z,defs",
|
|
"-Wl,-soname,reflektor_recursive_root.so",
|
|
"-Wl,--enable-new-dtags", "-Wl,-rpath,$ORIGIN",
|
|
"-o", root, filepath.Join("testdata", "c", "recursive_root.c"),
|
|
"-L" + outDir, "-Wl,--no-as-needed", "-lreflektor_middle",
|
|
})
|
|
case "windows":
|
|
leafImport := filepath.Join(outDir, "libreflektor_leaf.lib")
|
|
middleImport := filepath.Join(outDir, "libreflektor_middle.lib")
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-Wl,--out-implib," + leafImport,
|
|
"-o", leaf, filepath.Join("testdata", "c", "recursive_leaf.c"),
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-Wl,--out-implib," + middleImport,
|
|
"-o", middle, filepath.Join("testdata", "c", "recursive_middle.c"), leafImport,
|
|
})
|
|
buildRecursiveFixture(t, common, []string{
|
|
"-shared", "-o", root, filepath.Join("testdata", "c", "recursive_root.c"), middleImport,
|
|
})
|
|
default:
|
|
t.Fatalf("unsupported recursive shared-library OS %s", goos)
|
|
}
|
|
|
|
return recursiveSharedLibraries{root: root, middle: middle, leaf: leaf}
|
|
}
|
|
|
|
func buildRecursiveFixture(t *testing.T, common []string, args []string) {
|
|
t.Helper()
|
|
cmdArgs := append(append([]string{}, common...), args...)
|
|
cmd := exec.Command("zig", cmdArgs...)
|
|
cmd.Env = append(
|
|
os.Environ(),
|
|
"ZIG_GLOBAL_CACHE_DIR="+filepath.Join(os.TempDir(), "reflektor-zig-global-cache"),
|
|
"ZIG_LOCAL_CACHE_DIR="+filepath.Join(os.TempDir(), "reflektor-zig-local-cache"),
|
|
)
|
|
if output, err := cmd.CombinedOutput(); err != nil {
|
|
t.Fatalf("build recursive fixture with zig %s: %v\n%s", strings.Join(cmdArgs, " "), err, output)
|
|
}
|
|
}
|