Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions internal/email/coverage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1023,6 +1023,7 @@ func TestSMTPSender_Port25NoTLS(t *testing.T) {
// TestSender_VerificationPathWithEmailIdentityError tests the isEmailVerified error path in SendToEmail.
func TestSender_SendToEmail_GetEmailIdentityError(t *testing.T) {
mockSES := new(MockSESClient)
t.Cleanup(func() { mockSES.AssertExpectations(t) })
// Return sandbox mode
mockSES.On("GetAccount", mock.Anything, mock.AnythingOfType("*sesv2.GetAccountInput")).
Return(&sesv2.GetAccountOutput{ProductionAccessEnabled: false}, nil)
Expand Down Expand Up @@ -1290,6 +1291,7 @@ func TestSMTPSender_AllNotificationMethods_WithRealData(t *testing.T) {
// TestSender_SendMethods_ErrorPaths tests error paths in Sender template methods.
func TestSender_SendMethods_ErrorPaths(t *testing.T) {
mockSNS := new(MockSNSClient)
t.Cleanup(func() { mockSNS.AssertExpectations(t) })
mockSNS.On("Publish", mock.Anything, mock.Anything).Return(nil, assert.AnError)

sender := NewSenderWithClients(mockSNS, nil, SenderConfig{
Expand Down Expand Up @@ -1353,6 +1355,7 @@ func TestSender_SendMethods_ErrorPaths(t *testing.T) {
// TestSender_SendToEmail_EmailVerificationCheck tests email verification check path.
func TestSender_SendToEmail_EmailVerificationCheck(t *testing.T) {
mockSES := new(MockSESClient)
t.Cleanup(func() { mockSES.AssertExpectations(t) })

// Test case: sandbox mode, verification check fails but we still try to verify
mockSES.On("GetAccount", mock.Anything, mock.AnythingOfType("*sesv2.GetAccountInput")).
Expand Down
34 changes: 32 additions & 2 deletions internal/purchase/money_path_regression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@ func captureIdempotencyTokens(t *testing.T, exec *config.PurchaseExecution) map[
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })
t.Cleanup(func() { mockServiceClient.AssertExpectations(t) })

plan := &config.PurchasePlan{Name: "Direct purchase"}

mockStore.SavePurchaseExecutionFn = func(_ context.Context, _ *config.PurchaseExecution) error { return nil }
mockStore.On("SavePurchaseHistory", ctx, mock.AnythingOfType("*config.PurchaseHistoryRecord")).Return(nil)
mockEmail.On("SendPurchaseConfirmation", ctx, mock.AnythingOfType("email.NotificationData")).Return(nil)
// No SendPurchaseConfirmation expectation: processPurchaseRecommendations
// never sends it (its callers do), so mockEmail must see no call at all.

mockFactory.On("CreateAndValidateProvider", mock.Anything, "aws", mock.Anything).Return(mockProviderInst, nil)
mockProviderInst.On("GetServiceClient", mock.Anything, common.ServiceEC2, mock.Anything).Return(mockServiceClient, nil)
Expand Down Expand Up @@ -101,6 +106,10 @@ func TestOfferingClassStampedOnHistoryMatchesPurchase(t *testing.T) {
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })
t.Cleanup(func() { mockServiceClient.AssertExpectations(t) })

mockStore.On("GetGlobalConfig", ctx).Return(&config.GlobalConfig{OfferingClass: tc.configured}, nil)
var history *config.PurchaseHistoryRecord
Expand Down Expand Up @@ -141,6 +150,7 @@ func TestUnknownOfferingClassRefusesBeforePurchase(t *testing.T) {
ctx := context.Background()
mockStore := new(MockConfigStore)
mockFactory := new(MockProviderFactory)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
mockStore.On("GetGlobalConfig", ctx).Return(&config.GlobalConfig{OfferingClass: "Standard"}, nil)

manager := &Manager{config: mockStore, providerFactory: mockFactory}
Expand Down Expand Up @@ -233,6 +243,11 @@ func TestMultiAccountSeedsStablePerAccountKey(t *testing.T) {
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockEmail.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })
t.Cleanup(func() { mockServiceClient.AssertExpectations(t) })

baseExec := &config.PurchaseExecution{
ExecutionID: "root-exec",
Expand Down Expand Up @@ -299,6 +314,11 @@ func TestSQSRedeliveryDoesNotDoubleExecute(t *testing.T) {
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockEmail.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })
t.Cleanup(func() { mockServiceClient.AssertExpectations(t) })

newPending := func() *config.PurchaseExecution {
return &config.PurchaseExecution{
Expand Down Expand Up @@ -373,6 +393,11 @@ func TestMultiAccountPartialSuccessIsAcked(t *testing.T) {
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockEmail.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })
t.Cleanup(func() { mockServiceClient.AssertExpectations(t) })

accounts := []config.CloudAccount{
{ID: "acct-ok", Name: "OK", Provider: "aws", ExternalID: "111111111111", AWSAuthMode: "access_keys"},
Expand Down Expand Up @@ -476,6 +501,9 @@ func TestExecuteForAccount_CommittedButUnsavedIsAcked(t *testing.T) {
mockFactory := new(MockProviderFactory)
mockProviderInst := new(MockProvider)
mockServiceClient := new(MockServiceClient)
t.Cleanup(func() { mockStore.AssertExpectations(t) })
t.Cleanup(func() { mockFactory.AssertExpectations(t) })
t.Cleanup(func() { mockProviderInst.AssertExpectations(t) })

accounts := []config.CloudAccount{
// role_arn with no STS client wired fails credential resolution
Expand Down Expand Up @@ -525,7 +553,9 @@ func TestExecuteForAccount_CommittedButUnsavedIsAcked(t *testing.T) {
return nil
}
mockStore.On("SavePurchaseHistory", mock.Anything, mock.AnythingOfType("*config.PurchaseHistoryRecord")).Return(nil)
mockEmail.On("SendPurchaseConfirmation", ctx, mock.AnythingOfType("email.NotificationData")).Return(nil)
// No SendPurchaseConfirmation expectation: acct-unsaved's row never saves,
// so executeForAccount returns AUDIT LOSS before sendPurchaseNotification,
// and acct-bad never commits. No confirmation goes out on this run.

mockFactory.On("CreateAndValidateProvider", mock.Anything, "aws", mock.Anything).Return(mockProviderInst, nil)
mockProviderInst.On("GetServiceClient", mock.Anything, common.ServiceEC2, mock.Anything).Return(mockServiceClient, nil)
Expand Down
Loading