github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/tests/slice_to_array_ptr_test.go (about)

     1  package tests
     2  
     3  import (
     4  	"runtime"
     5  	"testing"
     6  )
     7  
     8  // https://tip.golang.org/ref/spec#Conversions_from_slice_to_array_pointer
     9  func TestSliceToArrayPointerConversion(t *testing.T) {
    10  	// GopherJS uses TypedArray for numeric types and Array for everything else
    11  	// since those are substantially different types, the tests are repeated
    12  	// for both.
    13  	expectOutOfBoundsPanic := func(t *testing.T) {
    14  		t.Helper()
    15  		if recover() == nil {
    16  			t.Error("out-of-bounds conversion of s should panic")
    17  		}
    18  	}
    19  
    20  	t.Run("Numeric", func(t *testing.T) {
    21  		s := make([]byte, 2, 4)
    22  		t.Run("NotNil", func(t *testing.T) {
    23  			s0 := (*[0]byte)(s)
    24  			if s0 == nil {
    25  				t.Error("s0 should not be nil")
    26  			}
    27  		})
    28  
    29  		t.Run("ElementPointerEquality", func(t *testing.T) {
    30  			s2 := (*[2]byte)(s)
    31  			if &s2[0] != &s[0] {
    32  				t.Error("&s2[0] should match &s[0]")
    33  			}
    34  			s3 := (*[1]byte)(s[1:])
    35  			if &s3[0] != &s[1] {
    36  				t.Error("&s3[0] should match &s[1]")
    37  			}
    38  		})
    39  
    40  		t.Run("SliceToLargerArray", func(t *testing.T) {
    41  			defer expectOutOfBoundsPanic(t)
    42  			s4 := (*[4]byte)(s)
    43  			_ = s4
    44  		})
    45  
    46  		t.Run("SharedMemory", func(t *testing.T) {
    47  			s2 := (*[2]byte)(s)
    48  			(*s2)[0] = 'x'
    49  			if s[0] != 'x' {
    50  				t.Errorf("s[0] should be changed")
    51  			}
    52  
    53  			s3 := (*[1]byte)(s[1:])
    54  			(*s3)[0] = 'y'
    55  			if s[1] != 'y' {
    56  				t.Errorf("s[1] should be changed")
    57  			}
    58  		})
    59  
    60  		var q []byte
    61  		t.Run("NilSlice", func(t *testing.T) {
    62  			q0 := (*[0]byte)(q)
    63  			if q0 != nil {
    64  				t.Error("q0 should be nil")
    65  			}
    66  		})
    67  
    68  		t.Run("NilSliceToLargerArray", func(t *testing.T) {
    69  			defer expectOutOfBoundsPanic(t)
    70  			q1 := (*[1]byte)(q)
    71  			_ = q1
    72  		})
    73  
    74  		t.Run("ZeroLenSlice", func(t *testing.T) {
    75  			u := make([]byte, 0)
    76  			u0 := (*[0]byte)(u)
    77  			if u0 == nil {
    78  				t.Error("u0 should not be nil")
    79  			}
    80  		})
    81  
    82  		t.Run("SliceToShorterArray", func(t *testing.T) {
    83  			s[0] = 'x'
    84  			s[1] = 'y'
    85  			s4 := (*[1]byte)(s[:])
    86  			if got := s4[0]; got != 'x' {
    87  				t.Errorf("Got s0[0] = %q, want 'x'", got)
    88  			}
    89  			if got := len(s4); got != 1 {
    90  				t.Errorf("Got len(s0) = %d, want 1.", got)
    91  			}
    92  
    93  			// Verify that the backing array size has been reduced to match the Go
    94  			// type. If not, a "source too large" runtime exception will be thrown
    95  			// upon the copy attempt.
    96  			s5 := [1]byte{}
    97  			s5 = *s4
    98  			runtime.KeepAlive(s5)
    99  		})
   100  	})
   101  
   102  	t.Run("String", func(t *testing.T) {
   103  		s := make([]string, 2, 2)
   104  		t.Run("NotNil", func(t *testing.T) {
   105  			s0 := (*[0]string)(s)
   106  			if s0 == nil {
   107  				t.Error("s0 should not be nil")
   108  			}
   109  		})
   110  
   111  		t.Run("ElementPointerEquality", func(t *testing.T) {
   112  			s2 := (*[2]string)(s)
   113  			if &s2[0] != &s[0] {
   114  				t.Error("&s2[0] should match &s[0]")
   115  			}
   116  
   117  			t.Skip("non-numeric slice to underlying array conversion is not supported for subslices")
   118  			s3 := (*[1]string)(s[1:])
   119  			if &s3[0] != &s[1] {
   120  				t.Error("&s3[0] should match &s[1]")
   121  			}
   122  		})
   123  
   124  		t.Run("SliceToLargerArray", func(t *testing.T) {
   125  			defer expectOutOfBoundsPanic(t)
   126  			s4 := (*[4]string)(s)
   127  			_ = s4
   128  		})
   129  
   130  		t.Run("SharedMemory", func(t *testing.T) {
   131  			s2 := (*[2]string)(s)
   132  			(*s2)[0] = "x"
   133  			if s[0] != "x" {
   134  				t.Errorf("s[0] should be changed")
   135  			}
   136  
   137  			t.Skip("non-numeric slice to underlying array conversion is not supported for subslices")
   138  			s3 := (*[1]string)(s[1:])
   139  			(*s3)[0] = "y"
   140  			if s[1] != "y" {
   141  				t.Errorf("s[1] should be changed")
   142  			}
   143  		})
   144  
   145  		var q []string
   146  		t.Run("NilSlice", func(t *testing.T) {
   147  			q0 := (*[0]string)(q)
   148  			if q0 != nil {
   149  				t.Error("q0 should be nil")
   150  			}
   151  		})
   152  
   153  		t.Run("NilSliceToLargerArray", func(t *testing.T) {
   154  			defer expectOutOfBoundsPanic(t)
   155  			q1 := (*[1]string)(q)
   156  			_ = q1
   157  		})
   158  
   159  		t.Run("ZeroLenSlice", func(t *testing.T) {
   160  			u := make([]string, 0)
   161  			u0 := (*[0]string)(u)
   162  			if u0 == nil {
   163  				t.Error("u0 should not be nil")
   164  			}
   165  		})
   166  	})
   167  }