agent-team/internal/scheduler/scheduler_test.go
scorpio d6df056687 feat: Part 模型 + 文件版本追踪 + 写手团队工作流 v2
- 数据层:messages 表增加 part_type 字段,新建 file_versions 表支持版本追踪
- 后端:saveWorkspace 版本追踪、saveAgentOutput 源头分离、generateBriefMessage 成员简报
- 后端:applyDocumentEdit 增量编辑、buildWorkflowStep phase-aware 工作流引擎
- API:文件版本查询/回退接口
- 前端:part_type 驱动渲染,产物面板版本历史
- 新增写手团队(主编/搜索员/策划编辑/合规审查员)配置
- store 模块、scheduler 模块、web-search skill

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 18:44:34 +08:00

150 lines
4.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package scheduler
import (
"testing"
"time"
)
func TestParseCron(t *testing.T) {
tests := []struct {
expr string
wantErr bool
}{
{"0 8 * * *", false}, // 每天8点
{"*/10 * * * *", false}, // 每10分钟
{"0 9 * * 1", false}, // 每周一9点
{"30 14 1 * *", false}, // 每月1日14:30
{"0,30 * * * *", false}, // 每小时0分和30分
{"0 9-17 * * 1-5", false}, // 工作日9-17点每小时
{"bad", true}, // 无效
{"* * *", true}, // 字段不足
{"60 * * * *", true}, // 分钟超范围
{"* 25 * * *", true}, // 小时超范围
}
for _, tt := range tests {
_, err := ParseCron(tt.expr)
if (err != nil) != tt.wantErr {
t.Errorf("ParseCron(%q) error=%v, wantErr=%v", tt.expr, err, tt.wantErr)
}
}
}
func TestCronMatch(t *testing.T) {
// 2026-03-07 是周六weekday=6
base := time.Date(2026, 3, 7, 8, 0, 0, 0, time.Local)
tests := []struct {
expr string
time time.Time
want bool
}{
// 每天8:00
{"0 8 * * *", base, true},
{"0 8 * * *", base.Add(1 * time.Minute), false}, // 8:01 不匹配
{"0 8 * * *", base.Add(-1 * time.Hour), false}, // 7:00 不匹配
// 每10分钟
{"*/10 * * * *", time.Date(2026, 3, 7, 8, 0, 0, 0, time.Local), true},
{"*/10 * * * *", time.Date(2026, 3, 7, 8, 10, 0, 0, time.Local), true},
{"*/10 * * * *", time.Date(2026, 3, 7, 8, 20, 0, 0, time.Local), true},
{"*/10 * * * *", time.Date(2026, 3, 7, 8, 5, 0, 0, time.Local), false},
// 每周一9:00周六不匹配
{"0 9 * * 1", base, false},
{"0 9 * * 1", time.Date(2026, 3, 9, 9, 0, 0, 0, time.Local), true}, // 周一
// 每周六8:00
{"0 8 * * 6", base, true},
// 多值
{"0,30 * * * *", time.Date(2026, 3, 7, 8, 0, 0, 0, time.Local), true},
{"0,30 * * * *", time.Date(2026, 3, 7, 8, 30, 0, 0, time.Local), true},
{"0,30 * * * *", time.Date(2026, 3, 7, 8, 15, 0, 0, time.Local), false},
// 范围
{"0 9-17 * * *", time.Date(2026, 3, 7, 9, 0, 0, 0, time.Local), true},
{"0 9-17 * * *", time.Date(2026, 3, 7, 17, 0, 0, 0, time.Local), true},
{"0 9-17 * * *", time.Date(2026, 3, 7, 8, 0, 0, 0, time.Local), false},
{"0 9-17 * * *", time.Date(2026, 3, 7, 18, 0, 0, 0, time.Local), false},
// 步进范围
{"0 9-17/2 * * *", time.Date(2026, 3, 7, 9, 0, 0, 0, time.Local), true},
{"0 9-17/2 * * *", time.Date(2026, 3, 7, 11, 0, 0, 0, time.Local), true},
{"0 9-17/2 * * *", time.Date(2026, 3, 7, 10, 0, 0, 0, time.Local), false},
}
for _, tt := range tests {
expr, err := ParseCron(tt.expr)
if err != nil {
t.Fatalf("ParseCron(%q) 解析失败: %v", tt.expr, err)
}
got := expr.Match(tt.time)
if got != tt.want {
t.Errorf("CronExpr(%q).Match(%s) = %v, want %v",
tt.expr, tt.time.Format("2006-01-02 15:04 Mon"), got, tt.want)
}
}
}
func TestMatchOnce(t *testing.T) {
now := time.Date(2026, 3, 7, 14, 30, 0, 0, time.Local)
tests := []struct {
expr string
want bool
}{
{"2026-03-07 14:30", true},
{"2026-03-07 14:31", false},
{"2026-03-08 14:30", false},
{"bad-format", false},
}
for _, tt := range tests {
got := matchOnce(tt.expr, now)
if got != tt.want {
t.Errorf("matchOnce(%q, %s) = %v, want %v", tt.expr, now.Format("2006-01-02 15:04"), got, tt.want)
}
}
}
func TestParseField(t *testing.T) {
tests := []struct {
field string
min int
max int
want []int
wantNil bool
}{
{"*", 0, 59, nil, true},
{"5", 0, 59, []int{5}, false},
{"1,3,5", 0, 59, []int{1, 3, 5}, false},
{"1-5", 0, 59, []int{1, 2, 3, 4, 5}, false},
{"*/15", 0, 59, []int{0, 15, 30, 45}, false},
{"10-20/3", 0, 59, []int{10, 13, 16, 19}, false},
}
for _, tt := range tests {
got, err := parseField(tt.field, tt.min, tt.max)
if err != nil {
t.Errorf("parseField(%q) 失败: %v", tt.field, err)
continue
}
if tt.wantNil {
if got != nil {
t.Errorf("parseField(%q) = %v, want nil", tt.field, got)
}
continue
}
if len(got) != len(tt.want) {
t.Errorf("parseField(%q) = %v, want %v", tt.field, got, tt.want)
continue
}
for i := range got {
if got[i] != tt.want[i] {
t.Errorf("parseField(%q)[%d] = %d, want %d", tt.field, i, got[i], tt.want[i])
}
}
}
}