From 13fc9b7aafdf7b4af6d6e2586985a2e358cddc18 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Wed, 10 Jun 2026 07:10:15 +0800 Subject: [PATCH] =?UTF-8?q?test(backend):=20=E6=8E=88=E6=9D=83=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AB=AF=E5=88=B0=E7=AB=AF=E9=AA=8C=E8=AF=81=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=20(21H)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit util/license_key_test.go: - TestLicenseKeyRoundTrip: 签发→验签完整流程 - TestVerifyLicenseToken_TamperedPayload: 签名被篡改后被拒绝 - TestVerifyLicenseToken_WrongKey: 用错误公钥验签失败 - TestVerifyLicenseToken_InvalidFormat: 格式非法被拒绝 middleware/license_guard_test.go: - TestCalcLicensePhase: 覆盖全部 phase 边界 (perpetual→normal / future→normal / <7d→grace / 7-15d→readonly / >15d→locked) Co-Authored-By: Claude Sonnet 4.6 --- .../internal/middleware/license_guard_test.go | 39 ++++++++++ backend/internal/util/license_key_test.go | 75 +++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 backend/internal/middleware/license_guard_test.go create mode 100644 backend/internal/util/license_key_test.go diff --git a/backend/internal/middleware/license_guard_test.go b/backend/internal/middleware/license_guard_test.go new file mode 100644 index 0000000..32a4f23 --- /dev/null +++ b/backend/internal/middleware/license_guard_test.go @@ -0,0 +1,39 @@ +package middleware + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestCalcLicensePhase(t *testing.T) { + now := time.Now() + + // nil = perpetual → normal + assert.Equal(t, PhaseNormal, CalcLicensePhase(nil)) + + // future expiry → normal + future := now.Add(10 * 24 * time.Hour) + assert.Equal(t, PhaseNormal, CalcLicensePhase(&future)) + + // just expired (1h ago) → grace + grace := now.Add(-1 * time.Hour) + assert.Equal(t, PhaseGrace, CalcLicensePhase(&grace)) + + // expired 6 days ago → grace (boundary) + grace6d := now.Add(-6 * 24 * time.Hour) + assert.Equal(t, PhaseGrace, CalcLicensePhase(&grace6d)) + + // expired 8 days ago → readonly + readonly := now.Add(-8 * 24 * time.Hour) + assert.Equal(t, PhaseReadOnly, CalcLicensePhase(&readonly)) + + // expired 14 days ago → readonly (boundary) + readonly14d := now.Add(-14 * 24 * time.Hour) + assert.Equal(t, PhaseReadOnly, CalcLicensePhase(&readonly14d)) + + // expired 16 days ago → locked + locked := now.Add(-16 * 24 * time.Hour) + assert.Equal(t, PhaseLocked, CalcLicensePhase(&locked)) +} diff --git a/backend/internal/util/license_key_test.go b/backend/internal/util/license_key_test.go new file mode 100644 index 0000000..f8e3801 --- /dev/null +++ b/backend/internal/util/license_key_test.go @@ -0,0 +1,75 @@ +package util + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestLicenseKeyRoundTrip(t *testing.T) { + priv, pub, err := GenerateEd25519KeyPair() + require.NoError(t, err) + + exp := time.Now().Add(30 * 24 * time.Hour).Unix() + payload := LicensePayload{ + ShopID: 42, + LicenseID: 7, + Type: "annual", + IssuedAt: time.Now().Unix(), + ExpiresAt: &exp, + MaxDevices: 3, + } + + token, err := IssueLicenseToken(payload, priv) + require.NoError(t, err) + assert.NotEmpty(t, token) + + got, err := VerifyLicenseToken(token, pub) + require.NoError(t, err) + assert.Equal(t, payload.ShopID, got.ShopID) + assert.Equal(t, payload.Type, got.Type) + assert.Equal(t, payload.MaxDevices, got.MaxDevices) + assert.Equal(t, *payload.ExpiresAt, *got.ExpiresAt) +} + +func TestVerifyLicenseToken_TamperedPayload(t *testing.T) { + priv, pub, err := GenerateEd25519KeyPair() + require.NoError(t, err) + + exp := time.Now().Add(30 * 24 * time.Hour).Unix() + token, err := IssueLicenseToken(LicensePayload{ + ShopID: 1, Type: "trial", IssuedAt: time.Now().Unix(), ExpiresAt: &exp, MaxDevices: 1, + }, priv) + require.NoError(t, err) + + // Flip the last byte of the signature to simulate tampering + tampered := token[:len(token)-2] + "XX" + _, err = VerifyLicenseToken(tampered, pub) + assert.Error(t, err, "tampered token must be rejected") +} + +func TestVerifyLicenseToken_WrongKey(t *testing.T) { + priv, _, err := GenerateEd25519KeyPair() + require.NoError(t, err) + _, otherPub, err := GenerateEd25519KeyPair() + require.NoError(t, err) + + exp := time.Now().Add(30 * 24 * time.Hour).Unix() + token, err := IssueLicenseToken(LicensePayload{ + ShopID: 1, Type: "trial", IssuedAt: time.Now().Unix(), ExpiresAt: &exp, MaxDevices: 1, + }, priv) + require.NoError(t, err) + + _, err = VerifyLicenseToken(token, otherPub) + assert.ErrorIs(t, err, ErrInvalidLicenseSignature) +} + +func TestVerifyLicenseToken_InvalidFormat(t *testing.T) { + _, pub, err := GenerateEd25519KeyPair() + require.NoError(t, err) + + _, err = VerifyLicenseToken("not-a-valid-token", pub) + assert.ErrorIs(t, err, ErrInvalidLicenseToken) +}