// // dice_test.cxx // dice-td // // Created by Sam Jaffe on 12/17/18. // Copyright © 2018 Sam Jaffe. All rights reserved. // #include #include "xcode_gtest_helper.h" #include "dice-roll/die.h" #include "dice-roll/exception.h" using unsigned_die = std::pair; namespace dice { bool operator==(die const & lhs, die const & rhs) { return lhs.sgn == rhs.sgn && lhs.num == rhs.num && lhs.sides == rhs.sides; } bool operator==(die const & lhs, unsigned_die const & rhs) { return lhs.num == rhs.first && lhs.sides == rhs.second; } } using namespace ::testing; TEST(Parser, ThrowsOnEmptyString) { EXPECT_THROW(dice::from_string(""), dice::unexpected_token); } TEST(Parser, ThrowsOnOpeningArithmetic) { EXPECT_THROW(dice::from_string("+5"), dice::unexpected_token); EXPECT_THROW(dice::from_string("-5"), dice::unexpected_token); EXPECT_THROW(dice::from_string("+1d4"), dice::unexpected_token); EXPECT_THROW(dice::from_string("-1d4"), dice::unexpected_token); } TEST(Parser, Implicit1dN) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("d4")); EXPECT_THAT(capture.num, Eq(1)); EXPECT_THAT(capture.of, SizeIs(1)); EXPECT_THAT(capture.of[0], Eq(unsigned_die(1, 4))); } TEST(Parser, Explicit1dN) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("1d4")); EXPECT_THAT(capture.num, Eq(1)); EXPECT_THAT(capture.of, SizeIs(1)); EXPECT_THAT(capture.of[0], Eq(unsigned_die(1, 4))); } TEST(Parser, CannotImplicitNumberOfSides) { EXPECT_THROW(dice::from_string("1d"), dice::unexpected_token); } TEST(Parser, AllowsMultipleDice) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("1d4+1d6")); EXPECT_THAT(capture.of, SizeIs(2)); EXPECT_THAT(capture.of, ElementsAre(Eq(unsigned_die(1, 4)), Eq(unsigned_die(1, 6)))); } TEST(Parser, CanIncludeConstant) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("1d4+1")); EXPECT_THAT(capture.of, SizeIs(1)); EXPECT_THAT(capture.modifier, SizeIs(1)); EXPECT_THAT(capture.modifier[0].value, 1); } TEST(Parser, ConstantSignIsInSgnMember) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("1d4-1")); EXPECT_THAT(capture.of, SizeIs(1)); EXPECT_THAT(capture.modifier, SizeIs(1)); EXPECT_THAT(capture.modifier[0].value, 1); } TEST(Parser, ThrowsIfUnterminatedArithmatic) { EXPECT_THROW(dice::from_string("1d4+"), dice::unexpected_token); } TEST(Parser, CanProduceMultiRollExpression) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("2{d4}")); EXPECT_THAT(capture.num, Eq(2)); EXPECT_THAT(capture.of, SizeIs(1)); } TEST(Parser, MultiRollWillThrowIfNoEndBrace) { EXPECT_THROW(dice::from_string("2{d4"), dice::unexpected_token); } TEST(Parser, IgnoresWhitespace) { dice::dice capture; EXPECT_NO_THROW(capture = dice::from_string("2 { d 4 + 5 }")); EXPECT_THAT(capture.num, Eq(2)); EXPECT_THAT(capture.of, SizeIs(1)); EXPECT_THAT(capture.modifier, SizeIs(1)); } TEST(Parser, CanParseDC) { EXPECT_NO_THROW(dice::from_string("1d20<10")); EXPECT_NO_THROW(dice::from_string("1d20<=10")); EXPECT_NO_THROW(dice::from_string("1d20>10")); EXPECT_NO_THROW(dice::from_string("1d20>=10")); } TEST(Parser, CanParseDCForMultiroll) { EXPECT_NO_THROW(dice::from_string("2{1d20<10}")); EXPECT_NO_THROW(dice::from_string("2{1d20<=10}")); EXPECT_NO_THROW(dice::from_string("2{1d20>10}")); EXPECT_NO_THROW(dice::from_string("2{1d20>=10}")); } TEST(Parser, MultirollDCMustAppearInsideBrackets) { EXPECT_NO_THROW(dice::from_string("2{1d20}<10")); EXPECT_NO_THROW(dice::from_string("2{1d20}<=10")); EXPECT_NO_THROW(dice::from_string("2{1d20}>10")); EXPECT_NO_THROW(dice::from_string("2{1d20}>=10")); } TEST(Parser, DCIsCaptured) { using test = dice::difficulty_class::test; EXPECT_THAT(dice::from_string("1d20<10").dc.against, 10); EXPECT_THAT(dice::from_string("1d20<10").dc.comp, test::Less); EXPECT_THAT(dice::from_string("1d20<=10").dc.comp, test::LessOrEqual); EXPECT_THAT(dice::from_string("1d20>10").dc.comp, test::Greater); EXPECT_THAT(dice::from_string("1d20>=10").dc.comp, test::GreaterOrEqual); } TEST(DiceIO, StringFormIsExplicit) { std::stringstream ss; ss << dice::from_string("2{2d6-d4+5}"); EXPECT_THAT(ss.str(), Eq("2{2d6-1d4+5}")); } TEST(DiceIO, AllModifiersComeAtTheEnd) { std::stringstream ss; ss << dice::from_string("2d6-4-1d6+5"); EXPECT_THAT(ss.str(), Eq("2d6-1d6-4+5")); } TEST(DiceIO, StringFormDoesNotPreserveWhitespace) { std::stringstream ss; ss << dice::from_string("2 { d 4 + 5 }"); EXPECT_THAT(ss.str(), Eq("2{1d4+5}")); }