test(supply-api): validate shipped config samples
Add regression tests for the shipped development and SMS sample configs, and fix the SMS example to match the runtime flat Config schema instead of nested provider blocks. Verified with fresh go test runs for ./internal/config and ./internal/sms before commit.
This commit is contained in:
37
supply-api/config/config.dev.yaml
Normal file
37
supply-api/config/config.dev.yaml
Normal file
@@ -0,0 +1,37 @@
|
||||
# Supply API Development Configuration
|
||||
server:
|
||||
addr: ":18082"
|
||||
read_timeout: 10s
|
||||
write_timeout: 15s
|
||||
idle_timeout: 30s
|
||||
shutdown_timeout: 5s
|
||||
|
||||
database:
|
||||
host: "localhost"
|
||||
port: 5432
|
||||
user: "postgres"
|
||||
password: ""
|
||||
database: "supply_db"
|
||||
max_open_conns: 25
|
||||
max_idle_conns: 5
|
||||
conn_max_lifetime: 1h
|
||||
conn_max_idle_time: 10m
|
||||
|
||||
redis:
|
||||
host: "localhost"
|
||||
port: 6379
|
||||
password: ""
|
||||
db: 0
|
||||
pool_size: 10
|
||||
|
||||
token:
|
||||
secret_key: "${SUPPLY_TOKEN_SECRET_KEY}"
|
||||
issuer: "lijiaoqiao/supply-api"
|
||||
access_token_ttl: 1h
|
||||
refresh_token_ttl: 168h
|
||||
revocation_cache_ttl: 30s
|
||||
|
||||
audit:
|
||||
buffer_size: 1000
|
||||
flush_interval: 5s
|
||||
export_timeout: 30s
|
||||
47
supply-api/config/sms.example.yaml
Normal file
47
supply-api/config/sms.example.yaml
Normal file
@@ -0,0 +1,47 @@
|
||||
# SMS Service Configuration
|
||||
# 短信服务配置
|
||||
|
||||
sms:
|
||||
# 是否启用SMS服务;默认 false 时运行时会拒绝验证码校验
|
||||
enabled: false
|
||||
|
||||
# SMS服务提供商: tencent (腾讯云) 或 aliyun (阿里云)
|
||||
provider: tencent
|
||||
|
||||
# 运行时读取扁平字段,而不是按 provider 分组的嵌套字段
|
||||
app_id: "1400123456" # 腾讯云: SDK AppID;阿里云: AccessKey ID
|
||||
app_secret: "your_app_key" # 腾讯云: AppKey;阿里云: AccessKey Secret
|
||||
sign_name: "供应链平台" # 短信签名
|
||||
template_code: "SMS_123456789" # 短信模板 CODE
|
||||
region: "ap-guangzhou" # 腾讯云区域;阿里云可忽略
|
||||
endpoint: "" # 自定义 endpoint,可选
|
||||
|
||||
# 通用配置
|
||||
code_length: 6 # 验证码长度,默认6位
|
||||
code_expire_mins: 5 # 验证码有效期(分钟),默认5分钟
|
||||
|
||||
# 示例:启用腾讯云SMS
|
||||
# sms:
|
||||
# enabled: true
|
||||
# provider: tencent
|
||||
# app_id: "1400123456"
|
||||
# app_secret: "a1b2c3d4e5f6g7h8i9j0"
|
||||
# sign_name: "供应链平台"
|
||||
# template_code: "SMS_123456789"
|
||||
# region: "ap-guangzhou"
|
||||
# code_length: 6
|
||||
# code_expire_mins: 5
|
||||
|
||||
# 示例:启用阿里云SMS
|
||||
# sms:
|
||||
# enabled: true
|
||||
# provider: aliyun
|
||||
# app_id: "LTAI5tXXXXXXXXXXXX"
|
||||
# app_secret: |
|
||||
# -----BEGIN PRIVATE KEY-----
|
||||
# MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
|
||||
# -----END PRIVATE KEY-----
|
||||
# sign_name: "供应链平台"
|
||||
# template_code: "SMS_123456789"
|
||||
# code_length: 6
|
||||
# code_expire_mins: 5
|
||||
31
supply-api/internal/config/config_samples_test.go
Normal file
31
supply-api/internal/config/config_samples_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDevSampleConfigLoads(t *testing.T) {
|
||||
configPath := filepath.Join("..", "..", "config", "config.dev.yaml")
|
||||
|
||||
cfg, err := LoadFromPath("dev", configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("expected dev sample config to load, got error: %v", err)
|
||||
}
|
||||
|
||||
if cfg.Server.Addr != ":18082" {
|
||||
t.Fatalf("expected addr :18082, got %s", cfg.Server.Addr)
|
||||
}
|
||||
if cfg.Database.Host != "localhost" {
|
||||
t.Fatalf("expected database host localhost, got %s", cfg.Database.Host)
|
||||
}
|
||||
if cfg.Redis.Host != "localhost" {
|
||||
t.Fatalf("expected redis host localhost, got %s", cfg.Redis.Host)
|
||||
}
|
||||
if cfg.Token.Issuer != "lijiaoqiao/supply-api" {
|
||||
t.Fatalf("expected issuer lijiaoqiao/supply-api, got %s", cfg.Token.Issuer)
|
||||
}
|
||||
if cfg.Settlement.WithdrawEnabled {
|
||||
t.Fatal("expected dev sample config to keep withdraw disabled by default")
|
||||
}
|
||||
}
|
||||
45
supply-api/internal/sms/config_example_test.go
Normal file
45
supply-api/internal/sms/config_example_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package sms
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type smsExampleRoot struct {
|
||||
SMS Config `yaml:"sms"`
|
||||
}
|
||||
|
||||
func TestSMSExampleYAML_MatchesRuntimeConfigShape(t *testing.T) {
|
||||
path := filepath.Join("..", "..", "config", "sms.example.yaml")
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read sms example config: %v", err)
|
||||
}
|
||||
|
||||
var root smsExampleRoot
|
||||
if err := yaml.Unmarshal(content, &root); err != nil {
|
||||
t.Fatalf("failed to parse sms example config: %v", err)
|
||||
}
|
||||
|
||||
if root.SMS.Provider != ProviderTencent {
|
||||
t.Fatalf("expected provider %q, got %q", ProviderTencent, root.SMS.Provider)
|
||||
}
|
||||
if root.SMS.CodeLength != 6 {
|
||||
t.Fatalf("expected code length 6, got %d", root.SMS.CodeLength)
|
||||
}
|
||||
if root.SMS.CodeExpireMins != 5 {
|
||||
t.Fatalf("expected code expiry 5, got %d", root.SMS.CodeExpireMins)
|
||||
}
|
||||
if root.SMS.SignName == "" {
|
||||
t.Fatal("expected sign_name to be populated in example config")
|
||||
}
|
||||
if root.SMS.TemplateCode == "" {
|
||||
t.Fatal("expected template_code to be populated in example config")
|
||||
}
|
||||
if root.SMS.Region == "" {
|
||||
t.Fatal("expected region to be populated in example config")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user