Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / tools / fuzzing / common / FuzzingTraits.h
blobb8c9d76ab743165e3f0b78a3c13a2eb68136a961
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_fuzzing_FuzzingTraits_h
8 #define mozilla_fuzzing_FuzzingTraits_h
10 #include "mozilla/Assertions.h"
11 #include <cmath>
12 #include <random>
13 #include <type_traits>
15 namespace mozilla {
16 namespace fuzzing {
18 class FuzzingTraits {
19 public:
20 static unsigned int Random(unsigned int aMax);
21 static bool Sometimes(unsigned int aProbability);
22 /**
23 * Frequency() defines how many mutations of a kind shall be applied to a
24 * target buffer by using a user definable factor. The higher the factor,
25 * the less mutations are being made.
27 static size_t Frequency(const size_t aSize, const uint64_t aFactor);
29 static std::mt19937_64& Rng();
32 /**
33 * RandomNumericLimit returns either the min or max limit of an arithmetic
34 * data type.
36 template <typename T>
37 T RandomNumericLimit() {
38 static_assert(std::is_arithmetic_v<T> == true,
39 "T must be an arithmetic type");
40 return FuzzingTraits::Sometimes(2) ? std::numeric_limits<T>::min()
41 : std::numeric_limits<T>::max();
44 /**
45 * RandomInteger generates negative and positive integers in 2**n increments.
47 template <typename T>
48 T RandomInteger() {
49 static_assert(std::is_integral_v<T> == true, "T must be an integral type");
50 double r =
51 static_cast<double>(FuzzingTraits::Random((sizeof(T) * CHAR_BIT) + 1));
52 T x = static_cast<T>(pow(2.0, r)) - 1;
53 if (std::numeric_limits<T>::is_signed && FuzzingTraits::Sometimes(2)) {
54 return (x * -1) - 1;
56 return x;
59 /**
60 * RandomIntegerRange returns a random integral within a [min, max] range.
62 template <typename T>
63 T RandomIntegerRange(T min, T max) {
64 static_assert(std::is_integral_v<T> == true, "T must be an integral type");
65 MOZ_ASSERT(min < max);
66 std::uniform_int_distribution<T> d(min, max);
67 return d(FuzzingTraits::Rng());
69 /**
70 * uniform_int_distribution is undefined for char/uchar. Need to handle them
71 * separately.
73 template <>
74 inline unsigned char RandomIntegerRange(unsigned char min, unsigned char max) {
75 MOZ_ASSERT(min < max);
76 std::uniform_int_distribution<unsigned short> d(min, max);
77 return static_cast<unsigned char>(d(FuzzingTraits::Rng()));
79 template <>
80 inline char RandomIntegerRange(char min, char max) {
81 MOZ_ASSERT(min < max);
82 std::uniform_int_distribution<short> d(min, max);
83 return static_cast<char>(d(FuzzingTraits::Rng()));
86 /**
87 * RandomFloatingPointRange returns a random floating-point number within a
88 * [min, max] range.
90 template <typename T>
91 T RandomFloatingPointRange(T min, T max) {
92 static_assert(std::is_floating_point_v<T> == true,
93 "T must be a floating point type");
94 MOZ_ASSERT(min < max);
95 std::uniform_real_distribution<T> d(
96 min, std::nextafter(max, std::numeric_limits<T>::max()));
97 return d(FuzzingTraits::Rng());
101 * RandomFloatingPoint returns a random floating-point number in 2**n
102 * increments.
104 template <typename T>
105 T RandomFloatingPoint() {
106 static_assert(std::is_floating_point_v<T> == true,
107 "T must be a floating point type");
108 int radix = RandomIntegerRange<int>(std::numeric_limits<T>::min_exponent,
109 std::numeric_limits<T>::max_exponent);
110 T x = static_cast<T>(pow(2.0, static_cast<double>(radix)));
111 return x * RandomFloatingPointRange<T>(-1.0, 1.0);
114 } // namespace fuzzing
115 } // namespace mozilla
117 #endif