132 lines
4.1 KiB
Go
132 lines
4.1 KiB
Go
package report
|
||
|
||
import (
|
||
"bytes"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// TestEscposQR_EmptyData 空数据应直接返回 nil,不写入任何指令
|
||
func TestEscposQR_EmptyData(t *testing.T) {
|
||
var buf bytes.Buffer
|
||
if err := escposQR(&buf, "", 6, 49); err != nil {
|
||
t.Fatalf("空数据应返回 nil,得到 err=%v", err)
|
||
}
|
||
if buf.Len() != 0 {
|
||
t.Errorf("空数据不应输出指令,实际写入 %d 字节", buf.Len())
|
||
}
|
||
}
|
||
|
||
// TestEscposQR_BasicCommands 验证基本 GS ( k 指令流
|
||
func TestEscposQR_BasicCommands(t *testing.T) {
|
||
var buf bytes.Buffer
|
||
data := "http://192.168.1.10:8080/reports/report-abc-10.0.0.1-20260824.html"
|
||
if err := escposQR(&buf, data, 6, 49); err != nil {
|
||
t.Fatalf("生成指令失败: %v", err)
|
||
}
|
||
|
||
got := buf.Bytes()
|
||
// 必须包含 GS ( k 起始
|
||
if !bytes.Contains(got, []byte{0x1d, 0x28, 0x6b}) {
|
||
t.Error("缺少 GS ( k 起始指令")
|
||
}
|
||
// 必须包含模型选择 cn=49 fn=65 n=50
|
||
if !bytes.Contains(got, []byte{0x31, 0x41, 0x32}) {
|
||
t.Error("缺少 QR 模型选择指令 (31 41 32)")
|
||
}
|
||
// 必须包含模块大小 n=6
|
||
if !bytes.Contains(got, []byte{0x31, 0x43, 0x06}) {
|
||
t.Error("缺少模块大小指令 (31 43 06)")
|
||
}
|
||
// 必须包含纠错级别 M (49)
|
||
if !bytes.Contains(got, []byte{0x31, 0x45, 49}) {
|
||
t.Error("缺少纠错级别指令 (31 45 49)")
|
||
}
|
||
// 必须包含数据存储 49 80 48
|
||
if !bytes.Contains(got, []byte{0x31, 0x50, 0x30}) {
|
||
t.Error("缺少数据存储指令 (31 50 30)")
|
||
}
|
||
// 必须包含打印指令 49 81 48
|
||
if !bytes.Contains(got, []byte{0x31, 0x51, 0x30}) {
|
||
t.Error("缺少打印指令 (31 51 30)")
|
||
}
|
||
// 数据本体
|
||
if !bytes.Contains(got, []byte(data)) {
|
||
t.Error("缺少 URL 数据本体")
|
||
}
|
||
}
|
||
|
||
// TestEscposQR_ClampSizeAndECC 验证 size/ecc 参数越界时自动夹紧
|
||
func TestEscposQR_ClampSizeAndECC(t *testing.T) {
|
||
var buf1, buf2, buf3 bytes.Buffer
|
||
// size 越界 0 → 夹紧为 1
|
||
_ = escposQR(&buf1, "abc", 0, 49)
|
||
// size 越界 99 → 夹紧为 16
|
||
_ = escposQR(&buf2, "abc", 99, 49)
|
||
// ecc 非法 99 → 夹紧为 49 (M)
|
||
_ = escposQR(&buf3, "abc", 6, 99)
|
||
|
||
if !bytes.Contains(buf1.Bytes(), []byte{0x31, 0x43, 0x01}) {
|
||
t.Error("size=0 应夹紧为 1,未生效")
|
||
}
|
||
if !bytes.Contains(buf2.Bytes(), []byte{0x31, 0x43, 0x10}) {
|
||
t.Error("size=99 应夹紧为 16,未生效")
|
||
}
|
||
if !bytes.Contains(buf3.Bytes(), []byte{0x31, 0x45, 49}) {
|
||
t.Error("ecc=99 应夹紧为 49(M),未生效")
|
||
}
|
||
}
|
||
|
||
// TestEscposQR_DataLengthEncoding pL/pH 编码正确(大数据场景)
|
||
// 指令布局: 1d 28 6b pL pH 31 50 30 <data>
|
||
func TestEscposQR_DataLengthEncoding(t *testing.T) {
|
||
var buf bytes.Buffer
|
||
// 200 字节数据 → pL = 203 (0xCB), pH = 0
|
||
data := strings.Repeat("a", 200)
|
||
_ = escposQR(&buf, data, 6, 49)
|
||
got := buf.Bytes()
|
||
|
||
wantPL := byte((200 + 3) & 0xff) // 203 = 0xCB
|
||
wantPH := byte(((200 + 3) >> 8) & 0xff)
|
||
|
||
// 数据存储标记 "31 50 30" 在 got 中的位置
|
||
dataMarker := []byte{0x31, 0x50, 0x30}
|
||
idx := bytes.Index(got, dataMarker)
|
||
if idx < 0 {
|
||
t.Fatal("未找到数据存储指令 31 50 30")
|
||
}
|
||
// 期望布局:1d(GS) 28 ( 6b k pL pH 31 50 30 ...
|
||
// got[idx-5] = 0x1d, got[idx-4] = 0x28, got[idx-3] = 0x6b
|
||
// got[idx-2] = pL, got[idx-1] = pH
|
||
if got[idx-5] != 0x1d || got[idx-4] != 0x28 || got[idx-3] != 0x6b {
|
||
t.Fatalf("pL/pH 前不是 GS ( k,实际前 5 字节 = % x", got[idx-5:idx])
|
||
}
|
||
if got[idx-2] != wantPL || got[idx-1] != wantPH {
|
||
t.Errorf("pL/pH 编码错误: got=0x%02x 0x%02x, want=0x%02x 0x%02x",
|
||
got[idx-2], got[idx-1], wantPL, wantPH)
|
||
}
|
||
}
|
||
|
||
// TestSystemPrinter_PrintQR 系统打印后端 no-op
|
||
func TestSystemPrinter_PrintQR(t *testing.T) {
|
||
p := &SystemPrinter{}
|
||
if err := p.PrintQR("http://example.com"); err != nil {
|
||
t.Errorf("SystemPrinter.PrintQR 应返回 nil,得到 %v", err)
|
||
}
|
||
}
|
||
|
||
// TestFilePrinter_PrintQR 文件后端写入提示行 + URL
|
||
func TestFilePrinter_PrintQR(t *testing.T) {
|
||
tmp := t.TempDir()
|
||
p, err := NewFilePrinter(tmp + "/out.log")
|
||
if err != nil {
|
||
t.Fatalf("创建 FilePrinter 失败: %v", err)
|
||
}
|
||
defer p.Close()
|
||
|
||
url := "http://192.168.1.10/reports/r.html"
|
||
if err := p.PrintQR(url); err != nil {
|
||
t.Fatalf("PrintQR 失败: %v", err)
|
||
}
|
||
}
|