github.com/icodeface/tls@v0.0.0-20230910023335-34df9250cd12/internal/x/crypto/cryptobyte/cryptobyte_test.go (about)

     1  // Copyright 2017 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 cryptobyte
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"testing"
    12  )
    13  
    14  func builderBytesEq(b *Builder, want ...byte) error {
    15  	got := b.BytesOrPanic()
    16  	if !bytes.Equal(got, want) {
    17  		return fmt.Errorf("Bytes() = %v, want %v", got, want)
    18  	}
    19  	return nil
    20  }
    21  
    22  func TestContinuationError(t *testing.T) {
    23  	const errorStr = "TestContinuationError"
    24  	var b Builder
    25  	b.AddUint8LengthPrefixed(func(b *Builder) {
    26  		b.AddUint8(1)
    27  		panic(BuildError{Err: errors.New(errorStr)})
    28  	})
    29  
    30  	ret, err := b.Bytes()
    31  	if ret != nil {
    32  		t.Error("expected nil result")
    33  	}
    34  	if err == nil {
    35  		t.Fatal("unexpected nil error")
    36  	}
    37  	if s := err.Error(); s != errorStr {
    38  		t.Errorf("expected error %q, got %v", errorStr, s)
    39  	}
    40  }
    41  
    42  func TestContinuationNonError(t *testing.T) {
    43  	defer func() {
    44  		recover()
    45  	}()
    46  
    47  	var b Builder
    48  	b.AddUint8LengthPrefixed(func(b *Builder) {
    49  		b.AddUint8(1)
    50  		panic(1)
    51  	})
    52  
    53  	t.Error("Builder did not panic")
    54  }
    55  
    56  func TestGeneratedPanic(t *testing.T) {
    57  	defer func() {
    58  		recover()
    59  	}()
    60  
    61  	var b Builder
    62  	b.AddUint8LengthPrefixed(func(b *Builder) {
    63  		var p *byte
    64  		*p = 0
    65  	})
    66  
    67  	t.Error("Builder did not panic")
    68  }
    69  
    70  func TestBytes(t *testing.T) {
    71  	var b Builder
    72  	v := []byte("foobarbaz")
    73  	b.AddBytes(v[0:3])
    74  	b.AddBytes(v[3:4])
    75  	b.AddBytes(v[4:9])
    76  	if err := builderBytesEq(&b, v...); err != nil {
    77  		t.Error(err)
    78  	}
    79  	s := String(b.BytesOrPanic())
    80  	for _, w := range []string{"foo", "bar", "baz"} {
    81  		var got []byte
    82  		if !s.ReadBytes(&got, 3) {
    83  			t.Errorf("ReadBytes() = false, want true (w = %v)", w)
    84  		}
    85  		want := []byte(w)
    86  		if !bytes.Equal(got, want) {
    87  			t.Errorf("ReadBytes(): got = %v, want %v", got, want)
    88  		}
    89  	}
    90  	if len(s) != 0 {
    91  		t.Errorf("len(s) = %d, want 0", len(s))
    92  	}
    93  }
    94  
    95  func TestUint8(t *testing.T) {
    96  	var b Builder
    97  	b.AddUint8(42)
    98  	if err := builderBytesEq(&b, 42); err != nil {
    99  		t.Error(err)
   100  	}
   101  
   102  	var s String = b.BytesOrPanic()
   103  	var v uint8
   104  	if !s.ReadUint8(&v) {
   105  		t.Error("ReadUint8() = false, want true")
   106  	}
   107  	if v != 42 {
   108  		t.Errorf("v = %d, want 42", v)
   109  	}
   110  	if len(s) != 0 {
   111  		t.Errorf("len(s) = %d, want 0", len(s))
   112  	}
   113  }
   114  
   115  func TestUint16(t *testing.T) {
   116  	var b Builder
   117  	b.AddUint16(65534)
   118  	if err := builderBytesEq(&b, 255, 254); err != nil {
   119  		t.Error(err)
   120  	}
   121  	var s String = b.BytesOrPanic()
   122  	var v uint16
   123  	if !s.ReadUint16(&v) {
   124  		t.Error("ReadUint16() == false, want true")
   125  	}
   126  	if v != 65534 {
   127  		t.Errorf("v = %d, want 65534", v)
   128  	}
   129  	if len(s) != 0 {
   130  		t.Errorf("len(s) = %d, want 0", len(s))
   131  	}
   132  }
   133  
   134  func TestUint24(t *testing.T) {
   135  	var b Builder
   136  	b.AddUint24(0xfffefd)
   137  	if err := builderBytesEq(&b, 255, 254, 253); err != nil {
   138  		t.Error(err)
   139  	}
   140  
   141  	var s String = b.BytesOrPanic()
   142  	var v uint32
   143  	if !s.ReadUint24(&v) {
   144  		t.Error("ReadUint8() = false, want true")
   145  	}
   146  	if v != 0xfffefd {
   147  		t.Errorf("v = %d, want fffefd", v)
   148  	}
   149  	if len(s) != 0 {
   150  		t.Errorf("len(s) = %d, want 0", len(s))
   151  	}
   152  }
   153  
   154  func TestUint24Truncation(t *testing.T) {
   155  	var b Builder
   156  	b.AddUint24(0x10111213)
   157  	if err := builderBytesEq(&b, 0x11, 0x12, 0x13); err != nil {
   158  		t.Error(err)
   159  	}
   160  }
   161  
   162  func TestUint32(t *testing.T) {
   163  	var b Builder
   164  	b.AddUint32(0xfffefdfc)
   165  	if err := builderBytesEq(&b, 255, 254, 253, 252); err != nil {
   166  		t.Error(err)
   167  	}
   168  
   169  	var s String = b.BytesOrPanic()
   170  	var v uint32
   171  	if !s.ReadUint32(&v) {
   172  		t.Error("ReadUint8() = false, want true")
   173  	}
   174  	if v != 0xfffefdfc {
   175  		t.Errorf("v = %x, want fffefdfc", v)
   176  	}
   177  	if len(s) != 0 {
   178  		t.Errorf("len(s) = %d, want 0", len(s))
   179  	}
   180  }
   181  
   182  func TestUMultiple(t *testing.T) {
   183  	var b Builder
   184  	b.AddUint8(23)
   185  	b.AddUint32(0xfffefdfc)
   186  	b.AddUint16(42)
   187  	if err := builderBytesEq(&b, 23, 255, 254, 253, 252, 0, 42); err != nil {
   188  		t.Error(err)
   189  	}
   190  
   191  	var s String = b.BytesOrPanic()
   192  	var (
   193  		x uint8
   194  		y uint32
   195  		z uint16
   196  	)
   197  	if !s.ReadUint8(&x) || !s.ReadUint32(&y) || !s.ReadUint16(&z) {
   198  		t.Error("ReadUint8() = false, want true")
   199  	}
   200  	if x != 23 || y != 0xfffefdfc || z != 42 {
   201  		t.Errorf("x, y, z = %d, %d, %d; want 23, 4294901244, 5", x, y, z)
   202  	}
   203  	if len(s) != 0 {
   204  		t.Errorf("len(s) = %d, want 0", len(s))
   205  	}
   206  }
   207  
   208  func TestUint8LengthPrefixedSimple(t *testing.T) {
   209  	var b Builder
   210  	b.AddUint8LengthPrefixed(func(c *Builder) {
   211  		c.AddUint8(23)
   212  		c.AddUint8(42)
   213  	})
   214  	if err := builderBytesEq(&b, 2, 23, 42); err != nil {
   215  		t.Error(err)
   216  	}
   217  
   218  	var base, child String = b.BytesOrPanic(), nil
   219  	var x, y uint8
   220  	if !base.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) ||
   221  		!child.ReadUint8(&y) {
   222  		t.Error("parsing failed")
   223  	}
   224  	if x != 23 || y != 42 {
   225  		t.Errorf("want x, y == 23, 42; got %d, %d", x, y)
   226  	}
   227  	if len(base) != 0 {
   228  		t.Errorf("len(base) = %d, want 0", len(base))
   229  	}
   230  	if len(child) != 0 {
   231  		t.Errorf("len(child) = %d, want 0", len(child))
   232  	}
   233  }
   234  
   235  func TestUint8LengthPrefixedMulti(t *testing.T) {
   236  	var b Builder
   237  	b.AddUint8LengthPrefixed(func(c *Builder) {
   238  		c.AddUint8(23)
   239  		c.AddUint8(42)
   240  	})
   241  	b.AddUint8(5)
   242  	b.AddUint8LengthPrefixed(func(c *Builder) {
   243  		c.AddUint8(123)
   244  		c.AddUint8(234)
   245  	})
   246  	if err := builderBytesEq(&b, 2, 23, 42, 5, 2, 123, 234); err != nil {
   247  		t.Error(err)
   248  	}
   249  
   250  	var s, child String = b.BytesOrPanic(), nil
   251  	var u, v, w, x, y uint8
   252  	if !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&u) || !child.ReadUint8(&v) ||
   253  		!s.ReadUint8(&w) || !s.ReadUint8LengthPrefixed(&child) || !child.ReadUint8(&x) || !child.ReadUint8(&y) {
   254  		t.Error("parsing failed")
   255  	}
   256  	if u != 23 || v != 42 || w != 5 || x != 123 || y != 234 {
   257  		t.Errorf("u, v, w, x, y = %d, %d, %d, %d, %d; want 23, 42, 5, 123, 234",
   258  			u, v, w, x, y)
   259  	}
   260  	if len(s) != 0 {
   261  		t.Errorf("len(s) = %d, want 0", len(s))
   262  	}
   263  	if len(child) != 0 {
   264  		t.Errorf("len(child) = %d, want 0", len(child))
   265  	}
   266  }
   267  
   268  func TestUint8LengthPrefixedNested(t *testing.T) {
   269  	var b Builder
   270  	b.AddUint8LengthPrefixed(func(c *Builder) {
   271  		c.AddUint8(5)
   272  		c.AddUint8LengthPrefixed(func(d *Builder) {
   273  			d.AddUint8(23)
   274  			d.AddUint8(42)
   275  		})
   276  		c.AddUint8(123)
   277  	})
   278  	if err := builderBytesEq(&b, 5, 5, 2, 23, 42, 123); err != nil {
   279  		t.Error(err)
   280  	}
   281  
   282  	var base, child1, child2 String = b.BytesOrPanic(), nil, nil
   283  	var u, v, w, x uint8
   284  	if !base.ReadUint8LengthPrefixed(&child1) {
   285  		t.Error("parsing base failed")
   286  	}
   287  	if !child1.ReadUint8(&u) || !child1.ReadUint8LengthPrefixed(&child2) || !child1.ReadUint8(&x) {
   288  		t.Error("parsing child1 failed")
   289  	}
   290  	if !child2.ReadUint8(&v) || !child2.ReadUint8(&w) {
   291  		t.Error("parsing child2 failed")
   292  	}
   293  	if u != 5 || v != 23 || w != 42 || x != 123 {
   294  		t.Errorf("u, v, w, x = %d, %d, %d, %d, want 5, 23, 42, 123",
   295  			u, v, w, x)
   296  	}
   297  	if len(base) != 0 {
   298  		t.Errorf("len(base) = %d, want 0", len(base))
   299  	}
   300  	if len(child1) != 0 {
   301  		t.Errorf("len(child1) = %d, want 0", len(child1))
   302  	}
   303  	if len(base) != 0 {
   304  		t.Errorf("len(child2) = %d, want 0", len(child2))
   305  	}
   306  }
   307  
   308  func TestPreallocatedBuffer(t *testing.T) {
   309  	var buf [5]byte
   310  	b := NewBuilder(buf[0:0])
   311  	b.AddUint8(1)
   312  	b.AddUint8LengthPrefixed(func(c *Builder) {
   313  		c.AddUint8(3)
   314  		c.AddUint8(4)
   315  	})
   316  	b.AddUint16(1286) // Outgrow buf by one byte.
   317  	want := []byte{1, 2, 3, 4, 0}
   318  	if !bytes.Equal(buf[:], want) {
   319  		t.Errorf("buf = %v want %v", buf, want)
   320  	}
   321  	if err := builderBytesEq(b, 1, 2, 3, 4, 5, 6); err != nil {
   322  		t.Error(err)
   323  	}
   324  }
   325  
   326  func TestWriteWithPendingChild(t *testing.T) {
   327  	var b Builder
   328  	b.AddUint8LengthPrefixed(func(c *Builder) {
   329  		c.AddUint8LengthPrefixed(func(d *Builder) {
   330  			defer func() {
   331  				if recover() == nil {
   332  					t.Errorf("recover() = nil, want error; c.AddUint8() did not panic")
   333  				}
   334  			}()
   335  			c.AddUint8(2) // panics
   336  
   337  			defer func() {
   338  				if recover() == nil {
   339  					t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
   340  				}
   341  			}()
   342  			b.AddUint8(2) // panics
   343  		})
   344  
   345  		defer func() {
   346  			if recover() == nil {
   347  				t.Errorf("recover() = nil, want error; b.AddUint8() did not panic")
   348  			}
   349  		}()
   350  		b.AddUint8(2) // panics
   351  	})
   352  }
   353  
   354  // ASN.1
   355  
   356  func TestASN1Int64(t *testing.T) {
   357  	tests := []struct {
   358  		in   int64
   359  		want []byte
   360  	}{
   361  		{-0x800000, []byte{2, 3, 128, 0, 0}},
   362  		{-256, []byte{2, 2, 255, 0}},
   363  		{-129, []byte{2, 2, 255, 127}},
   364  		{-128, []byte{2, 1, 128}},
   365  		{-1, []byte{2, 1, 255}},
   366  		{0, []byte{2, 1, 0}},
   367  		{1, []byte{2, 1, 1}},
   368  		{2, []byte{2, 1, 2}},
   369  		{127, []byte{2, 1, 127}},
   370  		{128, []byte{2, 2, 0, 128}},
   371  		{256, []byte{2, 2, 1, 0}},
   372  		{0x800000, []byte{2, 4, 0, 128, 0, 0}},
   373  	}
   374  	for i, tt := range tests {
   375  		var b Builder
   376  		b.AddASN1Int64(tt.in)
   377  		if err := builderBytesEq(&b, tt.want...); err != nil {
   378  			t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
   379  		}
   380  
   381  		var n int64
   382  		s := String(b.BytesOrPanic())
   383  		ok := s.ReadASN1Integer(&n)
   384  		if !ok || n != tt.in {
   385  			t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
   386  				ok, n, tt.in, i)
   387  		}
   388  		if len(s) != 0 {
   389  			t.Errorf("len(s) = %d, want 0", len(s))
   390  		}
   391  	}
   392  }
   393  
   394  func TestASN1Uint64(t *testing.T) {
   395  	tests := []struct {
   396  		in   uint64
   397  		want []byte
   398  	}{
   399  		{0, []byte{2, 1, 0}},
   400  		{1, []byte{2, 1, 1}},
   401  		{2, []byte{2, 1, 2}},
   402  		{127, []byte{2, 1, 127}},
   403  		{128, []byte{2, 2, 0, 128}},
   404  		{256, []byte{2, 2, 1, 0}},
   405  		{0x800000, []byte{2, 4, 0, 128, 0, 0}},
   406  		{0x7fffffffffffffff, []byte{2, 8, 127, 255, 255, 255, 255, 255, 255, 255}},
   407  		{0x8000000000000000, []byte{2, 9, 0, 128, 0, 0, 0, 0, 0, 0, 0}},
   408  		{0xffffffffffffffff, []byte{2, 9, 0, 255, 255, 255, 255, 255, 255, 255, 255}},
   409  	}
   410  	for i, tt := range tests {
   411  		var b Builder
   412  		b.AddASN1Uint64(tt.in)
   413  		if err := builderBytesEq(&b, tt.want...); err != nil {
   414  			t.Errorf("%v, (i = %d; in = %v)", err, i, tt.in)
   415  		}
   416  
   417  		var n uint64
   418  		s := String(b.BytesOrPanic())
   419  		ok := s.ReadASN1Integer(&n)
   420  		if !ok || n != tt.in {
   421  			t.Errorf("s.ReadASN1Integer(&n) = %v, n = %d; want true, n = %d (i = %d)",
   422  				ok, n, tt.in, i)
   423  		}
   424  		if len(s) != 0 {
   425  			t.Errorf("len(s) = %d, want 0", len(s))
   426  		}
   427  	}
   428  }