github.com/timandy/routine@v1.1.4/goid_test.go (about)

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