Skip to content
Merged
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
26 changes: 14 additions & 12 deletions cmd/anomalies.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"strconv"

"github.com/NoTIPswe/notip-simulator-cli/internal/client"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
)

Expand All @@ -15,6 +14,15 @@ var anomaliesCmd = &cobra.Command{
Short: "Trigger anomaly scenarios on gateways and sensors",
}

var exitProcess = os.Exit

func mustMarkRequired(cmd *cobra.Command, flagName string) {
if err := cmd.MarkFlagRequired(flagName); err != nil {
fmt.Fprintln(os.Stderr, err)
exitProcess(1)
}
}

// ── disconnect ────────────────────────────────────────────────────────────────

var anomaliesDisconnectCmd = &cobra.Command{
Expand All @@ -24,7 +32,7 @@ var anomaliesDisconnectCmd = &cobra.Command{
RunE: func(cmd *cobra.Command, args []string) error {
duration, _ := cmd.Flags().GetInt("duration")

spinner, _ := pterm.DefaultSpinner.Start(
spinner := startSpinner(
fmt.Sprintf("Triggering disconnect anomaly on gateway %s (%ds)...", args[0], duration),
)
if err := client.New(simulatorURL).Disconnect(args[0], duration); err != nil {
Expand All @@ -46,7 +54,7 @@ var anomaliesNetworkDegradationCmd = &cobra.Command{
duration, _ := cmd.Flags().GetInt("duration")
loss, _ := cmd.Flags().GetFloat64("packet-loss")

spinner, _ := pterm.DefaultSpinner.Start(
spinner := startSpinner(
fmt.Sprintf("Triggering network-degradation on gateway %s (%ds, %.0f%% loss)...",
args[0], duration, loss*100),
)
Expand Down Expand Up @@ -77,7 +85,7 @@ var anomaliesOutlierCmd = &cobra.Command{
valuePtr = &v
}

spinner, _ := pterm.DefaultSpinner.Start(
spinner := startSpinner(
fmt.Sprintf("Injecting outlier into sensor %d...", sensorID),
)
if err := client.New(simulatorURL).InjectOutlier(sensorID, valuePtr); err != nil {
Expand All @@ -101,18 +109,12 @@ func init() {

// disconnect flags
anomaliesDisconnectCmd.Flags().Int("duration", 0, "Disconnect duration in seconds (required, must be > 0)")
if err := anomaliesDisconnectCmd.MarkFlagRequired("duration"); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
mustMarkRequired(anomaliesDisconnectCmd, "duration")

// network-degradation flags
anomaliesNetworkDegradationCmd.Flags().Int("duration", 0, "Duration in seconds (required)")
anomaliesNetworkDegradationCmd.Flags().Float64("packet-loss", 0, "Packet loss fraction 0–1 (e.g. 0.3 = 30%); omit to use backend default of 0.3")
if err := anomaliesNetworkDegradationCmd.MarkFlagRequired("duration"); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
mustMarkRequired(anomaliesNetworkDegradationCmd, "duration")

// outlier flags
anomaliesOutlierCmd.Flags().Float64("value", 0, "Outlier value to inject; omit to let the backend decide")
Expand Down
46 changes: 46 additions & 0 deletions cmd/anomalies_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package cmd

import (
"testing"

"github.com/spf13/cobra"
)

func TestMustMarkRequired_Success(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
cmd.Flags().String("duration", "", "")

mustMarkRequired(cmd, "duration")

f := cmd.Flags().Lookup("duration")
if f == nil {
t.Fatal("duration flag should exist")
}
if f.Annotations == nil || len(f.Annotations[cobra.BashCompOneRequiredFlag]) == 0 {
t.Fatal("duration flag should be marked as required")
}
}

func TestMustMarkRequired_ErrorTriggersExit(t *testing.T) {
cmd := &cobra.Command{Use: "test"}
called := false
code := 0

prevExit := exitProcess
exitProcess = func(c int) {
called = true
code = c
}
t.Cleanup(func() {
exitProcess = prevExit
})

mustMarkRequired(cmd, "missing-flag")

if !called {
t.Fatal("expected exit function to be called")
}
if code != 1 {
t.Fatalf("exit code = %d, want 1", code)
}
}
Loading