summaryrefslogtreecommitdiff
path: root/addons/gdUnit4/src/fuzzers
diff options
context:
space:
mode:
Diffstat (limited to 'addons/gdUnit4/src/fuzzers')
-rw-r--r--addons/gdUnit4/src/fuzzers/BoolFuzzer.gd24
-rw-r--r--addons/gdUnit4/src/fuzzers/BoolFuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/FloatFuzzer.gd37
-rw-r--r--addons/gdUnit4/src/fuzzers/FloatFuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/Fuzzer.gd80
-rw-r--r--addons/gdUnit4/src/fuzzers/Fuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/IntFuzzer.gd77
-rw-r--r--addons/gdUnit4/src/fuzzers/IntFuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/StringFuzzer.gd112
-rw-r--r--addons/gdUnit4/src/fuzzers/StringFuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd45
-rw-r--r--addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd.uid1
-rw-r--r--addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd48
-rw-r--r--addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd.uid1
14 files changed, 430 insertions, 0 deletions
diff --git a/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd b/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd
new file mode 100644
index 0000000..906ee2c
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd
@@ -0,0 +1,24 @@
+## A fuzzer that generates random boolean values for testing.[br]
+##
+## This is useful for testing code paths that
+## depend on boolean conditions, flags, or toggle states.[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## func test_toggle_feature(fuzzer := BoolFuzzer.new(), _fuzzer_iterations = 100):
+## var enabled := fuzzer.next_value()
+## my_feature.set_enabled(enabled)
+## assert_bool(my_feature.is_enabled()),is_equal(enabled)
+## [/codeblock]
+class_name BoolFuzzer
+extends Fuzzer
+
+
+## Generates a random boolean value.[br]
+##
+## Returns either [code]true[/code] or [code]false[/code] with equal probability.
+## This method is called automatically during fuzz testing iterations.[br]
+##
+## @returns A randomly generated boolean value ([code]true[/code] or [code]false[/code]).
+func next_value() -> bool:
+ return randi() % 2
diff --git a/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd.uid
new file mode 100644
index 0000000..f2a9436
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/BoolFuzzer.gd.uid
@@ -0,0 +1 @@
+uid://c0b4yc7wahhsc
diff --git a/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd b/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd
new file mode 100644
index 0000000..5da1a77
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd
@@ -0,0 +1,37 @@
+## A fuzzer that generates random floating-point values within a specified range.[br]
+##
+## This is particularly useful for testing numerical calculations,
+## physics simulations, shader parameters, or any code that processes floating-point
+## values.[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## func test_calculate_damage(fuzzer := FloatFuzzer.new(0.0, 100.0), _fuzzer_iterations := 500):
+## var damage := fuzzer.next_value()
+## var result = calculate_damage_reduction(damage)
+## assert_float(result).is_between(0.0, damage)
+## [/codeblock]
+## [br]
+## [b]Note:[/b] The range is inclusive on both ends, and values are uniformly distributed.
+class_name FloatFuzzer
+extends Fuzzer
+
+## Minimum value (inclusive) for generated floats.
+var _from: float = 0
+## Maximum value (inclusive) for generated floats.
+var _to: float = 0
+
+func _init(from: float, to: float) -> void:
+ assert(from <= to, "Invalid range!")
+ _from = from
+ _to = to
+
+
+## Generates a random float value within the configured range.[br]
+##
+## Returns a uniformly distributed random float between [member _from] and
+## [member _to] (inclusive). Each call produces a new random value.[br]
+##
+## @returns A random float value within the specified range.
+func next_value() -> float:
+ return randf_range(_from, _to)
diff --git a/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd.uid
new file mode 100644
index 0000000..3c67b8a
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/FloatFuzzer.gd.uid
@@ -0,0 +1 @@
+uid://droy0thepcy
diff --git a/addons/gdUnit4/src/fuzzers/Fuzzer.gd b/addons/gdUnit4/src/fuzzers/Fuzzer.gd
new file mode 100644
index 0000000..e4e597d
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Fuzzer.gd
@@ -0,0 +1,80 @@
+## Base interface for fuzz testing.[br]
+##
+## Fuzzer is an abstract base class that provides the foundation for creating
+## custom fuzzers used in automated testing. Fuzz testing (fuzzing) is a software
+## testing technique that involves providing invalid, unexpected, or random data
+## as inputs to a program to find bugs and potential security vulnerabilities.
+## [br][br]
+## To use a fuzzer in your test cases, add optional parameters to your test function:
+## [codeblock]
+## func test_foo(fuzzer := Fuzzers.randomInt(), _fuzzer_iterations := 10, _fuzzer_seed := 12345):
+## var value := fuzzer.next_value()
+## # Test logic using the fuzzed value
+## [/codeblock]
+## [br]
+## @tutorial(Fuzzing on Wikipedia): https://en.wikipedia.org/wiki/Fuzzing
+@abstract
+class_name Fuzzer
+extends RefCounted
+
+## Default number of iterations for fuzz testing when not specified.
+const ITERATION_DEFAULT_COUNT := 1000
+## Parameter name for passing the fuzzer instance to test functions.
+const ARGUMENT_FUZZER_INSTANCE := "fuzzer"
+## Parameter name for specifying the number of iterations in test functions.
+const ARGUMENT_ITERATIONS := "fuzzer_iterations"
+## Parameter name for specifying the random seed in test functions.
+const ARGUMENT_SEED := "fuzzer_seed"
+
+## Current iteration index during fuzzing execution.
+var _iteration_index := 0
+## Maximum number of iterations to run for this fuzzer.
+var _iteration_limit := ITERATION_DEFAULT_COUNT
+
+
+## Generates the next fuzz value.[br]
+##
+## This abstract method must be implemented by derived classes to provide
+## the specific fuzzing logic for generating test values.[br]
+##
+## [b]Example implementation:[/b]
+## [codeblock]
+## func next_value() -> int:
+## return randi_range(0, 100)
+## [/codeblock]
+##
+## @returns The next generated fuzz value. The type depends on the specific fuzzer implementation.
+@abstract
+func next_value() -> Variant
+
+
+## Returns the current iteration index.[br]
+##
+## Useful for tracking progress during fuzzing or for debugging purposes
+## when a specific iteration causes a failure.[br]
+##
+## [b]Example:[/b]
+## [codeblock]
+## if fuzzer.iteration_index() % 100 == 0:
+## print("Processed %d iterations" % fuzzer.iteration_index())
+## [/codeblock]
+##
+## @returns The current iteration index, starting from 0.
+func iteration_index() -> int:
+ return _iteration_index
+
+
+## Returns the maximum number of iterations for this fuzzer.[br]
+##
+## This value determines how many times the fuzzer will generate values
+## during a test run. It can be overridden by the [code]fuzzer_iterations[/code]
+## parameter in test functions.[br]
+##
+## [b]Example:[/b]
+## [codeblock]
+## print("Running %d fuzzing iterations" % fuzzer.iteration_limit())
+## [/codeblock]
+##
+## @returns The maximum number of iterations to be executed.
+func iteration_limit() -> int:
+ return _iteration_limit
diff --git a/addons/gdUnit4/src/fuzzers/Fuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/Fuzzer.gd.uid
new file mode 100644
index 0000000..ca5a34d
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Fuzzer.gd.uid
@@ -0,0 +1 @@
+uid://dnqosea1sx5f4
diff --git a/addons/gdUnit4/src/fuzzers/IntFuzzer.gd b/addons/gdUnit4/src/fuzzers/IntFuzzer.gd
new file mode 100644
index 0000000..4100d51
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/IntFuzzer.gd
@@ -0,0 +1,77 @@
+## A fuzzer that generates random integer values with optional even/odd constraints.[br]
+##
+## It supports three modes: normal (any integer), even-only,
+## and odd-only generation. This is useful for testing array indices, loop counters,
+## enumeration values, or any code that processes integer values.[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## # Test with any integer in range
+## func test_array_access(fuzzer = IntFuzzer.new(0, 99), fuzzer_iterations = 100):
+## var index = fuzzer.next_value()
+## var array = create_array(100)
+## assert(array[index] != null)
+##
+## # Test with only even numbers
+## func test_even_processing(fuzzer := IntFuzzer.new(0, 100, IntFuzzer.EVEN)):
+## var even_num := fuzzer.next_value()
+## assert_int(even_num % 2).is_equal(0)
+## [/codeblock]
+class_name IntFuzzer
+extends Fuzzer
+
+
+## Generates any integer within the range.
+enum {
+ NORMAL, ## Generate any integer within the specified range.
+ EVEN, ## Generate only even integers within the specified range.
+ ODD ## Generate only odd integers within the specified range.
+}
+
+
+## Minimum value (inclusive) for generated integers.
+var _from: int = 0
+## Maximum value (inclusive) for generated integers.
+var _to: int = 0
+## Generation mode: NORMAL, EVEN, or ODD.
+var _mode: int = NORMAL
+
+
+func _init(from: int, to: int, mode: int = NORMAL) -> void:
+ assert(from <= to, "Invalid range!")
+ _from = from
+ _to = to
+ _mode = mode
+
+
+## Generates a random integer value based on the configured mode.[br]
+##
+## Returns a random integer between [member _from] and [member _to] (inclusive).[br]
+## The value will be constrained according to the [member _mode]:[br]
+## - [constant NORMAL]: Any integer in the range[br]
+## - [constant EVEN]: Only even integers[br]
+## - [constant ODD]: Only odd integers[br]
+##
+## [b]Example:[/b]
+## [codeblock]
+## var normal_fuzzer = IntFuzzer.new(1, 10, IntFuzzer.NORMAL)
+## var even_fuzzer = IntFuzzer.new(1, 10, IntFuzzer.EVEN)
+## var odd_fuzzer = IntFuzzer.new(1, 10, IntFuzzer.ODD)
+##
+## print(normal_fuzzer.next_value()) # Could be any: 1, 2, 3, ..., 10
+## print(even_fuzzer.next_value()) # Only even: 2, 4, 6, 8, 10
+## print(odd_fuzzer.next_value()) # Only odd: 1, 3, 5, 7, 9
+## [/codeblock]
+##
+## @returns A random integer value within the specified range and mode
+func next_value() -> int:
+ var value := randi_range(_from, _to)
+ match _mode:
+ NORMAL:
+ return value
+ EVEN:
+ return int((value / 2.0) * 2)
+ ODD:
+ return int((value / 2.0) * 2 + 1)
+ _:
+ return value
diff --git a/addons/gdUnit4/src/fuzzers/IntFuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/IntFuzzer.gd.uid
new file mode 100644
index 0000000..e5f1d95
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/IntFuzzer.gd.uid
@@ -0,0 +1 @@
+uid://bt16fv8esh0f8
diff --git a/addons/gdUnit4/src/fuzzers/StringFuzzer.gd b/addons/gdUnit4/src/fuzzers/StringFuzzer.gd
new file mode 100644
index 0000000..277b4ac
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/StringFuzzer.gd
@@ -0,0 +1,112 @@
+## A fuzzer that generates random strings with configurable length and character sets.[br]
+##
+## It supports custom character sets defined by patterns or ranges,
+## making it ideal for testing input validation, text processing, parsers, or any
+## code that handles string data.[br]
+##
+## The fuzzer uses a pattern syntax to define allowed characters:[br]
+## - Single characters: [code]abc[/code] allows 'a', 'b', 'c'[br]
+## - Ranges: [code]a-z[/code] allows lowercase letters[br]
+## - Special patterns: [code]\\w[/code] (word chars), [code]\\p{L}[/code] (letters), [code]\\p{N}[/code] (numbers)[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## # Test with alphanumeric strings
+## func test_username(fuzzer := StringFuzzer.new(3, 20, "a-zA-Z0-9"), _fuzzer_iterations := 100):
+## var username _= fuzzer.next_value()
+## assert_bool(validate_username(username)).is_true()
+##
+## # Test with special characters
+## func test_password(fuzzer := StringFuzzer.new(8, 32, "a-zA-Z0-9!@#$%"), _fuzzer_iterations := 100) -> void:
+## var password := fuzzer.next_value()
+## assert_str(password).has_length(8, Comparator.GREATER_EQUAL).has_length(32, Comparator.LESS_EQUAL)
+## [/codeblock]
+class_name StringFuzzer
+extends Fuzzer
+
+## Default character set pattern including word characters, letters, numbers, and common symbols.[br]
+## Includes: word characters (\\w), Unicode letters (\\p{L}), Unicode numbers (\\p{N}),
+## and the characters: +, -, _, '
+const DEFAULT_CHARSET = "\\w\\p{L}\\p{N}+-_'"
+
+## Minimum length for generated strings (inclusive).
+var _min_length: int
+## Maximum length for generated strings (inclusive).
+var _max_length: int
+## Array of character codes that can be used in generated strings.
+var _charset: PackedInt32Array
+
+
+func _init(min_length: int, max_length: int, pattern: String = DEFAULT_CHARSET) -> void:
+ _min_length = min_length
+ _max_length = max_length + 1 # +1 for inclusive
+ assert(not null or not pattern.is_empty())
+ assert(_min_length > 0 and _min_length < _max_length)
+ _charset = _extract_charset(pattern)
+
+
+## Generates a random string based on configured parameters.[br]
+##
+## Creates a string with random length between [member _min_length] and
+## [member _max_length], using only characters from the configured charset.
+## Each character is selected randomly and independently.[br]
+##
+## [b]Example:[/b]
+## [codeblock]
+## var fuzzer = StringFuzzer.new(5, 10, "ABC")
+## for i in range(5):
+## var str = fuzzer.next_value()
+## print("Generated: ", str)
+## # Possible outputs: "ABCAB", "BCAABCA", "CCCBAA", etc.
+## assert(str.length() >= 5 and str.length() <= 10)
+## for c in str:
+## assert(c in ["A", "B", "C"])
+## [/codeblock]
+##
+## @returns A random string matching the configured constraints.
+func next_value() -> String:
+ var value := PackedInt32Array()
+ var max_char := len(_charset)
+ var length: int = max(_min_length, randi() % _max_length)
+ for i in length:
+ @warning_ignore("return_value_discarded")
+ value.append(_charset[randi() % max_char])
+ return value.to_byte_array().get_string_from_utf32()
+
+
+static func _extract_charset(pattern: String) -> PackedInt32Array:
+ var reg := RegEx.new()
+ if reg.compile(pattern) != OK:
+ push_error("Invalid pattern to generate Strings! Use e.g '\\w\\p{L}\\p{N}+-_'")
+ return PackedInt32Array()
+
+ var charset := PackedInt32Array()
+ var char_before := -1
+ var index := 0
+ while index < pattern.length():
+ var char_current := pattern.unicode_at(index)
+ # - range token at first or last pos?
+ if char_current == 45 and (index == 0 or index == pattern.length()-1):
+ charset.append(char_current)
+ index += 1
+ continue
+ index += 1
+ # range starts
+ if char_current == 45 and char_before != -1:
+ var char_next := pattern.unicode_at(index)
+ var characters := _build_chars(char_before, char_next)
+ for character in characters:
+ charset.append(character)
+ char_before = -1
+ index += 1
+ continue
+ char_before = char_current
+ charset.append(char_current)
+ return charset
+
+
+static func _build_chars(from: int, to: int) -> PackedInt32Array:
+ var characters := PackedInt32Array()
+ for character in range(from+1, to+1):
+ characters.append(character)
+ return characters
diff --git a/addons/gdUnit4/src/fuzzers/StringFuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/StringFuzzer.gd.uid
new file mode 100644
index 0000000..3fa5555
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/StringFuzzer.gd.uid
@@ -0,0 +1 @@
+uid://b8l1qcoler3pb
diff --git a/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd b/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd
new file mode 100644
index 0000000..70ef31b
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd
@@ -0,0 +1,45 @@
+## A fuzzer that generates random Vector2 values within a specified rectangular range.[br]
+##
+## This is particularly useful for testing 2D physics, movement
+## systems, UI positioning, sprite coordinates, or any code that processes 2D vectors.[br]
+##
+## The fuzzer generates vectors where each component (x, y) is independently randomized
+## within its respective range, creating a uniform distribution over the rectangular area.[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## # Test 2D movement within screen bounds
+## func test_movement(fuzzer := Vector2Fuzzer.new(Vector2.ZERO, Vector2(1920, 1080)), _fuzzer_iterations := 200) -> void:
+## var position := fuzzer.next_value()
+## player.set_position(position)
+##
+## [/codeblock]
+class_name Vector2Fuzzer
+extends Fuzzer
+
+
+## Minimum bounds for the generated vectors (inclusive for both x and y).
+var _from: Vector2
+## Maximum bounds for the generated vectors (inclusive for both x and y).
+var _to: Vector2
+
+
+func _init(from: Vector2, to: Vector2) -> void:
+ assert(from <= to, "Invalid range!")
+ _from = from
+ _to = to
+
+
+## Generates a random Vector2 within the configured rectangular range.[br]
+##
+## Returns a Vector2 where each component is independently randomized:[br]
+## - x: random float between [code]_from.x[/code] and [code]_to.x[/code][br]
+## - y: random float between [code]_from.y[/code] and [code]_to.y[/code][br]
+##
+## The distribution is uniform over the rectangular area defined by the bounds.[br]
+##
+## @returns A random Vector2 within the specified range.
+func next_value() -> Vector2:
+ var x := randf_range(_from.x, _to.x)
+ var y := randf_range(_from.y, _to.y)
+ return Vector2(x, y)
diff --git a/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd.uid
new file mode 100644
index 0000000..c68746c
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Vector2Fuzzer.gd.uid
@@ -0,0 +1 @@
+uid://dvpctakk4c5u0
diff --git a/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd b/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd
new file mode 100644
index 0000000..b54870d
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd
@@ -0,0 +1,48 @@
+## A fuzzer that generates random Vector3 values within a specified box range.[br]
+##
+## This is particularly useful for testing 3D physics, spatial
+## positioning, camera systems, particle effects, or any code that processes 3D vectors.[br]
+##
+## The fuzzer generates vectors where each component (x, y, z) is independently
+## randomized within its respective range, creating a uniform distribution over the
+## 3D box volume.[br]
+##
+## [b]Usage example:[/b]
+## [codeblock]
+## # Test 3D object placement within world bounds
+## func test_spawn_position(fuzzer := Vector3Fuzzer.new(Vector3(-100, 0, -100), Vector3(100, 50, 100)), _fuzzer_iterations := 300):
+## var position := fuzzer.next_value()
+## var object = spawn_object(position)
+##
+## [/codeblock]
+class_name Vector3Fuzzer
+extends Fuzzer
+
+
+## Minimum bounds for the generated vectors (inclusive for x, y, and z).
+var _from: Vector3
+## Maximum bounds for the generated vectors (inclusive for x, y, and z).
+var _to: Vector3
+
+
+func _init(from: Vector3, to: Vector3) -> void:
+ assert(from <= to, "Invalid range!")
+ _from = from
+ _to = to
+
+
+## Generates a random Vector3 within the configured box range.[br]
+##
+## Returns a Vector3 where each component is independently randomized:[br]
+## - x: random float between [code]_from.x[/code] and [code]_to.x[/code][br]
+## - y: random float between [code]_from.y[/code] and [code]_to.y[/code][br]
+## - z: random float between [code]_from.z[/code] and [code]_to.z[/code][br]
+##
+## The distribution is uniform over the 3D box volume defined by the bounds.[br]
+##
+## @returns A random Vector3 within the specified range.
+func next_value() -> Vector3:
+ var x := randf_range(_from.x, _to.x)
+ var y := randf_range(_from.y, _to.y)
+ var z := randf_range(_from.z, _to.z)
+ return Vector3(x, y, z)
diff --git a/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd.uid b/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd.uid
new file mode 100644
index 0000000..cba3a8f
--- /dev/null
+++ b/addons/gdUnit4/src/fuzzers/Vector3Fuzzer.gd.uid
@@ -0,0 +1 @@
+uid://cde6yudknpbgf