You've already forked agentic-coding-workflow
154 lines
4.8 KiB
Go
154 lines
4.8 KiB
Go
package mcp
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCreateSubtaskTool(t *testing.T) {
|
|
deps := testDeps()
|
|
// parent
|
|
_, err := callTool(ctxWithAuth(Scope{}), deps, "create_issue", map[string]any{
|
|
"project_slug": "test-project", "title": "Parent",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
result, err := callTool(ctxWithAuth(Scope{}), deps, "create_subtask", map[string]any{
|
|
"project_slug": "test-project",
|
|
"parent_number": float64(1),
|
|
"title": "Child",
|
|
"priority": float64(2),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.False(t, result.IsError)
|
|
var out issueCreateOut
|
|
unmarshalStructured(t, result, &out)
|
|
assert.True(t, out.OK)
|
|
assert.Equal(t, "Child", out.Issue.Title)
|
|
}
|
|
|
|
func TestAddListRemoveDependencyTool(t *testing.T) {
|
|
deps := testDeps()
|
|
for _, title := range []string{"A", "B"} {
|
|
_, err := callTool(ctxWithAuth(Scope{}), deps, "create_issue", map[string]any{
|
|
"project_slug": "test-project", "title": title,
|
|
})
|
|
require.NoError(t, err)
|
|
}
|
|
// A(#1) blocked-by B(#2)
|
|
result, err := callTool(ctxWithAuth(Scope{}), deps, "add_dependency", map[string]any{
|
|
"project_slug": "test-project",
|
|
"blocked_number": float64(1),
|
|
"blocker_number": float64(2),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.False(t, result.IsError)
|
|
var addOut dependencyOut
|
|
unmarshalStructured(t, result, &addOut)
|
|
assert.True(t, addOut.OK)
|
|
|
|
// list_dependencies on A → blocked_by contains B
|
|
result, err = callTool(ctxWithAuth(Scope{}), deps, "list_dependencies", map[string]any{
|
|
"project_slug": "test-project", "number": float64(1),
|
|
})
|
|
require.NoError(t, err)
|
|
var listOut listDependenciesOut
|
|
unmarshalStructured(t, result, &listOut)
|
|
require.Len(t, listOut.BlockedBy, 1)
|
|
assert.Equal(t, 2, listOut.BlockedBy[0].Number)
|
|
|
|
// remove
|
|
result, err = callTool(ctxWithAuth(Scope{}), deps, "remove_dependency", map[string]any{
|
|
"project_slug": "test-project",
|
|
"blocked_number": float64(1),
|
|
"blocker_number": float64(2),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.False(t, result.IsError)
|
|
|
|
result, err = callTool(ctxWithAuth(Scope{}), deps, "list_dependencies", map[string]any{
|
|
"project_slug": "test-project", "number": float64(1),
|
|
})
|
|
require.NoError(t, err)
|
|
unmarshalStructured(t, result, &listOut)
|
|
assert.Empty(t, listOut.BlockedBy)
|
|
}
|
|
|
|
func TestAddDependencyTool_RejectsSelf(t *testing.T) {
|
|
deps := testDeps()
|
|
_, err := callTool(ctxWithAuth(Scope{}), deps, "create_issue", map[string]any{
|
|
"project_slug": "test-project", "title": "A",
|
|
})
|
|
require.NoError(t, err)
|
|
result, err := callTool(ctxWithAuth(Scope{}), deps, "add_dependency", map[string]any{
|
|
"project_slug": "test-project",
|
|
"blocked_number": float64(1),
|
|
"blocker_number": float64(1),
|
|
})
|
|
require.NoError(t, err)
|
|
assert.True(t, result.IsError, "自依赖应被工具拒绝")
|
|
}
|
|
|
|
func TestSubmitDecompositionTool(t *testing.T) {
|
|
deps := testDeps()
|
|
// anchor parent
|
|
_, err := callTool(ctxWithAuth(Scope{}), deps, "create_issue", map[string]any{
|
|
"project_slug": "test-project", "title": "Anchor",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
result, err := callTool(ctxWithAuth(Scope{}), deps, "submit_decomposition", map[string]any{
|
|
"project_slug": "test-project",
|
|
"parent_number": float64(1),
|
|
"subtasks": []any{
|
|
map[string]any{"ref": "a", "title": "Task A", "priority": float64(2)},
|
|
map[string]any{"ref": "b", "title": "Task B"},
|
|
},
|
|
"edges": []any{
|
|
map[string]any{"blocked_ref": "a", "blocker_ref": "b"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.False(t, result.IsError)
|
|
var out submitDecompositionOut
|
|
unmarshalStructured(t, result, &out)
|
|
assert.True(t, out.OK)
|
|
require.Contains(t, out.RefToNumber, "a")
|
|
require.Contains(t, out.RefToNumber, "b")
|
|
}
|
|
|
|
func TestSubmitDecompositionTool_RejectsCycle(t *testing.T) {
|
|
deps := testDeps()
|
|
result, err := callTool(ctxWithAuth(Scope{}), deps, "submit_decomposition", map[string]any{
|
|
"project_slug": "test-project",
|
|
"subtasks": []any{
|
|
map[string]any{"ref": "a", "title": "A"},
|
|
map[string]any{"ref": "b", "title": "B"},
|
|
},
|
|
"edges": []any{
|
|
map[string]any{"blocked_ref": "a", "blocker_ref": "b"},
|
|
map[string]any{"blocked_ref": "b", "blocker_ref": "a"},
|
|
},
|
|
})
|
|
require.NoError(t, err)
|
|
assert.True(t, result.IsError, "环应被拒绝")
|
|
}
|
|
|
|
func TestDecompositionToolsInSystemScope(t *testing.T) {
|
|
// 新工具必须在 system token 默认白名单内,规划阶段 agent 才能调用。
|
|
set := map[string]bool{}
|
|
for _, name := range defaultSystemTools {
|
|
set[name] = true
|
|
}
|
|
for _, name := range []string{
|
|
"create_subtask", "add_dependency", "remove_dependency",
|
|
"list_dependencies", "submit_decomposition",
|
|
} {
|
|
assert.True(t, set[name], "%s 应在 defaultSystemTools", name)
|
|
}
|
|
// create_acp_session 仍对 system token 禁用(不应在白名单)。
|
|
assert.False(t, set["create_acp_session"], "create_acp_session 不应在 system 白名单")
|
|
}
|