github.com/fmstephe/unsafeutil@v1.0.0/convert_test.go (about) 1 package unsafeutil 2 3 import ( 4 "reflect" 5 "testing" 6 "unsafe" 7 ) 8 9 func TestStringToBytes(t *testing.T) { 10 s := "string" 11 b := StringToBytes(s) 12 // Should have the same length 13 if len(s) != len(b) { 14 t.Errorf("Converted bytes have different length (%d) than the string (%d)", len(b), len(s)) 15 } 16 if len(s) != cap(b) { 17 t.Errorf("Converted bytes have capacity (%d) beyond the length of string (%d)", cap(b), len(s)) 18 } 19 // Should have same content 20 if s != string(b) { 21 t.Errorf("Converted bytes has different value %q than the string %q", string(b), s) 22 } 23 // Should point to the same data in memory 24 sData := (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data 25 bData := (*(*reflect.SliceHeader)(unsafe.Pointer(&b))).Data 26 if sData != bData { 27 t.Errorf("Converted bytes points to different data %d than the string %d", sData, bData) 28 } 29 } 30 31 func TestBytesToString(t *testing.T) { 32 b := []byte("bytes!") 33 s := BytesToString(b) 34 // Should have the same length 35 if len(s) != len(b) { 36 t.Errorf("Converted string has a different length (%d) than the bytes (%d)", len(s), len(b)) 37 } 38 // Should have same content 39 if s != string(b) { 40 t.Errorf("Converted string has a different value %q than the bytes %q", s, string(b)) 41 } 42 // Should point to the same data in memory 43 sData := (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data 44 bData := (*(*reflect.SliceHeader)(unsafe.Pointer(&b))).Data 45 if sData != bData { 46 t.Errorf("Converted string points to different data %d than the bytes %d", sData, bData) 47 } 48 } 49 50 // Check we don't access the entire byte slice's capacity 51 func TestBytesToString_WithUnusedBytes(t *testing.T) { 52 // make a long slice of bytes 53 bLongDontUse := []byte("bytes! and all these other bytes") 54 // just take the first 6 characters 55 b := bLongDontUse[:6] 56 s := BytesToString(b) 57 // Should have the same length 58 if len(s) != len(b) { 59 t.Errorf("Converted string has a different length (%d) than the bytes (%d)", len(s), len(b)) 60 } 61 // Should have same content 62 if s != string(b) { 63 t.Errorf("Converted string has a different value %q than the bytes %q", s, string(b)) 64 } 65 // Should point to the same data in memory 66 sData := (*(*reflect.StringHeader)(unsafe.Pointer(&s))).Data 67 bData := (*(*reflect.SliceHeader)(unsafe.Pointer(&b))).Data 68 if sData != bData { 69 t.Errorf("Converted string points to different data %d than the bytes %d", sData, bData) 70 } 71 } 72 73 func TestStringHeadersCompatible(t *testing.T) { 74 // Check to make sure string header is what reflect thinks it is. 75 // They should be the same except for the type of the data field. 76 if unsafe.Sizeof(stringHeader{}) != unsafe.Sizeof(reflect.StringHeader{}) { 77 t.Errorf("stringHeader layout has changed ours %#v theirs %#v", stringHeader{}, reflect.StringHeader{}) 78 } 79 x := stringHeader{} 80 y := reflect.StringHeader{} 81 x.data = unsafe.Pointer(y.Data) 82 y.Data = uintptr(x.data) 83 x.stringLen = y.Len 84 y.Len = x.stringLen 85 // If we can do all of that then the two structs are compatible 86 } 87 88 func TestSliceHeadersCompatible(t *testing.T) { 89 // Check to make sure string header is what reflect thinks it is. 90 // They should be the same except for the type of the data field. 91 if unsafe.Sizeof(sliceHeader{}) != unsafe.Sizeof(reflect.SliceHeader{}) { 92 t.Errorf("sliceHeader layout has changed ours %#v theirs %#v", sliceHeader{}, reflect.SliceHeader{}) 93 } 94 x := sliceHeader{} 95 y := reflect.SliceHeader{} 96 x.data = unsafe.Pointer(y.Data) 97 y.Data = uintptr(x.data) 98 x.sliceLen = y.Len 99 y.Len = x.sliceLen 100 x.sliceCap = y.Cap 101 y.Cap = x.sliceCap 102 // If we can do all of that then the two structs are compatible 103 }