package audit import ( "errors" "testing" "time" controltowerv1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/controltower/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // testSink is a cloudSink with no emitter, suitable for testing translation only. var testSink = &cloudSink{invocationID: "test-invocation"} func TestTranslateMalwareBlocked(t *testing.T) { event := AuditEvent{ Type: EventTypeMalwareBlocked, PackageVersion: testPackageVersion("evil-pkg", "1.2.3", "npm"), AnalysisID: "analysis-123", IsMalware: true, IsVerified: true, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_PACKAGE_DECISION, result.GetEventType()) require.True(t, result.HasPackageDecision()) decision := result.GetPackageDecision() assert.Equal(t, controltowerv1.PmgPackageAction_PMG_PACKAGE_ACTION_BLOCKED, decision.GetAction()) assert.Equal(t, "analysis-123", decision.GetAnalysisId()) assert.True(t, decision.GetIsMalware()) assert.True(t, decision.GetIsVerified()) assert.NotNil(t, decision.GetPackageVersion()) } func TestTranslateMalwareConfirmed(t *testing.T) { event := AuditEvent{ Type: EventTypeMalwareConfirmed, PackageVersion: testPackageVersion("suspect-pkg", "2.0.0", "npm"), AnalysisID: "analysis-456", IsMalware: false, IsVerified: false, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_PACKAGE_DECISION, result.GetEventType()) require.True(t, result.HasPackageDecision()) decision := result.GetPackageDecision() assert.Equal(t, controltowerv1.PmgPackageAction_PMG_PACKAGE_ACTION_CONFIRMED, decision.GetAction()) assert.Equal(t, "analysis-456", decision.GetAnalysisId()) assert.False(t, decision.GetIsMalware()) assert.False(t, decision.GetIsVerified()) assert.False(t, decision.GetIsVerified()) } func TestTranslateCooldownSkipped(t *testing.T) { event := AuditEvent{ Type: EventTypeCooldownSkipped, PackageVersion: testPackageVersion("exempt-pkg", "1.0.0", "npm"), Reason: "dependency_cooldown.skip", } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_PACKAGE_DECISION, result.GetEventType()) require.True(t, result.HasPackageDecision()) decision := result.GetPackageDecision() assert.Equal(t, controltowerv1.PmgPackageAction_PMG_PACKAGE_ACTION_COOLDOWN_SKIPPED, decision.GetAction()) require.NotNil(t, decision.GetPackageVersion(), "package_version must be propagated to the cloud sink") assert.Equal(t, "exempt-pkg", decision.GetPackageVersion().GetPackage().GetName()) assert.Equal(t, "1.0.0", decision.GetPackageVersion().GetVersion()) } func TestTranslateInstallTrustedAllowed(t *testing.T) { event := AuditEvent{ Type: EventTypeInstallTrustedAllowed, PackageVersion: testPackageVersion("trusted-pkg", "2.0.0", "npm"), } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_PACKAGE_DECISION, result.GetEventType()) require.True(t, result.HasPackageDecision()) decision := result.GetPackageDecision() assert.Equal(t, controltowerv1.PmgPackageAction_PMG_PACKAGE_ACTION_TRUSTED, decision.GetAction()) require.NotNil(t, decision.GetPackageVersion()) assert.Equal(t, "trusted-pkg", decision.GetPackageVersion().GetPackage().GetName()) } func TestTranslateInsecureBypassReturnsEmpty(t *testing.T) { event := AuditEvent{ Type: EventTypeInstallInsecureBypass, } results := testSink.translateToPmgEvents(event) assert.Empty(t, results) } func TestTranslateSandboxOverride(t *testing.T) { event := AuditEvent{ Type: EventTypeSandboxOverride, ProfileName: "strict", Overrides: []map[string]string{ {"read": "/tmp"}, {"write": "/var/log"}, }, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_SANDBOX_OVERRIDE, result.GetEventType()) require.True(t, result.HasSandboxOverride()) override := result.GetSandboxOverride() assert.Equal(t, "strict", override.GetSandboxProfile()) assert.ElementsMatch(t, []string{"read:/tmp", "write:/var/log"}, override.GetOverrides()) } func TestTranslateError(t *testing.T) { event := AuditEvent{ Type: EventTypeError, Message: "something went wrong", Error: errors.New("connection refused"), } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_ERROR, result.GetEventType()) require.True(t, result.HasError()) pmgErr := result.GetError() assert.Equal(t, "*errors.errorString", pmgErr.GetErrorType()) assert.Equal(t, "something went wrong", pmgErr.GetMessage()) } func TestTranslateErrorNilError(t *testing.T) { event := AuditEvent{ Type: EventTypeError, Message: "unknown issue", Error: nil, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] pmgErr := result.GetError() assert.Equal(t, "", pmgErr.GetErrorType()) assert.Equal(t, "unknown issue", pmgErr.GetMessage()) } func TestTranslateCooldownBlocked(t *testing.T) { publishDate := time.Date(2026, 5, 1, 0, 0, 0, 0, time.UTC) event := AuditEvent{ Type: EventTypeDependencyCooldown, PackageVersion: testPackageVersion("new-pkg", "1.0.0", "npm"), PublishDate: publishDate, CooldownDays: 30, DaysAgo: 6, DaysLeft: 24, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_PACKAGE_DECISION, result.GetEventType()) require.True(t, result.HasPackageDecision()) decision := result.GetPackageDecision() assert.Equal(t, controltowerv1.PmgPackageAction_PMG_PACKAGE_ACTION_COOLDOWN_BLOCKED, decision.GetAction()) assert.NotNil(t, decision.GetPackageVersion()) require.True(t, decision.HasCooldown()) cooldown := decision.GetCooldown() assert.Equal(t, publishDate.Unix(), cooldown.GetPublishDate().AsTime().Unix()) assert.Equal(t, uint32(30), cooldown.GetCooldownDays()) assert.Equal(t, uint32(6), cooldown.GetDaysSincePublish()) assert.Equal(t, uint32(24), cooldown.GetDaysRemaining()) } func TestTranslateHostObservation(t *testing.T) { event := AuditEvent{ Type: EventTypeProxyHostObserved, Hostname: "evil.example.com", Method: "CONNECT", } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) result := results[0] assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_HOST_OBSERVATION, result.GetEventType()) require.True(t, result.HasHostObservation()) obs := result.GetHostObservation() assert.Equal(t, "evil.example.com", obs.GetHostname()) assert.Equal(t, "CONNECT", obs.GetMethod()) } func TestTranslateUnsupportedEventReturnsEmpty(t *testing.T) { unsupported := []EventType{ EventTypeDependencyResolved, EventTypeInstallStarted, EventTypeInstallAllowed, EventTypeInstallInsecureBypass, } for _, et := range unsupported { t.Run(string(et), func(t *testing.T) { results := testSink.translateToPmgEvents(AuditEvent{Type: et}) assert.Empty(t, results) }) } } func TestMapPackageManager(t *testing.T) { tests := []struct { name string input string expected controltowerv1.PmgPackageManager }{ {"npm", "npm", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_NPM}, {"npx", "npx", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_NPM}, {"pnpm", "pnpm", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PNPM}, {"pnpx", "pnpx", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PNPM}, {"yarn", "yarn", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_YARN}, {"bun", "bun", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_BUN}, {"pip", "pip", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PIP}, {"pip3", "pip3", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PIP}, {"pipx", "pipx", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PIP}, {"poetry", "poetry", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_POETRY}, {"uv", "uv", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_UV}, {"uvx", "uvx", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_UV}, {"unknown", "cargo", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_UNSPECIFIED}, {"empty", "", controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_UNSPECIFIED}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { assert.Equal(t, tc.expected, mapPackageManager(tc.input)) }) } } func TestTranslateSessionComplete(t *testing.T) { event := AuditEvent{ Type: EventTypeSessionComplete, SessionData: &SessionData{ PackageManager: "npm", FlowType: FlowTypeProxy, Outcome: OutcomeSuccess, TotalAnalyzed: 10, AllowedCount: 8, BlockedCount: 1, ConfirmedCount: 1, TrustedSkipped: 2, InsecureBypassed: 0, CooldownBlockedCount: 3, Duration: 5 * time.Second, SandboxEnabled: true, ParanoidMode: false, }, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 1) summary := results[0].GetSessionSummary() require.NotNil(t, summary) assert.Equal(t, controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_NPM, summary.GetPackageManager()) assert.Equal(t, controltowerv1.PmgFlowType_PMG_FLOW_TYPE_PROXY, summary.GetFlowType()) assert.Equal(t, uint32(10), summary.GetTotalAnalyzed()) assert.Equal(t, uint32(8), summary.GetAllowedCount()) assert.Equal(t, uint32(1), summary.GetBlockedCount()) assert.Equal(t, uint32(1), summary.GetConfirmedCount()) assert.Equal(t, uint32(2), summary.GetTrustedSkipped()) assert.Equal(t, uint32(3), summary.GetCooldownBlockedCount()) assert.True(t, summary.GetSandboxEnabled()) assert.False(t, summary.GetParanoidMode()) assert.Equal(t, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_SUCCESS, summary.GetOutcome()) } func TestTranslateSessionCompleteWithInsecureBypass(t *testing.T) { event := AuditEvent{ Type: EventTypeSessionComplete, SessionData: &SessionData{ PackageManager: "pip", FlowType: FlowTypeProxy, Outcome: OutcomeInsecureBypass, InsecureBypassed: 3, }, } results := testSink.translateToPmgEvents(event) require.Len(t, results, 2) assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_SESSION_SUMMARY, results[0].GetEventType()) assert.Equal(t, controltowerv1.PmgEventType_PMG_EVENT_TYPE_INSECURE_BYPASS, results[1].GetEventType()) bypass := results[1].GetInsecureBypass() require.NotNil(t, bypass) assert.Equal(t, controltowerv1.PmgPackageManager_PMG_PACKAGE_MANAGER_PIP, bypass.GetPackageManager()) assert.Equal(t, uint32(3), bypass.GetPackagesBypassed()) } func TestTranslateSessionCompleteNilSessionData(t *testing.T) { event := AuditEvent{ Type: EventTypeSessionComplete, SessionData: nil, } results := testSink.translateToPmgEvents(event) assert.Empty(t, results) } func TestMapFlowType(t *testing.T) { tests := []struct { name string input FlowType expected controltowerv1.PmgFlowType }{ {"proxy", FlowTypeProxy, controltowerv1.PmgFlowType_PMG_FLOW_TYPE_PROXY}, {"legacy guard maps to unspecified", FlowType("guard"), controltowerv1.PmgFlowType_PMG_FLOW_TYPE_UNSPECIFIED}, {"unknown", FlowType("other"), controltowerv1.PmgFlowType_PMG_FLOW_TYPE_UNSPECIFIED}, {"empty", FlowType(""), controltowerv1.PmgFlowType_PMG_FLOW_TYPE_UNSPECIFIED}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { assert.Equal(t, tc.expected, mapFlowType(tc.input)) }) } } func TestMapSessionOutcome(t *testing.T) { tests := []struct { name string input Outcome expected controltowerv1.PmgSessionOutcome }{ {"success", OutcomeSuccess, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_SUCCESS}, {"blocked", OutcomeBlocked, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_BLOCKED}, {"user_cancelled", OutcomeUserCancelled, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_USER_CANCELLED}, {"error", OutcomeError, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_ERROR}, {"dry_run", OutcomeDryRun, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_DRY_RUN}, {"insecure_bypass", OutcomeInsecureBypass, controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_INSECURE_BYPASS}, {"unknown", Outcome("other"), controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_UNSPECIFIED}, {"empty", Outcome(""), controltowerv1.PmgSessionOutcome_PMG_SESSION_OUTCOME_UNSPECIFIED}, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { assert.Equal(t, tc.expected, mapSessionOutcome(tc.input)) }) } }