.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / sys@v0.0.0-20210124154548-22da62e12c0c / internal / unsafeheader / unsafeheader_test.go
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package unsafeheader_test
6
7 import (
8         "bytes"
9         "reflect"
10         "testing"
11         "unsafe"
12
13         "golang.org/x/sys/internal/unsafeheader"
14 )
15
16 // TestTypeMatchesReflectType ensures that the name and layout of the
17 // unsafeheader types matches the corresponding Header types in the reflect
18 // package.
19 func TestTypeMatchesReflectType(t *testing.T) {
20         t.Run("Slice", func(t *testing.T) {
21                 testHeaderMatchesReflect(t, unsafeheader.Slice{}, reflect.SliceHeader{})
22         })
23
24         t.Run("String", func(t *testing.T) {
25                 testHeaderMatchesReflect(t, unsafeheader.String{}, reflect.StringHeader{})
26         })
27 }
28
29 func testHeaderMatchesReflect(t *testing.T, header, reflectHeader interface{}) {
30         h := reflect.TypeOf(header)
31         rh := reflect.TypeOf(reflectHeader)
32
33         for i := 0; i < h.NumField(); i++ {
34                 f := h.Field(i)
35                 rf, ok := rh.FieldByName(f.Name)
36                 if !ok {
37                         t.Errorf("Field %d of %v is named %s, but no such field exists in %v", i, h, f.Name, rh)
38                         continue
39                 }
40                 if !typeCompatible(f.Type, rf.Type) {
41                         t.Errorf("%v.%s has type %v, but %v.%s has type %v", h, f.Name, f.Type, rh, rf.Name, rf.Type)
42                 }
43                 if f.Offset != rf.Offset {
44                         t.Errorf("%v.%s has offset %d, but %v.%s has offset %d", h, f.Name, f.Offset, rh, rf.Name, rf.Offset)
45                 }
46         }
47
48         if h.NumField() != rh.NumField() {
49                 t.Errorf("%v has %d fields, but %v has %d", h, h.NumField(), rh, rh.NumField())
50         }
51         if h.Align() != rh.Align() {
52                 t.Errorf("%v has alignment %d, but %v has alignment %d", h, h.Align(), rh, rh.Align())
53         }
54 }
55
56 var (
57         unsafePointerType = reflect.TypeOf(unsafe.Pointer(nil))
58         uintptrType       = reflect.TypeOf(uintptr(0))
59 )
60
61 func typeCompatible(t, rt reflect.Type) bool {
62         return t == rt || (t == unsafePointerType && rt == uintptrType)
63 }
64
65 // TestWriteThroughHeader ensures that the headers in the unsafeheader package
66 // can successfully mutate variables of the corresponding built-in types.
67 //
68 // This test is expected to fail under -race (which implicitly enables
69 // -d=checkptr) if the runtime views the header types as incompatible with the
70 // underlying built-in types.
71 func TestWriteThroughHeader(t *testing.T) {
72         t.Run("Slice", func(t *testing.T) {
73                 s := []byte("Hello, checkptr!")[:5]
74
75                 var alias []byte
76                 hdr := (*unsafeheader.Slice)(unsafe.Pointer(&alias))
77                 hdr.Data = unsafe.Pointer(&s[0])
78                 hdr.Cap = cap(s)
79                 hdr.Len = len(s)
80
81                 if !bytes.Equal(alias, s) {
82                         t.Errorf("alias of %T(%q) constructed via Slice = %T(%q)", s, s, alias, alias)
83                 }
84                 if cap(alias) != cap(s) {
85                         t.Errorf("alias of %T with cap %d has cap %d", s, cap(s), cap(alias))
86                 }
87         })
88
89         t.Run("String", func(t *testing.T) {
90                 s := "Hello, checkptr!"
91
92                 var alias string
93                 hdr := (*unsafeheader.String)(unsafe.Pointer(&alias))
94                 hdr.Data = (*unsafeheader.String)(unsafe.Pointer(&s)).Data
95                 hdr.Len = len(s)
96
97                 if alias != s {
98                         t.Errorf("alias of %q constructed via String = %q", s, alias)
99                 }
100         })
101 }