tape_test.cxx 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //
  2. // tape_test.cpp
  3. // shared_random_generator-test
  4. //
  5. // Created by Sam Jaffe on 3/19/23.
  6. // Copyright © 2023 Sam Jaffe. All rights reserved.
  7. //
  8. #include "random/tape.h"
  9. #include <cstdlib>
  10. #include <scope_guard/scope_guard.hpp>
  11. #include "random/distribution.h"
  12. #include "random/random.h"
  13. #include "xcode_gtest_helper.h"
  14. using testing::ElementsAre;
  15. using testing::FieldsAre;
  16. template <typename T> class Uniform : public engine::random::Uniform<T> {
  17. public:
  18. Uniform(T min, T max) : engine::random::Uniform<T>(min, max) {}
  19. T operator()(engine::random::Device &) const final { throw; }
  20. };
  21. MATCHER_P(BytesAre, value, "") {
  22. *result_listener << "whose bytes are " << std::hex << arg;
  23. return reinterpret_cast<double const &>(arg) == value;
  24. }
  25. TEST(TapeTest, CanRecordIntData) {
  26. engine::random::Tape tape;
  27. tape.apply(Uniform(0u, 100u), 50u);
  28. EXPECT_EQ(tape.apply(Uniform(0u, 100u)), 50);
  29. }
  30. TEST(TapeTest, CanRecordDoubleData) {
  31. engine::random::Tape tape;
  32. tape.apply(Uniform(0.0, 100.0), 50.0);
  33. EXPECT_EQ(tape.apply(Uniform(0.0, 100.0)), 50.0);
  34. tape.apply(Uniform(0.0, 100.0), 50.0);
  35. EXPECT_EQ(tape.apply(Uniform(0.0, 100.0)), 50.0);
  36. }
  37. TEST(TapeTest, ThrowsOnOverFetch) {
  38. engine::random::Tape tape;
  39. tape.apply(Uniform(0, 100), 50);
  40. EXPECT_EQ(tape.apply(Uniform(0, 100)), 50);
  41. EXPECT_THROW(tape.apply(Uniform(0, 100)), std::out_of_range);
  42. }
  43. TEST(TapeTest, BadRequestIsNoOp) {
  44. engine::random::Tape tape;
  45. tape.apply(Uniform(0, 100), 50);
  46. EXPECT_ANY_THROW(tape.apply(Uniform(0, 1)));
  47. EXPECT_EQ(tape.apply(Uniform(0, 100)), 50);
  48. }
  49. TEST(TapeTest, ThrowsOnTypeMismatch) {
  50. engine::random::Tape tape;
  51. tape.apply(Uniform(0u, 100u), 50u);
  52. EXPECT_THROW(tape.apply(Uniform(0.0, 100.0)), std::logic_error);
  53. EXPECT_THROW(tape.apply(Uniform(0, 100)), std::logic_error);
  54. EXPECT_NO_THROW(tape.apply(Uniform(0u, 100u)));
  55. }
  56. TEST(TapeTest, ThrowsOnBoundsMismatch) {
  57. engine::random::Tape tape;
  58. tape.apply(Uniform(0.0, 100.0), 50.0);
  59. EXPECT_THROW(tape.apply(Uniform(0.0, 1.0)), std::logic_error);
  60. }
  61. TEST(TapeTest, IsOrdered) {
  62. engine::random::Tape tape;
  63. tape.apply(Uniform(0.0, 100.0), 50.0);
  64. tape.apply(Uniform(10.0, 90.0), 50.0);
  65. EXPECT_THROW(tape.apply(Uniform(10.0, 90.0)), std::logic_error);
  66. EXPECT_EQ(tape.apply(Uniform(0.0, 100.0)), 50.0);
  67. EXPECT_EQ(tape.apply(Uniform(10.0, 90.0)), 50.0);
  68. }
  69. TEST(TapeTest, IsSerializable) {
  70. engine::random::Tape tape;
  71. tape.apply(Uniform(0, 100), 50);
  72. tape.apply(Uniform(0u, 100u), 50u);
  73. tape.apply(Uniform(0.0, 100.0), 50.0);
  74. auto serial = engine::random::Tape::serial_type(tape);
  75. EXPECT_THAT(serial, ElementsAre(FieldsAre("iUniform[0,100]", 50),
  76. FieldsAre("jUniform[0,100]", 50),
  77. FieldsAre("dUniform[0,100)", BytesAre(50))));
  78. tape = engine::random::Tape(serial);
  79. EXPECT_EQ(tape.apply(Uniform(0, 100)), 50);
  80. EXPECT_EQ(tape.apply(Uniform(0u, 100u)), 50u);
  81. EXPECT_EQ(tape.apply(Uniform(0.0, 100.0)), 50.0);
  82. }
  83. TEST(TapeTest, IndexNotIncludedInSerialization) {
  84. engine::random::Tape tape;
  85. tape.apply(Uniform(0, 100), 50);
  86. tape.apply(Uniform(0u, 100u), 50u);
  87. tape.apply(Uniform(0.0, 100.0), 50.0);
  88. EXPECT_EQ(tape.apply(Uniform(0, 100)), 50);
  89. EXPECT_EQ(tape.apply(Uniform(0u, 100u)), 50u);
  90. auto serial = engine::random::Tape::serial_type(tape);
  91. EXPECT_THAT(serial, ElementsAre(FieldsAre("iUniform[0,100]", 50),
  92. FieldsAre("jUniform[0,100]", 50),
  93. FieldsAre("dUniform[0,100)", BytesAre(50))));
  94. tape = engine::random::Tape(serial);
  95. EXPECT_EQ(tape.apply(Uniform(0, 100)), 50);
  96. EXPECT_EQ(tape.apply(Uniform(0u, 100u)), 50u);
  97. EXPECT_EQ(tape.apply(Uniform(0.0, 100.0)), 50.0);
  98. }
  99. TEST(TapeTest, CanAttachToRandom) {
  100. engine::random::Random random;
  101. auto tape = std::make_shared<engine::random::Tape>();
  102. auto scope = random.record(tape);
  103. auto result = random(engine::random::Uniform(0, 100));
  104. EXPECT_EQ(tape->apply(engine::random::Uniform(0, 100)), result);
  105. }
  106. TEST(TapeTest, StopsRecordingOnScopeExit) {
  107. engine::random::Random random;
  108. auto tape = std::make_shared<engine::random::Tape>();
  109. {
  110. auto scope = random.record(tape);
  111. random(engine::random::Uniform(0, 100));
  112. }
  113. random(engine::random::Uniform(0, 100));
  114. EXPECT_NO_THROW(tape->apply(engine::random::Uniform(0, 100)));
  115. EXPECT_THROW(tape->apply(engine::random::Uniform(0, 100)), std::out_of_range);
  116. }