RandomnessSource.h 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. /*
  2. * Copyright (c) 2023, Martin Janiczek <martin@janiczek.cz>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Function.h>
  8. #include <LibTest/Randomized/RandomRun.h>
  9. #include <LibTest/TestResult.h>
  10. namespace Test {
  11. namespace Randomized {
  12. // RandomnessSource provides random bits to Generators.
  13. //
  14. // If it's live, a PRNG will be used and the random values will be recorded into
  15. // its RandomRun.
  16. //
  17. // If it's recorded, its RandomRun will be used to "mock" the PRNG. This allows
  18. // us to replay the generation of a particular value, and to test out
  19. // "alternative histories": "what if the PRNG generated 0 instead of 13 here?"
  20. class RandomnessSource {
  21. public:
  22. static RandomnessSource live() { return RandomnessSource(RandomRun(), true); }
  23. static RandomnessSource recorded(RandomRun const& run) { return RandomnessSource(run, false); }
  24. RandomRun& run() { return m_run; }
  25. u64 draw_value(u64 max, Function<u64()> random_generator)
  26. {
  27. // Live: use the random generator and remember the value.
  28. if (m_is_live) {
  29. u64 value = random_generator();
  30. m_run.append(value);
  31. return value;
  32. }
  33. // Not live! let's get another prerecorded value.
  34. auto next = m_run.next();
  35. if (next.has_value()) {
  36. return min(next.value(), max);
  37. }
  38. // Signal a failure. The value returned doesn't matter at this point but
  39. // we need to return something.
  40. set_current_test_result(TestResult::Overrun);
  41. return 0;
  42. }
  43. private:
  44. explicit RandomnessSource(RandomRun const& run, bool is_live)
  45. : m_run(run)
  46. , m_is_live(is_live)
  47. {
  48. }
  49. RandomRun m_run;
  50. bool m_is_live;
  51. };
  52. } // namespace Randomized
  53. } // namespace Test