Skip to content

Commit 96ef010

Browse files
[Autoloop: python-to-go-migration] Iteration 118: Extend 7 thin Go test suites with 866 new lines
Run: https://github.com/githubnext/apm/actions/runs/26005714107 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2ff96f1 commit 96ef010

8 files changed

Lines changed: 918 additions & 3 deletions

File tree

benchmarks/migration-status.json

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"original_python_lines": 87626,
3-
"migrated_python_lines": 872793,
3+
"migrated_python_lines": 872814,
44
"migrated_modules": [
55
{
66
"module": "deps/apm_resolver",
@@ -16670,10 +16670,59 @@
1667016670
"python_lines": 58,
1667116671
"status": "test-migrated",
1667216672
"notes": "Extended policy matcher test suite: DoubleStarOnly, TrailingStar, ExactNoWildcard, DenyThenAllow, NilDeny, NotInAllowList, SingleStarInMiddle"
16673+
},
16674+
{
16675+
"module": "instructionintegrator-extra-tests",
16676+
"go_package": "internal/integration/instructionintegrator/instructionintegrator_extra_test.go",
16677+
"python_lines": 183,
16678+
"status": "test-migrated",
16679+
"notes": "Extended Go test file with additional edge-case coverage"
16680+
},
16681+
{
16682+
"module": "primparser-extra-tests",
16683+
"go_package": "internal/primitives/primparser/primparser_extra_test.go",
16684+
"python_lines": 128,
16685+
"status": "test-migrated",
16686+
"notes": "Extended Go test file with additional edge-case coverage"
16687+
},
16688+
{
16689+
"module": "templatebuilder-extra-tests",
16690+
"go_package": "internal/compilation/templatebuilder/templatebuilder_extra_test.go",
16691+
"python_lines": 116,
16692+
"status": "test-migrated",
16693+
"notes": "Extended Go test file with additional edge-case coverage"
16694+
},
16695+
{
16696+
"module": "diagnostics-extra-tests",
16697+
"go_package": "internal/utils/diagnostics/diagnostics_extra_test.go",
16698+
"python_lines": 119,
16699+
"status": "test-migrated",
16700+
"notes": "Extended Go test file with additional edge-case coverage"
16701+
},
16702+
{
16703+
"module": "conflictdetector-extra-tests",
16704+
"go_package": "internal/core/conflictdetector/conflictdetector_extra_test.go",
16705+
"python_lines": 115,
16706+
"status": "test-migrated",
16707+
"notes": "Extended Go test file with additional edge-case coverage"
16708+
},
16709+
{
16710+
"module": "inheritance-extra-tests",
16711+
"go_package": "internal/policy/inheritance/inheritance_extra_test.go",
16712+
"python_lines": 121,
16713+
"status": "test-migrated",
16714+
"notes": "Extended Go test file with additional edge-case coverage"
16715+
},
16716+
{
16717+
"module": "localcontent-extra-tests",
16718+
"go_package": "internal/install/phases/localcontent/localcontent_extra_test.go",
16719+
"python_lines": 84,
16720+
"status": "test-migrated",
16721+
"notes": "Extended localcontent test suite with multi-subdir, nested file, and edge-case coverage"
1667316722
}
1667416723
],
16675-
"last_updated": "2026-05-17T20:26:02Z",
16676-
"iteration": 81,
16724+
"last_updated": "2026-05-17T23:24:00Z",
16725+
"iteration": 82,
1667716726
"python_lines_migrated_pct": 995.11,
1667816727
"modules_migrated": 2253,
1667916728
"modules": [
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package templatebuilder_test
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/githubnext/apm/internal/compilation/templatebuilder"
8+
)
9+
10+
func identity(inst templatebuilder.Instruction) []string {
11+
return []string{inst.Content, ""}
12+
}
13+
14+
func TestRenderInstructionsBlock_MixedGlobalAndScoped(t *testing.T) {
15+
instructions := []templatebuilder.Instruction{
16+
{Name: "global", Content: "global-content"},
17+
{Name: "scoped", Content: "scoped-content", ApplyTo: "**/*.py"},
18+
}
19+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
20+
joined := strings.Join(lines, "\n")
21+
if !strings.Contains(joined, "## Global Instructions") {
22+
t.Error("expected global heading")
23+
}
24+
if !strings.Contains(joined, "## Files matching") {
25+
t.Error("expected scoped heading")
26+
}
27+
if !strings.Contains(joined, "global-content") {
28+
t.Error("expected global content")
29+
}
30+
if !strings.Contains(joined, "scoped-content") {
31+
t.Error("expected scoped content")
32+
}
33+
}
34+
35+
func TestRenderInstructionsBlock_MultiplePatterns(t *testing.T) {
36+
instructions := []templatebuilder.Instruction{
37+
{Name: "b", Content: "b-content", ApplyTo: "b-pattern"},
38+
{Name: "a", Content: "a-content", ApplyTo: "a-pattern"},
39+
{Name: "c", Content: "c-content", ApplyTo: "c-pattern"},
40+
}
41+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
42+
joined := strings.Join(lines, "\n")
43+
aIdx := strings.Index(joined, "a-pattern")
44+
bIdx := strings.Index(joined, "b-pattern")
45+
cIdx := strings.Index(joined, "c-pattern")
46+
if aIdx > bIdx || bIdx > cIdx {
47+
t.Error("patterns should be sorted alphabetically: a < b < c")
48+
}
49+
}
50+
51+
func TestRenderInstructionsBlock_AllScopedNoGlobal(t *testing.T) {
52+
instructions := []templatebuilder.Instruction{
53+
{Name: "x", Content: "x-content", ApplyTo: "**/*.go"},
54+
}
55+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
56+
joined := strings.Join(lines, "\n")
57+
if strings.Contains(joined, "## Global Instructions") {
58+
t.Error("should not have global heading when no global instructions")
59+
}
60+
if !strings.Contains(joined, "x-content") {
61+
t.Error("expected scoped content")
62+
}
63+
}
64+
65+
func TestRenderInstructionsBlock_AllEmptySkipped(t *testing.T) {
66+
instructions := []templatebuilder.Instruction{
67+
{Name: "empty1", Content: "", ApplyTo: "**/*.ts"},
68+
{Name: "empty2", Content: ""},
69+
}
70+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
71+
if len(lines) != 0 {
72+
t.Errorf("expected no output for all-empty instructions, got %v", lines)
73+
}
74+
}
75+
76+
func TestRenderInstructionsBlock_SamePatternGrouped(t *testing.T) {
77+
instructions := []templatebuilder.Instruction{
78+
{Name: "first", Content: "first-content", ApplyTo: "**/*.go"},
79+
{Name: "second", Content: "second-content", ApplyTo: "**/*.go"},
80+
}
81+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
82+
joined := strings.Join(lines, "\n")
83+
// Only one heading for the pattern
84+
count := strings.Count(joined, "## Files matching `**/*.go`")
85+
if count != 1 {
86+
t.Errorf("expected 1 heading for pattern, got %d", count)
87+
}
88+
if !strings.Contains(joined, "first-content") || !strings.Contains(joined, "second-content") {
89+
t.Error("both contents should be present")
90+
}
91+
}
92+
93+
func TestRenderInstructionsBlock_NilVsEmpty(t *testing.T) {
94+
linesNil := templatebuilder.RenderInstructionsBlock(nil, "/base", identity)
95+
linesEmpty := templatebuilder.RenderInstructionsBlock([]templatebuilder.Instruction{}, "/base", identity)
96+
if len(linesNil) != 0 {
97+
t.Errorf("nil: expected 0 lines, got %d", len(linesNil))
98+
}
99+
if len(linesEmpty) != 0 {
100+
t.Errorf("empty: expected 0 lines, got %d", len(linesEmpty))
101+
}
102+
}
103+
104+
func TestRenderInstructionsBlock_GlobalSortedByPath(t *testing.T) {
105+
instructions := []templatebuilder.Instruction{
106+
{Name: "z", FilePath: "/base/z.instructions.md", Content: "z-content"},
107+
{Name: "a", FilePath: "/base/a.instructions.md", Content: "a-content"},
108+
}
109+
lines := templatebuilder.RenderInstructionsBlock(instructions, "/base", identity)
110+
joined := strings.Join(lines, "\n")
111+
aIdx := strings.Index(joined, "a-content")
112+
zIdx := strings.Index(joined, "z-content")
113+
if aIdx > zIdx {
114+
t.Error("global instructions should be sorted by relative path (a before z)")
115+
}
116+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package conflictdetector_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/githubnext/apm/internal/core/conflictdetector"
7+
)
8+
9+
func TestGetExistingServerConfigs_Nil(t *testing.T) {
10+
d := conflictdetector.New(nil, nil, nil)
11+
cfg := d.GetExistingServerConfigs()
12+
if cfg == nil {
13+
t.Error("expected non-nil empty map for nil GetExistingServers")
14+
}
15+
if len(cfg) != 0 {
16+
t.Errorf("expected empty map, got %v", cfg)
17+
}
18+
}
19+
20+
func TestGetExistingServerConfigs_NonEmpty(t *testing.T) {
21+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
22+
return map[string]conflictdetector.ServerConfig{
23+
"server-a": {"type": "command"},
24+
"server-b": {"type": "url"},
25+
}
26+
}, nil, nil)
27+
cfg := d.GetExistingServerConfigs()
28+
if len(cfg) != 2 {
29+
t.Errorf("expected 2 configs, got %d", len(cfg))
30+
}
31+
}
32+
33+
func TestCheckServerExists_MultipleServersNoMatch(t *testing.T) {
34+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
35+
return map[string]conflictdetector.ServerConfig{
36+
"alpha": {},
37+
"beta": {},
38+
}
39+
}, nil, nil)
40+
res := d.CheckServerExists("gamma")
41+
if res.Exists {
42+
t.Error("expected no conflict for 'gamma'")
43+
}
44+
}
45+
46+
func TestCheckServerExists_EmptyRef(t *testing.T) {
47+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
48+
return map[string]conflictdetector.ServerConfig{"": {}}
49+
}, nil, nil)
50+
// Empty ref should match empty key (edge case).
51+
res := d.CheckServerExists("")
52+
_ = res // just verifying no panic
53+
}
54+
55+
func TestGetCanonicalServerName_SlashSeparated(t *testing.T) {
56+
d := conflictdetector.New(nil, nil, nil)
57+
name := d.GetCanonicalServerName("org/repo/tool")
58+
if name != "tool" {
59+
t.Errorf("expected 'tool', got %q", name)
60+
}
61+
}
62+
63+
func TestGetCanonicalServerName_NilResolver(t *testing.T) {
64+
d := conflictdetector.New(nil, nil, nil)
65+
name := d.GetCanonicalServerName("just-name")
66+
if name != "just-name" {
67+
t.Errorf("expected 'just-name', got %q", name)
68+
}
69+
}
70+
71+
func TestFindConflicts_Multiple(t *testing.T) {
72+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
73+
return map[string]conflictdetector.ServerConfig{
74+
"server1": {},
75+
"server2": {},
76+
}
77+
}, nil, nil)
78+
// Neither server1 nor server2 matches "new-server" by canonical name.
79+
conflicts := d.FindConflicts("owner/new-server")
80+
if len(conflicts) != 0 {
81+
t.Errorf("expected no conflicts, got %v", conflicts)
82+
}
83+
}
84+
85+
func TestFindConflicts_ExactMatch(t *testing.T) {
86+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
87+
return map[string]conflictdetector.ServerConfig{
88+
"my-server": {},
89+
}
90+
}, nil, nil)
91+
conflicts := d.FindConflicts("owner/my-server")
92+
if len(conflicts) != 1 {
93+
t.Errorf("expected 1 conflict, got %d: %v", len(conflicts), conflicts)
94+
}
95+
if conflicts[0] != "my-server" {
96+
t.Errorf("expected 'my-server', got %q", conflicts[0])
97+
}
98+
}
99+
100+
func TestCheckServerExists_CustomNameResolver(t *testing.T) {
101+
d := conflictdetector.New(func() map[string]conflictdetector.ServerConfig {
102+
return map[string]conflictdetector.ServerConfig{
103+
"resolved-name": {},
104+
}
105+
}, func(ref string) (string, error) {
106+
return "resolved-name", nil
107+
}, nil)
108+
res := d.CheckServerExists("any/ref")
109+
if !res.Exists {
110+
t.Error("expected conflict with custom name resolver")
111+
}
112+
if res.ConflictName != "resolved-name" {
113+
t.Errorf("expected 'resolved-name', got %q", res.ConflictName)
114+
}
115+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package localcontent
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"testing"
7+
)
8+
9+
func TestProjectHasRootPrimitives_NonExistentDir(t *testing.T) {
10+
if ProjectHasRootPrimitives("/nonexistent/path/abc123") {
11+
t.Error("expected false for non-existent root")
12+
}
13+
}
14+
15+
func TestHasLocalApmContent_MultipleSubdirs(t *testing.T) {
16+
dir := t.TempDir()
17+
apmDir := filepath.Join(dir, ".apm")
18+
// Create multiple recognized subdirs, only one with a file
19+
for _, sub := range []string{"skills", "instructions", "chatmodes"} {
20+
os.MkdirAll(filepath.Join(apmDir, sub), 0o755)
21+
}
22+
os.WriteFile(filepath.Join(apmDir, "instructions", "lint.instructions.md"), []byte("x"), 0o644)
23+
if !HasLocalApmContent(dir) {
24+
t.Error("expected true when instructions has a file")
25+
}
26+
}
27+
28+
func TestHasLocalApmContent_AgentsSubdir(t *testing.T) {
29+
dir := t.TempDir()
30+
apmDir := filepath.Join(dir, ".apm", "agents")
31+
os.MkdirAll(apmDir, 0o755)
32+
os.WriteFile(filepath.Join(apmDir, "my.agent.md"), []byte("agent"), 0o644)
33+
if !HasLocalApmContent(dir) {
34+
t.Error("expected true for agents subdir with file")
35+
}
36+
}
37+
38+
func TestHasLocalApmContent_PromptsSubdir(t *testing.T) {
39+
dir := t.TempDir()
40+
apmDir := filepath.Join(dir, ".apm", "prompts")
41+
os.MkdirAll(apmDir, 0o755)
42+
os.WriteFile(filepath.Join(apmDir, "foo.prompt.md"), []byte("x"), 0o644)
43+
if !HasLocalApmContent(dir) {
44+
t.Error("expected true for prompts subdir with file")
45+
}
46+
}
47+
48+
func TestHasLocalApmContent_HooksSubdir(t *testing.T) {
49+
dir := t.TempDir()
50+
apmDir := filepath.Join(dir, ".apm", "hooks")
51+
os.MkdirAll(apmDir, 0o755)
52+
os.WriteFile(filepath.Join(apmDir, "pre-install.sh"), []byte("#!/bin/bash"), 0o644)
53+
if !HasLocalApmContent(dir) {
54+
t.Error("expected true for hooks subdir with file")
55+
}
56+
}
57+
58+
func TestHasLocalApmContent_CommandsSubdir(t *testing.T) {
59+
dir := t.TempDir()
60+
apmDir := filepath.Join(dir, ".apm", "commands")
61+
os.MkdirAll(apmDir, 0o755)
62+
os.WriteFile(filepath.Join(apmDir, "custom.md"), []byte("x"), 0o644)
63+
if !HasLocalApmContent(dir) {
64+
t.Error("expected true for commands subdir with file")
65+
}
66+
}
67+
68+
func TestHasLocalApmContent_ApmFileNotDir(t *testing.T) {
69+
dir := t.TempDir()
70+
os.WriteFile(filepath.Join(dir, ".apm"), []byte("x"), 0o644)
71+
if HasLocalApmContent(dir) {
72+
t.Error("expected false when .apm is a file, not a directory")
73+
}
74+
}
75+
76+
func TestHasLocalApmContent_DeepNestedFile(t *testing.T) {
77+
dir := t.TempDir()
78+
nested := filepath.Join(dir, ".apm", "skills", "sub", "deep")
79+
os.MkdirAll(nested, 0o755)
80+
os.WriteFile(filepath.Join(nested, "SKILL.md"), []byte("x"), 0o644)
81+
if !HasLocalApmContent(dir) {
82+
t.Error("expected true for deeply nested file in recognized subdir")
83+
}
84+
}

0 commit comments

Comments
 (0)