feat(tools/basic): 内置基础工具(calculator(注入安全)/datetime/random/text/json/markdown)+ 批量注册
This commit is contained in:
1 parent
b3c61aa1ff
commit
08223c06a5
19 files changed
+2074
No files matched your search
@@ -0,0 +1,107 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestText_Execute_Normal covers each supported operation.
|
||||
func TestText_Execute_Normal(t *testing.T) {
|
||||
t.Parallel()
|
||||
tool := text{}
|
||||
cases := []struct {
|
||||
name string
|
||||
args map[string]any
|
||||
check func(t *testing.T, m map[string]any)
|
||||
}{
|
||||
{name: "upper", args: map[string]any{"operation": "upper", "input": "abc"}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "ABC" {
|
||||
t.Fatalf("result = %q, want ABC", got)
|
||||
}
|
||||
}},
|
||||
{name: "lower", args: map[string]any{"operation": "lower", "input": "ABC"}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "abc" {
|
||||
t.Fatalf("result = %q, want abc", got)
|
||||
}
|
||||
}},
|
||||
{name: "trim", args: map[string]any{"operation": "trim", "input": " x "}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "x" {
|
||||
t.Fatalf("result = %q, want x", got)
|
||||
}
|
||||
}},
|
||||
{name: "title", args: map[string]any{"operation": "title", "input": "hello world"}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "Hello World" {
|
||||
t.Fatalf("result = %q, want Hello World", got)
|
||||
}
|
||||
}},
|
||||
{name: "length", args: map[string]any{"operation": "length", "input": "héllo"}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldInt(t, m, "result"); got != 5 {
|
||||
t.Fatalf("result = %d, want 5 runes", got)
|
||||
}
|
||||
}},
|
||||
{name: "split", args: map[string]any{"operation": "split", "input": "a,b,c", "delimiter": ","}, check: func(t *testing.T, m map[string]any) {
|
||||
got := m["result"].([]any)
|
||||
if !reflect.DeepEqual(got, []any{"a", "b", "c"}) {
|
||||
t.Fatalf("result = %v, want [a b c]", got)
|
||||
}
|
||||
}},
|
||||
{name: "replace", args: map[string]any{"operation": "replace", "input": "a-b-a", "old": "a", "new": "x"}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "x-b-x" {
|
||||
t.Fatalf("result = %q, want x-b-x", got)
|
||||
}
|
||||
}},
|
||||
{name: "template", args: map[string]any{"operation": "template", "input": "Hello {name}!", "values": map[string]any{"name": "Ada"}}, check: func(t *testing.T, m map[string]any) {
|
||||
if got := fieldString(t, m, "result"); got != "Hello Ada!" {
|
||||
t.Fatalf("result = %q, want Hello Ada!", got)
|
||||
}
|
||||
}},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := run(t, tool, tc.args)
|
||||
assertNoErr(t, err)
|
||||
tc.check(t, mapResult(t, got))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestText_Execute_Errors covers unknown operations and missing per-op inputs.
|
||||
func TestText_Execute_Errors(t *testing.T) {
|
||||
t.Parallel()
|
||||
tool := text{}
|
||||
cases := []struct {
|
||||
name string
|
||||
args map[string]any
|
||||
target error
|
||||
}{
|
||||
{name: "unknown operation", args: map[string]any{"operation": "frobnicate", "input": "x"}, target: ErrUnsupported},
|
||||
{name: "missing input", args: map[string]any{"operation": "upper"}, target: ErrInvalidArgument},
|
||||
{name: "non-string input", args: map[string]any{"operation": "upper", "input": 9}, target: ErrInvalidArgument},
|
||||
{name: "split without delimiter", args: map[string]any{"operation": "split", "input": "a"}, target: ErrInvalidArgument},
|
||||
{name: "replace without old", args: map[string]any{"operation": "replace", "input": "a", "new": "b"}, target: ErrInvalidArgument},
|
||||
{name: "replace without new", args: map[string]any{"operation": "replace", "input": "a", "old": "a"}, target: ErrInvalidArgument},
|
||||
{name: "template without values", args: map[string]any{"operation": "template", "input": "{x}"}, target: ErrInvalidArgument},
|
||||
{name: "unbalanced placeholder", args: map[string]any{"operation": "template", "input": "{x", "values": map[string]any{}}, target: ErrInvalidArgument},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := run(t, tool, tc.args)
|
||||
assertIs(t, err, tc.target)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestText_Schema verifies required fields.
|
||||
func TestText_Schema(t *testing.T) {
|
||||
t.Parallel()
|
||||
p, err := text{}.Parameters()
|
||||
assertNoErr(t, err)
|
||||
reqs := p["required"].([]any)
|
||||
if len(reqs) != 2 || reqs[0] != "operation" || reqs[1] != "input" {
|
||||
t.Fatalf("required = %v, want [operation input]", reqs)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user