Files
Bridge-and-Join-s/internal/nsdadapter/sender_test.go
T
zuevav 9737c787f9 feat: живой цикл M2M с НРД + мастер установки ключа на флешку
Инфраструктура M2M (живой обмен с НРД через ИШ):
- обработка M2MTransferResponse: ERROR(M2Mxx) → заявка Отклонена, сохранение
  ответа; INFO → ждём Decision; идемпотентность поллера
- fallback-корреляция ответов с нулевым GUID (M2M14/M2M17) по FIFO
- сырой XML ответа НРД в карточке заявки (для пересылки в ТП)
- тестовый пакет роботу приведён к эталону m2m_robot_samples (CostInfo=Yes,
  4 бумаги, IsolationStatus, DocumentSeries=сценарий); override паспорта
- редирект из теста сразу в карточку заявки

Мастер установки ключа Валидаты на флешку (admin/setup/keywizard):
- пошаговый: загрузка .7z+пароль → выбор флешки → запись → справочник
  сертификатов (CRL) → перезапуск+проверка ИШ → готово
- привилегированный воркер (bj-keymedia) в host-namespace через файл-обмен,
  bj-server остаётся в песочнице
- сохранение структуры профиля архива (spr<N>), перечисление съёмных USB

Прочее:
- пакет-доказательство для ТП НРД + форма регистрации участника M2M
- эталонные образцы робота (DOC/m2m_robot_samples)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-19 00:03:21 +03:00

112 lines
3.5 KiB
Go

package nsdadapter_test
import (
"context"
"testing"
"time"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/m2m"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter"
"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/nsdadapter/igw"
)
type mockIGW struct {
gotChannel string
gotType string
gotBody []byte
returnID string
returnErr error
}
func (m *mockIGW) SendPackage(_ context.Context, channel, packageType string, body []byte) (string, error) {
m.gotChannel = channel
m.gotType = packageType
m.gotBody = append([]byte(nil), body...)
return m.returnID, m.returnErr
}
func (m *mockIGW) ListIncoming(_ context.Context, _ string, _ time.Time, _ string) ([]igw.Package, error) {
return nil, nil
}
// validRequest строит минимально валидный M2MTransferRequest для теста Sender.
func validRequest() *m2m.M2MTransferRequest {
whole := uint64(100)
isin := m2m.ISIN("RU0007661625")
return &m2m.M2MTransferRequest{
Header: m2m.RequestHeader{
GUID: m2m.UUID("c02a1d5e-c2af-4799-bab4-953f133c5133"),
SenderCode: "MC0079200000",
ReceiverCode: "MC0010300000",
CostInfo: m2m.CostInfo{No: &m2m.CostInfoNo{}},
},
Data: m2m.RequestData{
InvestorInformation: m2m.InvestorInformation{
LastName: "Иванов",
FirstName: "Иван",
IdentityDocument: m2m.IdentityDocument{
DocumentType: m2m.DocCode21,
DocumentNumber: m2m.IdentityDocSerial("654321"),
},
},
TransferringDepository: m2m.SettlementRequisites{INN: "7702070139"},
ReceivingDepository: m2m.SettlementRequisites{INN: "7802031669"},
TransferredSecurities: m2m.RequestTransferredSecurities{
Securities: []m2m.RequestSecurity{
{
ReferenceID: "M2M2026030200001",
SecurityCode: "MM0766162534",
SecurityDetails: m2m.SecurityDetails{ISIN: &isin},
Quantity: m2m.Quantity{Whole: &whole},
SettlementAccount: []m2m.RequestSettlementAccount{
{
SettlementRequisites: m2m.SettlementRequisites{INN: "7702070139"},
SettlementLocation: m2m.SettlementDepositoryLocation{
DeponentCode: "DP789456",
AccountID: "31MC0021900000F01",
SectionID: "P001",
},
},
},
IsolationStatus: m2m.IsolationSGDN,
},
},
},
},
}
}
func TestSenderSend(t *testing.T) {
profile, err := nsdadapter.LookupProfile("test3-gost")
if err != nil {
t.Fatal(err)
}
mock := &mockIGW{returnID: "pkg-1"}
s := nsdadapter.NewSender(profile, mock)
_, err = s.Send(context.Background(), validRequest())
if err != nil {
t.Fatalf("Send: %v", err)
}
// ИШ резолвит канал по составному коду: код канала + код депонента-
// отправителя (channels.code = channelCode+deponentCode). Для профиля
// test3-gost и отправителя MC0079200000 это TEST3MC0079200000.
if mock.gotChannel != "TEST3MC0079200000" {
t.Errorf("channel = %q, ожидалось TEST3MC0079200000", mock.gotChannel)
}
if mock.gotType != string(nsdadapter.PackageM2MTransferRequest) {
t.Errorf("type = %q, ожидалось %s", mock.gotType, nsdadapter.PackageM2MTransferRequest)
}
if len(mock.gotBody) == 0 {
t.Error("body пустой")
}
}
func TestSenderSendNilRequest(t *testing.T) {
profile, _ := nsdadapter.LookupProfile("guest-gost")
s := nsdadapter.NewSender(profile, &mockIGW{})
if _, err := s.Send(context.Background(), nil); err == nil {
t.Error("ожидалась ошибка на nil request")
}
}