From f3990f950277c2f61e0e1811b4b8a81fc0219da4 Mon Sep 17 00:00:00 2001 From: Will Hawkins Date: Wed, 13 Dec 2023 19:56:03 -0500 Subject: [Feature] Support for testing upload/download in parallel Use the `--rpm.parallel` to test in parallel mode. The default testing mode is serial. Signed-off-by: Will Hawkins --- executor/executor.go | 53 ++++++++++++++++++++++++++++++++++++++++++++ executor/executor_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 executor/executor.go create mode 100644 executor/executor_test.go (limited to 'executor') diff --git a/executor/executor.go b/executor/executor.go new file mode 100644 index 0000000..22c1235 --- /dev/null +++ b/executor/executor.go @@ -0,0 +1,53 @@ +package executor + +import ( + "sync" +) + +type ExecutionMethod int + +const ( + Parallel ExecutionMethod = iota + Serial +) + +type ExecutionUnit func() + +func (ep ExecutionMethod) ToString() string { + switch ep { + case Parallel: + return "Parallel" + case Serial: + return "Serial" + } + return "Unrecognized execution method" +} + +func Execute(executionMethod ExecutionMethod, executionUnits []ExecutionUnit) *sync.WaitGroup { + waiter := &sync.WaitGroup{} + + // Make sure that we Add to the wait group all the execution units + // before starting to run any -- there is a potential race condition + // otherwise. + (*waiter).Add(len(executionUnits)) + + for _, executionUnit := range executionUnits { + // Stupid capture in Go! Argh. + executionUnit := executionUnit + + invoker := func() { + executionUnit() + (*waiter).Done() + } + switch executionMethod { + case Parallel: + go invoker() + case Serial: + invoker() + default: + panic("Invalid execution method value given.") + } + } + + return waiter +} diff --git a/executor/executor_test.go b/executor/executor_test.go new file mode 100644 index 0000000..9c3af7e --- /dev/null +++ b/executor/executor_test.go @@ -0,0 +1,56 @@ +package executor_test + +import ( + "testing" + "time" + + "github.com/network-quality/goresponsiveness/executor" +) + +var countToFive = func() { + time.Sleep(5 * time.Second) +} + +var countToThree = func() { + time.Sleep(3 * time.Second) +} + +var executionUnits = []executor.ExecutionUnit{countToFive, countToThree} + +func TestSerial(t *testing.T) { + then := time.Now() + waiter := executor.Execute(executor.Serial, executionUnits) + waiter.Wait() + when := time.Now() + + if when.Sub(then) < 7*time.Second { + t.Fatalf("Execution did not happen serially -- the wait was too short: %v", when.Sub(then).Seconds()) + } +} + +func TestParallel(t *testing.T) { + then := time.Now() + waiter := executor.Execute(executor.Parallel, executionUnits) + waiter.Wait() + when := time.Now() + + if when.Sub(then) > 6*time.Second { + t.Fatalf("Execution did not happen in parallel -- the wait was too long: %v", when.Sub(then).Seconds()) + } +} + +func TestExecutionMethodParallelToString(t *testing.T) { + executionMethod := executor.Parallel + + if executionMethod.ToString() != "Parallel" { + t.Fatalf("Incorrect result from ExecutionMethod.ToString; expected Parallel but got %v", executionMethod.ToString()) + } +} + +func TestExecutionMethodSerialToString(t *testing.T) { + executionMethod := executor.Serial + + if executionMethod.ToString() != "Serial" { + t.Fatalf("Incorrect result from ExecutionMethod.ToString; expected Serial but got %v", executionMethod.ToString()) + } +} -- cgit v1.2.3