Files
junhong_cmp_fiber/pkg/validator/iccid_test.go
huang a924e63e68
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 4m42s
feat: 实现物联网卡独立管理和批量导入功能
新增物联网卡独立管理模块,支持单卡查询、批量导入和状态管理。主要变更包括:

功能特性:
- 新增物联网卡 CRUD 接口(查询、分页列表、删除)
- 支持 CSV/Excel 批量导入物联网卡
- 实现异步导入任务处理和进度跟踪
- 新增 ICCID 号码格式校验器(支持 Luhn 算法)
- 新增 CSV 文件解析工具(支持编码检测和错误处理)

数据库变更:
- 移除 iot_card 和 device 表的 owner_id/owner_type 字段
- 新增 iot_card_import_task 导入任务表
- 为导入任务添加运营商类型字段

测试覆盖:
- 新增 IoT 卡 Store 层单元测试
- 新增 IoT 卡导入任务单元测试
- 新增 IoT 卡集成测试(包含导入流程测试)
- 新增 CSV 工具和 ICCID 校验器测试

文档更新:
- 更新 OpenAPI 文档(新增 7 个 IoT 卡接口)
- 归档 OpenSpec 变更提案
- 更新 API 文档规范和生成器指南

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-24 11:03:43 +08:00

268 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package validator
import (
"testing"
"github.com/break/junhong_cmp_fiber/pkg/constants"
"github.com/stretchr/testify/assert"
)
func TestValidateICCID(t *testing.T) {
tests := []struct {
name string
iccid string
carrierType string
wantValid bool
wantMessage string
}{
// 空值测试
{
name: "空ICCID应该返回错误",
iccid: "",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 不能为空",
},
// 电信 ICCID 测试19位
{
name: "电信有效ICCID-19位数字",
iccid: "8986031234567890123",
carrierType: constants.CarrierCodeCTCC,
wantValid: true,
wantMessage: "",
},
{
name: "电信ICCID-20位应该失败",
iccid: "89860312345678901234",
carrierType: constants.CarrierCodeCTCC,
wantValid: false,
wantMessage: "电信 ICCID 必须为 19 位",
},
{
name: "电信ICCID-18位应该失败",
iccid: "898603123456789012",
carrierType: constants.CarrierCodeCTCC,
wantValid: false,
wantMessage: "电信 ICCID 必须为 19 位",
},
// 移动 ICCID 测试20位
{
name: "移动有效ICCID-20位数字",
iccid: "89860012345678901234",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "移动有效ICCID-含字母",
iccid: "8986001234567890123A",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "移动ICCID-19位应该失败",
iccid: "8986001234567890123",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "该运营商 ICCID 必须为 20 位",
},
// 联通 ICCID 测试20位
{
name: "联通有效ICCID-20位数字",
iccid: "89860112345678901234",
carrierType: constants.CarrierCodeCUCC,
wantValid: true,
wantMessage: "",
},
{
name: "联通ICCID-21位应该失败",
iccid: "898601123456789012345",
carrierType: constants.CarrierCodeCUCC,
wantValid: false,
wantMessage: "该运营商 ICCID 必须为 20 位",
},
// 广电 ICCID 测试20位
{
name: "广电有效ICCID-20位数字",
iccid: "89860412345678901234",
carrierType: constants.CarrierCodeCBN,
wantValid: true,
wantMessage: "",
},
// 特殊字符测试
{
name: "ICCID包含特殊字符应该失败",
iccid: "8986001234567890123!",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
{
name: "ICCID包含空格应该失败",
iccid: "8986001234567890123 ",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
{
name: "ICCID包含中划线应该失败",
iccid: "8986001234-678901234",
carrierType: constants.CarrierCodeCMCC,
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
// 大小写字母测试
{
name: "ICCID包含小写字母有效",
iccid: "8986001234567890123a",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
{
name: "ICCID包含大写字母有效",
iccid: "8986001234567890123A",
carrierType: constants.CarrierCodeCMCC,
wantValid: true,
wantMessage: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateICCID(tt.iccid, tt.carrierType)
assert.Equal(t, tt.wantValid, result.Valid, "Valid 不匹配")
assert.Equal(t, tt.wantMessage, result.Message, "Message 不匹配")
})
}
}
func TestValidateICCIDWithoutCarrier(t *testing.T) {
tests := []struct {
name string
iccid string
wantValid bool
wantMessage string
}{
// 空值测试
{
name: "空ICCID应该返回错误",
iccid: "",
wantValid: false,
wantMessage: "ICCID 不能为空",
},
// 有效长度测试19位或20位
{
name: "19位ICCID有效",
iccid: "8986031234567890123",
wantValid: true,
wantMessage: "",
},
{
name: "20位ICCID有效",
iccid: "89860012345678901234",
wantValid: true,
wantMessage: "",
},
// 无效长度测试
{
name: "18位ICCID无效",
iccid: "898603123456789012",
wantValid: false,
wantMessage: "ICCID 长度必须为 19 位或 20 位",
},
{
name: "21位ICCID无效",
iccid: "898600123456789012345",
wantValid: false,
wantMessage: "ICCID 长度必须为 19 位或 20 位",
},
// 特殊字符测试
{
name: "包含特殊字符应该失败",
iccid: "8986001234567890123!",
wantValid: false,
wantMessage: "ICCID 只能包含字母和数字",
},
// 字母数字混合测试
{
name: "20位含字母有效",
iccid: "8986001234567890AB12",
wantValid: true,
wantMessage: "",
},
{
name: "19位含字母有效",
iccid: "898603123456789AB12",
wantValid: true,
wantMessage: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := ValidateICCIDWithoutCarrier(tt.iccid)
assert.Equal(t, tt.wantValid, result.Valid, "Valid 不匹配")
assert.Equal(t, tt.wantMessage, result.Message, "Message 不匹配")
})
}
}
// TestGetExpectedICCIDLength 测试获取期望的 ICCID 长度
func TestGetExpectedICCIDLength(t *testing.T) {
tests := []struct {
name string
carrierType string
expectedLength int
}{
{
name: "电信应该返回19",
carrierType: constants.CarrierCodeCTCC,
expectedLength: 19,
},
{
name: "移动应该返回20",
carrierType: constants.CarrierCodeCMCC,
expectedLength: 20,
},
{
name: "联通应该返回20",
carrierType: constants.CarrierCodeCUCC,
expectedLength: 20,
},
{
name: "广电应该返回20",
carrierType: constants.CarrierCodeCBN,
expectedLength: 20,
},
{
name: "未知运营商应该返回20",
carrierType: "UNKNOWN",
expectedLength: 20,
},
{
name: "空运营商应该返回20",
carrierType: "",
expectedLength: 20,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := getExpectedICCIDLength(tt.carrierType)
assert.Equal(t, tt.expectedLength, result)
})
}
}