mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
* feat: Add post install reporting support * fix: UI report handling * fix: Duplicate reporting * fix: Show warning on insecure bypass * fix: Proxy event log insecure skip installation * fix: Proxy event log insecure skip installation * fix: Common definition for infer outcome
273 lines
7.9 KiB
Go
273 lines
7.9 KiB
Go
package flows
|
|
|
|
import (
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/safedep/pmg/internal/ui"
|
|
)
|
|
|
|
func TestInferOutcome(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
insecureMode bool
|
|
dryRun bool
|
|
blockedCount int
|
|
userCancelledCount int
|
|
err error
|
|
expectedOutcome ui.ExecutionOutcome
|
|
}{
|
|
{
|
|
name: "success - no issues",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeSuccess,
|
|
},
|
|
{
|
|
name: "error with no blocked packages",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: errors.New("execution failed"),
|
|
expectedOutcome: ui.OutcomeError,
|
|
},
|
|
{
|
|
name: "error with blocked packages - blocked takes precedence",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 2,
|
|
userCancelledCount: 0,
|
|
err: errors.New("execution failed"),
|
|
expectedOutcome: ui.OutcomeBlocked,
|
|
},
|
|
{
|
|
name: "insecure mode - bypasses all checks",
|
|
insecureMode: true,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeInsecureBypass,
|
|
},
|
|
{
|
|
name: "insecure mode with error - error takes precedence when blockedCount is 0",
|
|
insecureMode: true,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: errors.New("some error"),
|
|
expectedOutcome: ui.OutcomeError,
|
|
},
|
|
{
|
|
name: "insecure mode with blocked packages",
|
|
insecureMode: true,
|
|
dryRun: false,
|
|
blockedCount: 3,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeInsecureBypass,
|
|
},
|
|
{
|
|
name: "dry run mode",
|
|
insecureMode: false,
|
|
dryRun: true,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeDryRun,
|
|
},
|
|
{
|
|
name: "dry run with error - error takes precedence when blockedCount is 0",
|
|
insecureMode: false,
|
|
dryRun: true,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: errors.New("some error"),
|
|
expectedOutcome: ui.OutcomeError,
|
|
},
|
|
{
|
|
name: "dry run with user cancelled",
|
|
insecureMode: false,
|
|
dryRun: true,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeDryRun,
|
|
},
|
|
{
|
|
name: "user cancelled",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeUserCancelled,
|
|
},
|
|
{
|
|
name: "user cancelled with error - error takes precedence when blockedCount is 0",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: errors.New("some error"),
|
|
expectedOutcome: ui.OutcomeError,
|
|
},
|
|
{
|
|
name: "blocked packages",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 1,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeBlocked,
|
|
},
|
|
{
|
|
name: "blocked packages with user cancelled - user cancelled takes precedence for UX",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 2,
|
|
userCancelledCount: 2,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeUserCancelled,
|
|
},
|
|
{
|
|
name: "precedence test - insecure overrides dry run",
|
|
insecureMode: true,
|
|
dryRun: true,
|
|
blockedCount: 0,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeInsecureBypass,
|
|
},
|
|
{
|
|
name: "precedence test - insecure overrides user cancelled",
|
|
insecureMode: true,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeInsecureBypass,
|
|
},
|
|
{
|
|
name: "precedence test - insecure overrides blocked",
|
|
insecureMode: true,
|
|
dryRun: false,
|
|
blockedCount: 5,
|
|
userCancelledCount: 0,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeInsecureBypass,
|
|
},
|
|
{
|
|
name: "precedence test - dry run overrides user cancelled",
|
|
insecureMode: false,
|
|
dryRun: true,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeDryRun,
|
|
},
|
|
{
|
|
name: "precedence test - error overrides user cancelled when blockedCount is 0",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 0,
|
|
userCancelledCount: 1,
|
|
err: errors.New("execution failed"),
|
|
expectedOutcome: ui.OutcomeError,
|
|
},
|
|
{
|
|
name: "precedence test - user cancelled overrides blocked",
|
|
insecureMode: false,
|
|
dryRun: false,
|
|
blockedCount: 1,
|
|
userCancelledCount: 1,
|
|
err: nil,
|
|
expectedOutcome: ui.OutcomeUserCancelled,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
outcome := inferOutcome(tt.insecureMode, tt.dryRun, tt.blockedCount, tt.userCancelledCount, tt.err)
|
|
|
|
if outcome != tt.expectedOutcome {
|
|
t.Errorf("inferOutcome() = %v, want %v", outcome, tt.expectedOutcome)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestInferOutcomePrecedence specifically tests the precedence order documented in the function
|
|
func TestInferOutcomePrecedence(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
setup func() (insecureMode, dryRun bool, blockedCount, userCancelledCount int, err error)
|
|
expected ui.ExecutionOutcome
|
|
description string
|
|
}{
|
|
{
|
|
name: "1. error takes precedence when no blocks",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return false, false, 0, 0, errors.New("error")
|
|
},
|
|
expected: ui.OutcomeError,
|
|
description: "Error should be returned when blockedCount is 0",
|
|
},
|
|
{
|
|
name: "2. insecure mode overrides everything",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return true, true, 5, 2, errors.New("error")
|
|
},
|
|
expected: ui.OutcomeInsecureBypass,
|
|
description: "Insecure mode is highest priority after error check",
|
|
},
|
|
{
|
|
name: "3. dry run overrides user actions",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return false, true, 0, 1, nil
|
|
},
|
|
expected: ui.OutcomeDryRun,
|
|
description: "Dry run takes precedence over user cancellation",
|
|
},
|
|
{
|
|
name: "4. error overrides user cancelled when blockedCount is 0",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return false, false, 0, 1, errors.New("error")
|
|
},
|
|
expected: ui.OutcomeError,
|
|
description: "Error takes precedence when blockedCount is 0, even with user cancellation",
|
|
},
|
|
{
|
|
name: "5. blocked packages override everything below",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return false, false, 3, 0, nil
|
|
},
|
|
expected: ui.OutcomeBlocked,
|
|
description: "Blocked packages take precedence when count > 0",
|
|
},
|
|
{
|
|
name: "6. success is default",
|
|
setup: func() (bool, bool, int, int, error) {
|
|
return false, false, 0, 0, nil
|
|
},
|
|
expected: ui.OutcomeSuccess,
|
|
description: "Success when no conditions are met",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
insecureMode, dryRun, blockedCount, userCancelledCount, err := tt.setup()
|
|
outcome := inferOutcome(insecureMode, dryRun, blockedCount, userCancelledCount, err)
|
|
|
|
if outcome != tt.expected {
|
|
t.Errorf("%s: got %v, want %v", tt.description, outcome, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|