Testing with Fuzzers

Definition

Fuzz Testing or Fuzzing is a software testing technique of putting invalid or random data called FUZZ into software system to discover coding errors and security loopholes. The purpose of fuzz testing is inserting data using automated or semi-automated techniques and testing the system for various exceptions like system crashing or failure of built-in code, etc.

  •     func test_my_test(fuzzer := <Fuzzer>, <fuzzer_iterations>, <fuzzer_seed>):
    
Advice
Fuzzing is current only supported for GdScripts.

Fuzzers Overview

For now GdUnit provides only this very small set of Fuzzer implementations and will be extend later!

Fuzzer Description
rangei(from, to) Generates a random integer in the range from from to to, inclusive.
eveni(from, to) Generates an even integer in the range from from to to, inclusive.
oddi(from, to) Generates an odd integer in the range from from to to, inclusive.
rangev2(from, to) Generates a random 2D vector with each component in the range from from to to, inclusive.
rangev3(from, to) Generates a random 3D vector with each component in the range from from to to, inclusive.
rand_str(min_length, max_length, charset) Generates a random string with a length between min_length and max_length, inclusive, using characters from the specified charset.

Using Fuzzers

To use a fuzzer, you only need to add the argument ‘fuzzer = ' to your test. The name of the fuzzer argument must always start with the prefix `fuzzer`, followed by characters such as '_' and alphanumeric characters.

If your test is configured with a fuzzer argument, it will iterate multiple times with a new value generated by the fuzzer implementation.
The default number of iterations is set to 1000 and can be configured with the optional argument fuzzer_iterations. If you want to have the same fuzzer results, you can set a seed with the optional argument fuzzer_seed.

  •     func test_name(fuzzer := <Fuzzer>, <fuzzer_iterations>, <fuzzer_seed>):
    
  •     ..
    

Here is an example of using a fuzzer that generates random values in the range from -23 to 22 and iterates 100 times:

    func test_fuzzer_inject_value(fuzzer := Fuzzers.rangei(-23, 22), fuzzer_iterations = 100):
        assert_int(fuzzer.next_value()).is_in_range(-23, 22)


    # using multiple fuzzers in test are allowed
    func test_fuzzer_inject_value(fuzzer_a := Fuzzers.rangei(-23, 22), fuzzer_b := Fuzzers.rangei(0, 42), fuzzer_iterations = 100):
        assert_int(fuzzer_a.next_value()).is_in_range(-23, 22)
        assert_int(fuzzer_b.next_value()).is_in_range(-23, 22)
  • fuzzer_iterations
    If you want to iterate more or less than the default of 1000 iterations, you can set the number of iterations using the fuzzer_iterations argument.

          # execute this test 5000 times
          func test_fuzzer_inject_value(fuzzer := Fuzzers.rangei(-100000, 100000), fuzzer_iterations=5000):
    
  • fuzzer_seed
    If you want to ensure consistent test results for a random generating fuzzer, you can specify a seed using the fuzzer_seed argument.

          # execute this test with a seed value of 123456
          func test_fuzzer_inject_value(fuzzer := Fuzzers.rangei(-100000, 100000), fuzzer_seed=123456):
    

Create a Custom Fuzzer

If you need a custom fuzzer you do this by extend from class Fuzzer and implement the function next_value()

    # Base interface for fuzz testing
    class_name Fuzzer
    extends Resource

        # generates the next fuzz value
        # needs to be implement 
        func next_value():
            push_error("Invalid vall. Fuzzer not implemented 'next_value()'")
            return null

Here a small example custom fuzzer implementation:

    # A simple test fuzzer where a random value of a hard coded set of values is provided
    class TestFuzzer extends Fuzzer:
        var _data := [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

        func next_value():
            return _data[randi_range(0, _data.size())]

document version v4.1.0


Copyright © 2021-2024 Mike Schulze. Distributed by an MIT license.