github.com/liangmanlin/routine@v1.1.0/goid_test.go (about)

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