1d6ab86a57
- internal/m2m/types.go: enum'ы и simple-типы из XSD НРД (M2MSchemas_260408) - internal/m2m/validators.go: pattern-валидаторы ReferenceID/ISIN/INN/UUID/SecurityCode/IdentityDocSerial/AccountID + перечисления - internal/m2m/messages.go: структуры 6 типов сообщений M2M, choice-типы через указатели, IsM2M=true автоматически в MarshalXML - internal/nsdxml/datetime.go: тип NSDDateTime (формат "YYYY-MM-DDThh:mm:ss(МСК+N)") - internal/nsdxml/codec.go: Marshal/Unmarshal XML в windows-1251 (собственный кодек CP1251, без внешних зависимостей) - internal/m2m/messages_test.go: round-trip тесты на 6 примерах + 2 эталонах из DOC/ Покрытие: m2m 73.9%, nsdxml 92.5%. make ci зелёный. Отклонение от спеки: вместо golang.org/x/text/encoding/charmap собственная таблица CP1251 на ~60 строк, потому что прокси zetit блокирует proxy.golang.org, goproxy.cn и redirect-хосты Go-модулей. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
package nsdxml_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/xml"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdxml"
|
|
)
|
|
|
|
func TestCharmap1251RoundTrip(t *testing.T) {
|
|
cases := []string{
|
|
"",
|
|
"abc",
|
|
"Привет, мир!",
|
|
"Иванов И.И.",
|
|
"АБВГД абвгд",
|
|
"символы: №, ©, ®, «», „текст", // включая cp1251 пунктуацию
|
|
}
|
|
for _, s := range cases {
|
|
s := s
|
|
t.Run(s, func(t *testing.T) {
|
|
enc, err := nsdxml.EncodeWindows1251([]byte(s))
|
|
if err != nil {
|
|
t.Fatalf("EncodeWindows1251: %v", err)
|
|
}
|
|
dec := nsdxml.DecodeWindows1251(enc)
|
|
if string(dec) != s {
|
|
t.Errorf("round-trip разошёлся: %q -> %x -> %q", s, enc, dec)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEncodeUnmappable(t *testing.T) {
|
|
_, err := nsdxml.EncodeWindows1251([]byte("эмодзи: 😀"))
|
|
if !errors.Is(err, nsdxml.ErrUnmappable) {
|
|
t.Errorf("ожидалась ErrUnmappable, получено: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCharsetReader(t *testing.T) {
|
|
src := []byte{0xC8, 0xE2, 0xE0, 0xED, 0xEE, 0xE2} // "Иванов" в windows-1251
|
|
r, err := nsdxml.CharsetReader("windows-1251", bytes.NewReader(src))
|
|
if err != nil {
|
|
t.Fatalf("CharsetReader: %v", err)
|
|
}
|
|
buf := new(bytes.Buffer)
|
|
if _, err := buf.ReadFrom(r); err != nil {
|
|
t.Fatalf("ReadFrom: %v", err)
|
|
}
|
|
if buf.String() != "Иванов" {
|
|
t.Errorf("получено %q, ожидалось %q", buf.String(), "Иванов")
|
|
}
|
|
}
|
|
|
|
func TestCharsetReaderUnknown(t *testing.T) {
|
|
_, err := nsdxml.CharsetReader("koi8-r", bytes.NewReader(nil))
|
|
if err == nil {
|
|
t.Error("ожидалась ошибка для неизвестной кодировки")
|
|
}
|
|
}
|
|
|
|
func TestMarshalUnmarshalRoundTrip(t *testing.T) {
|
|
type entry struct {
|
|
XMLName xml.Name `xml:"entry"`
|
|
Name string `xml:"name"`
|
|
Value string `xml:"value"`
|
|
}
|
|
original := entry{Name: "Иванов И.И.", Value: "тест"}
|
|
data, err := nsdxml.Marshal(original)
|
|
if err != nil {
|
|
t.Fatalf("Marshal: %v", err)
|
|
}
|
|
if !strings.HasPrefix(string(nsdxml.DecodeWindows1251(data)), `<?xml version="1.0" encoding="windows-1251"?>`) {
|
|
t.Fatalf("в выходе нет пролога windows-1251")
|
|
}
|
|
var parsed entry
|
|
if err := nsdxml.Unmarshal(data, &parsed); err != nil {
|
|
t.Fatalf("Unmarshal: %v", err)
|
|
}
|
|
if parsed.Name != original.Name || parsed.Value != original.Value {
|
|
t.Errorf("round-trip разошёлся: %+v vs %+v", original, parsed)
|
|
}
|
|
}
|