Skip to content

Commit 1b8ce94

Browse files
authored
test: add targeted unit tests for backend flame graph hotspots (#1864)
* test: add targeted unit tests for backend flame graph hotspots Adds ~1000 lines of tests across three high-miss-rate files: gateway.go (mcp-server): - Auth method name coverage: oauth2, hmac, mtls, unknown - Protocol string coverage: GRPC, WEBHOOK, MQTT, AMQP, UNSPECIFIED - InstructionStatus string coverage: DISPATCHING, DELIVERED, ACKNOWLEDGED, RETRYING, EXPIRED, UNSPECIFIED - Priority string coverage: LOW, CRITICAL, UNSPECIFIED - Pagination token in list responses (instructions and connections) - GetConnection nil response path - CancelInstruction nil response path - InstructionDetail nil response path - Valid time range date filter applied to gRPC request - Instruction detail with metadata, scheduling, and attempt fields export.go (control-plane): - NewExportService happy path and nil-collectors defaulting - nil-collector + non-nil-fallback for Organizations, InternalAccounts, MarketData, and OperationalGateway collect functions - isNotFound with wrapped errors - Fallback-only section source labels (mappings, party_types, payment_rails) - ToProtoResponse with nil warnings webhook.go (control-plane/stripe): - PaymentIntentSucceeded with missing latest_charge returns 500 - PaymentIntentFailed with nil LastPaymentError still returns 200 - PaymentIntentFailed with minimal payload - ChargeRefunded missing tenant_id returns 200 with context message - ChargeRefunded missing party_id returns 200 with context message - ChargeRefunded publish failure returns 500 - ChargeRefunded with nil PaymentIntent uses charge metadata only * chore: apply gofmt formatting to coverage test files * test: add fmt.Errorf %w wrapped error assertion to TestIsNotFound_WrappedError --------- Co-authored-by: Ben Coombs <bjcoombs@users.noreply.github.com>
1 parent 729801b commit 1b8ce94

3 files changed

Lines changed: 1075 additions & 0 deletions

File tree

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
package manifest
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"testing"
8+
9+
controlplanev1 "github.com/meridianhub/meridian/api/proto/meridian/control_plane/v1"
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
// TestNewExportService_ValidInputs verifies the happy path constructor.
15+
func TestNewExportService_ValidInputs(t *testing.T) {
16+
repo := &Repository{}
17+
history, err := NewHistoryService(repo)
18+
require.NoError(t, err)
19+
20+
svc, err := NewExportService(history, &ExportCollectors{})
21+
require.NoError(t, err)
22+
require.NotNil(t, svc)
23+
}
24+
25+
// TestNewExportService_NilCollectors_DefaultsToEmpty verifies that passing nil
26+
// collectors is treated as an empty collectors set (no panic, no error).
27+
func TestNewExportService_NilCollectors_DefaultsToEmpty(t *testing.T) {
28+
repo := &Repository{}
29+
history, err := NewHistoryService(repo)
30+
require.NoError(t, err)
31+
32+
svc, err := NewExportService(history, nil)
33+
require.NoError(t, err)
34+
require.NotNil(t, svc)
35+
36+
// Verify that a collect call with nil collectors and nil fallback is a no-op.
37+
result := &ExportResult{
38+
Manifest: &controlplanev1.Manifest{Version: "1.0"},
39+
SectionSources: make(map[string]string),
40+
}
41+
svc.collectInstruments(context.Background(), result, nil, "")
42+
assert.Nil(t, result.Manifest.Instruments)
43+
assert.Empty(t, result.SectionSources)
44+
}
45+
46+
// TestIsNotFound_WrappedError verifies that isNotFound detects wrapped ErrVersionNotFound.
47+
func TestIsNotFound_WrappedError(t *testing.T) {
48+
wrapped := errors.New("context: " + ErrVersionNotFound.Error())
49+
wrappedWithW := fmt.Errorf("wrapped: %w", ErrVersionNotFound)
50+
wrapErr := errors.Join(ErrVersionNotFound, errors.New("extra context"))
51+
assert.True(t, isNotFound(ErrVersionNotFound))
52+
assert.False(t, isNotFound(wrapped))
53+
assert.True(t, isNotFound(wrappedWithW))
54+
assert.True(t, isNotFound(wrapErr))
55+
}
56+
57+
// TestExportService_CollectFallbackOnlySections_WithNilFallback verifies that
58+
// all fallback-only collect functions are no-ops when fallback is nil.
59+
func TestExportService_CollectFallbackOnlySections_WithNilFallback(t *testing.T) {
60+
svc := &ExportService{collectors: &ExportCollectors{}}
61+
62+
result := &ExportResult{
63+
Manifest: &controlplanev1.Manifest{},
64+
SectionSources: make(map[string]string),
65+
}
66+
67+
svc.collectValuationRules(result, nil, "")
68+
assert.Nil(t, result.Manifest.ValuationRules)
69+
assert.Empty(t, result.SectionSources["valuation_rules"])
70+
71+
svc.collectMappings(result, nil, "")
72+
assert.Nil(t, result.Manifest.Mappings)
73+
assert.Empty(t, result.SectionSources["mappings"])
74+
75+
svc.collectPartyTypes(result, nil, "")
76+
assert.Nil(t, result.Manifest.PartyTypes)
77+
assert.Empty(t, result.SectionSources["party_types"])
78+
79+
svc.collectPaymentRails(result, nil, "")
80+
assert.Nil(t, result.Manifest.PaymentRails)
81+
assert.Empty(t, result.SectionSources["payment_rails"])
82+
}
83+
84+
// TestExportService_CollectOrganizations_WithNilFallback verifies no panic when
85+
// the organizations collector errors and there is no fallback.
86+
func TestExportService_CollectOrganizations_WithNilFallback(t *testing.T) {
87+
svc := &ExportService{
88+
collectors: &ExportCollectors{
89+
Organizations: &mockOrganizationCollector{err: errors.New("timeout")},
90+
},
91+
}
92+
result := &ExportResult{
93+
Manifest: &controlplanev1.Manifest{},
94+
SectionSources: make(map[string]string),
95+
}
96+
97+
svc.collectOrganizations(context.Background(), result, nil, "")
98+
assert.Nil(t, result.Manifest.Organizations)
99+
require.Len(t, result.Warnings, 1)
100+
assert.Contains(t, result.Warnings[0], "timeout")
101+
}
102+
103+
// TestExportService_CollectInternalAccounts_WithNilFallback verifies no panic
104+
// when internal accounts collector errors without fallback.
105+
func TestExportService_CollectInternalAccounts_WithNilFallback(t *testing.T) {
106+
svc := &ExportService{
107+
collectors: &ExportCollectors{
108+
InternalAccounts: &mockInternalAccountCollector{err: errors.New("unreachable")},
109+
},
110+
}
111+
result := &ExportResult{
112+
Manifest: &controlplanev1.Manifest{},
113+
SectionSources: make(map[string]string),
114+
}
115+
116+
svc.collectInternalAccounts(context.Background(), result, nil, "")
117+
assert.Nil(t, result.Manifest.InternalAccounts)
118+
require.Len(t, result.Warnings, 1)
119+
assert.Contains(t, result.Warnings[0], "unreachable")
120+
}
121+
122+
// TestExportService_CollectOperationalGateway_WithNilFallback verifies no panic
123+
// when gateway collector errors without fallback.
124+
func TestExportService_CollectOperationalGateway_WithNilFallback(t *testing.T) {
125+
svc := &ExportService{
126+
collectors: &ExportCollectors{
127+
OperationalGateway: &mockOperationalGatewayCollector{
128+
connErr: errors.New("gateway down"),
129+
routeErr: errors.New("route fail"),
130+
},
131+
},
132+
}
133+
result := &ExportResult{
134+
Manifest: &controlplanev1.Manifest{},
135+
SectionSources: make(map[string]string),
136+
}
137+
138+
svc.collectOperationalGateway(context.Background(), result, nil, "")
139+
assert.Nil(t, result.Manifest.OperationalGateway)
140+
require.Len(t, result.Warnings, 1)
141+
assert.Contains(t, result.Warnings[0], "gateway down")
142+
assert.Contains(t, result.Warnings[0], "route fail")
143+
}
144+
145+
// TestExportService_CollectMarketData_WithNilFallback verifies no panic when
146+
// market data collector errors without fallback.
147+
func TestExportService_CollectMarketData_WithNilFallback(t *testing.T) {
148+
svc := &ExportService{
149+
collectors: &ExportCollectors{
150+
MarketData: &mockMarketDataCollector{srcErr: errors.New("market error")},
151+
},
152+
}
153+
result := &ExportResult{
154+
Manifest: &controlplanev1.Manifest{},
155+
SectionSources: make(map[string]string),
156+
}
157+
158+
svc.collectMarketData(context.Background(), result, nil, "")
159+
assert.Nil(t, result.Manifest.MarketData)
160+
require.Len(t, result.Warnings, 1)
161+
assert.Contains(t, result.Warnings[0], "market error")
162+
}
163+
164+
// TestExportService_ManifestChecksumEmpty verifies checksum of empty manifest.
165+
func TestExportService_ManifestChecksumEmpty(t *testing.T) {
166+
sum, err := manifestChecksum(&controlplanev1.Manifest{})
167+
require.NoError(t, err)
168+
assert.Len(t, sum, 64)
169+
assert.NotEmpty(t, sum)
170+
}
171+
172+
// TestExportResult_ToProtoResponse_EmptyWarnings verifies nil warnings are
173+
// preserved correctly in the proto response.
174+
func TestExportResult_ToProtoResponse_EmptyWarnings(t *testing.T) {
175+
result := &ExportResult{
176+
Manifest: &controlplanev1.Manifest{Version: "2.0"},
177+
Checksum: "deadbeef",
178+
SectionSources: map[string]string{},
179+
Warnings: nil,
180+
}
181+
resp := result.ToProtoResponse()
182+
assert.Equal(t, "2.0", resp.Manifest.Version)
183+
assert.Nil(t, resp.Warnings)
184+
}
185+
186+
// TestExportService_CollectOrganizations_NilCollector_WithFallback verifies that
187+
// when Organizations collector is nil, data is sourced from the fallback manifest.
188+
func TestExportService_CollectOrganizations_NilCollector_WithFallback(t *testing.T) {
189+
svc := &ExportService{collectors: &ExportCollectors{}} // nil Organizations collector
190+
191+
fb := testFallbackManifest()
192+
fb.Organizations = []*controlplanev1.OrganizationDefinition{
193+
{Code: "PLATFORM", Name: "Platform Org", PartyType: "ORGANIZATION"},
194+
}
195+
196+
result := &ExportResult{
197+
Manifest: &controlplanev1.Manifest{},
198+
SectionSources: make(map[string]string),
199+
}
200+
201+
svc.collectOrganizations(context.Background(), result, fb, "1.5")
202+
assert.Equal(t, fb.Organizations, result.Manifest.Organizations)
203+
assert.Equal(t, "fallback:manifest-v1.5", result.SectionSources["organizations"])
204+
}
205+
206+
// TestExportService_CollectInternalAccounts_NilCollector_WithFallback verifies that
207+
// when InternalAccounts collector is nil, data is sourced from the fallback manifest.
208+
func TestExportService_CollectInternalAccounts_NilCollector_WithFallback(t *testing.T) {
209+
svc := &ExportService{collectors: &ExportCollectors{}} // nil InternalAccounts collector
210+
211+
fb := testFallbackManifest()
212+
fb.InternalAccounts = []*controlplanev1.InternalAccountDefinition{
213+
{Code: "NOSTRO_GBP", AccountType: "NOSTRO", Instrument: "GBP"},
214+
}
215+
216+
result := &ExportResult{
217+
Manifest: &controlplanev1.Manifest{},
218+
SectionSources: make(map[string]string),
219+
}
220+
221+
svc.collectInternalAccounts(context.Background(), result, fb, "1.5")
222+
assert.Equal(t, fb.InternalAccounts, result.Manifest.InternalAccounts)
223+
assert.Equal(t, "fallback:manifest-v1.5", result.SectionSources["internal_accounts"])
224+
}
225+
226+
// TestExportService_CollectMarketData_NilCollector_WithFallback verifies that
227+
// when MarketData collector is nil, data is sourced from the fallback manifest.
228+
func TestExportService_CollectMarketData_NilCollector_WithFallback(t *testing.T) {
229+
svc := &ExportService{collectors: &ExportCollectors{}} // nil MarketData collector
230+
231+
fb := testFallbackManifest()
232+
fb.MarketData = &controlplanev1.MarketDataConfig{
233+
Sources: []*controlplanev1.MarketDataSourceDefinition{
234+
{Code: "ECB", Name: "European Central Bank"},
235+
},
236+
}
237+
238+
result := &ExportResult{
239+
Manifest: &controlplanev1.Manifest{},
240+
SectionSources: make(map[string]string),
241+
}
242+
243+
svc.collectMarketData(context.Background(), result, fb, "1.5")
244+
assert.Equal(t, fb.MarketData, result.Manifest.MarketData)
245+
assert.Equal(t, "fallback:manifest-v1.5", result.SectionSources["market_data"])
246+
}
247+
248+
// TestExportService_CollectOperationalGateway_NilCollector_WithFallback verifies
249+
// that when OperationalGateway collector is nil, data comes from the fallback.
250+
func TestExportService_CollectOperationalGateway_NilCollector_WithFallback(t *testing.T) {
251+
svc := &ExportService{collectors: &ExportCollectors{}} // nil OperationalGateway collector
252+
253+
fb := testFallbackManifest()
254+
fb.OperationalGateway = &controlplanev1.OperationalGatewayConfig{
255+
ProviderConnections: []*controlplanev1.ProviderConnectionConfig{
256+
{ConnectionId: "stripe", ProviderName: "Stripe"},
257+
},
258+
}
259+
260+
result := &ExportResult{
261+
Manifest: &controlplanev1.Manifest{},
262+
SectionSources: make(map[string]string),
263+
}
264+
265+
svc.collectOperationalGateway(context.Background(), result, fb, "1.5")
266+
assert.Equal(t, fb.OperationalGateway, result.Manifest.OperationalGateway)
267+
assert.Equal(t, "fallback:manifest-v1.5", result.SectionSources["operational_gateway"])
268+
}
269+
270+
// TestExportService_CollectAllFallbackSections_SourceLabels verifies that
271+
// fallback-only sections use the correct version label in SectionSources.
272+
func TestExportService_CollectAllFallbackSections_SourceLabels(t *testing.T) {
273+
svc := &ExportService{collectors: &ExportCollectors{}}
274+
275+
// Use testFallbackManifest which has non-nil ValuationRules.
276+
fb := testFallbackManifest()
277+
278+
result := &ExportResult{
279+
Manifest: &controlplanev1.Manifest{},
280+
SectionSources: make(map[string]string),
281+
}
282+
283+
svc.collectValuationRules(result, fb, "3.0")
284+
assert.Equal(t, "fallback:manifest-v3.0", result.SectionSources["valuation_rules"])
285+
286+
svc.collectMappings(result, fb, "3.0")
287+
assert.Equal(t, "fallback:manifest-v3.0", result.SectionSources["mappings"])
288+
289+
svc.collectPartyTypes(result, fb, "3.0")
290+
assert.Equal(t, "fallback:manifest-v3.0", result.SectionSources["party_types"])
291+
292+
svc.collectPaymentRails(result, fb, "3.0")
293+
assert.Equal(t, "fallback:manifest-v3.0", result.SectionSources["payment_rails"])
294+
}

0 commit comments

Comments
 (0)