package pub import ( "context" "errors" "fmt" "testing" "time" permModel "perms-system-server/internal/model/perm" productModel "perms-system-server/internal/model/product" "perms-system-server/internal/response" "perms-system-server/internal/testutil" "perms-system-server/internal/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func insertSyncTestProduct(t *testing.T, ctx context.Context, code, appKey, appSecret string, status int64) (int64, func()) { t.Helper() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() now := time.Now().Unix() res, err := svcCtx.SysProductModel.Insert(ctx, &productModel.SysProduct{ Code: code, Name: code, AppKey: appKey, AppSecret: appSecret, Status: status, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) id, _ := res.LastInsertId() cleanup := func() { testutil.CleanTable(ctx, conn, "`sys_product`", id) } return id, cleanup } // TC-0019: 全部新增 func TestSyncPerms_AllNew(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", pc) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: "perm_a", Name: "Perm A", Remark: "remark a"}, {Code: "perm_b", Name: "Perm B"}, {Code: "perm_c", Name: "Perm C"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(3), resp.Added) assert.Equal(t, int64(0), resp.Updated) assert.Equal(t, int64(0), resp.Disabled) } // TC-0020: 更新已有(名称变更) func TestSyncPerms_UpdateExisting(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "Old Name", Code: "upd_code", Remark: "old remark", Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) permId, _ := permRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: "upd_code", Name: "New Name", Remark: "new remark"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(1), resp.Updated) assert.Equal(t, int64(0), resp.Disabled) updated, err := svcCtx.SysPermModel.FindOne(ctx, permId) require.NoError(t, err) assert.Equal(t, "New Name", updated.Name) assert.Equal(t, "new remark", updated.Remark) assert.Equal(t, int64(1), updated.Status) } // TC-0021: 无变化 func TestSyncPerms_NoChanges(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "Same Name", Code: "same_code", Remark: "same remark", Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) permId, _ := permRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: "same_code", Name: "Same Name", Remark: "same remark"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(0), resp.Updated) assert.Equal(t, int64(0), resp.Disabled) } // TC-0022: 禁用权限重启 func TestSyncPerms_ReEnableDisabled(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) permRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "Disabled Perm", Code: "dis_code", Remark: "", Status: 2, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) permId, _ := permRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permId) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: "dis_code", Name: "Disabled Perm"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(1), resp.Updated) reEnabled, err := svcCtx.SysPermModel.FindOne(ctx, permId) require.NoError(t, err) assert.Equal(t, int64(1), reEnabled.Status) } // TC-0023: 移除不在列表的权限 func TestSyncPerms_DisableNotInList(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) keepCode := testutil.UniqueId() removeCode := testutil.UniqueId() keepRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "Keep", Code: keepCode, Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) keepId, _ := keepRes.LastInsertId() removeRes, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "Remove", Code: removeCode, Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) removeId, _ := removeRes.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", keepId, removeId) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: keepCode, Name: "Keep"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(1), resp.Disabled) disabled, err := svcCtx.SysPermModel.FindOne(ctx, removeId) require.NoError(t, err) assert.Equal(t, int64(2), disabled.Status) kept, err := svcCtx.SysPermModel.FindOne(ctx, keepId) require.NoError(t, err) assert.Equal(t, int64(1), kept.Status) } // TC-0024: 空perms数组 func TestSyncPerms_EmptyPermsDisablesAll(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) p1Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "P1", Code: testutil.UniqueId(), Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) p1Id, _ := p1Res.LastInsertId() p2Res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: "P2", Code: testutil.UniqueId(), Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) p2Id, _ := p2Res.LastInsertId() t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", p1Id, p2Id) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{}, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(0), resp.Updated) assert.Equal(t, int64(2), resp.Disabled) d1, err := svcCtx.SysPermModel.FindOne(ctx, p1Id) require.NoError(t, err) assert.Equal(t, int64(2), d1.Status) d2, err := svcCtx.SysPermModel.FindOne(ctx, p2Id) require.NoError(t, err) assert.Equal(t, int64(2), d2.Status) } // TC-0026: appKey无效 func TestSyncPerms_InvalidAppKey(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: "nonexistent_key_" + testutil.UniqueId(), AppSecret: "whatever", Perms: []types.SyncPermItem{{Code: "x", Name: "x"}}, }) require.Nil(t, resp) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 401, codeErr.Code()) assert.Equal(t, "无效的appKey", codeErr.Error()) } // TC-0027: appSecret错误 func TestSyncPerms_WrongAppSecret(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: "wrong_secret", Perms: []types.SyncPermItem{{Code: "x", Name: "x"}}, }) require.Nil(t, resp) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 401, codeErr.Code()) assert.Equal(t, "appSecret验证失败", codeErr.Error()) } // TC-0028: 产品已禁用 func TestSyncPerms_ProductDisabled(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 2) t.Cleanup(cleanProduct) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{{Code: "x", Name: "x"}}, }) require.Nil(t, resp) require.Error(t, err) var codeErr *response.CodeError require.True(t, errors.As(err, &codeErr)) assert.Equal(t, 403, codeErr.Code()) assert.Equal(t, "产品已被禁用", codeErr.Error()) } // TC-0029: 大批量(1000条) func TestSyncPerms_LargeBatch1000(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) t.Cleanup(func() { testutil.CleanTableByField(ctx, conn, "`sys_perm`", "productCode", pc) }) perms := make([]types.SyncPermItem, 1000) for i := 0; i < 1000; i++ { perms[i] = types.SyncPermItem{ Code: fmt.Sprintf("batch_%s_%d", pc, i), Name: fmt.Sprintf("Perm_%d", i), } } logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: perms, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(1000), resp.Added) assert.Equal(t, int64(0), resp.Updated) assert.Equal(t, int64(0), resp.Disabled) } // TC-0025: 验证disabled返回值 func TestSyncPerms_VerifyDisabledCount(t *testing.T) { ctx := context.Background() svcCtx := newTestSvcCtx() conn := testutil.GetTestSqlConn() pc := testutil.UniqueId() appKey := testutil.UniqueId() appSecret := testutil.UniqueId() now := time.Now().Unix() _, cleanProduct := insertSyncTestProduct(t, ctx, pc, appKey, appSecret, 1) t.Cleanup(cleanProduct) var permIds []int64 for i := 0; i < 5; i++ { res, err := svcCtx.SysPermModel.Insert(ctx, &permModel.SysPerm{ ProductCode: pc, Name: fmt.Sprintf("p%d", i), Code: fmt.Sprintf("code_%s_%d", pc, i), Status: 1, CreateTime: now, UpdateTime: now, }) require.NoError(t, err) id, _ := res.LastInsertId() permIds = append(permIds, id) } t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", permIds...) }) logic := NewSyncPermsLogic(ctx, svcCtx) resp, err := logic.SyncPerms(&types.SyncPermsReq{ AppKey: appKey, AppSecret: appSecret, Perms: []types.SyncPermItem{ {Code: fmt.Sprintf("code_%s_0", pc), Name: "p0"}, {Code: fmt.Sprintf("code_%s_1", pc), Name: "p1"}, }, }) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, int64(0), resp.Added) assert.Equal(t, int64(3), resp.Disabled) }