github.com/mutagen-io/mutagen@v0.18.0-rc1/pkg/multiplexing/ring/buffer_test.go (about)

     1  package ring
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"io"
     7  	"testing"
     8  )
     9  
    10  // operation represents an operation on a Buffer.
    11  type operation interface {
    12  	// perform performs the operation, validating that results and error
    13  	// conditions behave as expected. It should only return an error if the
    14  	// operation's behavior doesn't match what's expected.
    15  	perform(buffer *Buffer) error
    16  }
    17  
    18  // write encodes a call to Buffer.Write.
    19  type write struct {
    20  	// data is the Write argument.
    21  	data []byte
    22  	// result is the expected count return value.
    23  	result int
    24  	// err is the expected error return value.
    25  	err error
    26  }
    27  
    28  // perform implements operation.perform.
    29  func (w *write) perform(buffer *Buffer) error {
    30  	if result, err := buffer.Write(w.data); err != w.err {
    31  		if err != nil {
    32  			return errors.New("unexpectedly nil error")
    33  		}
    34  		return err
    35  	} else if result != w.result {
    36  		return errors.New("Write returned unexpected count")
    37  	}
    38  	return nil
    39  }
    40  
    41  // writeByte encodes a call to Buffer.WriteByte.
    42  type writeByte struct {
    43  	// value is the WriteByte argument.
    44  	value byte
    45  	// err is the expected error return value.
    46  	err error
    47  }
    48  
    49  // perform implements operation.perform.
    50  func (w *writeByte) perform(buffer *Buffer) error {
    51  	if err := buffer.WriteByte(w.value); err != w.err {
    52  		if err != nil {
    53  			return errors.New("unexpectedly nil error")
    54  		}
    55  		return err
    56  	}
    57  	return nil
    58  }
    59  
    60  // readNFrom encodes a call to Buffer.ReadNFrom.
    61  type readNFrom struct {
    62  	// data is the data used to populate a bytes.Reader passed to ReadNFrom.
    63  	data []byte
    64  	// n is the requested number of bytes to read.
    65  	n int
    66  	// result is the expected count return value.
    67  	result int
    68  	// err is the expected error return value.
    69  	err error
    70  }
    71  
    72  // perform implements operation.perform.
    73  func (r *readNFrom) perform(buffer *Buffer) error {
    74  	source := bytes.NewReader(r.data)
    75  	if result, err := buffer.ReadNFrom(source, r.n); err != r.err {
    76  		if err != nil {
    77  			return errors.New("unexpectedly nil error")
    78  		}
    79  		return err
    80  	} else if result != r.result {
    81  		return errors.New("ReadNFrom returned unexpected count")
    82  	} else if result+source.Len() != len(r.data) {
    83  		return errors.New("ReadNFrom reported incorrect number of bytes")
    84  	}
    85  	return nil
    86  }
    87  
    88  // sameCallEOFReader is an io.Reader that fills a buffer and returns io.EOF on
    89  // the same call.
    90  type sameCallEOFReader struct{}
    91  
    92  // Read implements io.Reader.Read.
    93  func (r *sameCallEOFReader) Read(buffer []byte) (int, error) {
    94  	return len(buffer), io.EOF
    95  }
    96  
    97  // readNFromEOFSameCall encodes a call to Buffer.ReadNFrom with a single-element
    98  // reader that returns io.EOF on the same call from which it returns data.
    99  type readNFromEOFSameCall struct {
   100  	// n is the requested number of bytes to read.
   101  	n int
   102  }
   103  
   104  // perform implements operation.perform.
   105  func (r *readNFromEOFSameCall) perform(buffer *Buffer) error {
   106  	if result, err := buffer.ReadNFrom(&sameCallEOFReader{}, r.n); err != nil {
   107  		return err
   108  	} else if result != r.n {
   109  		return errors.New("unexpected result count")
   110  	}
   111  	return nil
   112  }
   113  
   114  // read encodes a call to Buffer.Read.
   115  type read struct {
   116  	// buffer is the Read argument.
   117  	buffer []byte
   118  	// expected is the expected resulting value of buffer after the read.
   119  	expected []byte
   120  	// result is the expected count return value.
   121  	result int
   122  	// err is the expected error return value.
   123  	err error
   124  }
   125  
   126  // perform implements operation.perform.
   127  func (r *read) perform(buffer *Buffer) error {
   128  	if len(r.buffer) != len(r.expected) {
   129  		return errors.New("invalid read operation specification")
   130  	} else if result, err := buffer.Read(r.buffer); err != r.err {
   131  		if err != nil {
   132  			return errors.New("unexpectedly nil error")
   133  		}
   134  		return err
   135  	} else if result != r.result {
   136  		return errors.New("Read returned unexpected count")
   137  	} else if !bytes.Equal(r.buffer, r.expected) {
   138  		return errors.New("Read results do not match expected")
   139  	}
   140  	return nil
   141  }
   142  
   143  // readByte encodes a call to Buffer.ReadByte.
   144  type readByte struct {
   145  	// result is the expected byte return value.
   146  	result byte
   147  	// err is the expected error return value.
   148  	err error
   149  }
   150  
   151  // perform implements operation.perform.
   152  func (r *readByte) perform(buffer *Buffer) error {
   153  	if result, err := buffer.ReadByte(); err != r.err {
   154  		if err != nil {
   155  			return errors.New("unexpectedly nil error")
   156  		}
   157  		return err
   158  	} else if result != r.result {
   159  		return errors.New("ReadByte returned unexpected value")
   160  	}
   161  	return nil
   162  }
   163  
   164  // writeTo encodes a call to Buffer.WriteTo.
   165  type writeTo struct {
   166  	// expected is the data expected to be written to the bytes.Buffer passed to
   167  	// WriteTo.
   168  	expected []byte
   169  }
   170  
   171  // perform implements operation.perform.
   172  func (w *writeTo) perform(buffer *Buffer) error {
   173  	destination := &bytes.Buffer{}
   174  	if result, err := buffer.WriteTo(destination); err != nil {
   175  		return err
   176  	} else if result != int64(destination.Len()) {
   177  		return errors.New("WriteTo reported incorrect number of bytes")
   178  	} else if destination.Len() != len(w.expected) {
   179  		return errors.New("number of bytes written does not match expected")
   180  	} else if !bytes.Equal(destination.Bytes(), w.expected) {
   181  		return errors.New("bytes written do not match expected")
   182  	}
   183  	return nil
   184  }
   185  
   186  // TestBuffer tests Buffer.
   187  func TestBuffer(t *testing.T) {
   188  	// Define test cases.
   189  	tests := []struct {
   190  		buffer     *Buffer
   191  		size       int
   192  		operations []operation
   193  		expected   *Buffer
   194  	}{
   195  		// Test zero-value buffer.
   196  		{&Buffer{}, 0, []operation{&write{nil, 0, nil}}, &Buffer{}},
   197  
   198  		// Test NewBuffer.
   199  		{nil, -1, nil, &Buffer{}},
   200  		{nil, 0, nil, &Buffer{}},
   201  		{nil, 1, nil, &Buffer{storage: make([]byte, 1), size: 1}},
   202  		{nil, 2, nil, &Buffer{storage: make([]byte, 2), size: 2}},
   203  		{nil, 4, nil, &Buffer{storage: make([]byte, 4), size: 4}},
   204  		{nil, 128, nil, &Buffer{storage: make([]byte, 128), size: 128}},
   205  		{nil, 1 << 16, nil, &Buffer{storage: make([]byte, 1<<16), size: 1 << 16}},
   206  
   207  		// Test Buffer.Write.
   208  		{
   209  			nil, 0,
   210  			[]operation{
   211  				&write{nil, 0, nil},
   212  			},
   213  			&Buffer{},
   214  		},
   215  		{
   216  			nil, 0,
   217  			[]operation{
   218  				&write{[]byte{1}, 0, ErrBufferFull},
   219  			},
   220  			&Buffer{},
   221  		},
   222  		{
   223  			nil, 1,
   224  			[]operation{
   225  				&write{nil, 0, nil},
   226  			},
   227  			&Buffer{storage: []byte{0}, size: 1},
   228  		},
   229  		{
   230  			nil, 1,
   231  			[]operation{
   232  				&write{[]byte{1}, 1, nil},
   233  			},
   234  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   235  		},
   236  		{
   237  			nil, 1,
   238  			[]operation{
   239  				&write{[]byte{1}, 1, nil},
   240  				&write{[]byte{2}, 0, ErrBufferFull},
   241  			},
   242  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   243  		},
   244  		{
   245  			nil, 1,
   246  			[]operation{
   247  				&write{[]byte{1, 2}, 1, ErrBufferFull},
   248  			},
   249  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   250  		},
   251  		{
   252  			nil, 2,
   253  			[]operation{
   254  				&write{[]byte{1}, 1, nil},
   255  				&write{[]byte{2}, 1, nil},
   256  			},
   257  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   258  		},
   259  		{
   260  			nil, 2,
   261  			[]operation{
   262  				&write{[]byte{1}, 1, nil},
   263  				&write{[]byte{2}, 1, nil},
   264  				&write{[]byte{3}, 0, ErrBufferFull},
   265  			},
   266  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   267  		},
   268  		{
   269  			nil, 2,
   270  			[]operation{
   271  				&write{[]byte{1, 2}, 2, nil},
   272  			},
   273  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   274  		},
   275  		{
   276  			nil, 3,
   277  			[]operation{
   278  				&write{[]byte{1, 2}, 2, nil},
   279  				&write{[]byte{3, 4}, 1, ErrBufferFull},
   280  			},
   281  			&Buffer{storage: []byte{1, 2, 3}, size: 3, used: 3},
   282  		},
   283  		{
   284  			&Buffer{storage: []byte{0, 0, 1, 0}, size: 4, start: 2, used: 1}, 0,
   285  			[]operation{
   286  				&write{[]byte{2, 3}, 2, nil},
   287  				&write{[]byte{4, 5}, 1, ErrBufferFull},
   288  			},
   289  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4, start: 2, used: 4},
   290  		},
   291  		{
   292  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 2}, 0,
   293  			[]operation{
   294  				&write{[]byte{3, 4}, 2, nil},
   295  				&write{[]byte{5, 6}, 0, ErrBufferFull},
   296  			},
   297  			&Buffer{storage: []byte{2, 3, 4, 1}, size: 4, start: 3, used: 4},
   298  		},
   299  		{
   300  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 2}, 0,
   301  			[]operation{
   302  				&write{[]byte{3, 4, 5}, 2, ErrBufferFull},
   303  			},
   304  			&Buffer{storage: []byte{2, 3, 4, 1}, size: 4, start: 3, used: 4},
   305  		},
   306  
   307  		// Test Buffer.WriteByte.
   308  		{
   309  			nil, 0,
   310  			[]operation{
   311  				&writeByte{1, ErrBufferFull},
   312  			},
   313  			&Buffer{},
   314  		},
   315  		{
   316  			nil, 1,
   317  			[]operation{
   318  				&writeByte{1, nil},
   319  			},
   320  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   321  		},
   322  		{
   323  			nil, 1,
   324  			[]operation{
   325  				&writeByte{1, nil},
   326  				&writeByte{2, ErrBufferFull},
   327  			},
   328  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   329  		},
   330  		{
   331  			nil, 2,
   332  			[]operation{
   333  				&writeByte{1, nil},
   334  			},
   335  			&Buffer{storage: []byte{1, 0}, size: 2, used: 1},
   336  		},
   337  		{
   338  			nil, 2,
   339  			[]operation{
   340  				&writeByte{1, nil},
   341  				&writeByte{2, nil},
   342  				&writeByte{3, ErrBufferFull},
   343  			},
   344  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   345  		},
   346  		{
   347  			&Buffer{storage: []byte{0, 0, 1, 0}, size: 4, start: 2, used: 1}, 0,
   348  			[]operation{
   349  				&writeByte{2, nil},
   350  				&writeByte{3, nil},
   351  				&writeByte{4, nil},
   352  				&writeByte{5, ErrBufferFull},
   353  			},
   354  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4, start: 2, used: 4},
   355  		},
   356  		{
   357  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 2}, 0,
   358  			[]operation{
   359  				&writeByte{3, nil},
   360  				&writeByte{4, nil},
   361  				&writeByte{5, ErrBufferFull},
   362  			},
   363  			&Buffer{storage: []byte{2, 3, 4, 1}, size: 4, start: 3, used: 4},
   364  		},
   365  
   366  		// Test Buffer.ReadNFrom.
   367  		{
   368  			nil, 0,
   369  			[]operation{
   370  				&readNFrom{nil, 0, 0, nil},
   371  			},
   372  			&Buffer{},
   373  		},
   374  		{
   375  			nil, 0,
   376  			[]operation{
   377  				&readNFrom{[]byte{1}, 1, 0, ErrBufferFull},
   378  			},
   379  			&Buffer{},
   380  		},
   381  		{
   382  			nil, 1,
   383  			[]operation{
   384  				&readNFrom{nil, 0, 0, nil},
   385  			},
   386  			&Buffer{storage: []byte{0}, size: 1},
   387  		},
   388  		{
   389  			nil, 1,
   390  			[]operation{
   391  				&readNFrom{[]byte{1}, 1, 1, nil},
   392  			},
   393  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   394  		},
   395  		{
   396  			nil, 1,
   397  			[]operation{
   398  				&readNFrom{[]byte{1, 2}, 2, 1, ErrBufferFull},
   399  			},
   400  			&Buffer{storage: []byte{1}, size: 1, used: 1},
   401  		},
   402  		{
   403  			nil, 2,
   404  			[]operation{
   405  				&readNFrom{[]byte{1, 2}, 2, 2, nil},
   406  			},
   407  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   408  		},
   409  		{
   410  			nil, 2,
   411  			[]operation{
   412  				&readNFrom{[]byte{1, 2, 3}, 3, 2, ErrBufferFull},
   413  			},
   414  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   415  		},
   416  		{
   417  			nil, 2,
   418  			[]operation{
   419  				&write{[]byte{1, 2}, 2, nil},
   420  			},
   421  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2},
   422  		},
   423  		{
   424  			nil, 3,
   425  			[]operation{
   426  				&write{[]byte{1, 2}, 2, nil},
   427  				&readNFrom{[]byte{3, 4}, 2, 1, ErrBufferFull},
   428  			},
   429  			&Buffer{storage: []byte{1, 2, 3}, size: 3, used: 3},
   430  		},
   431  		{
   432  			&Buffer{storage: []byte{0, 0, 1, 0}, size: 4, start: 2, used: 1}, 0,
   433  			[]operation{
   434  				&readNFrom{[]byte{2, 3}, 2, 2, nil},
   435  				&readNFrom{[]byte{4, 5}, 2, 1, ErrBufferFull},
   436  			},
   437  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4, start: 2, used: 4},
   438  		},
   439  		{
   440  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 2}, 0,
   441  			[]operation{
   442  				&readNFrom{[]byte{3, 4}, 2, 2, nil},
   443  				&write{[]byte{5, 6}, 0, ErrBufferFull},
   444  			},
   445  			&Buffer{storage: []byte{2, 3, 4, 1}, size: 4, start: 3, used: 4},
   446  		},
   447  		{
   448  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 2}, 0,
   449  			[]operation{
   450  				&readNFromEOFSameCall{2},
   451  			},
   452  			&Buffer{storage: []byte{2, 0, 0, 1}, size: 4, start: 3, used: 4},
   453  		},
   454  
   455  		// Test Buffer.Read.
   456  		{
   457  			nil, 0,
   458  			[]operation{
   459  				&read{[]byte{}, []byte{}, 0, nil},
   460  			},
   461  			&Buffer{},
   462  		},
   463  		{
   464  			nil, 0,
   465  			[]operation{
   466  				&read{[]byte{0}, []byte{0}, 0, io.EOF},
   467  			},
   468  			&Buffer{},
   469  		},
   470  		{
   471  			&Buffer{storage: []byte{1, 2, 3, 4}, size: 4, used: 4}, 0,
   472  			[]operation{
   473  				&read{[]byte{0, 0, 0, 0}, []byte{1, 2, 3, 4}, 4, nil},
   474  			},
   475  			&Buffer{storage: []byte{1, 2, 3, 4}, size: 4},
   476  		},
   477  		{
   478  			&Buffer{storage: []byte{1, 2, 3, 4}, size: 4, used: 4}, 0,
   479  			[]operation{
   480  				&read{[]byte{0, 0}, []byte{1, 2}, 2, nil},
   481  			},
   482  			&Buffer{storage: []byte{1, 2, 3, 4}, size: 4, start: 2, used: 2},
   483  		},
   484  		{
   485  			&Buffer{storage: []byte{1, 0, 0, 0}, size: 4, used: 1}, 0,
   486  			[]operation{
   487  				&read{[]byte{0, 2, 3, 4}, []byte{1, 2, 3, 4}, 1, io.EOF},
   488  			},
   489  			&Buffer{storage: []byte{1, 0, 0, 0}, size: 4},
   490  		},
   491  		{
   492  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4, start: 2, used: 4}, 0,
   493  			[]operation{
   494  				&read{[]byte{0, 0, 0, 0}, []byte{1, 2, 3, 4}, 4, nil},
   495  			},
   496  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4},
   497  		},
   498  		{
   499  			&Buffer{storage: []byte{3, 4, 0, 0, 1, 2}, size: 6, start: 4, used: 4}, 0,
   500  			[]operation{
   501  				&read{[]byte{0, 0, 0, 0, 0}, []byte{1, 2, 3, 4, 0}, 4, nil},
   502  			},
   503  			&Buffer{storage: []byte{3, 4, 0, 0, 1, 2}, size: 6},
   504  		},
   505  		{
   506  			&Buffer{storage: []byte{0, 0, 1, 2}, size: 4, start: 2, used: 2}, 0,
   507  			[]operation{
   508  				&read{[]byte{0, 0, 0, 0, 0}, []byte{1, 2, 0, 0, 0}, 2, nil},
   509  			},
   510  			&Buffer{storage: []byte{0, 0, 1, 2}, size: 4},
   511  		},
   512  
   513  		// Test Buffer.ReadByte.
   514  		{
   515  			nil, 0,
   516  			[]operation{
   517  				&readByte{0, io.EOF},
   518  			},
   519  			&Buffer{},
   520  		},
   521  		{
   522  			nil, 1,
   523  			[]operation{
   524  				&readByte{0, io.EOF},
   525  			},
   526  			&Buffer{storage: []byte{0}, size: 1},
   527  		},
   528  		{
   529  			&Buffer{storage: []byte{1, 0}, size: 2, used: 1}, 0,
   530  			[]operation{
   531  				&readByte{1, nil},
   532  				&readByte{0, io.EOF},
   533  			},
   534  			&Buffer{storage: []byte{1, 0}, size: 2},
   535  		},
   536  		{
   537  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2}, 0,
   538  			[]operation{
   539  				&readByte{1, nil},
   540  				&readByte{2, nil},
   541  			},
   542  			&Buffer{storage: []byte{1, 2}, size: 2},
   543  		},
   544  		{
   545  			&Buffer{storage: []byte{0, 1}, size: 2, start: 1, used: 1}, 0,
   546  			[]operation{
   547  				&readByte{1, nil},
   548  				&readByte{0, io.EOF},
   549  			},
   550  			&Buffer{storage: []byte{0, 1}, size: 2},
   551  		},
   552  
   553  		// Test Buffer.WriteTo.
   554  		{
   555  			nil, 0,
   556  			[]operation{
   557  				&writeTo{[]byte{}},
   558  			},
   559  			&Buffer{},
   560  		},
   561  		{
   562  			nil, 1,
   563  			[]operation{
   564  				&writeTo{[]byte{}},
   565  			},
   566  			&Buffer{storage: []byte{0}, size: 1},
   567  		},
   568  		{
   569  			nil, 2,
   570  			[]operation{
   571  				&writeTo{[]byte{}},
   572  			},
   573  			&Buffer{storage: []byte{0, 0}, size: 2},
   574  		},
   575  		{
   576  			&Buffer{storage: []byte{1}, size: 1, used: 1}, 0,
   577  			[]operation{
   578  				&writeTo{[]byte{1}},
   579  			},
   580  			&Buffer{storage: []byte{1}, size: 1},
   581  		},
   582  		{
   583  			&Buffer{storage: []byte{1, 2}, size: 2, used: 2}, 0,
   584  			[]operation{
   585  				&writeTo{[]byte{1, 2}},
   586  			},
   587  			&Buffer{storage: []byte{1, 2}, size: 2},
   588  		},
   589  		{
   590  			&Buffer{storage: []byte{1, 0, 0}, size: 3, used: 1}, 0,
   591  			[]operation{
   592  				&writeTo{[]byte{1}},
   593  			},
   594  			&Buffer{storage: []byte{1, 0, 0}, size: 3},
   595  		},
   596  		{
   597  			&Buffer{storage: []byte{0, 1, 2}, size: 3, start: 1, used: 2}, 0,
   598  			[]operation{
   599  				&writeTo{[]byte{1, 2}},
   600  			},
   601  			&Buffer{storage: []byte{0, 1, 2}, size: 3},
   602  		},
   603  		{
   604  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4, start: 2, used: 4}, 0,
   605  			[]operation{
   606  				&writeTo{[]byte{1, 2, 3, 4}},
   607  			},
   608  			&Buffer{storage: []byte{3, 4, 1, 2}, size: 4},
   609  		},
   610  		{
   611  			&Buffer{storage: []byte{0, 1, 2, 0}, size: 4, start: 1, used: 2}, 0,
   612  			[]operation{
   613  				&writeTo{[]byte{1, 2}},
   614  			},
   615  			&Buffer{storage: []byte{0, 1, 2, 0}, size: 4},
   616  		},
   617  		{
   618  			&Buffer{storage: []byte{3, 4, 0, 0, 1, 2}, size: 6, start: 4, used: 4}, 0,
   619  			[]operation{
   620  				&writeTo{[]byte{1, 2, 3, 4}},
   621  			},
   622  			&Buffer{storage: []byte{3, 4, 0, 0, 1, 2}, size: 6},
   623  		},
   624  	}
   625  
   626  	// Process test cases.
   627  ProcessTests:
   628  	for i, test := range tests {
   629  		// If an initial buffer has been provided, then use that, otherwise
   630  		// create one of the specified size and ensure that it's non-nil.
   631  		buffer := test.buffer
   632  		if buffer == nil {
   633  			buffer = NewBuffer(test.size)
   634  			if buffer == nil {
   635  				t.Errorf("test index %d: newly create buffer is nil", i)
   636  				continue
   637  			}
   638  		}
   639  
   640  		// Perform the requested operations.
   641  		for o, operation := range test.operations {
   642  			if err := operation.perform(buffer); err != nil {
   643  				t.Errorf("test index %d, operation index %o: unexpected error: %s", i, o, err)
   644  				continue ProcessTests
   645  			}
   646  		}
   647  
   648  		// Compare the resulting buffer state with the expected value.
   649  		var invalid bool
   650  		if len(buffer.storage) != len(test.expected.storage) {
   651  			t.Errorf("test index %d: resulting buffer storage size does not match expected: %d != %d",
   652  				i, len(buffer.storage), len(test.expected.storage),
   653  			)
   654  			invalid = true
   655  		} else if !bytes.Equal(buffer.storage, test.expected.storage) {
   656  			t.Errorf("test index %d: resulting buffer storage does not match expected", i)
   657  			invalid = true
   658  		}
   659  		if buffer.size != test.expected.size {
   660  			t.Errorf("test index %d: resulting cached buffer size does not match expected: %d != %d",
   661  				i, buffer.size, test.expected.size,
   662  			)
   663  			invalid = true
   664  		}
   665  		if buffer.start != test.expected.start {
   666  			t.Errorf("test index %d: resulting buffer start index does not match expected: %d != %d",
   667  				i, buffer.start, test.expected.start,
   668  			)
   669  			invalid = true
   670  		}
   671  		if buffer.used != test.expected.used {
   672  			t.Errorf("test index %d: resulting buffer data count does not match expected: %d != %d",
   673  				i, buffer.used, test.expected.used,
   674  			)
   675  			invalid = true
   676  		}
   677  
   678  		// If the buffer was invalid, then continue.
   679  		if invalid {
   680  			continue
   681  		}
   682  
   683  		// Otherwise, perform generic invariant checks.
   684  		if bs := buffer.Size(); bs != buffer.size {
   685  			t.Errorf("test index %d: size accessor returned incorrect value: %d != %d",
   686  				i, bs, buffer.size,
   687  			)
   688  			invalid = true
   689  		}
   690  		if bu := buffer.Used(); bu != buffer.used {
   691  			t.Errorf("test index %d: used accessor returned incorrect value: %d != %d",
   692  				i, bu, buffer.used,
   693  			)
   694  			invalid = true
   695  		}
   696  		if ba := buffer.Free(); ba != (buffer.size - buffer.used) {
   697  			t.Errorf("test index %d: free accessor returned incorrect value: %d != %d",
   698  				i, ba, buffer.size-buffer.used,
   699  			)
   700  			invalid = true
   701  		}
   702  		if buffer.size > 0 && buffer.start >= buffer.size {
   703  			t.Errorf("test index %d: buffer start index invalid: %d >= %d",
   704  				i, buffer.start, buffer.size,
   705  			)
   706  		}
   707  		if buffer.used > buffer.size {
   708  			t.Errorf("test index %d: buffer data count invalid: %d > %d",
   709  				i, buffer.used, buffer.size,
   710  			)
   711  		}
   712  
   713  		// If invariants were invalid, then continue.
   714  		if invalid {
   715  			continue
   716  		}
   717  
   718  		// Otherwise, perform a reset test.
   719  		buffer.Reset()
   720  		if buffer.start != 0 {
   721  			t.Errorf("test index %d: buffer start index non-0 after reset: %d", i, buffer.start)
   722  		}
   723  		if buffer.used != 0 {
   724  			t.Errorf("test index %d: buffer data count non-0 after reset: %d", i, buffer.used)
   725  		}
   726  	}
   727  }