Skip to content

Commit cdc93ca

Browse files
[Autoloop: python-to-go-migration] Iteration 110: extend 6 thin Go test suites with 367 new lines
Run: https://github.com/githubnext/apm/actions/runs/25994892054 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f16d918 commit cdc93ca

7 files changed

Lines changed: 411 additions & 1 deletion

File tree

benchmarks/migration-status.json

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"original_python_lines": 87626,
3-
"migrated_python_lines": 869537,
3+
"migrated_python_lines": 869904,
44
"migrated_modules": [
55
{
66
"module": "deps/apm_resolver",
@@ -16406,6 +16406,48 @@
1640616406
"python_lines": 52,
1640716407
"status": "test-migrated",
1640816408
"notes": "Extended request_test.go with zero value, skill subset, frozen, OnlyPackages tests"
16409+
},
16410+
{
16411+
"module": "test/marketplace/mkterrors/extended-iter110",
16412+
"go_package": "internal/marketplace/mkterrors",
16413+
"python_lines": 70,
16414+
"status": "test-migrated",
16415+
"notes": "Extended mkterrors_test.go with message content, empty input, multi-name, error inheritance tests"
16416+
},
16417+
{
16418+
"module": "test/integration/dispatch/extended-iter110",
16419+
"go_package": "internal/integration/dispatch",
16420+
"python_lines": 71,
16421+
"status": "test-migrated",
16422+
"notes": "Extended dispatch_test.go with integrate methods, sync methods, all integrator classes validation"
16423+
},
16424+
{
16425+
"module": "test/utils/helpers/extended-iter110",
16426+
"go_package": "internal/utils/helpers",
16427+
"python_lines": 66,
16428+
"status": "test-migrated",
16429+
"notes": "Extended helpers_test.go with FindPluginJSON subdirs, ClaudePlugin, CursorPlugin, precedence tests"
16430+
},
16431+
{
16432+
"module": "test/install/summary/extended-iter110",
16433+
"go_package": "internal/install/summary",
16434+
"python_lines": 60,
16435+
"status": "test-migrated",
16436+
"notes": "Extended summary_test.go with zero values, all fields, no-errors, no-stales, period ending"
16437+
},
16438+
{
16439+
"module": "test/marketplace/gitutils/extended-iter110",
16440+
"go_package": "internal/marketplace/gitutils",
16441+
"python_lines": 35,
16442+
"status": "test-migrated",
16443+
"notes": "Extended gitutils_test.go with complex URL, git clone URL, multi-query tokens, path preservation"
16444+
},
16445+
{
16446+
"module": "test/deps/aggregator/extended-iter110",
16447+
"go_package": "internal/deps/aggregator",
16448+
"python_lines": 65,
16449+
"status": "test-migrated",
16450+
"notes": "Extended aggregator_test.go with single MCP, deduplication across files, recursive scan"
1640916451
}
1641016452
],
1641116453
"last_updated": "2026-05-17T08:23:58Z",

internal/deps/aggregator/aggregator_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,68 @@ if len(servers) != 0 {
6666
t.Errorf("expected empty result for .md file (not .prompt.md), got %v", servers)
6767
}
6868
}
69+
70+
func TestScanWorkflowsForDependencies_SingleMCP(t *testing.T) {
71+
dir := t.TempDir()
72+
content := "---\nmcp:\n - only-server\n---\n"
73+
if err := os.WriteFile(filepath.Join(dir, "single.prompt.md"), []byte(content), 0o644); err != nil {
74+
t.Fatal(err)
75+
}
76+
servers, err := aggregator.ScanWorkflowsForDependencies(dir)
77+
if err != nil {
78+
t.Fatalf("unexpected error: %v", err)
79+
}
80+
if !servers["only-server"] {
81+
t.Errorf("expected only-server in %v", servers)
82+
}
83+
if len(servers) != 1 {
84+
t.Errorf("expected 1 server, got %d: %v", len(servers), servers)
85+
}
86+
}
87+
88+
func TestScanWorkflowsForDependencies_DeduplicatesAcrossFiles(t *testing.T) {
89+
dir := t.TempDir()
90+
c1 := "---\nmcp:\n - shared-server\n - file1-only\n---\n"
91+
c2 := "---\nmcp:\n - shared-server\n - file2-only\n---\n"
92+
if err := os.WriteFile(filepath.Join(dir, "a.prompt.md"), []byte(c1), 0o644); err != nil {
93+
t.Fatal(err)
94+
}
95+
if err := os.WriteFile(filepath.Join(dir, "b.prompt.md"), []byte(c2), 0o644); err != nil {
96+
t.Fatal(err)
97+
}
98+
servers, err := aggregator.ScanWorkflowsForDependencies(dir)
99+
if err != nil {
100+
t.Fatalf("unexpected error: %v", err)
101+
}
102+
if !servers["shared-server"] {
103+
t.Errorf("expected shared-server, got %v", servers)
104+
}
105+
if !servers["file1-only"] {
106+
t.Errorf("expected file1-only, got %v", servers)
107+
}
108+
if !servers["file2-only"] {
109+
t.Errorf("expected file2-only, got %v", servers)
110+
}
111+
if len(servers) != 3 {
112+
t.Errorf("expected 3 unique servers, got %d: %v", len(servers), servers)
113+
}
114+
}
115+
116+
func TestScanWorkflowsForDependencies_Recursive(t *testing.T) {
117+
dir := t.TempDir()
118+
sub := filepath.Join(dir, "subdir")
119+
if err := os.MkdirAll(sub, 0o755); err != nil {
120+
t.Fatal(err)
121+
}
122+
content := "---\nmcp:\n - nested-server\n---\n"
123+
if err := os.WriteFile(filepath.Join(sub, "nested.prompt.md"), []byte(content), 0o644); err != nil {
124+
t.Fatal(err)
125+
}
126+
servers, err := aggregator.ScanWorkflowsForDependencies(dir)
127+
if err != nil {
128+
t.Fatalf("unexpected error: %v", err)
129+
}
130+
if !servers["nested-server"] {
131+
t.Errorf("expected nested-server, got %v", servers)
132+
}
133+
}

internal/install/summary/summary_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,63 @@ func TestHasCriticalSecurityError(t *testing.T) {
6565
t.Error("expected false: critical=false, force=true")
6666
}
6767
}
68+
69+
func TestFormatSummary_Zero(t *testing.T) {
70+
r := SummaryResult{}
71+
got := FormatSummary(r)
72+
if !strings.Contains(got, "0 APM package(s)") {
73+
t.Errorf("expected 0 APM packages, got %q", got)
74+
}
75+
if !strings.Contains(got, "0 MCP server(s)") {
76+
t.Errorf("expected 0 MCP servers, got %q", got)
77+
}
78+
}
79+
80+
func TestFormatSummary_AllFields(t *testing.T) {
81+
r := SummaryResult{ApmCount: 2, McpCount: 3, Errors: 1, StalesCleaned: 4, ElapsedSecs: 10.5}
82+
got := FormatSummary(r)
83+
if !strings.Contains(got, "2 APM package(s)") {
84+
t.Errorf("expected APM count, got %q", got)
85+
}
86+
if !strings.Contains(got, "3 MCP server(s)") {
87+
t.Errorf("expected MCP count, got %q", got)
88+
}
89+
if !strings.Contains(got, "1 error(s)") {
90+
t.Errorf("expected errors, got %q", got)
91+
}
92+
if !strings.Contains(got, "4 stale artifact(s)") {
93+
t.Errorf("expected stales, got %q", got)
94+
}
95+
if !strings.Contains(got, "10.5s") {
96+
t.Errorf("expected elapsed, got %q", got)
97+
}
98+
}
99+
100+
func TestFormatSummary_NoErrors(t *testing.T) {
101+
r := SummaryResult{ApmCount: 1, McpCount: 1, Errors: 0}
102+
got := FormatSummary(r)
103+
if strings.Contains(got, "error") {
104+
t.Errorf("should not contain error when Errors=0: %q", got)
105+
}
106+
}
107+
108+
func TestFormatSummary_NoStales(t *testing.T) {
109+
r := SummaryResult{ApmCount: 1, McpCount: 0, StalesCleaned: 0}
110+
got := FormatSummary(r)
111+
if strings.Contains(got, "stale") {
112+
t.Errorf("should not contain stale when StalesCleaned=0: %q", got)
113+
}
114+
}
115+
116+
func TestFormatSummary_EndsWithPeriod(t *testing.T) {
117+
cases := []SummaryResult{
118+
{},
119+
{ApmCount: 1, McpCount: 2, Errors: 3, StalesCleaned: 4, ElapsedSecs: 5.0},
120+
}
121+
for _, r := range cases {
122+
got := FormatSummary(r)
123+
if !strings.HasSuffix(got, ".") {
124+
t.Errorf("FormatSummary should end with period: %q", got)
125+
}
126+
}
127+
}

internal/integration/dispatch/dispatch_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,75 @@ func TestDefaultDispatchTable_IntegratorClasses(t *testing.T) {
5757
t.Errorf("unexpected: %q", table["skills"].IntegratorClass)
5858
}
5959
}
60+
61+
func TestDefaultDispatchTable_IntegrateMethods(t *testing.T) {
62+
table := dispatch.DefaultDispatchTable()
63+
cases := map[string]string{
64+
"prompts": "integrate_prompts_for_target",
65+
"agents": "integrate_agents_for_target",
66+
"commands": "integrate_commands_for_target",
67+
"instructions": "integrate_instructions_for_target",
68+
"hooks": "integrate_hooks_for_target",
69+
"skills": "integrate_package_skill",
70+
}
71+
for key, want := range cases {
72+
if got := table[key].IntegrateMethod; got != want {
73+
t.Errorf("table[%q].IntegrateMethod=%q, want %q", key, got, want)
74+
}
75+
}
76+
}
77+
78+
func TestDefaultDispatchTable_SyncMethods(t *testing.T) {
79+
table := dispatch.DefaultDispatchTable()
80+
perTarget := map[string]bool{"prompts": true, "agents": true, "commands": true, "instructions": true}
81+
for key, entry := range table {
82+
if perTarget[key] {
83+
if entry.SyncMethod != "sync_for_target" {
84+
t.Errorf("table[%q].SyncMethod=%q, want sync_for_target", key, entry.SyncMethod)
85+
}
86+
} else {
87+
if entry.SyncMethod != "sync_integration" {
88+
t.Errorf("table[%q].SyncMethod=%q, want sync_integration", key, entry.SyncMethod)
89+
}
90+
}
91+
}
92+
}
93+
94+
func TestDefaultDispatchTable_AllIntegratorClassesSet(t *testing.T) {
95+
table := dispatch.DefaultDispatchTable()
96+
for key, entry := range table {
97+
if entry.IntegratorClass == "" {
98+
t.Errorf("table[%q].IntegratorClass is empty", key)
99+
}
100+
}
101+
}
102+
103+
func TestDefaultDispatchTable_AllIntegrateMethodsSet(t *testing.T) {
104+
table := dispatch.DefaultDispatchTable()
105+
for key, entry := range table {
106+
if entry.IntegrateMethod == "" {
107+
t.Errorf("table[%q].IntegrateMethod is empty", key)
108+
}
109+
}
110+
}
111+
112+
func TestDefaultDispatchTable_AgentsIntegratorClass(t *testing.T) {
113+
table := dispatch.DefaultDispatchTable()
114+
if table["agents"].IntegratorClass != "AgentIntegrator" {
115+
t.Errorf("agents IntegratorClass=%q, want AgentIntegrator", table["agents"].IntegratorClass)
116+
}
117+
}
118+
119+
func TestDefaultDispatchTable_HooksIntegratorClass(t *testing.T) {
120+
table := dispatch.DefaultDispatchTable()
121+
if table["hooks"].IntegratorClass != "HookIntegrator" {
122+
t.Errorf("hooks IntegratorClass=%q, want HookIntegrator", table["hooks"].IntegratorClass)
123+
}
124+
}
125+
126+
func TestDefaultDispatchTable_InstructionsIntegratorClass(t *testing.T) {
127+
table := dispatch.DefaultDispatchTable()
128+
if table["instructions"].IntegratorClass != "InstructionIntegrator" {
129+
t.Errorf("instructions IntegratorClass=%q, want InstructionIntegrator", table["instructions"].IntegratorClass)
130+
}
131+
}

internal/marketplace/gitutils/gitutils_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,38 @@ func TestRedactToken_empty(t *testing.T) {
6767
t.Errorf("expected empty, got %q", got)
6868
}
6969
}
70+
71+
func TestRedactToken_ComplexURL(t *testing.T) {
72+
input := "https://ghp_tokenABC123@github.com/org/repo.git"
73+
got := RedactToken(input)
74+
if strings.Contains(got, "ghp_tokenABC123") {
75+
t.Errorf("token still visible: %q", got)
76+
}
77+
if !strings.Contains(got, "***@github.com") {
78+
t.Errorf("expected redacted form: %q", got)
79+
}
80+
}
81+
82+
func TestRedactToken_GitCloneURL(t *testing.T) {
83+
input := "git clone https://user:pat@ghe.example.com/repo.git"
84+
got := RedactToken(input)
85+
if strings.Contains(got, "pat") {
86+
t.Errorf("token still visible: %q", got)
87+
}
88+
}
89+
90+
func TestRedactToken_MultipleQueryTokens(t *testing.T) {
91+
input := "https://example.com/a?token=tok1 and https://other.com/b?token=tok2"
92+
got := RedactToken(input)
93+
if strings.Contains(got, "tok1") || strings.Contains(got, "tok2") {
94+
t.Errorf("tokens still visible: %q", got)
95+
}
96+
}
97+
98+
func TestRedactToken_PreservesPath(t *testing.T) {
99+
input := "https://token123@github.com/owner/repo/path/to/file"
100+
got := RedactToken(input)
101+
if !strings.Contains(got, "github.com/owner/repo/path/to/file") {
102+
t.Errorf("path should be preserved: %q", got)
103+
}
104+
}

internal/marketplace/mkterrors/mkterrors_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,73 @@ func TestMarketplaceFetchError(t *testing.T) {
5656
t.Fatalf("Error() mismatch")
5757
}
5858
}
59+
60+
func TestMarketplaceNotFoundError_MessageContainsHost(t *testing.T) {
61+
err := mkterrors.NewMarketplaceNotFoundError("corp-market", "ghe.corp.io")
62+
msg := err.Error()
63+
if !strings.Contains(msg, "ghe.corp.io") {
64+
t.Errorf("error message should contain custom host, got %q", msg)
65+
}
66+
}
67+
68+
func TestMarketplaceNotFoundError_MessageContainsRunInstruction(t *testing.T) {
69+
err := mkterrors.NewMarketplaceNotFoundError("x", "")
70+
msg := err.Error()
71+
if !strings.Contains(msg, "apm marketplace add") {
72+
t.Errorf("error message should contain apm marketplace add, got %q", msg)
73+
}
74+
}
75+
76+
func TestPluginNotFoundError_MessageContainsMarketplace(t *testing.T) {
77+
err := mkterrors.NewPluginNotFoundError("cool-plugin", "central")
78+
msg := err.Error()
79+
if !strings.Contains(msg, "central") {
80+
t.Errorf("error message should mention marketplace name, got %q", msg)
81+
}
82+
}
83+
84+
func TestMarketplaceYmlError_EmptyMessage(t *testing.T) {
85+
err := mkterrors.NewMarketplaceYmlError("")
86+
if err.Message != "" {
87+
t.Errorf("expected empty Message, got %q", err.Message)
88+
}
89+
if err.Error() != "" {
90+
t.Errorf("expected empty Error(), got %q", err.Error())
91+
}
92+
}
93+
94+
func TestMarketplaceFetchError_EmptyMessage(t *testing.T) {
95+
err := mkterrors.NewMarketplaceFetchError("")
96+
if err.Error() != "" {
97+
t.Errorf("expected empty Error(), got %q", err.Error())
98+
}
99+
}
100+
101+
func TestMarketplaceNotFoundError_DifferentNames(t *testing.T) {
102+
names := []string{"alpha", "beta-market", "gamma_market"}
103+
for _, name := range names {
104+
err := mkterrors.NewMarketplaceNotFoundError(name, "")
105+
if err.Name != name {
106+
t.Errorf("Name=%q, want %q", err.Name, name)
107+
}
108+
if !strings.Contains(err.Error(), name) {
109+
t.Errorf("error should mention %q, got %q", name, err.Error())
110+
}
111+
}
112+
}
113+
114+
func TestPluginNotFoundError_DifferentPlugins(t *testing.T) {
115+
cases := []struct{ plugin, market string }{
116+
{"plugin-a", "mkt-1"},
117+
{"plugin-b", "mkt-2"},
118+
}
119+
for _, c := range cases {
120+
err := mkterrors.NewPluginNotFoundError(c.plugin, c.market)
121+
if err.PluginName != c.plugin {
122+
t.Errorf("PluginName=%q, want %q", err.PluginName, c.plugin)
123+
}
124+
if err.MarketplaceName != c.market {
125+
t.Errorf("MarketplaceName=%q, want %q", err.MarketplaceName, c.market)
126+
}
127+
}
128+
}

0 commit comments

Comments
 (0)