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

128 lines
5.1 KiB
Go

package lsp
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
)
// TestIsNuGetAdvisoryCode pins the advisory-code predicate: it must match the
// NU#### NuGet family (the audit/restore advisories we filter) and must NOT
// match real CS#### compiler codes — filtering those would hide genuine errors.
func TestIsNuGetAdvisoryCode(t *testing.T) {
cases := []struct {
code string
want bool
}{
{"NU1902", true}, // the transitive-vuln advisory that bites csharp-ls
{"NU1903", true},
{"NU1605", true},
{"NU1", true},
{"nu1902", true}, // prefix is case-insensitive
{"CS0246", false}, // real compiler error — must survive the filter
{"CS1591", false},
{"NU", false}, // no digits
{"NUGET", false}, // letters after NU
{"NU19A2", false}, // non-digit inside the number
{"1902", false},
{"N", false},
{"", false},
}
for _, c := range cases {
assert.Equalf(t, c.want, isNuGetAdvisoryCode(c.code), "isNuGetAdvisoryCode(%q)", c.code)
}
}
// TestDiagCodeString covers the wire-type normalisation: string codes pass
// through, json.Number renders, and anything else (incl. JSON-unmarshalled
// numeric float64) yields "" — sufficient because NU codes are always strings.
func TestDiagCodeString(t *testing.T) {
assert.Equal(t, "NU1902", diagCodeString("NU1902"))
assert.Equal(t, "1902", diagCodeString(json.Number("1902")))
assert.Equal(t, "", diagCodeString(float64(1902)))
assert.Equal(t, "", diagCodeString(1902))
assert.Equal(t, "", diagCodeString(nil))
}
// TestFilterCSharpAdvisoryDiags verifies the filter drops only NU#### NuGet
// advisories, preserves real CS#### diagnostics and their order, and returns
// the input untouched when there is nothing to drop.
func TestFilterCSharpAdvisoryDiags(t *testing.T) {
// No advisories → same slice handed back, unchanged.
clean := []Diagnostic{
{Code: "CS0246", Severity: DiagSeverityError, Message: "type or namespace not found"},
{Code: "CS1591", Severity: DiagSeverityWarning, Message: "missing XML comment"},
}
assert.Equal(t, clean, filterCSharpAdvisoryDiags(clean))
// Mixed: NU advisories dropped, CS diagnostics kept in original order.
mixed := []Diagnostic{
{Code: "NU1902", Severity: DiagSeverityError, Message: "package has a known vulnerability"},
{Code: "CS0246", Severity: DiagSeverityError, Message: "type or namespace not found"},
{Code: "NU1903", Severity: DiagSeverityWarning, Message: "high severity vulnerability"},
{Code: "CS0103", Severity: DiagSeverityError, Message: "name does not exist"},
}
got := filterCSharpAdvisoryDiags(mixed)
assert.Len(t, got, 2)
assert.Equal(t, "CS0246", got[0].Code)
assert.Equal(t, "CS0103", got[1].Code)
// All advisories → empty result.
assert.Empty(t, filterCSharpAdvisoryDiags([]Diagnostic{{Code: "NU1902"}, {Code: "NU1605"}}))
// Empty / nil input is safe.
assert.Empty(t, filterCSharpAdvisoryDiags(nil))
}
// TestServesCSharp checks the language-scoping guard used to confine the
// C#-specific behaviour to C# providers.
func TestServesCSharp(t *testing.T) {
assert.True(t, (&Provider{languages: []string{"csharp"}}).servesCSharp())
assert.True(t, (&Provider{languages: []string{"go", "csharp"}}).servesCSharp())
assert.False(t, (&Provider{languages: []string{"go"}}).servesCSharp())
assert.False(t, (&Provider{}).servesCSharp())
}
// TestCSharpDiagFilterEnabled confirms the filter is ON by default and only
// the explicit falsey values disable it.
func TestCSharpDiagFilterEnabled(t *testing.T) {
t.Setenv(CSharpDiagFilterEnv, "") // unset-equivalent → default ON
assert.True(t, csharpDiagFilterEnabled())
for _, off := range []string{"0", "off", "false", "none", "OFF", "False"} {
t.Setenv(CSharpDiagFilterEnv, off)
assert.Falsef(t, csharpDiagFilterEnabled(), "value %q should disable the filter", off)
}
t.Setenv(CSharpDiagFilterEnv, "1")
assert.True(t, csharpDiagFilterEnabled())
}
// TestCSharpPreRestoreEligible verifies the pre-restore gate: ON by default for
// a C# provider that is spawning, disabled only by an explicit falsey
// CSharpRestoreEnv, and never active for a non-C# provider or a passive attach
// (where the IDE owns restore).
func TestCSharpPreRestoreEligible(t *testing.T) {
csharp := func() *Provider { return &Provider{languages: []string{"csharp"}} }
t.Setenv(CSharpRestoreEnv, "") // unset-equivalent → default ON
assert.True(t, csharp().csharpPreRestoreEligible(), "on by default for a spawning C# provider")
for _, off := range []string{"0", "off", "false", "none", "OFF", "False"} {
t.Setenv(CSharpRestoreEnv, off)
assert.Falsef(t, csharp().csharpPreRestoreEligible(), "value %q should disable pre-restore", off)
}
t.Setenv(CSharpRestoreEnv, "1")
assert.True(t, csharp().csharpPreRestoreEligible(), "explicitly enabled + serves C# + spawning")
// Not a C# provider → never restore, even with restore enabled.
assert.False(t, (&Provider{languages: []string{"go"}}).csharpPreRestoreEligible())
// C# but passively attached (the IDE owns restore) → skip.
p := csharp()
p.connect = &ConnectSpec{}
assert.False(t, p.csharpPreRestoreEligible(), "passive-attach must not trigger restore")
}