// // tape_test.cpp // shared_random_generator-test // // Created by Sam Jaffe on 3/19/23. // Copyright © 2023 Sam Jaffe. All rights reserved. // #include "random/tape.h" #include #include #include "random/random.h" #include "xcode_gtest_helper.h" using testing::ElementsAre; using testing::FieldsAre; MATCHER_P(BytesAre, value, "") { *result_listener << "whose bytes are " << std::hex << arg; return reinterpret_cast(arg) == value; } TEST(TapeTest, CanRecordIntData) { engine::random::Tape tape; tape.inclusive(0u, 100u, 50u); EXPECT_EQ(tape.inclusive(0u, 100u), 50); } TEST(TapeTest, CanRecordDoubleData) { engine::random::Tape tape; tape.exclusive(0.0, 100.0, 50.0); EXPECT_EQ(tape.exclusive(0.0, 100.0), 50.0); tape.exclusive(0.0, 100.0, 50.0); EXPECT_EQ(tape.exclusive(0.0, 100.0), 50.0); } TEST(TapeTest, ThrowsOnOverFetch) { engine::random::Tape tape; tape.inclusive(0, 100, 50); EXPECT_EQ(tape.inclusive(0, 100), 50); EXPECT_THROW(tape.inclusive(0, 100), std::out_of_range); } TEST(TapeTest, BadRequestIsNoOp) { engine::random::Tape tape; tape.inclusive(0, 100, 50); EXPECT_ANY_THROW(tape.inclusive(0, 1)); EXPECT_EQ(tape.inclusive(0, 100), 50); } TEST(TapeTest, ThrowsOnTypeMismatch) { engine::random::Tape tape; tape.inclusive(0u, 100u, 50u); EXPECT_THROW(tape.exclusive(0.0, 100.0), std::domain_error); EXPECT_THROW(tape.inclusive(0, 100), std::domain_error); EXPECT_NO_THROW(tape.inclusive(0u, 100u)); } TEST(TapeTest, ThrowsOnBoundsMismatch) { engine::random::Tape tape; tape.exclusive(0.0, 100.0, 50.0); EXPECT_THROW(tape.exclusive(0.0, 1.0), std::logic_error); } TEST(TapeTest, IsOrdered) { engine::random::Tape tape; tape.exclusive(0.0, 100.0, 50.0); tape.exclusive(10.0, 90.0, 50.0); EXPECT_THROW(tape.exclusive(10.0, 90.0), std::logic_error); EXPECT_EQ(tape.exclusive(0.0, 100.0), 50.0); EXPECT_EQ(tape.exclusive(10.0, 90.0), 50.0); } TEST(TapeTest, IsSerializable) { engine::random::Tape tape; tape.inclusive(0, 100, 50); tape.inclusive(0u, 100u, 50u); tape.exclusive(0.0, 100.0, 50.0); auto serial = engine::random::Tape::serial_type(tape); EXPECT_THAT( serial, ElementsAre(FieldsAre("i", 0, 100, 50), FieldsAre("j", 0, 100, 50), FieldsAre("d", BytesAre(0), BytesAre(100), BytesAre(50)))); tape = engine::random::Tape(serial); EXPECT_EQ(tape.inclusive(0, 100), 50); EXPECT_EQ(tape.inclusive(0u, 100u), 50u); EXPECT_EQ(tape.exclusive(0.0, 100.0), 50.0); } TEST(TapeTest, IndexNotIncludedInSerialization) { engine::random::Tape tape; tape.inclusive(0, 100, 50); tape.inclusive(0u, 100u, 50u); tape.exclusive(0.0, 100.0, 50.0); EXPECT_EQ(tape.inclusive(0, 100), 50); EXPECT_EQ(tape.inclusive(0u, 100u), 50u); auto serial = engine::random::Tape::serial_type(tape); EXPECT_THAT( serial, ElementsAre(FieldsAre("i", 0, 100, 50), FieldsAre("j", 0, 100, 50), FieldsAre("d", BytesAre(0), BytesAre(100), BytesAre(50)))); tape = engine::random::Tape(serial); EXPECT_EQ(tape.inclusive(0, 100), 50); EXPECT_EQ(tape.inclusive(0u, 100u), 50u); EXPECT_EQ(tape.exclusive(0.0, 100.0), 50.0); } TEST(TapeTest, CanAttachToRandom) { engine::random::Random random; auto tape = std::make_shared(); auto scope = random.record(tape); auto result = random.inclusive(0, 100); EXPECT_EQ(tape->inclusive(0, 100), result); } TEST(TapeTest, StopsRecordingOnScopeExit) { engine::random::Random random; auto tape = std::make_shared(); { auto scope = random.record(tape); random.inclusive(0, 100); } random.inclusive(0, 100); EXPECT_NO_THROW(tape->inclusive(0, 100)); EXPECT_THROW(tape->inclusive(0, 100), std::out_of_range); }