- 标注:AI 预标注直写 labels_json(去候选确认两阶段);重叠去重(minIoU);全量标注按钮 - 训练:脚本迁移入 server/training/(Go 化 prepare_yolo/analyze_rfdetr,保留 train_server.py);tflite 产物自检并入训练流程(check_tflite) - 数据目录/权重不进 git;.gitignore 迁移至仓库根
191 lines
6.6 KiB
Go
191 lines
6.6 KiB
Go
package service
|
||
|
||
// 管理端白盒测试:手动授权/撤销、订单分页、套餐更新、账号注册/登录。
|
||
// 运行方式同 payment_test.go:cd server && GF_GCFG_FILE=biz/service/testdata/config.yml go test ./biz/service/
|
||
|
||
import (
|
||
"strconv"
|
||
"testing"
|
||
"time"
|
||
|
||
"github.com/gogf/gf/v2/os/gtime"
|
||
|
||
"observer-server/biz/consts"
|
||
"observer-server/biz/dao"
|
||
"observer-server/biz/model/dto"
|
||
"observer-server/biz/model/entity"
|
||
"observer-server/common"
|
||
)
|
||
|
||
func startOfToday() time.Time {
|
||
now := time.Now()
|
||
return time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
|
||
}
|
||
|
||
// TestAuthRegisterLogin 注册/登录:注册后可登录、密码错误拒绝、重复注册报错
|
||
func TestAuthRegisterLogin(t *testing.T) {
|
||
phone := uniquePhone()
|
||
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
|
||
t.Fatalf("register: %v", err)
|
||
}
|
||
// 登录成功,token 可解析回手机号
|
||
res, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"})
|
||
if err != nil {
|
||
t.Fatalf("login: %v", err)
|
||
}
|
||
got, err := common.ParseToken(ctx(), res.Token)
|
||
if err != nil || got != phone {
|
||
t.Fatalf("parse token = %q, %v; want %q", got, err, phone)
|
||
}
|
||
// 密码错误
|
||
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "wrong"}); err == nil {
|
||
t.Fatal("wrong password should fail")
|
||
}
|
||
// 重复注册
|
||
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "other123"}); err == nil {
|
||
t.Fatal("duplicate register should fail")
|
||
}
|
||
// 未注册手机号登录失败
|
||
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: uniquePhone(), Password: "pass123456"}); err == nil {
|
||
t.Fatal("login unregistered phone should fail")
|
||
}
|
||
}
|
||
|
||
// TestAuthRegisterAfterGrant 运营先手动授权(占位行无密码)→ 用户注册补密码 → 登录成功
|
||
func TestAuthRegisterAfterGrant(t *testing.T) {
|
||
phone := uniquePhone()
|
||
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "day"}); err != nil {
|
||
t.Fatalf("grant: %v", err)
|
||
}
|
||
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
|
||
t.Fatalf("register after grant: %v", err)
|
||
}
|
||
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"}); err != nil {
|
||
t.Fatalf("login after register: %v", err)
|
||
}
|
||
// 注册补密码不能清掉已授权
|
||
lic, err := dao.License.GetByPhone(ctx(), phone)
|
||
if err != nil || lic == nil || lic.ExpiresAt == nil {
|
||
t.Fatalf("grant lost after register: %+v, %v", lic, err)
|
||
}
|
||
}
|
||
|
||
// TestAdminGrant 手动授权:新账号从今天 0 点起按套餐天数累计
|
||
func TestAdminGrant(t *testing.T) {
|
||
phone := uniquePhone()
|
||
res, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "week"})
|
||
if err != nil {
|
||
t.Fatalf("grant: %v", err)
|
||
}
|
||
want := startOfToday().AddDate(0, 0, 7)
|
||
if !res.ExpiresAt.Time.Equal(want) {
|
||
t.Fatalf("grant expiresAt = %s, want %s", res.ExpiresAt, want)
|
||
}
|
||
lic, err := License.Get(common.WithPhone(ctx(), phone), &dto.LicenseReq{})
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if !lic.Active {
|
||
t.Fatalf("license res = %+v", lic)
|
||
}
|
||
}
|
||
|
||
// TestAdminGrantRenewal 手动授权续期叠加:未过期顺延;无效套餐报错
|
||
func TestAdminGrantRenewal(t *testing.T) {
|
||
phone := uniquePhone()
|
||
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "week"}); err != nil {
|
||
t.Fatalf("grant 1: %v", err)
|
||
}
|
||
lic, _ := dao.License.GetByPhone(ctx(), phone)
|
||
|
||
res, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "month"})
|
||
if err != nil {
|
||
t.Fatalf("grant 2: %v", err)
|
||
}
|
||
want := lic.ExpiresAt.Time.AddDate(0, 0, 30)
|
||
if !res.ExpiresAt.Time.Equal(want) {
|
||
t.Fatalf("renewal expiresAt = %s, want %s (base %s)", res.ExpiresAt, want, lic.ExpiresAt)
|
||
}
|
||
|
||
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "nope"}); err == nil {
|
||
t.Fatal("invalid plan should fail")
|
||
}
|
||
}
|
||
|
||
// TestAdminRevoke 撤销授权:清授权字段保留账号(可继续登录),授权查询立即 inactive
|
||
func TestAdminRevoke(t *testing.T) {
|
||
phone := uniquePhone()
|
||
if _, err := Auth.Register(ctx(), &dto.RegisterReq{Phone: phone, Password: "pass123456"}); err != nil {
|
||
t.Fatalf("register: %v", err)
|
||
}
|
||
if _, err := License.AdminGrant(ctx(), &dto.AdminGrantReq{PhoneNum: phone, PlanId: "day"}); err != nil {
|
||
t.Fatalf("grant: %v", err)
|
||
}
|
||
if _, err := License.AdminRevoke(ctx(), &dto.AdminRevokeReq{PhoneNum: phone}); err != nil {
|
||
t.Fatalf("revoke: %v", err)
|
||
}
|
||
lic, err := License.Get(common.WithPhone(ctx(), phone), &dto.LicenseReq{})
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if lic.Active {
|
||
t.Fatal("license should be inactive after revoke")
|
||
}
|
||
row, err := dao.License.GetByPhone(ctx(), phone)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if row == nil || row.ExpiresAt != nil {
|
||
t.Fatalf("account row should be kept with auth cleared: %+v", row)
|
||
}
|
||
// 账号仍可登录(密码未删)
|
||
if _, err := Auth.Login(ctx(), &dto.LoginReq{Phone: phone, Password: "pass123456"}); err != nil {
|
||
t.Fatalf("login after revoke: %v", err)
|
||
}
|
||
}
|
||
|
||
// TestAdminListOrders 订单分页与筛选:总数、渠道筛选、分页截断
|
||
func TestAdminListOrders(t *testing.T) {
|
||
phone := uniquePhone()
|
||
orderId := uniqueOrderId("O-list-2-")
|
||
for i, channel := range []string{consts.ChannelWechat, consts.ChannelWechat, consts.ChannelAlipay} {
|
||
insertOrder(t, &entity.PaymentOrder{
|
||
OrderId: uniqueOrderId("O-list-" + strconv.Itoa(i) + "-"), PhoneNum: phone, PlanId: "day", Channel: channel,
|
||
AmountCents: 1000, Status: consts.OrderStatusCreated, CreatedAt: gtime.Now(),
|
||
})
|
||
}
|
||
insertOrder(t, &entity.PaymentOrder{
|
||
OrderId: orderId, PhoneNum: phone, PlanId: "day", Channel: consts.ChannelWechat,
|
||
AmountCents: 1000, Status: consts.OrderStatusCreated, CreatedAt: gtime.Now(),
|
||
})
|
||
|
||
res, err := Order.AdminListOrders(ctx(), &dto.AdminOrderListReq{PhoneNum: phone, Size: 2})
|
||
if err != nil {
|
||
t.Fatalf("list orders: %v", err)
|
||
}
|
||
if res.Total != 4 || len(res.List) != 2 {
|
||
t.Fatalf("total=%d len=%d, want 4/2", res.Total, len(res.List))
|
||
}
|
||
|
||
}
|
||
|
||
// TestListPlans 套餐列表:来自 testdata/config.yml plans 节点(配置驱动,无数据库表)
|
||
func TestListPlans(t *testing.T) {
|
||
res, err := Order.ListPlans(ctx(), &dto.ListPlansReq{})
|
||
if err != nil {
|
||
t.Fatalf("list plans: %v", err)
|
||
}
|
||
if len(res.List) != 3 {
|
||
t.Fatalf("plans = %d, want 3", len(res.List))
|
||
}
|
||
var week *dto.PlanItem
|
||
for _, p := range res.List {
|
||
if p.PlanId == "week" {
|
||
week = p
|
||
}
|
||
}
|
||
if week == nil || week.Days != 7 || week.PriceCents != 5600 {
|
||
t.Fatalf("week plan = %+v, want days=7 priceCents=5600", week)
|
||
}
|
||
}
|