github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/cmd/trace/trace_test.go (about) 1 package main 2 3 import ( 4 "internal/trace" 5 "strings" 6 "testing" 7 ) 8 9 // TestGoroutineCount tests runnable/running goroutine counts computed by generateTrace 10 // remain in the valid range. 11 // - the counts must not be negative. generateTrace will return an error. 12 // - the counts must not include goroutines blocked waiting on channels or in syscall. 13 func TestGoroutineCount(t *testing.T) { 14 w := trace.NewWriter() 15 w.Emit(trace.EvBatch, 0, 0) // start of per-P batch event [pid, timestamp] 16 w.Emit(trace.EvFrequency, 1) // [ticks per second] 17 18 // In this test, we assume a valid trace contains EvGoWaiting or EvGoInSyscall 19 // event for every blocked goroutine. 20 21 // goroutine 10: blocked 22 w.Emit(trace.EvGoCreate, 1, 10, 1, 1) // [timestamp, new goroutine id, new stack id, stack id] 23 w.Emit(trace.EvGoWaiting, 1, 10) // [timestamp, goroutine id] 24 25 // goroutine 20: in syscall 26 w.Emit(trace.EvGoCreate, 1, 20, 2, 1) 27 w.Emit(trace.EvGoInSyscall, 1, 20) // [timestamp, goroutine id] 28 29 // goroutine 30: runnable 30 w.Emit(trace.EvGoCreate, 1, 30, 5, 1) 31 32 w.Emit(trace.EvProcStart, 2, 0) // [timestamp, thread id] 33 34 // goroutine 40: runnable->running->runnable 35 w.Emit(trace.EvGoCreate, 1, 40, 7, 1) 36 w.Emit(trace.EvGoStartLocal, 1, 40) // [timestamp, goroutine id] 37 w.Emit(trace.EvGoSched, 1, 8) // [timestamp, stack] 38 39 events, err := trace.Parse(w, "") 40 if err != nil { 41 t.Fatalf("failed to parse test trace: %v", err) 42 } 43 44 params := &traceParams{ 45 events: events, 46 endTime: int64(1<<63 - 1), 47 } 48 49 // If the counts drop below 0, generateTrace will return an error. 50 viewerData, err := generateTrace(params) 51 if err != nil { 52 t.Fatalf("generateTrace failed: %v", err) 53 } 54 for _, ev := range viewerData.Events { 55 if ev.Name == "Goroutines" { 56 cnt := ev.Arg.(*goroutineCountersArg) 57 if cnt.Runnable+cnt.Running > 2 { 58 t.Errorf("goroutine count=%+v; want no more than 2 goroutines in runnable/running state", cnt) 59 } 60 t.Logf("read %+v %+v", ev, cnt) 61 } 62 } 63 } 64 65 func TestGoroutineFilter(t *testing.T) { 66 // Test that we handle state changes to selected goroutines 67 // caused by events on goroutines that are not selected. 68 69 w := trace.NewWriter() 70 w.Emit(trace.EvBatch, 0, 0) // start of per-P batch event [pid, timestamp] 71 w.Emit(trace.EvFrequency, 1) // [ticks per second] 72 73 // goroutine 10: blocked 74 w.Emit(trace.EvGoCreate, 1, 10, 1, 1) // [timestamp, new goroutine id, new stack id, stack id] 75 w.Emit(trace.EvGoWaiting, 1, 10) // [timestamp, goroutine id] 76 77 // goroutine 20: runnable->running->unblock 10 78 w.Emit(trace.EvGoCreate, 1, 20, 7, 1) 79 w.Emit(trace.EvGoStartLocal, 1, 20) // [timestamp, goroutine id] 80 w.Emit(trace.EvGoUnblockLocal, 1, 10, 8) // [timestamp, goroutine id, stack] 81 w.Emit(trace.EvGoEnd, 1) // [timestamp] 82 83 // goroutine 10: runnable->running->block 84 w.Emit(trace.EvGoStartLocal, 1, 10) // [timestamp, goroutine id] 85 w.Emit(trace.EvGoBlock, 1, 9) // [timestamp, stack] 86 87 events, err := trace.Parse(w, "") 88 if err != nil { 89 t.Fatalf("failed to parse test trace: %v", err) 90 } 91 92 params := &traceParams{ 93 events: events, 94 endTime: int64(1<<63 - 1), 95 gs: map[uint64]bool{10: true}, 96 } 97 98 _, err = generateTrace(params) 99 if err != nil { 100 t.Fatalf("generateTrace failed: %v", err) 101 } 102 } 103 104 func TestPreemptedMarkAssist(t *testing.T) { 105 w := trace.NewWriter() 106 w.Emit(trace.EvBatch, 0, 0) // start of per-P batch event [pid, timestamp] 107 w.Emit(trace.EvFrequency, 1) // [ticks per second] 108 109 // goroutine 9999: running -> mark assisting -> preempted -> assisting -> running -> block 110 w.Emit(trace.EvGoCreate, 1, 9999, 1, 1) // [timestamp, new goroutine id, new stack id, stack id] 111 w.Emit(trace.EvGoStartLocal, 1, 9999) // [timestamp, goroutine id] 112 w.Emit(trace.EvGCMarkAssistStart, 1, 2) // [timestamp, stack] 113 w.Emit(trace.EvGoPreempt, 1, 3) // [timestamp, stack] 114 w.Emit(trace.EvGoStartLocal, 1, 9999) // [timestamp, goroutine id] 115 w.Emit(trace.EvGCMarkAssistDone, 1) // [timestamp] 116 w.Emit(trace.EvGoBlock, 1, 4) // [timestamp, stack] 117 118 events, err := trace.Parse(w, "") 119 if err != nil { 120 t.Fatalf("failed to parse test trace: %v", err) 121 } 122 123 params := &traceParams{ 124 events: events, 125 endTime: int64(1<<63 - 1), 126 } 127 128 viewerData, err := generateTrace(params) 129 if err != nil { 130 t.Fatalf("generateTrace failed: %v", err) 131 } 132 133 marks := 0 134 for _, ev := range viewerData.Events { 135 if strings.Contains(ev.Name, "MARK ASSIST") { 136 marks++ 137 } 138 } 139 if marks != 2 { 140 t.Errorf("Got %v MARK ASSIST events, want %v", marks, 2) 141 } 142 }