Files
zzet--gortex/internal/contracts/routeguard_consumer_test.go
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

81 lines
2.4 KiB
Go

package contracts
import "testing"
// consumerPaths returns the set of HTTP consumer route paths the extractor
// minted for src, keyed by path.
func consumerPaths(t *testing.T, file string, src string) map[string]bool {
t.Helper()
nodes := makeNodes(file, []struct {
name string
start, end int
}{
{"caller", 1, 20},
})
ext := &HTTPExtractor{}
out := ext.Extract(file, []byte(src), nodes, nil)
got := map[string]bool{}
for _, c := range out {
if c.Type == ContractHTTP && c.Role == RoleConsumer {
if p, _ := c.Meta["path"].(string); p != "" {
got[p] = true
}
}
}
return got
}
// TestConsumerGuard_StaticAssetRejected pins the consumer-pass acceptance: a
// static-asset fetch is not an API consumer, while a real API fetch still is.
func TestConsumerGuard_StaticAssetRejected(t *testing.T) {
got := consumerPaths(t, "app.js", `
async function load() {
await fetch('/static/app.js');
await fetch('/api/x');
}
`)
if got["/static/app.js"] {
t.Errorf("static asset /static/app.js minted a consumer contract")
}
if !got["/api/x"] {
t.Errorf("expected /api/x to still mint a consumer contract; got %v", got)
}
}
// TestConsumerGuard_FilesystemConfigRejected covers the filesystem/config
// false-positive: a rooted config-file literal is not an HTTP consumer.
func TestConsumerGuard_FilesystemConfigRejected(t *testing.T) {
got := consumerPaths(t, "app.js", `
async function load() {
await fetch('/etc/app.conf');
await fetch('/var/log/app.log');
await fetch('/api/users');
}
`)
if got["/etc/app.conf"] {
t.Errorf("config path /etc/app.conf minted a consumer contract")
}
if got["/var/log/app.log"] {
t.Errorf("log path /var/log/app.log minted a consumer contract")
}
if !got["/api/users"] {
t.Errorf("expected /api/users to still mint a consumer contract; got %v", got)
}
}
// TestConsumerGuard_RelativeAndURLPreserved guards against over-filtering:
// non-rooted (relative/template) and absolute-URL consumers keep their
// existing behaviour and are not dropped by the rooted-path gate.
func TestConsumerGuard_AbsoluteURLPreserved(t *testing.T) {
got := consumerPaths(t, "client.py", `
import requests
def call():
requests.get("http://service/api/users")
`)
// The literal does not start with "/" (it starts with "http://"), so the
// rooted-path gate never touches it — the consumer must survive.
if len(got) == 0 {
t.Errorf("absolute-URL consumer should still mint a contract; got none")
}
}