package trafficcutoff import ( "context" "errors" "testing" "git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/service/batchresult" ) func TestValidateTaskFailsOnCanceledCard(t *testing.T) { task := validTask() task.Details[0].Card.BossCardStatus = BossCardStatusCanceled if validateTask(task) { t.Fatal("expected canceled card to fail validation") } if task.Details[0].Reason != statusCanceledReason { t.Fatalf("reason = %q, want %q", task.Details[0].Reason, statusCanceledReason) } } func TestValidateTaskFailsOnMixedCardStatus(t *testing.T) { task := validTask() task.Details = append(task.Details, &Detail{ RowNo: 2, ICCID: "898600000000002", Authorized: true, Card: &Card{ ID: 2, ICCID: "898600000000002", MSISDN: "13800000002", IMSI: "460001000000002", BossCardStatus: 5, }, }) if validateTask(task) { t.Fatal("expected mixed status batch to fail validation") } for _, detail := range task.Details { if detail.Reason != statusInconsistentReason { t.Fatalf("detail %d reason = %q, want %q", detail.RowNo, detail.Reason, statusInconsistentReason) } } } func TestValidateTaskFailsOnUnauthorizedAndCascades(t *testing.T) { task := validTask() task.Details = append(task.Details, &Detail{ RowNo: 2, ICCID: "898600000000002", Authorized: false, Card: &Card{ ID: 2, ICCID: "898600000000002", MSISDN: "13800000002", IMSI: "460001000000002", BossCardStatus: 4, }, }) if validateTask(task) { t.Fatal("expected unauthorized row to fail validation") } if task.Details[1].Reason != unauthorizedReason { t.Fatalf("unauthorized reason = %q", task.Details[1].Reason) } if task.Details[0].Reason != cascadeFailureReason { t.Fatalf("cascade reason = %q", task.Details[0].Reason) } } func TestExecuteHappyPathCommitsAndSavesResult(t *testing.T) { task := validTask() repo := &fakeRepository{task: task} if err := NewExecutor(repo).Execute(context.Background(), "DCT-1"); err != nil { t.Fatalf("Execute() error = %v", err) } if !repo.committed { t.Fatal("expected business commit") } if repo.validationSaved { t.Fatal("did not expect validation failure save") } if !repo.resultSaved { t.Fatal("expected result file save") } if repo.resultRequest.BatchType != 107 || len(repo.resultRequest.Rows) != 1 { t.Fatalf("unexpected result request: %+v", repo.resultRequest) } } func TestExecuteValidationFailureSkipsCommit(t *testing.T) { task := validTask() task.Details[0].Authorized = false repo := &fakeRepository{task: task} if err := NewExecutor(repo).Execute(context.Background(), "DCT-2"); err != nil { t.Fatalf("Execute() error = %v", err) } if !repo.validationSaved { t.Fatal("expected validation failure save") } if repo.committed { t.Fatal("did not expect business commit") } if !repo.resultSaved { t.Fatal("expected result file save") } } func TestExecuteCommitFailurePropagatesAndSkipsResult(t *testing.T) { task := validTask() commitErr := errors.New("transaction failed") repo := &fakeRepository{task: task, commitErr: commitErr} err := NewExecutor(repo).Execute(context.Background(), "DCT-3") if err == nil || !errors.Is(err, commitErr) { t.Fatalf("Execute() error = %v, want wrap of %v", err, commitErr) } if repo.resultSaved { t.Fatal("result file should not be saved after commit error") } } func validTask() *Task { return &Task{ Batch: Batch{BatchNo: "DCT-1", BatchType: 107, TenantID: "000000"}, TrafficCutoffStatus: 1, TrafficCutoffThreshold: 1024.5, ThresholdUnit: "MB", Details: []*Detail{ { RowNo: 1, ICCID: "898600000000001", Authorized: true, Card: &Card{ ID: 1, ICCID: "898600000000001", MSISDN: "13800000001", IMSI: "460001000000001", BossCardStatus: 4, }, }, }, } } type fakeRepository struct { task *Task committed bool commitErr error validationSaved bool resultSaved bool resultRequest batchresult.Request } func (r *fakeRepository) Load(_ context.Context, _ string) (*Task, error) { return r.task, nil } func (r *fakeRepository) SaveValidationFailure(_ context.Context, _ *Task) error { r.validationSaved = true return nil } func (r *fakeRepository) CommitBusiness(_ context.Context, _ *Task) error { r.committed = true return r.commitErr } func (r *fakeRepository) SaveResultFile(_ context.Context, _ *Task, request batchresult.Request) error { r.resultSaved = true r.resultRequest = request return nil }