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,99 @@
|
||||
package basic
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TestDatetime_Execute_Normal covers default, formatted and zone-shifted output.
|
||||
func TestDatetime_Execute_Normal(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := datetime{}
|
||||
|
||||
t.Run("default", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := run(t, c, nil)
|
||||
assertNoErr(t, err)
|
||||
m := mapResult(t, got)
|
||||
if fieldString(t, m, "timezone") != "UTC" {
|
||||
t.Fatalf("timezone = %v, want UTC", m["timezone"])
|
||||
}
|
||||
if fieldString(t, m, "format") != time.RFC3339 {
|
||||
t.Fatalf("format = %v, want RFC3339", m["format"])
|
||||
}
|
||||
if _, err := time.Parse(time.RFC3339, fieldString(t, m, "now")); err != nil {
|
||||
t.Fatalf("now %q is not RFC3339: %v", m["now"], err)
|
||||
}
|
||||
if fieldInt64(t, m, "unix") <= 0 {
|
||||
t.Fatalf("unix = %v, want positive", m["unix"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("custom format", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := run(t, c, map[string]any{"format": "2006-01-02"})
|
||||
assertNoErr(t, err)
|
||||
m := mapResult(t, got)
|
||||
if len(fieldString(t, m, "now")) != 10 {
|
||||
t.Fatalf("now = %v, want 10-char date", m["now"])
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("non-UTC zone", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
if _, err := time.LoadLocation("Asia/Shanghai"); err != nil {
|
||||
t.Skipf("tzdata not available: %v", err)
|
||||
}
|
||||
got, err := run(t, c, map[string]any{"timezone": "Asia/Shanghai"})
|
||||
assertNoErr(t, err)
|
||||
m := mapResult(t, got)
|
||||
if fieldString(t, m, "timezone") != "Asia/Shanghai" {
|
||||
t.Fatalf("timezone = %v, want Asia/Shanghai", m["timezone"])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// TestDatetime_Execute_Errors covers invalid zones and overlong inputs.
|
||||
func TestDatetime_Execute_Errors(t *testing.T) {
|
||||
t.Parallel()
|
||||
c := datetime{}
|
||||
cases := []struct {
|
||||
name string
|
||||
args map[string]any
|
||||
target error
|
||||
}{
|
||||
{name: "invalid zone", args: map[string]any{"timezone": "Not/AZone"}, target: nil},
|
||||
{name: "zone too long", args: map[string]any{"timezone": string(make([]byte, 65))}, target: ErrInvalidArgument},
|
||||
{name: "layout too long", args: map[string]any{"format": string(make([]byte, 129))}, target: ErrInvalidArgument},
|
||||
{name: "non-string timezone", args: map[string]any{"timezone": 123}, target: ErrInvalidArgument},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := run(t, c, tc.args)
|
||||
if err == nil {
|
||||
t.Fatalf("want error, got nil")
|
||||
}
|
||||
if tc.target != nil {
|
||||
assertIs(t, err, tc.target)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TestDatetime_Schema verifies the JSON Schema contract.
|
||||
func TestDatetime_Schema(t *testing.T) {
|
||||
t.Parallel()
|
||||
p, err := datetime{}.Parameters()
|
||||
assertNoErr(t, err)
|
||||
if _, ok := p["required"].([]any); ok {
|
||||
t.Fatalf("datetime schema should have no required fields")
|
||||
}
|
||||
props := p["properties"].(map[string]any)
|
||||
for _, field := range []string{"format", "timezone"} {
|
||||
if props[field].(map[string]any)["type"] != "string" {
|
||||
t.Fatalf("%s type should be string", field)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user