Files
OpenFlare/internal/apps/openflare/tls/tasks_test.go
T
ryan 943818f7d4 refactor(repository): 收敛 model/repository 分层为唯一持久化入口
将 OpenFlare 与平台业务的数据访问从 model 与 apps 直连迁入 repository,
model 仅保留实体与无 IO 规则;补充 code-check 架构守卫与开发规范。
2026-07-24 17:00:17 +08:00

158 lines
4.0 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
package tls
import (
"context"
"encoding/json"
"errors"
"testing"
"github.com/Rain-kl/Wavelet/internal/repository"
"github.com/Rain-kl/Wavelet/internal/model"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSSLSingleRenewHandler_ValidatePayload(t *testing.T) {
tests := []struct {
name string
payload []byte
wantErr bool
errMsg string
}{
{
name: "empty payload",
payload: nil,
wantErr: true,
errMsg: "任务参数不能为空",
},
{
name: "invalid JSON",
payload: []byte(`{`),
wantErr: true,
errMsg: "无效的 JSON 格式",
},
{
name: "zero ID",
payload: []byte(`{"id":0}`),
wantErr: true,
errMsg: "证书 ID 不能为空或零",
},
{
name: "valid ID",
payload: []byte(`{"id":123}`),
wantErr: false,
},
}
handler := &SSLSingleRenewHandler{}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := handler.ValidatePayload(tt.payload)
if tt.wantErr {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errMsg)
assert.Nil(t, got)
} else {
require.NoError(t, err)
var payload SSLSingleRenewPayload
err = json.Unmarshal(got, &payload)
require.NoError(t, err)
assert.Equal(t, uint(123), payload.ID)
}
})
}
}
func TestSSLSingleRenewHandler_Execute(t *testing.T) {
cleanup := setupTLSTestDB(t)
defer cleanup()
ctx := context.Background()
handler := &SSLSingleRenewHandler{}
t.Run("invalid payload", func(t *testing.T) {
_, err := handler.Execute(ctx, []byte(`{`))
require.Error(t, err)
})
t.Run("certificate not found", func(t *testing.T) {
payload, err := json.Marshal(SSLSingleRenewPayload{ID: 999})
require.NoError(t, err)
_, err = handler.Execute(ctx, payload)
require.Error(t, err)
assert.Contains(t, err.Error(), "获取证书记录失败")
})
t.Run("certificate provider is not ACME", func(t *testing.T) {
cert := &model.TLSCertificate{
Name: "custom-cert",
Provider: "custom",
PrimaryDomain: "example.com",
}
err := repository.CreateTLSCertificateRecord(ctx, cert)
require.NoError(t, err)
payload, err := json.Marshal(SSLSingleRenewPayload{ID: cert.ID})
require.NoError(t, err)
_, err = handler.Execute(ctx, payload)
require.Error(t, err)
assert.Contains(t, err.Error(), "不是 ACME 托管证书")
})
t.Run("successful renewal", func(t *testing.T) {
cert := &model.TLSCertificate{
Name: "acme-cert-success",
Provider: tlsProviderACME,
PrimaryDomain: "success.example.com",
}
err := repository.CreateTLSCertificateRecord(ctx, cert)
require.NoError(t, err)
// Mock obtainCertificate to succeed
restore := SetObtainCertificateFuncForTest(func(ctx context.Context, c *model.TLSCertificate) error {
c.ApplyStatus = tlsApplyStatusReady
return repository.SaveTLSCertificate(ctx, c)
})
defer restore()
payload, err := json.Marshal(SSLSingleRenewPayload{ID: cert.ID})
require.NoError(t, err)
res, err := handler.Execute(ctx, payload)
require.NoError(t, err)
assert.Contains(t, res.Message, "续签成功")
updated, err := repository.GetTLSCertificateByID(ctx, cert.ID)
require.NoError(t, err)
assert.Equal(t, tlsApplyStatusReady, updated.ApplyStatus)
})
t.Run("failed renewal in obtain", func(t *testing.T) {
cert := &model.TLSCertificate{
Name: "acme-cert-fail",
Provider: tlsProviderACME,
PrimaryDomain: "fail.example.com",
}
err := repository.CreateTLSCertificateRecord(ctx, cert)
require.NoError(t, err)
// Mock obtainCertificate to fail
restore := SetObtainCertificateFuncForTest(func(ctx context.Context, c *model.TLSCertificate) error {
return errors.New("ACME server timeout")
})
defer restore()
payload, err := json.Marshal(SSLSingleRenewPayload{ID: cert.ID})
require.NoError(t, err)
_, err = handler.Execute(ctx, payload)
require.Error(t, err)
assert.Equal(t, "ACME server timeout", err.Error())
})
}