findMapByProductCodeWithTx_audit_test.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package perm_test
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "perms-system-server/internal/model/perm"
  7. "perms-system-server/internal/testutil"
  8. "github.com/stretchr/testify/assert"
  9. "github.com/stretchr/testify/require"
  10. "github.com/zeromicro/go-zero/core/stores/sqlx"
  11. )
  12. // ---------------------------------------------------------------------------
  13. // 覆盖目标:审计 M-6 修复的基础设施 —— FindMapByProductCodeWithTx。L-5 审计把非事务版
  14. // FindMapByProductCode 作为僵尸接口移除,这里改为只钉死 WithTx 版本的三条契约:
  15. // 1) 必须在 TransactCtx 内跑通,并返回当前产品下"全量"权限(含 status!=1 的行),
  16. // 因为 SyncPermsService 依赖读出现状对比(禁用重启分支);
  17. // 2) 返回 map 的 key 必须严格等于 SysPerm.Code,便于上层直接按 code 去重;
  18. // 3) 当 productCode 下没有任何行时,返回 empty map 而不是 nil(避免上层 `m[code] = x`
  19. // 时的 nil map 赋值 panic)。
  20. // ---------------------------------------------------------------------------
  21. // TC-0807: FindMapByProductCodeWithTx 返回覆盖全状态行 + key 等于 Code
  22. func TestSysPermModel_FindMapByProductCodeWithTx_EqualsNonTx(t *testing.T) {
  23. ctx := context.Background()
  24. m := newTestSysPermModel(t)
  25. conn := testutil.GetTestSqlConn()
  26. productCode := "pc_fmwtx_" + testutil.UniqueId()
  27. now := time.Now().Unix()
  28. codeA := "a_" + testutil.UniqueId()
  29. codeB := "b_" + testutil.UniqueId()
  30. res1, err := m.Insert(ctx, &perm.SysPerm{
  31. ProductCode: productCode, Name: "a", Code: codeA,
  32. Status: 1, CreateTime: now, UpdateTime: now,
  33. })
  34. require.NoError(t, err)
  35. id1, _ := res1.LastInsertId()
  36. res2, err := m.Insert(ctx, &perm.SysPerm{
  37. ProductCode: productCode, Name: "b", Code: codeB,
  38. Status: 2, CreateTime: now, UpdateTime: now, // 禁用行也必须被 Map 出来
  39. })
  40. require.NoError(t, err)
  41. id2, _ := res2.LastInsertId()
  42. t.Cleanup(func() { testutil.CleanTable(ctx, conn, "`sys_perm`", id1, id2) })
  43. var withTx map[string]*perm.SysPerm
  44. require.NoError(t, m.TransactCtx(ctx, func(c context.Context, session sqlx.Session) error {
  45. var err error
  46. withTx, err = m.FindMapByProductCodeWithTx(c, session, productCode)
  47. return err
  48. }))
  49. require.Len(t, withTx, 2)
  50. pA, ok := withTx[codeA]
  51. require.True(t, ok, "map key 必须等于 SysPerm.Code")
  52. assert.Equal(t, id1, pA.Id)
  53. assert.Equal(t, int64(1), pA.Status)
  54. assert.Equal(t, "a", pA.Name)
  55. pB, ok := withTx[codeB]
  56. require.True(t, ok, "禁用行同样必须出现在 map 中(M-6 依赖它识别 disabled 重启)")
  57. assert.Equal(t, id2, pB.Id)
  58. assert.Equal(t, int64(2), pB.Status, "status 必须真实透传,不得被过滤")
  59. }
  60. // TC-0808: 空 productCode 下 FindMapByProductCodeWithTx 返回非 nil 的空 map。
  61. // 上层同步逻辑里会对 map 直接做 `_, ok := existingMap[item.Code]`;如果是 nil 依然安全,
  62. // 但若不慎写成 `existingMap[item.Code] = ...` 就会炸,因此约定为"空 map"更稳。
  63. func TestSysPermModel_FindMapByProductCodeWithTx_EmptyIsNonNil(t *testing.T) {
  64. ctx := context.Background()
  65. m := newTestSysPermModel(t)
  66. productCode := "pc_empty_" + testutil.UniqueId()
  67. var withTx map[string]*perm.SysPerm
  68. require.NoError(t, m.TransactCtx(ctx, func(c context.Context, session sqlx.Session) error {
  69. var err error
  70. withTx, err = m.FindMapByProductCodeWithTx(c, session, productCode)
  71. return err
  72. }))
  73. require.NotNil(t, withTx, "空集必须是 empty map,而不是 nil(避免上层误用 map 赋值时 panic)")
  74. assert.Empty(t, withTx)
  75. }