Source file src/internal/fuzz/mutators_byteslice_test.go

     1  // Copyright 2021 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 fuzz
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"testing"
    11  )
    12  
    13  type mockRand struct {
    14  	values  []int
    15  	counter int
    16  	b       bool
    17  }
    18  
    19  func (mr *mockRand) uint32() uint32 {
    20  	c := mr.values[mr.counter]
    21  	mr.counter++
    22  	return uint32(c)
    23  }
    24  
    25  func (mr *mockRand) intn(n int) int {
    26  	c := mr.values[mr.counter]
    27  	mr.counter++
    28  	return c % n
    29  }
    30  
    31  func (mr *mockRand) uint32n(n uint32) uint32 {
    32  	c := mr.values[mr.counter]
    33  	mr.counter++
    34  	return uint32(c) % n
    35  }
    36  
    37  func (mr *mockRand) bool() bool {
    38  	b := mr.b
    39  	mr.b = !mr.b
    40  	return b
    41  }
    42  
    43  func (mr *mockRand) save(*uint64, *uint64) {
    44  	panic("unimplemented")
    45  }
    46  
    47  func (mr *mockRand) restore(uint64, uint64) {
    48  	panic("unimplemented")
    49  }
    50  
    51  func TestByteSliceMutators(t *testing.T) {
    52  	for _, tc := range []struct {
    53  		name     string
    54  		mutator  func(*mutator, []byte) []byte
    55  		randVals []int
    56  		input    []byte
    57  		expected []byte
    58  	}{
    59  		{
    60  			name:     "byteSliceRemoveBytes",
    61  			mutator:  byteSliceRemoveBytes,
    62  			input:    []byte{1, 2, 3, 4},
    63  			expected: []byte{4},
    64  		},
    65  		{
    66  			name:     "byteSliceInsertRandomBytes",
    67  			mutator:  byteSliceInsertRandomBytes,
    68  			input:    make([]byte, 4, 8),
    69  			expected: []byte{3, 4, 5, 0, 0, 0, 0},
    70  		},
    71  		{
    72  			name:     "byteSliceDuplicateBytes",
    73  			mutator:  byteSliceDuplicateBytes,
    74  			input:    append(make([]byte, 0, 13), []byte{1, 2, 3, 4}...),
    75  			expected: []byte{1, 1, 2, 3, 4, 2, 3, 4},
    76  		},
    77  		{
    78  			name:     "byteSliceOverwriteBytes",
    79  			mutator:  byteSliceOverwriteBytes,
    80  			input:    []byte{1, 2, 3, 4},
    81  			expected: []byte{1, 1, 3, 4},
    82  		},
    83  		{
    84  			name:     "byteSliceBitFlip",
    85  			mutator:  byteSliceBitFlip,
    86  			input:    []byte{1, 2, 3, 4},
    87  			expected: []byte{3, 2, 3, 4},
    88  		},
    89  		{
    90  			name:     "byteSliceXORByte",
    91  			mutator:  byteSliceXORByte,
    92  			input:    []byte{1, 2, 3, 4},
    93  			expected: []byte{3, 2, 3, 4},
    94  		},
    95  		{
    96  			name:     "byteSliceSwapByte",
    97  			mutator:  byteSliceSwapByte,
    98  			input:    []byte{1, 2, 3, 4},
    99  			expected: []byte{2, 1, 3, 4},
   100  		},
   101  		{
   102  			name:     "byteSliceArithmeticUint8",
   103  			mutator:  byteSliceArithmeticUint8,
   104  			input:    []byte{1, 2, 3, 4},
   105  			expected: []byte{255, 2, 3, 4},
   106  		},
   107  		{
   108  			name:     "byteSliceArithmeticUint16",
   109  			mutator:  byteSliceArithmeticUint16,
   110  			input:    []byte{1, 2, 3, 4},
   111  			expected: []byte{1, 3, 3, 4},
   112  		},
   113  		{
   114  			name:     "byteSliceArithmeticUint32",
   115  			mutator:  byteSliceArithmeticUint32,
   116  			input:    []byte{1, 2, 3, 4},
   117  			expected: []byte{2, 2, 3, 4},
   118  		},
   119  		{
   120  			name:     "byteSliceArithmeticUint64",
   121  			mutator:  byteSliceArithmeticUint64,
   122  			input:    []byte{1, 2, 3, 4, 5, 6, 7, 8},
   123  			expected: []byte{2, 2, 3, 4, 5, 6, 7, 8},
   124  		},
   125  		{
   126  			name:     "byteSliceOverwriteInterestingUint8",
   127  			mutator:  byteSliceOverwriteInterestingUint8,
   128  			input:    []byte{1, 2, 3, 4},
   129  			expected: []byte{255, 2, 3, 4},
   130  		},
   131  		{
   132  			name:     "byteSliceOverwriteInterestingUint16",
   133  			mutator:  byteSliceOverwriteInterestingUint16,
   134  			input:    []byte{1, 2, 3, 4},
   135  			expected: []byte{255, 127, 3, 4},
   136  		},
   137  		{
   138  			name:     "byteSliceOverwriteInterestingUint32",
   139  			mutator:  byteSliceOverwriteInterestingUint32,
   140  			input:    []byte{1, 2, 3, 4},
   141  			expected: []byte{250, 0, 0, 250},
   142  		},
   143  		{
   144  			name:     "byteSliceInsertConstantBytes",
   145  			mutator:  byteSliceInsertConstantBytes,
   146  			input:    append(make([]byte, 0, 8), []byte{1, 2, 3, 4}...),
   147  			expected: []byte{3, 3, 3, 1, 2, 3, 4},
   148  		},
   149  		{
   150  			name:     "byteSliceOverwriteConstantBytes",
   151  			mutator:  byteSliceOverwriteConstantBytes,
   152  			input:    []byte{1, 2, 3, 4},
   153  			expected: []byte{3, 3, 3, 4},
   154  		},
   155  		{
   156  			name:     "byteSliceShuffleBytes",
   157  			mutator:  byteSliceShuffleBytes,
   158  			input:    []byte{1, 2, 3, 4},
   159  			expected: []byte{2, 3, 1, 4},
   160  		},
   161  		{
   162  			name:     "byteSliceSwapBytes",
   163  			mutator:  byteSliceSwapBytes,
   164  			randVals: []int{0, 2, 0, 2},
   165  			input:    append(make([]byte, 0, 9), []byte{1, 2, 3, 4}...),
   166  			expected: []byte{3, 2, 1, 4},
   167  		},
   168  	} {
   169  		t.Run(tc.name, func(t *testing.T) {
   170  			r := &mockRand{values: []int{0, 1, 2, 3, 4, 5}}
   171  			if tc.randVals != nil {
   172  				r.values = tc.randVals
   173  			}
   174  			m := &mutator{r: r}
   175  			b := tc.mutator(m, tc.input)
   176  			if !bytes.Equal(b, tc.expected) {
   177  				t.Errorf("got %x, want %x", b, tc.expected)
   178  			}
   179  		})
   180  	}
   181  }
   182  
   183  func BenchmarkByteSliceMutators(b *testing.B) {
   184  	tests := [...]struct {
   185  		name    string
   186  		mutator func(*mutator, []byte) []byte
   187  	}{
   188  		{"RemoveBytes", byteSliceRemoveBytes},
   189  		{"InsertRandomBytes", byteSliceInsertRandomBytes},
   190  		{"DuplicateBytes", byteSliceDuplicateBytes},
   191  		{"OverwriteBytes", byteSliceOverwriteBytes},
   192  		{"BitFlip", byteSliceBitFlip},
   193  		{"XORByte", byteSliceXORByte},
   194  		{"SwapByte", byteSliceSwapByte},
   195  		{"ArithmeticUint8", byteSliceArithmeticUint8},
   196  		{"ArithmeticUint16", byteSliceArithmeticUint16},
   197  		{"ArithmeticUint32", byteSliceArithmeticUint32},
   198  		{"ArithmeticUint64", byteSliceArithmeticUint64},
   199  		{"OverwriteInterestingUint8", byteSliceOverwriteInterestingUint8},
   200  		{"OverwriteInterestingUint16", byteSliceOverwriteInterestingUint16},
   201  		{"OverwriteInterestingUint32", byteSliceOverwriteInterestingUint32},
   202  		{"InsertConstantBytes", byteSliceInsertConstantBytes},
   203  		{"OverwriteConstantBytes", byteSliceOverwriteConstantBytes},
   204  		{"ShuffleBytes", byteSliceShuffleBytes},
   205  		{"SwapBytes", byteSliceSwapBytes},
   206  	}
   207  
   208  	for _, tc := range tests {
   209  		b.Run(tc.name, func(b *testing.B) {
   210  			for size := 64; size <= 1024; size *= 2 {
   211  				b.Run(fmt.Sprintf("%d", size), func(b *testing.B) {
   212  					m := &mutator{r: newPcgRand()}
   213  					input := make([]byte, size)
   214  					for i := 0; i < b.N; i++ {
   215  						tc.mutator(m, input)
   216  					}
   217  				})
   218  			}
   219  		})
   220  	}
   221  }
   222  

View as plain text