github.com/xg0n/routine@v0.0.0-20240119033701-c364deb94aee/goid_test.go (about) 1 package routine 2 3 import ( 4 "reflect" 5 "runtime" 6 "testing" 7 "unsafe" 8 9 "github.com/stretchr/testify/assert" 10 ) 11 12 func TestG_Goid(t *testing.T) { 13 runTest(t, func() { 14 gp := getg() 15 runtime.GC() 16 assert.Equal(t, curGoroutineID(), gp.goid) 17 }) 18 } 19 20 func TestG_Paniconfault(t *testing.T) { 21 runTest(t, func() { 22 gp := getg() 23 runtime.GC() 24 //read-1 25 assert.False(t, setPanicOnFault(false)) 26 assert.False(t, gp.getPanicOnFault()) 27 //read-2 28 setPanicOnFault(true) 29 assert.True(t, gp.getPanicOnFault()) 30 //write-1 31 gp.setPanicOnFault(false) 32 assert.False(t, setPanicOnFault(false)) 33 //write-2 34 gp.setPanicOnFault(true) 35 assert.True(t, setPanicOnFault(true)) 36 //write-read-1 37 gp.setPanicOnFault(false) 38 assert.False(t, gp.getPanicOnFault()) 39 //write-read-2 40 gp.setPanicOnFault(true) 41 assert.True(t, gp.getPanicOnFault()) 42 //restore 43 gp.setPanicOnFault(false) 44 }) 45 } 46 47 func TestG_Gopc(t *testing.T) { 48 runTest(t, func() { 49 gp := getg() 50 runtime.GC() 51 assert.Greater(t, int64(*gp.gopc), int64(0)) 52 }) 53 } 54 55 func TestG_ProfLabel(t *testing.T) { 56 runTest(t, func() { 57 ptr := unsafe.Pointer(&struct{}{}) 58 null := unsafe.Pointer(nil) 59 assert.NotEqual(t, ptr, null) 60 // 61 gp := getg() 62 runtime.GC() 63 //read-1 64 assert.Equal(t, null, getProfLabel()) 65 assert.Equal(t, null, gp.getLabels()) 66 //read-2 67 setProfLabel(ptr) 68 assert.Equal(t, ptr, gp.getLabels()) 69 //write-1 70 gp.setLabels(nil) 71 assert.Equal(t, null, getProfLabel()) 72 //write-2 73 gp.setLabels(ptr) 74 assert.Equal(t, ptr, getProfLabel()) 75 //write-read-1 76 gp.setLabels(nil) 77 assert.Equal(t, null, gp.getLabels()) 78 //write-read-2 79 gp.setLabels(ptr) 80 assert.Equal(t, ptr, gp.getLabels()) 81 //restore 82 gp.setLabels(null) 83 }) 84 } 85 86 func TestOffset(t *testing.T) { 87 runTest(t, func() { 88 assert.Panics(t, func() { 89 gt := reflect.TypeOf(0) 90 offset(gt, "hello") 91 }) 92 assert.PanicsWithValue(t, "No such field 'hello' of struct 'runtime.g'.", func() { 93 gt := getgt() 94 offset(gt, "hello") 95 }) 96 }) 97 } 98 99 // curGoroutineID parse the current g's goid from caller stack. 100 // 101 //go:linkname curGoroutineID net/http.http2curGoroutineID 102 func curGoroutineID() int64 103 104 // setPanicOnFault controls the runtime's behavior when a program faults at an unexpected (non-nil) address. 105 // 106 //go:linkname setPanicOnFault runtime/debug.setPanicOnFault 107 func setPanicOnFault(new bool) (old bool) 108 109 // getProfLabel get current g's labels which will be inherited by new goroutine. 110 // 111 //go:linkname getProfLabel runtime/pprof.runtime_getProfLabel 112 func getProfLabel() unsafe.Pointer 113 114 // setProfLabel set current g's labels which will be inherited by new goroutine. 115 // 116 //go:linkname setProfLabel runtime/pprof.runtime_setProfLabel 117 func setProfLabel(labels unsafe.Pointer) 118 119 //=== 120 121 // BenchmarkGohack-8 258425366 4.808 ns/op 0 B/op 0 allocs/op 122 func BenchmarkGohack(b *testing.B) { 123 _ = getg() 124 b.ReportAllocs() 125 b.ResetTimer() 126 for i := 0; i < b.N; i++ { 127 gp := getg() 128 _ = gp.goid 129 _ = gp.gopc 130 _ = gp.getLabels() 131 _ = gp.getPanicOnFault() 132 gp.setLabels(nil) 133 gp.setPanicOnFault(false) 134 } 135 }