github.com/lingyao2333/mo-zero@v1.4.1/core/mr/mapreduce_fuzzcase_test.go (about) 1 //go:build fuzz 2 // +build fuzz 3 4 package mr 5 6 import ( 7 "fmt" 8 "math/rand" 9 "runtime" 10 "strconv" 11 "strings" 12 "sync" 13 "testing" 14 "time" 15 16 "github.com/lingyao2333/mo-zero/core/threading" 17 "github.com/stretchr/testify/assert" 18 "gopkg.in/cheggaaa/pb.v1" 19 ) 20 21 // If Fuzz stuck, we don't know why, because it only returns hung or unexpected, 22 // so we need to simulate the fuzz test in test mode. 23 func TestMapReduceRandom(t *testing.T) { 24 rand.Seed(time.Now().UnixNano()) 25 26 const ( 27 times = 10000 28 nRange = 500 29 mega = 1024 * 1024 30 ) 31 32 bar := pb.New(times).Start() 33 runner := threading.NewTaskRunner(runtime.NumCPU()) 34 var wg sync.WaitGroup 35 wg.Add(times) 36 for i := 0; i < times; i++ { 37 runner.Schedule(func() { 38 start := time.Now() 39 defer func() { 40 if time.Since(start) > time.Minute { 41 t.Fatal("timeout") 42 } 43 wg.Done() 44 }() 45 46 t.Run(strconv.Itoa(i), func(t *testing.T) { 47 n := rand.Int63n(nRange)%nRange + nRange 48 workers := rand.Int()%50 + runtime.NumCPU()/2 49 genPanic := rand.Intn(100) == 0 50 mapperPanic := rand.Intn(100) == 0 51 reducerPanic := rand.Intn(100) == 0 52 genIdx := rand.Int63n(n) 53 mapperIdx := rand.Int63n(n) 54 reducerIdx := rand.Int63n(n) 55 squareSum := (n - 1) * n * (2*n - 1) / 6 56 57 fn := func() (interface{}, error) { 58 return MapReduce(func(source chan<- interface{}) { 59 for i := int64(0); i < n; i++ { 60 source <- i 61 if genPanic && i == genIdx { 62 panic("foo") 63 } 64 } 65 }, func(item interface{}, writer Writer, cancel func(error)) { 66 v := item.(int64) 67 if mapperPanic && v == mapperIdx { 68 panic("bar") 69 } 70 writer.Write(v * v) 71 }, func(pipe <-chan interface{}, writer Writer, cancel func(error)) { 72 var idx int64 73 var total int64 74 for v := range pipe { 75 if reducerPanic && idx == reducerIdx { 76 panic("baz") 77 } 78 total += v.(int64) 79 idx++ 80 } 81 writer.Write(total) 82 }, WithWorkers(int(workers)%50+runtime.NumCPU()/2)) 83 } 84 85 if genPanic || mapperPanic || reducerPanic { 86 var buf strings.Builder 87 buf.WriteString(fmt.Sprintf("n: %d", n)) 88 buf.WriteString(fmt.Sprintf(", genPanic: %t", genPanic)) 89 buf.WriteString(fmt.Sprintf(", mapperPanic: %t", mapperPanic)) 90 buf.WriteString(fmt.Sprintf(", reducerPanic: %t", reducerPanic)) 91 buf.WriteString(fmt.Sprintf(", genIdx: %d", genIdx)) 92 buf.WriteString(fmt.Sprintf(", mapperIdx: %d", mapperIdx)) 93 buf.WriteString(fmt.Sprintf(", reducerIdx: %d", reducerIdx)) 94 assert.Panicsf(t, func() { fn() }, buf.String()) 95 } else { 96 val, err := fn() 97 assert.Nil(t, err) 98 assert.Equal(t, squareSum, val.(int64)) 99 } 100 bar.Increment() 101 }) 102 }) 103 } 104 105 wg.Wait() 106 bar.Finish() 107 }