bitbucket.org/ai69/amoy@v0.2.3/worker_test.go (about) 1 package amoy 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 ) 9 10 func TestParallelTaskRun(t *testing.T) { 11 tests := []struct { 12 name string 13 timeOut time.Duration 14 num int 15 tasks []string 16 eta time.Duration 17 wantErr bool 18 }{ 19 {"1 Worker for 1 Task (Min)", ZeroDuration, 0, []string{"a"}, ZeroDuration, true}, 20 {"1 Worker for 1 Task", ZeroDuration, 1, []string{"a"}, Seconds(1), false}, 21 {"1 Worker for 2 Task", ZeroDuration, 1, []string{"a", "b"}, Seconds(2), false}, 22 {"2 Workers for 2 Tasks", ZeroDuration, 2, []string{"a", "b"}, Seconds(1), false}, 23 {"2 Workers for 3 Tasks", ZeroDuration, 2, []string{"a", "b", "c"}, Seconds(2), false}, 24 {"2 Workers for 7 Tasks", ZeroDuration, 2, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(4), false}, 25 {"2 Workers for 7 Tasks With 0 Sec Timeout", Milliseconds(1), 2, []string{"a", "b", "c", "d", "e", "f", "g"}, ZeroDuration, true}, 26 {"2 Workers for 7 Tasks With 0.5 Sec Timeout", Seconds(0.5), 2, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(0.5), true}, 27 {"2 Workers for 7 Tasks With 3.5 Sec Timeout", Seconds(3.5), 2, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(3.5), true}, 28 {"2 Workers for 7 Tasks With 5 Sec Timeout", Seconds(5), 2, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(4), false}, 29 {"7 Workers for 7 Tasks", ZeroDuration, 7, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(1), false}, 30 {"7 Workers for 7 Tasks (Max)", ZeroDuration, 20, []string{"a", "b", "c", "d", "e", "f", "g"}, Seconds(1), false}, 31 } 32 tolerance := Milliseconds(100) 33 for _, tt := range tests { 34 t.Run(tt.name, func(t *testing.T) { 35 // create context 36 ctx := context.Background() 37 if tt.timeOut > 0 { 38 t.Logf("set context timeout: %v", tt.timeOut) 39 ctx, _ = context.WithTimeout(ctx, tt.timeOut) 40 } 41 // run 42 start := time.Now() 43 callTestParallelTaskRunTest(ctx, t, tt.name, tt.num, tt.tasks, tt.wantErr) 44 elapsed := time.Since(start) 45 // check elapsed time 46 if elapsed > tt.eta+tolerance { 47 t.Errorf("ParallelTaskRun() took too long (time cost: %v, expected: %v)", elapsed, tt.eta) 48 } else if elapsed < tt.eta-tolerance { 49 t.Errorf("ParallelTaskRun() took too short (time cost: %v, expected: %v)", elapsed, tt.eta) 50 } 51 }) 52 } 53 } 54 55 func callTestParallelTaskRunTest(ctx context.Context, t *testing.T, name string, num int, tasks []string, wantErr bool) { 56 timeStart := time.Now() 57 timeLapsedStr := func() string { 58 return fmt.Sprintf("%02.3f", float64(time.Since(timeStart).Microseconds())/1e6) 59 } 60 err := ParallelTaskRun(ctx, num, len(tasks), func(ctx context.Context, id int) (interface{}, error) { 61 task := tasks[id] 62 t.Logf("[%s][%s] got task%d to run: %s", name, timeLapsedStr(), id, task) 63 if err := SleepWithContext(ctx, Seconds(1)); err != nil { 64 return nil, err 65 } 66 if FeelLucky(0.3) { 67 return nil, fmt.Errorf("feel unlucky") 68 } 69 return "[" + task + "]", nil 70 }, func(ctx context.Context, id int, result interface{}, err error) { 71 task := tasks[id] 72 t.Logf("[%s][%s] got task%d %q result: %v, error: %v", name, timeLapsedStr(), id, task, result, err) 73 }) 74 if wantErr && err == nil { 75 t.Errorf("[%s] should return error (time cost: %v)", name, time.Since(timeStart)) 76 } else if !wantErr && err != nil { 77 t.Errorf("[%s] failed (time cost: %v), error: %v", name, time.Since(timeStart), err) 78 } else { 79 t.Logf("[%s] all tasks are done (time_cost: %v), error: %v", name, time.Since(timeStart), err) 80 } 81 }