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
93 lines
3.1 KiB
Go
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")
|
|
}
|