package upstream import ( "strings" "testing" ) func TestSplitSubmitContentUCS2LongMessage(t *testing.T) { content := strings.Repeat("测试", 40) parts, err := splitSubmitContent(8, content) if err != nil { t.Fatalf("splitSubmitContent returned error: %v", err) } if len(parts) < 2 { t.Fatalf("expected multipart content, got %d part", len(parts)) } total := uint8(len(parts)) ref := []byte(parts[0].MsgContent)[3] for i, part := range parts { if part.PkTotal != total { t.Fatalf("part %d PkTotal = %d, want %d", i, part.PkTotal, total) } if part.PkNumber != uint8(i+1) { t.Fatalf("part %d PkNumber = %d, want %d", i, part.PkNumber, i+1) } if part.TpUdhi != 1 { t.Fatalf("part %d TpUdhi = %d, want 1", i, part.TpUdhi) } raw := []byte(part.MsgContent) if len(raw) > maxSingleMessageBytes { t.Fatalf("part %d length = %d, want <= %d", i, len(raw), maxSingleMessageBytes) } if raw[0] != 0x05 || raw[1] != 0x00 || raw[2] != 0x03 { t.Fatalf("part %d missing standard concat UDH: %v", i, raw[:concatUDHLength]) } if raw[3] != ref || raw[4] != total || raw[5] != uint8(i+1) { t.Fatalf("part %d UDH = %v, ref=%d total=%d number=%d", i, raw[:concatUDHLength], ref, total, i+1) } if len(raw[concatUDHLength:])%2 != 0 { t.Fatalf("part %d UCS2 payload length must be even, got %d", i, len(raw[concatUDHLength:])) } } } func TestSplitSubmitContentSingleShortMessage(t *testing.T) { parts, err := splitSubmitContent(15, "hello") if err != nil { t.Fatalf("splitSubmitContent returned error: %v", err) } if len(parts) != 1 { t.Fatalf("expected one part, got %d", len(parts)) } if parts[0].PkTotal != 1 || parts[0].PkNumber != 1 || parts[0].TpUdhi != 0 { t.Fatalf("unexpected single part metadata: %+v", parts[0]) } } func TestAssembleLongUplinkOutOfOrder(t *testing.T) { content := strings.Repeat("上行", 40) parts, err := splitSubmitContent(8, content) if err != nil { t.Fatalf("splitSubmitContent returned error: %v", err) } if len(parts) < 2 { t.Fatalf("expected multipart content, got %d part", len(parts)) } assemblies := map[string]*longUplinkAssembly{} key := "channel:phone:dest:ref" for i := len(parts) - 1; i >= 0; i-- { _, total, number, payload, ok := parseConcatSegment(parts[i].MsgContent) if !ok { t.Fatalf("part %d did not parse as concat segment", i) } assembled, complete, err := assembleLongUplink(assemblies, key, 8, total, number, payload) if err != nil { t.Fatalf("assembleLongUplink returned error: %v", err) } if i > 0 && complete { t.Fatalf("assembly completed before all parts arrived") } if i == 0 { if !complete { t.Fatalf("assembly did not complete after all parts arrived") } if assembled != content { t.Fatalf("assembled content mismatch: got %q want %q", assembled, content) } } } if len(assemblies) != 0 { t.Fatalf("expected completed assembly to be removed, got %d", len(assemblies)) } }