Files
junhong_cmp_fiber/pkg/utils/csv_test.go
huang 45aa7deb87
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 5m33s
feat: 添加环境变量管理工具和部署配置改版
主要改动:
- 新增交互式环境配置脚本 (scripts/setup-env.sh)
- 新增本地启动快捷脚本 (scripts/run-local.sh)
- 新增环境变量模板文件 (.env.example)
- 部署模式改版:使用嵌入式配置 + 环境变量覆盖
- 添加对象存储功能支持
- 改进 IoT 卡片导入任务
- 优化 OpenAPI 文档生成
- 删除旧的配置文件,改用嵌入式默认配置
2026-01-26 10:28:29 +08:00

221 lines
6.4 KiB
Go

package utils
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseCardCSV(t *testing.T) {
tests := []struct {
name string
csvContent string
wantCards []CardInfo
wantTotalCount int
wantErrorCount int
wantError error
}{
{
name: "标准双列无表头",
csvContent: "89860012345678901234,13800000001\n89860012345678901235,13800000002",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
{ICCID: "89860012345678901235", MSISDN: "13800000002"},
},
wantTotalCount: 2,
wantErrorCount: 0,
},
{
name: "标准双列有表头-英文",
csvContent: "iccid,msisdn\n89860012345678901234,13800000001\n89860012345678901235,13800000002",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
{ICCID: "89860012345678901235", MSISDN: "13800000002"},
},
wantTotalCount: 2,
wantErrorCount: 0,
},
{
name: "标准双列有表头-中文",
csvContent: "卡号,接入号\n89860012345678901234,13800000001",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
},
wantTotalCount: 1,
wantErrorCount: 0,
},
{
name: "标准双列有表头-手机号",
csvContent: "ICCID,手机号\n89860012345678901234,13800000001",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
},
wantTotalCount: 1,
wantErrorCount: 0,
},
{
name: "单列CSV格式拒绝-有表头",
csvContent: "iccid\n89860012345678901234",
wantCards: nil,
wantTotalCount: 0,
wantErrorCount: 0,
wantError: ErrInvalidCSVFormat,
},
{
name: "单列CSV格式-无表头记录错误",
csvContent: "89860012345678901234\n89860012345678901235",
wantCards: []CardInfo{},
wantTotalCount: 2,
wantErrorCount: 2,
},
{
name: "MSISDN为空记录失败",
csvContent: "iccid,msisdn\n89860012345678901234,13800000001\n89860012345678901235,",
wantCards: []CardInfo{{ICCID: "89860012345678901234", MSISDN: "13800000001"}},
wantTotalCount: 2,
wantErrorCount: 1,
},
{
name: "ICCID为空记录失败",
csvContent: "iccid,msisdn\n89860012345678901234,13800000001\n,13800000002",
wantCards: []CardInfo{{ICCID: "89860012345678901234", MSISDN: "13800000001"}},
wantTotalCount: 2,
wantErrorCount: 1,
},
{
name: "空文件",
csvContent: "",
wantCards: []CardInfo{},
wantTotalCount: 0,
wantErrorCount: 0,
},
{
name: "只有表头",
csvContent: "iccid,msisdn",
wantCards: []CardInfo{},
wantTotalCount: 0,
wantErrorCount: 0,
},
{
name: "包含空行",
csvContent: "89860012345678901234,13800000001\n\n89860012345678901235,13800000002",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
{ICCID: "89860012345678901235", MSISDN: "13800000002"},
},
wantTotalCount: 2,
wantErrorCount: 0,
},
{
name: "ICCID和MSISDN前后有空格",
csvContent: " 89860012345678901234 , 13800000001 ",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
},
wantTotalCount: 1,
wantErrorCount: 0,
},
{
name: "多于两列只取前两列",
csvContent: "89860012345678901234,13800000001,额外数据\n89860012345678901235,13800000002,忽略",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
{ICCID: "89860012345678901235", MSISDN: "13800000002"},
},
wantTotalCount: 2,
wantErrorCount: 0,
},
{
name: "Windows换行符CRLF",
csvContent: "89860012345678901234,13800000001\r\n89860012345678901235,13800000002",
wantCards: []CardInfo{
{ICCID: "89860012345678901234", MSISDN: "13800000001"},
{ICCID: "89860012345678901235", MSISDN: "13800000002"},
},
wantTotalCount: 2,
wantErrorCount: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
reader := strings.NewReader(tt.csvContent)
result, err := ParseCardCSV(reader)
if tt.wantError != nil {
require.ErrorIs(t, err, tt.wantError)
return
}
require.NoError(t, err)
assert.Equal(t, tt.wantCards, result.Cards, "Cards 不匹配")
assert.Equal(t, tt.wantTotalCount, result.TotalCount, "TotalCount 不匹配")
assert.Equal(t, tt.wantErrorCount, len(result.ParseErrors), "ParseErrors 数量不匹配")
})
}
}
func TestParseCardCSV_ErrorDetails(t *testing.T) {
t.Run("MSISDN为空时记录详细错误", func(t *testing.T) {
csvContent := "iccid,msisdn\n89860012345678901234,"
reader := strings.NewReader(csvContent)
result, err := ParseCardCSV(reader)
require.NoError(t, err)
require.Len(t, result.ParseErrors, 1)
assert.Equal(t, 2, result.ParseErrors[0].Line)
assert.Equal(t, "89860012345678901234", result.ParseErrors[0].ICCID)
assert.Equal(t, "MSISDN 不能为空", result.ParseErrors[0].Reason)
})
t.Run("ICCID为空时记录详细错误", func(t *testing.T) {
csvContent := "iccid,msisdn\n,13800000001"
reader := strings.NewReader(csvContent)
result, err := ParseCardCSV(reader)
require.NoError(t, err)
require.Len(t, result.ParseErrors, 1)
assert.Equal(t, 2, result.ParseErrors[0].Line)
assert.Equal(t, "13800000001", result.ParseErrors[0].MSISDN)
assert.Equal(t, "ICCID 不能为空", result.ParseErrors[0].Reason)
})
t.Run("列数不足时记录详细错误", func(t *testing.T) {
csvContent := "89860012345678901234"
reader := strings.NewReader(csvContent)
result, err := ParseCardCSV(reader)
require.NoError(t, err)
require.Len(t, result.ParseErrors, 1)
assert.Equal(t, 1, result.ParseErrors[0].Line)
assert.Equal(t, "89860012345678901234", result.ParseErrors[0].ICCID)
assert.Contains(t, result.ParseErrors[0].Reason, "列数不足")
})
}
func TestIsHeader(t *testing.T) {
tests := []struct {
col1 string
col2 string
expected bool
}{
{"iccid", "msisdn", true},
{"ICCID", "MSISDN", true},
{"卡号", "接入号", true},
{"号码", "手机号", true},
{"iccid", "电话", true},
{"89860012345678901234", "13800000001", false},
{"iccid", "", false},
{"", "msisdn", false},
}
for _, tt := range tests {
t.Run(tt.col1+"_"+tt.col2, func(t *testing.T) {
result := isHeader(tt.col1, tt.col2)
assert.Equal(t, tt.expected, result)
})
}
}