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

96 lines
2.7 KiB
Go

package languages
import "testing"
func TestPHPStringCallable_ArrayMap(t *testing.T) {
src := []byte(`<?php
function helper($x) { return $x; }
function run($xs) {
return array_map('helper', $xs);
}
`)
res, err := NewPHPExtractor().Extract("a.php", src)
if err != nil {
t.Fatal(err)
}
cands := fnValueCands(res)
meta, ok := cands["helper"]
if !ok {
t.Fatalf("array_map string callable not captured (got: %v)", keys(cands))
}
if meta["skip_gate"] != true {
t.Errorf("skip_gate = %v, want true", meta["skip_gate"])
}
if meta["fn_ref_form"] != "php_string_callable" {
t.Errorf("fn_ref_form = %v, want php_string_callable", meta["fn_ref_form"])
}
}
func TestPHPStringCallable_NonHOFIgnored(t *testing.T) {
src := []byte(`<?php
function helper() {}
function run() {
some_other_fn('helper');
}
`)
res, err := NewPHPExtractor().Extract("a.php", src)
if err != nil {
t.Fatal(err)
}
if _, ok := fnValueCands(res)["helper"]; ok {
t.Error("a non-HOF call must not trigger string-callable capture")
}
}
func TestPHPStringCallable_StaticAndArrayForms(t *testing.T) {
src := []byte(`<?php
function run($a, $svc) {
usort($a, 'cmp');
call_user_func('Foo::bar');
array_map([$svc, 'handle'], $a);
array_filter($a, ['Acme', 'isValid']);
}
`)
res, err := NewPHPExtractor().Extract("a.php", src)
if err != nil {
t.Fatal(err)
}
cands := fnValueCands(res)
if _, ok := cands["cmp"]; !ok {
t.Errorf("usort string callable cmp not captured (got: %v)", keys(cands))
}
if m, ok := cands["bar"]; !ok || m["fn_ref_recv_hint"] != "Foo" {
t.Errorf("Foo::bar static-string callable not captured with recv hint (got: %v)", cands["bar"])
}
if _, ok := cands["handle"]; !ok {
t.Errorf("[$svc, 'handle'] array callable not captured (got: %v)", keys(cands))
}
if m, ok := cands["isValid"]; !ok || m["fn_ref_recv_hint"] != "Acme" {
t.Errorf("['Acme','isValid'] array callable not captured with recv hint (got: %v)", cands["isValid"])
}
}
func TestPHPStringCallable_ExtendedBuiltins(t *testing.T) {
src := []byte(`<?php
function run($a, $b, $s, $obj) {
array_udiff($a, $b, 'cmp');
preg_replace_callback_array(['/x/' => 'cb', '/y/' => 'Acme::handle'], $s);
set_exception_handler('onError');
register_tick_function([$obj, 'tick']);
}
`)
res, err := NewPHPExtractor().Extract("a.php", src)
if err != nil {
t.Fatal(err)
}
cands := fnValueCands(res)
for _, name := range []string{"cmp", "cb", "handle", "onError", "tick"} {
if _, ok := cands[name]; !ok {
t.Errorf("expected callable %q captured (got: %v)", name, keys(cands))
}
}
if m, ok := cands["handle"]; !ok || m["fn_ref_recv_hint"] != "Acme" {
t.Errorf("preg_replace_callback_array value Acme::handle recv hint = %v", cands["handle"])
}
}