parser_test.cxx 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // dice_test.cxx
  3. // dice-td
  4. //
  5. // Created by Sam Jaffe on 12/17/18.
  6. // Copyright © 2018 Sam Jaffe. All rights reserved.
  7. //
  8. #include <sstream>
  9. #include "xcode_gtest_helper.h"
  10. #include "dice-roll/die.h"
  11. #include "dice-roll/exception.h"
  12. using unsigned_die = std::pair<int, int>;
  13. namespace dice {
  14. bool operator==(die const & lhs, die const & rhs) {
  15. return lhs.sgn == rhs.sgn && lhs.num == rhs.num && lhs.sides == rhs.sides;
  16. }
  17. bool operator==(die const & lhs, unsigned_die const & rhs) {
  18. return lhs.num == rhs.first && lhs.sides == rhs.second;
  19. }
  20. }
  21. using namespace ::testing;
  22. TEST(ParserTest, ThrowsOnEmptyString) {
  23. EXPECT_THROW(dice::from_string(""), dice::unexpected_token);
  24. }
  25. TEST(ParserTest, ThrowsOnOpeningArithmetic) {
  26. EXPECT_THROW(dice::from_string("+5"), dice::unexpected_token);
  27. EXPECT_THROW(dice::from_string("-5"), dice::unexpected_token);
  28. EXPECT_THROW(dice::from_string("+1d4"), dice::unexpected_token);
  29. EXPECT_THROW(dice::from_string("-1d4"), dice::unexpected_token);
  30. }
  31. TEST(ParserTest, Implicit1dN) {
  32. dice::dice capture;
  33. EXPECT_NO_THROW(capture = dice::from_string("d4"));
  34. EXPECT_THAT(capture.num, Eq(1));
  35. EXPECT_THAT(capture.of, SizeIs(1));
  36. EXPECT_THAT(capture.of[0], Eq(unsigned_die(1, 4)));
  37. }
  38. TEST(ParserTest, Explicit1dN) {
  39. dice::dice capture;
  40. EXPECT_NO_THROW(capture = dice::from_string("1d4"));
  41. EXPECT_THAT(capture.num, Eq(1));
  42. EXPECT_THAT(capture.of, SizeIs(1));
  43. EXPECT_THAT(capture.of[0], Eq(unsigned_die(1, 4)));
  44. }
  45. TEST(ParserTest, CannotImplicitNumberOfSides) {
  46. EXPECT_THROW(dice::from_string("1d"), dice::unexpected_token);
  47. }
  48. TEST(ParserTest, AllowsMultipleDice) {
  49. dice::dice capture;
  50. EXPECT_NO_THROW(capture = dice::from_string("1d4+1d6"));
  51. EXPECT_THAT(capture.of, SizeIs(2));
  52. EXPECT_THAT(capture.of,
  53. ElementsAre(Eq(unsigned_die(1, 4)), Eq(unsigned_die(1, 6))));
  54. }
  55. TEST(ParserTest, CanIncludeConstant) {
  56. dice::dice capture;
  57. EXPECT_NO_THROW(capture = dice::from_string("1d4+1"));
  58. EXPECT_THAT(capture.of, SizeIs(1));
  59. EXPECT_THAT(capture.modifier, SizeIs(1));
  60. EXPECT_THAT(capture.modifier[0].value, 1);
  61. }
  62. TEST(ParserTest, ConstantSignIsInSgnMember) {
  63. dice::dice capture;
  64. EXPECT_NO_THROW(capture = dice::from_string("1d4-1"));
  65. EXPECT_THAT(capture.of, SizeIs(1));
  66. EXPECT_THAT(capture.modifier, SizeIs(1));
  67. EXPECT_THAT(capture.modifier[0].value, 1);
  68. }
  69. TEST(ParserTest, ThrowsIfUnterminatedArithmatic) {
  70. EXPECT_THROW(dice::from_string("1d4+"), dice::unexpected_token);
  71. }
  72. TEST(ParserTest, CanProduceMultiRollExpression) {
  73. dice::dice capture;
  74. EXPECT_NO_THROW(capture = dice::from_string("2{d4}"));
  75. EXPECT_THAT(capture.num, Eq(2));
  76. EXPECT_THAT(capture.of, SizeIs(1));
  77. }
  78. TEST(ParserTest, MultiRollWillThrowIfNoEndBrace) {
  79. EXPECT_THROW(dice::from_string("2{d4"), dice::unexpected_token);
  80. }
  81. TEST(ParserTest, IgnoresWhitespace) {
  82. dice::dice capture;
  83. EXPECT_NO_THROW(capture = dice::from_string("2 { d 4 + 5 }"));
  84. EXPECT_THAT(capture.num, Eq(2));
  85. EXPECT_THAT(capture.of, SizeIs(1));
  86. EXPECT_THAT(capture.modifier, SizeIs(1));
  87. }
  88. TEST(ParserTest, CanParseDC) {
  89. EXPECT_NO_THROW(dice::from_string("1d20<10"));
  90. EXPECT_NO_THROW(dice::from_string("1d20<=10"));
  91. EXPECT_NO_THROW(dice::from_string("1d20>10"));
  92. EXPECT_NO_THROW(dice::from_string("1d20>=10"));
  93. }
  94. TEST(ParserTest, DCCannotBeNegative) {
  95. EXPECT_THROW(dice::from_string("1d20>-1"), dice::unexpected_token);
  96. }
  97. TEST(ParserTest, DCCanBeWhitespacePadded) {
  98. EXPECT_NO_THROW(dice::from_string("1d20 < 10"));
  99. }
  100. TEST(ParserTest, CanParseDCForMultiroll) {
  101. EXPECT_NO_THROW(dice::from_string("2{1d20<10}"));
  102. EXPECT_NO_THROW(dice::from_string("2{1d20<=10}"));
  103. EXPECT_NO_THROW(dice::from_string("2{1d20>10}"));
  104. EXPECT_NO_THROW(dice::from_string("2{1d20>=10}"));
  105. }
  106. TEST(ParserTest, MultirollDCMustAppearInsideBrackets) {
  107. EXPECT_NO_THROW(dice::from_string("2{1d20}<10"));
  108. EXPECT_NO_THROW(dice::from_string("2{1d20}<=10"));
  109. EXPECT_NO_THROW(dice::from_string("2{1d20}>10"));
  110. EXPECT_NO_THROW(dice::from_string("2{1d20}>=10"));
  111. }
  112. TEST(ParserTest, DCIsCaptured) {
  113. using test = dice::difficulty_class::test;
  114. EXPECT_THAT(dice::from_string("1d20<10").dc.against, 10);
  115. EXPECT_THAT(dice::from_string("1d20<10").dc.comp, test::Less);
  116. EXPECT_THAT(dice::from_string("1d20<=10").dc.comp, test::LessOrEqual);
  117. EXPECT_THAT(dice::from_string("1d20>10").dc.comp, test::Greater);
  118. EXPECT_THAT(dice::from_string("1d20>=10").dc.comp, test::GreaterOrEqual);
  119. }