github.com/mitranim/gg@v0.1.17/unsafe_test.go (about)

     1  package gg_test
     2  
     3  import (
     4  	"math"
     5  	r "reflect"
     6  	"testing"
     7  	u "unsafe"
     8  
     9  	"github.com/mitranim/gg"
    10  	"github.com/mitranim/gg/gtest"
    11  )
    12  
    13  func TestAnyNoEscUnsafe(t *testing.T) {
    14  	defer gtest.Catch(t)
    15  
    16  	testAnyNoEscUnsafe(any(nil))
    17  	testAnyNoEscUnsafe(``)
    18  	testAnyNoEscUnsafe(`str`)
    19  	testAnyNoEscUnsafe(0)
    20  	testAnyNoEscUnsafe(10)
    21  	testAnyNoEscUnsafe(SomeModel{})
    22  	testAnyNoEscUnsafe((func())(nil))
    23  }
    24  
    25  /*
    26  This doesn't verify that the value doesn't escape, because it's tricky to
    27  implement for different types. Instead, various benchmarks serve as indirect
    28  indicators.
    29  */
    30  func testAnyNoEscUnsafe[A any](src A) {
    31  	tar := gg.AnyNoEscUnsafe(src)
    32  	gtest.Equal(r.TypeOf(tar), r.TypeOf(src))
    33  	gtest.Equal(tar, any(src))
    34  }
    35  
    36  func BenchmarkAnyNoEscUnsafe(b *testing.B) {
    37  	for ind := 0; ind < b.N; ind++ {
    38  		val := []int{ind}
    39  		gg.Nop1(esc(gg.AnyNoEscUnsafe(val)))
    40  	}
    41  }
    42  
    43  func BenchmarkSize(b *testing.B) {
    44  	defer gtest.Catch(b)
    45  
    46  	for ind := 0; ind < b.N; ind++ {
    47  		gg.Nop1(gg.Size[string]())
    48  	}
    49  }
    50  
    51  func TestAsBytes(t *testing.T) {
    52  	defer gtest.Catch(t)
    53  
    54  	gtest.Zero(gg.AsBytes[struct{}](nil))
    55  	gtest.Zero(gg.AsBytes[bool](nil))
    56  	gtest.Zero(gg.AsBytes[uint64](nil))
    57  
    58  	{
    59  		var src struct{}
    60  		tar := gg.AsBytes(&src)
    61  
    62  		gtest.Equal(tar, []byte{})
    63  		gtest.Eq(u.Pointer(u.SliceData(tar)), u.Pointer(&src))
    64  		gtest.Eq(u.Pointer(u.SliceData(tar)), u.Pointer(u.SliceData([]struct{}{})), `zerobase`)
    65  		gtest.Len(tar, 0)
    66  		gtest.Cap(tar, 0)
    67  	}
    68  
    69  	{
    70  		var src bool
    71  		gtest.False(src)
    72  
    73  		tar := gg.AsBytes(&src)
    74  
    75  		gtest.Equal(tar, []byte{0})
    76  		gtest.Eq(u.Pointer(u.SliceData(tar)), u.Pointer(&src))
    77  		gtest.Len(tar, 1)
    78  		gtest.Cap(tar, 1)
    79  
    80  		tar[0] = 1
    81  		gtest.True(src)
    82  	}
    83  
    84  	{
    85  		var src uint64
    86  		gtest.Eq(src, 0)
    87  
    88  		tar := gg.AsBytes(&src)
    89  
    90  		gtest.Equal(tar, make([]byte, 8))
    91  		gtest.Eq(u.Pointer(u.SliceData(tar)), u.Pointer(&src))
    92  		gtest.Len(tar, 8)
    93  		gtest.Cap(tar, 8)
    94  
    95  		for ind := range tar {
    96  			tar[ind] = 255
    97  		}
    98  
    99  		gtest.Eq(src, math.MaxUint64)
   100  	}
   101  }
   102  
   103  func TestCast(t *testing.T) {
   104  	defer gtest.Catch(t)
   105  
   106  	gtest.PanicStr(`size mismatch: uint8 (size 1) vs int64 (size 8)`, func() {
   107  		gg.Cast[int64](byte(0))
   108  	})
   109  
   110  	gtest.PanicStr(`size mismatch: int64 (size 8) vs uint8 (size 1)`, func() {
   111  		gg.Cast[byte](int64(0))
   112  	})
   113  
   114  	gtest.PanicStr(`size mismatch: string (size 16) vs []uint8 (size 24)`, func() {
   115  		gg.Cast[[]byte](string(``))
   116  	})
   117  
   118  	gtest.PanicStr(`size mismatch: []uint8 (size 24) vs string (size 16)`, func() {
   119  		gg.Cast[string]([]byte(nil))
   120  	})
   121  
   122  	gtest.Zero(gg.Cast[struct{}]([0]struct{}{}))
   123  	gtest.Eq(gg.Cast[int8](uint8(math.MaxUint8)), -1)
   124  	gtest.Eq(gg.Cast[uint8](int8(math.MaxInt8)), 127)
   125  	gtest.Eq(gg.Cast[uint8](int8(math.MinInt8)), 128)
   126  
   127  	{
   128  		type Src [16]byte
   129  		type Tar struct{ Src }
   130  
   131  		src := Src([]byte(`ef1e7d2249dc45fc`))
   132  		gtest.Eq(string(src[:]), `ef1e7d2249dc45fc`)
   133  
   134  		tar := gg.Cast[Tar](src)
   135  		gtest.Eq(tar.Src, src)
   136  		gtest.Eq(gg.Cast[Src](tar), src)
   137  	}
   138  }
   139  
   140  func TestCastSlice(t *testing.T) {
   141  	defer gtest.Catch(t)
   142  
   143  	gtest.PanicStr(`size mismatch: uint8 (size 1) vs int64 (size 8)`, func() {
   144  		gg.CastSlice[int64, byte](nil)
   145  	})
   146  
   147  	gtest.PanicStr(`size mismatch: int64 (size 8) vs uint8 (size 1)`, func() {
   148  		gg.CastSlice[byte, int64](nil)
   149  	})
   150  
   151  	gtest.PanicStr(`size mismatch: string (size 16) vs []uint8 (size 24)`, func() {
   152  		gg.CastSlice[[]byte, string](nil)
   153  	})
   154  
   155  	gtest.PanicStr(`size mismatch: []uint8 (size 24) vs string (size 16)`, func() {
   156  		gg.CastSlice[string, []byte](nil)
   157  	})
   158  
   159  	gtest.Zero(gg.CastSlice[uint8, int8](nil))
   160  	gtest.Zero(gg.CastSlice[int8, uint8](nil))
   161  
   162  	{
   163  		src := []int8{-128, -127, -1, 0, 1, 127}
   164  		tar := gg.CastSlice[uint8](src)
   165  
   166  		gtest.Equal(tar, []uint8{128, 129, 255, 0, 1, 127})
   167  		gtest.Eq(u.Pointer(u.SliceData(tar)), u.Pointer(u.SliceData(src)))
   168  		gtest.Len(tar, len(src))
   169  		gtest.Cap(tar, cap(src))
   170  	}
   171  }