| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- package services
- import (
- "context"
- "strings"
- "testing"
- "time"
- "fwh-toolbox-server/domain"
- "fwh-toolbox-server/repositories"
- )
- func TestFaultSubMatchesCallable(t *testing.T) {
- candidate := domain.FaultRecordCallableInfo{FailureTime: "2026-09-22 12:30:00", TriggerSourceCode: "E42"}
- sub := domain.FaultRecordSubInfo{FailureTime: "2026-09-22 12:30:00", EventTriggerSource: "E42"}
- if !faultSubMatchesCallable(sub, candidate) {
- t.Fatal("matching time and code should match")
- }
- sub.EventTriggerSource = "E43"
- if faultSubMatchesCallable(sub, candidate) {
- t.Fatal("different fault code must not match")
- }
- }
- func TestExistingFaultRecordRequiresCompleteSubList(t *testing.T) {
- candidates := []domain.FaultRecordCallableInfo{{FailureTime: "2026-09-22 12:30:00", TriggerSourceCode: "E42"}}
- subs := []domain.FaultRecordSubInfo{{Id: 10, FailureTime: candidates[0].FailureTime, EventTriggerSource: candidates[0].TriggerSourceCode}}
- matched := []bool{false}
- record := domain.FaultRecordInfo{Id: 99, FaultRecordsCount: 2}
- if got := matchExistingFaultRecord(record, subs, candidates, matched); len(got) != 0 || matched[0] {
- t.Fatalf("incomplete record was reused: %+v", got)
- }
- record.FaultRecordsCount = 1
- if got := matchExistingFaultRecord(record, subs, candidates, matched); len(got) != 1 || !matched[0] {
- t.Fatalf("complete record not reused: %+v", got)
- }
- }
- func TestResolveFaultRecordSourcesReusesVerifiedSubrecord(t *testing.T) {
- originalCatalog := repositories.QueryFaultRecordCallableList
- originalList := repositories.QueryFaultRecordList
- originalSubs := repositories.QueryFaultRecordSubList
- t.Cleanup(func() {
- repositories.QueryFaultRecordCallableList = originalCatalog
- repositories.QueryFaultRecordList = originalList
- repositories.QueryFaultRecordSubList = originalSubs
- })
- repositories.QueryFaultRecordCallableList = func(_ int, _ string) ([]domain.FaultRecordCallableInfo, error) {
- return []domain.FaultRecordCallableInfo{{Idx: 7, FailureTime: "2026-09-22 12:30:00", TriggerSourceCode: "E42"}}, nil
- }
- repositories.QueryFaultRecordList = func(_, _, _ string) ([]domain.FaultRecordInfo, error) {
- return []domain.FaultRecordInfo{{Id: 99, GatewayId: "GATE-1", DeviceType: 1, FaultRecordsCount: 1}}, nil
- }
- repositories.QueryFaultRecordSubList = func(_ int64) ([]domain.FaultRecordSubInfo, error) {
- return []domain.FaultRecordSubInfo{{Id: 10, FaultId: 99, GatewayId: "GATE-1", FailureTime: "2026-09-22 12:30:00", EventTriggerSource: "E42"}}, nil
- }
- start := time.Date(2026, 9, 22, 0, 0, 0, 0, time.UTC)
- sources, err := resolveFaultRecordSources(context.Background(), &domain.DataDownloadItem{DeviceSN: "GATE-1"}, "document-1", 1, start, start.Add(24*time.Hour-time.Second))
- if err != nil {
- t.Fatal(err)
- }
- if len(sources) != 1 || sources[0].sub.Id != 10 {
- t.Fatalf("sources = %+v", sources)
- }
- }
- func TestFindFaultCallByRequestChecksAllIdentityFields(t *testing.T) {
- original := repositories.QueryFaultRecordCallRecordPageContext
- t.Cleanup(func() { repositories.QueryFaultRecordCallRecordPageContext = original })
- sn := "GATE-1"
- other := "GATE-2"
- status := 0
- calledAt := time.Date(2026, 9, 23, 12, 0, 0, 0, time.UTC)
- repositories.QueryFaultRecordCallRecordPageContext = func(_ context.Context, page, size int) ([]domain.FaultRecordInfo, error) {
- if page > 1 {
- return nil, nil
- }
- return []domain.FaultRecordInfo{
- {Id: 101, DeviceType: 1, GatewayId: other, FaultRecordsCount: 2, TriggerType: 2, CellTime: "2026-09-23 12:00:00", Status: &status},
- {Id: 102, DeviceType: 1, GatewayId: sn, FaultRecordsCount: 1, TriggerType: 2, CellTime: "2026-09-23 12:00:00", Status: &status},
- {Id: 103, DeviceType: 1, GatewayId: sn, FaultRecordsCount: 2, TriggerType: 1, CellTime: "2026-09-23 12:00:00", Status: &status},
- {Id: 104, DeviceType: 1, GatewayId: sn, FaultRecordsCount: 2, TriggerType: 2, CellTime: "2026-09-23 12:02:00", Status: &status},
- {Id: 105, DeviceType: 1, GatewayId: sn, FaultRecordsCount: 2, TriggerType: 2, CellTime: "2026-09-23 12:00:30", Status: &status},
- }, nil
- }
- record, err := findFaultCallByRequest(context.Background(), sn, 1, 2, calledAt)
- if err != nil {
- t.Fatal(err)
- }
- if record == nil || record.Id != 105 {
- t.Fatalf("got %+v, want ID 105", record)
- }
- }
- func TestFindFaultCallByIDUsesPageSearch(t *testing.T) {
- original := repositories.QueryFaultRecordCallRecordPageContext
- t.Cleanup(func() { repositories.QueryFaultRecordCallRecordPageContext = original })
- queries := 0
- repositories.QueryFaultRecordCallRecordPageContext = func(_ context.Context, page, size int) ([]domain.FaultRecordInfo, error) {
- queries++
- if page > 128 {
- return nil, nil
- }
- rows := make([]domain.FaultRecordInfo, size)
- for i := range rows {
- rows[i].Id = int64(6401 - (page-1)*size - i)
- }
- return rows, nil
- }
- record, err := findFaultCallByID(context.Background(), 1600)
- if err != nil {
- t.Fatal(err)
- }
- if record == nil || record.Id != 1600 {
- t.Fatalf("got %+v, want ID 1600", record)
- }
- if queries > 16 {
- t.Fatalf("used %d queries for a record on page 97", queries)
- }
- }
- func TestSummonFaultRecordsHonorsElapsedTimeout(t *testing.T) {
- started := time.Now().UTC().Add(-faultCallTimeout - time.Minute)
- item := &domain.DataDownloadItem{CallRequestedAt: &started, DeviceSN: "GATE-1"}
- _, err := summonFaultRecords(context.Background(), item, "document-1", 1, []int{1})
- if err == nil || !strings.Contains(err.Error(), "timed out after 2h") {
- t.Fatalf("got %v, want timeout", err)
- }
- }
- func TestActiveFaultCallKeepsOwnershipAfterCancellation(t *testing.T) {
- started := time.Now().UTC().Add(-time.Minute)
- item := &domain.DataDownloadItem{Kind: domain.DataDownloadFaultRecord, CallRequestedAt: &started}
- if err := ReleaseFaultCallOwnership(context.Background(), item); err != nil {
- t.Fatal(err)
- }
- }
|