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

113 lines
4.5 KiB
Go

package semantic
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"github.com/zzet/gortex/internal/graph"
)
// slowSolutionProvider models a Roslyn/MSBuild-class server: its queries only
// succeed once its solution has loaded, which the manager triggers by calling
// WaitReady before the enrichment deadline. It records whether readiness ran
// and only lands edges when it did.
type slowSolutionProvider struct {
name string
languages []string
waited bool
ready bool
}
func (s *slowSolutionProvider) Name() string { return s.name }
func (s *slowSolutionProvider) Languages() []string { return s.languages }
func (s *slowSolutionProvider) Available() bool { return true }
func (s *slowSolutionProvider) Close() error { return nil }
func (s *slowSolutionProvider) Enrich(g graph.Store, repoRoot string) (*EnrichResult, error) {
return nil, nil
}
func (s *slowSolutionProvider) EnrichFile(g graph.Store, repoRoot, filePath string) (*EnrichResult, error) {
return nil, nil
}
func (s *slowSolutionProvider) WaitReady(ctx context.Context, repoRoot string) error {
s.waited = true
s.ready = true
return nil
}
func (s *slowSolutionProvider) EnrichRepoContext(ctx context.Context, g graph.Store, repoPrefix, repoRoot string, deadline EnrichDeadlinePolicy) (*EnrichResult, error) {
res := &EnrichResult{Provider: s.name, Language: s.languages[0]}
// A solution-load server serves empty results until its load finishes; the
// readiness gate must run first for the pass to land any edges.
if s.ready {
res.EdgesAdded = 3
}
return res, nil
}
// TestRunEnrichOne_ReadinessGate: a ReadinessProber provider is brought to
// readiness BEFORE the enrichment deadline starts, so its pass lands edges
// instead of spending the whole budget on the cold solution load.
func TestRunEnrichOne_ReadinessGate(t *testing.T) {
mgr := NewManager(Config{Enabled: true}, zap.NewNop())
p := &slowSolutionProvider{name: "csharp-like", languages: []string{"csharp"}}
results := mgr.runEnrichOne(graph.New(), "repo", "/tmp/repo", "csharp", p, 10, RepoEnrichState{}, nil, map[string]bool{})
require.True(t, p.waited, "readiness prober must be invoked before the enrichment pass")
require.Len(t, results, 1)
assert.Equal(t, 3, results[0].EdgesAdded,
"the pass lands edges because the deadline started only after readiness")
}
// TestRunEnrichOne_FastProviderSkipsReadiness: a provider that does not
// implement ReadinessProber (a gopls-shaped server, ready after initialize)
// runs without incurring the readiness wait.
func TestRunEnrichOne_FastProviderSkipsReadiness(t *testing.T) {
mgr := NewManager(Config{Enabled: true}, zap.NewNop())
// mockProvider (from manager_test.go) does not implement ReadinessProber.
p := &mockProvider{name: "gopls-like", languages: []string{"go"}, available: true}
results := mgr.runEnrichOne(graph.New(), "repo", "/tmp/repo", "go", p, 10, RepoEnrichState{}, nil, map[string]bool{})
require.Len(t, results, 1, "a fast provider still runs; the readiness gate is simply skipped")
assert.Equal(t, "gopls-like", results[0].Provider)
}
// notReadyProvider models a ReadinessProber whose workspace never finishes
// loading: WaitReady reports ErrWorkspaceNotReady. The manager must record the
// honest not-ready state and skip the sweep instead of running it against an
// empty server and reporting a misleading "completed, 0 coverage".
type notReadyProvider struct {
slowSolutionProvider
}
func (n *notReadyProvider) WaitReady(ctx context.Context, repoRoot string) error {
n.waited = true
return ErrWorkspaceNotReady
}
// TestRunEnrichOne_NeverReadySkipsSweepWithHonestState: when readiness never
// confirms, the pass is skipped and recorded as not_ready — no result is
// produced, so a later cycle retries.
func TestRunEnrichOne_NeverReadySkipsSweepWithHonestState(t *testing.T) {
mgr := NewManager(Config{Enabled: true}, zap.NewNop())
p := &notReadyProvider{slowSolutionProvider{name: "csharp-like", languages: []string{"csharp"}}}
results := mgr.runEnrichOne(graph.New(), "repo", "/tmp/repo", "csharp", p, 10, RepoEnrichState{}, nil, map[string]bool{})
require.True(t, p.waited, "readiness prober must be invoked")
assert.Empty(t, results, "the sweep is skipped, so no result is produced")
statuses := mgr.EnrichmentStatuses()
require.Len(t, statuses, 1)
assert.Equal(t, EnrichStateNotReady, statuses[0].State,
"a workspace that never loads is recorded as not_ready, not completed")
}