github.com/fluhus/gostuff@v0.4.1-0.20240331134726-be71864f2b5d/ppln/serial_test.go (about) 1 package ppln 2 3 import ( 4 "fmt" 5 "math/rand" 6 "testing" 7 "time" 8 9 "github.com/fluhus/gostuff/gnum" 10 ) 11 12 func ExampleSerial() { 13 ngoroutines := 4 14 var results []float64 15 16 Serial( 17 ngoroutines, 18 // Read/generate input data. 19 func(push func(int), stop func() bool) error { 20 for i := 1; i <= 100; i++ { 21 push(i) 22 } 23 return nil 24 }, 25 // Some processing. 26 func(a int, i, g int) (float64, error) { 27 return float64(a*a) + 0.5, nil 28 }, 29 // Accumulate/forward outputs. 30 func(a float64) error { 31 results = append(results, a) 32 return nil 33 }) 34 35 fmt.Println(results[:3], results[len(results)-3:]) 36 37 // Output: 38 // [1.5 4.5 9.5] [9604.5 9801.5 10000.5] 39 } 40 41 func ExampleSerial_parallelAggregation() { 42 ngoroutines := 4 43 results := make([]int, ngoroutines) // Goroutine-specific data and objects. 44 45 Serial( 46 ngoroutines, 47 // Read/generate input data. 48 func(push func(int), stop func() bool) error { 49 for i := 1; i <= 100; i++ { 50 push(i) 51 } 52 return nil 53 }, 54 // Accumulate in goroutine-specific memory. 55 func(a int, i, g int) (int, error) { 56 results[g] += a 57 return 0, nil // Unused. 58 }, 59 // No outputs. 60 func(a int) error { return nil }) 61 62 // Collect the results of all goroutines. 63 fmt.Println("Sum of 1-100:", gnum.Sum(results)) 64 65 // Output: 66 // Sum of 1-100: 5050 67 } 68 69 func TestSerial(t *testing.T) { 70 for _, nt := range []int{0, 1, 2, 4, 8} { 71 t.Run(fmt.Sprint(nt), func(t *testing.T) { 72 n := nt * 100 73 var result []int 74 err := Serial(nt, func(push func(int), stop func() bool) error { 75 for i := 0; i < n; i++ { 76 push(i) 77 } 78 return nil 79 }, func(a int, i int, g int) (int, error) { 80 time.Sleep(time.Millisecond * time.Duration(rand.Intn(3))) 81 return a * a, nil 82 }, func(i int) error { 83 result = append(result, i) 84 return nil 85 }) 86 if err != nil { 87 t.Fatalf("Serial2(...) failed: %d", err) 88 } 89 for i := range result { 90 if result[i] != i*i { 91 t.Errorf("result[%d]=%d, want %d", i, result[i], i*i) 92 } 93 } 94 }) 95 } 96 } 97 98 func TestSerial_error(t *testing.T) { 99 for _, nt := range []int{0, 1, 2, 4, 8} { 100 t.Run(fmt.Sprint(nt), func(t *testing.T) { 101 n := nt * 100 102 var result []int 103 err := Serial(nt, func(push func(int), stop func() bool) error { 104 for i := 0; i < n; i++ { 105 if stop() { 106 break 107 } 108 push(i) 109 } 110 return nil 111 }, func(a int, i int, g int) (int, error) { 112 time.Sleep(time.Millisecond * time.Duration(rand.Intn(3))) 113 if a > 300 { 114 return 0, fmt.Errorf("a too big: %d", a) 115 } 116 return a * a, nil 117 }, func(i int) error { 118 result = append(result, i) 119 return nil 120 }) 121 if nt <= 3 { 122 if err != nil { 123 t.Fatalf("Serial2(...) failed: %d", err) 124 } 125 for i := range result { 126 if result[i] != i*i { 127 t.Errorf("result[%d]=%d, want %d", i, result[i], i*i) 128 } 129 } 130 } else { // n > 3 131 if err == nil { 132 t.Fatalf("Serial2(...) succeeded, want error") 133 } 134 } 135 }) 136 } 137 }