add test coverage for cgo

Signed-off-by: Alex Goodman <wagoodman@users.noreply.github.com>
This commit is contained in:
Alex Goodman 2025-12-16 13:47:55 -05:00
parent 281a9b87de
commit b361427043
4 changed files with 58 additions and 3 deletions

View File

@ -7,6 +7,7 @@ import (
"testing" "testing"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -265,6 +266,38 @@ func Test_elfGoToolchainDetection(t *testing.T) {
} }
} }
func Test_elfCgoToolchainDetection(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper()
f, err := os.Open(filepath.Join("test-fixtures/golang", fixture))
require.NoError(t, err)
return f
}
t.Run("cgo binary has both go and c toolchains", func(t *testing.T) {
reader := readerForFixture(t, "bin/hello_linux_cgo")
f, err := elf.NewFile(reader)
require.NoError(t, err)
toolchains := elfToolchains(reader, f)
// versions are dynamic based on Docker image, so we ignore them in comparison
want := []file.Toolchain{
{Name: "go", Kind: file.ToolchainKindCompiler},
{Name: "gcc", Kind: file.ToolchainKindCompiler},
}
if d := cmp.Diff(want, toolchains, cmpopts.IgnoreFields(file.Toolchain{}, "Version")); d != "" {
t.Errorf("elfToolchains() mismatch (-want +got):\n%s", d)
}
// verify versions are populated
for _, tc := range toolchains {
assert.NotEmpty(t, tc.Version, "expected version to be set for %s toolchain", tc.Name)
}
})
}
func Test_elfGoSymbolCapture(t *testing.T) { func Test_elfGoSymbolCapture(t *testing.T) {
readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader { readerForFixture := func(t *testing.T, fixture string) unionreader.UnionReader {
t.Helper() t.Helper()

View File

@ -5,10 +5,14 @@ WORKDIR /app
COPY go.mod go.sum ./ COPY go.mod go.sum ./
RUN go mod download RUN go mod download
COPY main.go ./ COPY main.go cgo_main.go ./
# pure Go builds (no CGO)
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /hello_linux . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /hello_linux .
RUN CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o /hello_mac . RUN CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o /hello_mac .
RUN CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o /hello.exe . RUN CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o /hello.exe .
# CGO-enabled build (Linux only, uses gcc)
RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o /hello_linux_cgo ./cgo_main.go

View File

@ -19,12 +19,12 @@ tools-check:
tools: tools:
@(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || \ @(docker inspect $(TOOL_IMAGE) > /dev/null && make tools-check) || \
(docker build -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256) (docker build --platform=linux/amd64 -t $(TOOL_IMAGE) . && sha256sum Dockerfile > Dockerfile.sha256)
build: tools build: tools
@mkdir -p $(BIN) @mkdir -p $(BIN)
docker run -i -v $(shell pwd)/$(BIN):/out $(TOOL_IMAGE) sh -c \ docker run -i -v $(shell pwd)/$(BIN):/out $(TOOL_IMAGE) sh -c \
"cp /hello_linux /hello_mac /hello.exe /out/" "cp /hello_linux /hello_mac /hello.exe /hello_linux_cgo /out/"
debug: debug:
docker run -it --rm -v $(shell pwd):/mount -w /mount $(TOOL_IMAGE) sh docker run -it --rm -v $(shell pwd):/mount -w /mount $(TOOL_IMAGE) sh

View File

@ -0,0 +1,18 @@
package main
/*
#include <string.h>
#include <stdio.h>
int get_length(const char* s) {
return strlen(s);
}
*/
import "C"
import "fmt"
func main() {
msg := C.CString("Hello from CGO!")
length := C.get_length(msg)
fmt.Printf("String length: %d\n", int(length))
}