Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

93 lines
3.1 KiB
Go

package resolver
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestCFnAddressCrossFileComparison pins the classic function-pointer identity
// check: `c->cmd->proc != execCommand` in one translation unit references a
// function defined in another. C's flat extern namespace makes these bind
// repo-globally.
func TestCFnAddressCrossFileComparison(t *testing.T) {
g := loadCSources(t, map[string]string{
"cmd.h": "typedef void (*cmdProc)(void);\n",
"exec.c": "void execCommand(void) {}\n",
"server.c": "" +
"int isExec(cmdProc p) {\n" + // line 1
" return p != execCommand;\n" + // line 2
"}\n",
})
ResolveFnValueCallbacks(g)
e := refEdgeAt(g, "server.c::isExec", 2)
require.NotNil(t, e, "cross-file function-address comparison must bind")
assert.Equal(t, "exec.c::execCommand", e.To)
}
// TestCFnAddressAssignment covers a function-pointer assignment right-hand side.
func TestCFnAddressAssignment(t *testing.T) {
g := loadCSources(t, map[string]string{
"exec.c": "void execCommand(void) {}\n",
"wire.c": "" +
"void wire(cmdProc *slot) {\n" + // line 1
" *slot = execCommand;\n" + // line 2
"}\n",
})
ResolveFnValueCallbacks(g)
e := refEdgeAt(g, "wire.c::wire", 2)
require.NotNil(t, e, "function-pointer assignment must bind")
assert.Equal(t, "exec.c::execCommand", e.To)
}
// TestCFnAddressAmpersand covers the `&fn` address-of form and its tag.
func TestCFnAddressAmpersand(t *testing.T) {
g := loadCSources(t, map[string]string{
"h.c": "void handler(void) {}\n",
"reg.c": "" +
"void setup(void) {\n" + // line 1
" install(&handler);\n" + // line 2
"}\n",
})
ResolveFnValueCallbacks(g)
e := refEdgeAt(g, "reg.c::setup", 2)
require.NotNil(t, e, "&handler must bind")
assert.Equal(t, "h.c::handler", e.To)
assert.Equal(t, "address_of", e.Meta["fn_ref_form"])
}
// TestCFnAddressStaticNotCrossFile pins the scope_static guard: a file-local
// static function is invisible to another translation unit, so a same-named
// cross-file reference must not bind it.
func TestCFnAddressStaticNotCrossFile(t *testing.T) {
g := loadCSources(t, map[string]string{
"a.c": "static void helper(void) {}\n",
"b.c": "" +
"void use(cmdProc *slot) {\n" + // line 1
" *slot = helper;\n" + // line 2
"}\n",
})
ResolveFnValueCallbacks(g)
assert.Nil(t, refEdgeAt(g, "b.c::use", 2),
"a cross-file reference must not bind a file-local static function")
}
// TestCFnAddressSameFileStaticWins pins same-file precedence: when a static in
// the referencing file and an extern elsewhere share a name, the same-file
// definition is chosen.
func TestCFnAddressSameFileStaticWins(t *testing.T) {
g := loadCSources(t, map[string]string{
"a.c": "" +
"static void dispatch(void) {}\n" + // line 1
"void user(void) {\n" + // line 2
" register_cb(dispatch);\n" + // line 3
"}\n",
"c.c": "void dispatch(void) {}\n", // extern, different file
})
ResolveFnValueCallbacks(g)
e := refEdgeAt(g, "a.c::user", 3)
require.NotNil(t, e, "same-file dispatch must bind")
assert.Equal(t, "a.c::dispatch", e.To, "same-file static wins over cross-file extern")
}