github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/stdlibs/testing/fuzz_test.gno (about)

     1  package testing
     2  
     3  import (
     4  	"encoding/binary"
     5  	"strings"
     6  	"time"
     7  )
     8  
     9  func TestMutate(t *T) {
    10  	originalValue := "Hello"
    11  	fuzzer := StringFuzzer{Value: originalValue}
    12  
    13  	newFuzzer := fuzzer.Mutate().(*StringFuzzer)
    14  
    15  	if newFuzzer.Value == originalValue {
    16  		t.Errorf("Mutate did not change the string: got %v, want different from %v", newFuzzer.Value, originalValue)
    17  	}
    18  
    19  	if len(newFuzzer.Value) != len(originalValue) {
    20  		t.Errorf("Mutated string has different length: got %s (len=%v), want %s (len=%v)", newFuzzer.Value, len(newFuzzer.Value), originalValue, len(originalValue))
    21  	}
    22  }
    23  
    24  func TestSelection(t *T) {
    25  	tests := []struct {
    26  		name       string
    27  		population []*Individual
    28  	}{
    29  		{
    30  			name:       "Empty population",
    31  			population: []*Individual{},
    32  		},
    33  		{
    34  			name: "Uniform fitness",
    35  			population: []*Individual{
    36  				{Fitness: 10},
    37  				{Fitness: 10},
    38  				{Fitness: 10},
    39  			},
    40  		},
    41  		{
    42  			name: "Different fitness",
    43  			population: []*Individual{
    44  				{Fitness: 5},
    45  				{Fitness: 15},
    46  				{Fitness: 10},
    47  			},
    48  		},
    49  	}
    50  
    51  	for _, tc := range tests {
    52  		t.Run(tc.name, func(t *T) {
    53  			selected := Selection(tc.population)
    54  			if len(selected) != len(tc.population) {
    55  				t.Errorf("Expected selected length to be %d, got %d", len(tc.population), len(selected))
    56  			}
    57  		})
    58  	}
    59  }
    60  
    61  func TestCrossover(t *T) {
    62  	parent1 := NewIndividual(&StringFuzzer{Value: "foobar"})
    63  	parent2 := NewIndividual(&StringFuzzer{Value: "bazbiz"})
    64  
    65  	var child1, child2 *Individual
    66  	for i := 0; i < 100; i++ {
    67  		child1, child2 = Crossover(parent1, parent2)
    68  	}
    69  
    70  	if child1.Fuzzer.String() == "foobar" || child2.Fuzzer.String() == "bazbiz" {
    71  		t.Errorf("Crossover did not modify children correctly, got %s and %s", child1.Fuzzer.String(), child2.Fuzzer.String())
    72  	}
    73  }
    74  
    75  func Test_StringManipulation(t *T) {
    76  	f := &F{
    77  		corpus: []string{"hello", "world", "foo", "bar"},
    78  	}
    79  
    80  	f.evolve(30)
    81  
    82  	if len(f.corpus) != 4 {
    83  		t.Fatalf("corpus length is %d, want 4", len(f.corpus))
    84  	}
    85  
    86  	for i, c := range f.corpus {
    87  		if c == "" {
    88  			t.Fatalf("corpus[%d] is empty", i)
    89  		}
    90  
    91  		if len(c) < 3 {
    92  			t.Fatalf("corpus[%d] is too short: %s", i, c)
    93  		}
    94  
    95  		if f.corpus[0] == "hello" {
    96  			t.Fatalf("corpus[0] is still the same: %s", f.corpus[0])
    97  		}
    98  
    99  		if f.corpus[1] == "world" {
   100  			t.Fatalf("corpus[1] is still the same: %s", f.corpus[1])
   101  		}
   102  
   103  		if f.corpus[2] == "foo" {
   104  			t.Fatalf("corpus[2] is still the same: %s", f.corpus[2])
   105  		}
   106  
   107  		if f.corpus[3] == "bar" {
   108  			t.Fatalf("corpus[3] is still the same: %s", f.corpus[3])
   109  		}
   110  
   111  	}
   112  }
   113  
   114  func TestFuzz(t *T) {
   115  	f := F{}
   116  	f.Add("hello", "world", "foo")
   117  	f.Fuzz(func(t *T, inputs ...interface{}) {
   118  		for _, input := range inputs {
   119  			strInput, ok := input.(string)
   120  			if !ok {
   121  				t.Errorf("Type mismatch, expected a string but got %T", input)
   122  				continue
   123  			}
   124  
   125  			words := strings.Fields(strInput)
   126  			if len(words) == 0 {
   127  				t.Errorf("Expected non-empty input")
   128  			}
   129  		}
   130  	}, 15)
   131  
   132  	if len(f.corpus) == 0 {
   133  		t.Fatalf("Fuzzing corpus is empty after testing")
   134  	}
   135  
   136  	if len(f.corpus) > 3 {
   137  		t.Fatalf("Fuzzing corpus has more than 3 elements: %v", f.corpus)
   138  	}
   139  
   140  	for _, c := range f.corpus {
   141  		if c == "hello" || c == "world" || c == "foo" {
   142  			t.Fatalf("Fuzzing corpus still contains the original elements: %v", f.corpus)
   143  		}
   144  	}
   145  }
   146  
   147  func TestF_Fail(t *T) {
   148  	f := F{}
   149  	f.Fail()
   150  
   151  	if !f.failed {
   152  		t.Errorf("Fail did not set the failed flag.")
   153  	}
   154  }
   155  
   156  func TestF_Fatal(t *T) {
   157  	f := F{}
   158  	testMessage := "test failure message"
   159  	f.Fatal(testMessage)
   160  
   161  	if !f.failed {
   162  		t.Errorf("Fatal did not set the failed flag.")
   163  	}
   164  
   165  	if len(f.msgs) != 1 {
   166  		t.Fatalf("Fatal did not set the message correctly: got %v, want %v", f.msgs, testMessage)
   167  	}
   168  
   169  	if !strings.Contains(f.msgs[0], testMessage) {
   170  		t.Errorf("Fatal did not set the message correctly: got %v, want %v", f.msgs[0], testMessage)
   171  	}
   172  }