github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/reflectkit/func_code_test.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package reflectkit
     7  
     8  import (
     9  	"bytes"
    10  	"io"
    11  	"reflect"
    12  	"runtime"
    13  	"testing"
    14  
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestCodeOf(t *testing.T) {
    19  	var v interface{}
    20  
    21  	v = TestCodeOf
    22  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v))
    23  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(reflect.ValueOf(v).Interface()))
    24  
    25  	v = bytes.NewBufferString("abc").Len
    26  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v))
    27  	require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf))
    28  
    29  	var vi io.Writer
    30  	vi = bytes.NewBufferString("abc")
    31  	v = vi.Write
    32  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v))
    33  	require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf))
    34  
    35  	v = (*bytes.Buffer).Len
    36  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v))
    37  	require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf))
    38  
    39  	v = io.Writer.Write
    40  	require.Equal(t, reflect.ValueOf(v).Pointer(), CodeOf(v))
    41  	require.NotEqual(t, reflect.ValueOf(v).Pointer(), CodeOf(TestCodeOf))
    42  }
    43  
    44  func TestCodeOfNegative(t *testing.T) {
    45  	require.Panics(t, func() { CodeOf(nil) })
    46  	require.Panics(t, func() { CodeOf(1) })
    47  	require.Panics(t, func() { CodeOf(bytes.NewBufferString("abc")) })
    48  	require.Panics(t, func() { CodeOf(uintptr(0)) })
    49  	require.Panics(t, func() { CodeOf(reflect.ValueOf(TestCodeOf)) })
    50  	require.Panics(t, func() { CodeOf(reflect.ValueOf(TestCodeOf).Pointer()) })
    51  }
    52  
    53  func BenchmarkCodeOf(t *testing.B) {
    54  	samples := [5]interface{}{TestCodeOf, bytes.NewBufferString("abc").Len, (*bytes.Buffer).Len, io.Writer.Write,
    55  		((io.Writer)(bytes.NewBufferString("abc"))).Write,
    56  	}
    57  
    58  	count := t.N * 100000000
    59  	t.Run("baseline", func(b *testing.B) {
    60  		for i := count; i > 0; i-- {
    61  			if v := samples[i%len(samples)]; v == nil {
    62  				runtime.KeepAlive(i)
    63  			}
    64  		}
    65  	})
    66  
    67  	t.Run("reflect", func(b *testing.B) {
    68  		for i := count; i > 0; i-- {
    69  			if v := reflect.ValueOf(samples[i%len(samples)]).Pointer(); v+1 == 0 {
    70  				runtime.KeepAlive(v)
    71  			}
    72  		}
    73  	})
    74  
    75  	t.Run("direct", func(b *testing.B) {
    76  		for i := count; i > 0; i-- {
    77  			if v := CodeOf(samples[i%len(samples)]); v+1 == 0 {
    78  				runtime.KeepAlive(v)
    79  			}
    80  		}
    81  	})
    82  }
    83  
    84  func TestIsNil(t *testing.T) {
    85  	require.True(t, IsNil(nil))
    86  	require.False(t, IsNil(""))
    87  	require.False(t, IsNil(uintptr(0)))
    88  	require.False(t, IsNil(0))
    89  	require.False(t, IsNil(1))
    90  	require.False(t, IsNil(struct{}{}))
    91  	require.False(t, IsNil(&struct{}{}))
    92  
    93  	var p *string
    94  	require.True(t, IsNil(p))
    95  	s := "x"
    96  	p = &s
    97  	var i interface{} = p
    98  	require.False(t, IsNil(&s))
    99  	require.False(t, IsNil(p))
   100  	require.False(t, IsNil(i))
   101  
   102  	p = nil
   103  	i = p
   104  	require.True(t, IsNil(p))
   105  	require.True(t, IsNil(i))
   106  }
   107  
   108  func BenchmarkTestNil(t *testing.B) {
   109  	var pn *string
   110  	var n interface{} = pn
   111  
   112  	t.Run("reflect", func(b *testing.B) {
   113  		for i := b.N; i > 0; i-- {
   114  			if !reflectIsNil(n) {
   115  				b.Fail()
   116  			}
   117  		}
   118  	})
   119  
   120  	t.Run("direct", func(b *testing.B) {
   121  		for i := b.N; i > 0; i-- {
   122  			if !IsNil(n) {
   123  				b.Fail()
   124  			}
   125  		}
   126  	})
   127  }
   128  
   129  func reflectIsNil(v interface{}) bool {
   130  	if v == nil {
   131  		return true
   132  	}
   133  	switch rv := reflect.ValueOf(v); rv.Kind() {
   134  	case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
   135  		return rv.IsNil()
   136  	}
   137  	return false
   138  }