detail_test.cxx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include <stdexcept>
  2. #include <type_traits>
  3. #include <gmock/gmock.h>
  4. #include <gtest/gtest.h>
  5. #include <jvalidate/adapters/jsoncpp.h>
  6. #include <jvalidate/detail/anchor.h>
  7. #include <jvalidate/detail/number.h>
  8. #include <jvalidate/detail/pointer.h>
  9. #include <jvalidate/detail/relative_pointer.h>
  10. #include <jvalidate/detail/string.h>
  11. #include <jvalidate/detail/string_adapter.h>
  12. #include <jvalidate/enum.h>
  13. #include "matchers.h"
  14. using namespace jvalidate::detail;
  15. using JsonCppAdapter = jvalidate::adapter::JsonCppAdapter<Json::Value const>;
  16. using jvalidate::adapter::Type;
  17. using testing::Eq;
  18. using testing::Test;
  19. using testing::ThrowsMessage;
  20. using testing::Types;
  21. using testing::VariantWith;
  22. TEST(AnchorTest, PermitsEmpty) { EXPECT_NO_THROW(Anchor("")); }
  23. TEST(AnchorTest, PermitsFirstCharWord) { EXPECT_NO_THROW(Anchor("here")); }
  24. TEST(AnchorTest, PermitsFirstCharUnderscore) { EXPECT_NO_THROW(Anchor("_here")); }
  25. TEST(AnchorTest, ForbidsFirstCharNumber) { EXPECT_THROW(Anchor("0here"), std::runtime_error); }
  26. TEST(AnchorTest, AllowsDotDashAlnum) { EXPECT_NO_THROW(Anchor("here.0-_")); }
  27. TEST(AnchorTest, ForbidsSpecial) { EXPECT_THROW(Anchor("h$"), std::runtime_error); }
  28. TEST(AnchorTest, CanViewString) { EXPECT_THAT(static_cast<std::string>(Anchor("here")), "here"); }
  29. TEST(AnchorTest, Print) { EXPECT_THAT(testing::PrintToString(Anchor("here")), "here"); }
  30. TEST(PointerTest, BackCoercesIntToString) {
  31. EXPECT_THAT("/0"_jptr.back(), "0");
  32. EXPECT_THAT("/A"_jptr.back(), "A");
  33. }
  34. TEST(PointerTest, BackIsEmptySafe) { EXPECT_THAT(""_jptr.back(), ""); }
  35. TEST(PointerTest, ForbidsBadTilde) {
  36. EXPECT_NO_THROW("/~1"_jptr);
  37. EXPECT_THROW("/~2"_jptr, std::runtime_error);
  38. }
  39. TEST(PointerTest, CanConcatenate) { EXPECT_THAT("/A"_jptr / "/B"_jptr, "/A/B"_jptr); }
  40. TEST(PointerTest, CanGoToParent) { EXPECT_THAT("/A/B"_jptr / parent, "/A"_jptr); }
  41. TEST(PointerTest, Print) { EXPECT_THAT(testing::PrintToString(Pointer("/B/0/A")), "/B/0/A"); }
  42. TEST(RelatvivePointerTest, CannotPrefixWithZero) {
  43. EXPECT_THROW(RelativePointer("01"), std::runtime_error);
  44. }
  45. TEST(RelatvivePointerTest, Print) {
  46. EXPECT_THAT(testing::PrintToString(RelativePointer("0")), "0");
  47. EXPECT_THAT(testing::PrintToString(RelativePointer("1#")), "1#");
  48. EXPECT_THAT(testing::PrintToString(RelativePointer("1/B/0/A")), "1/B/0/A");
  49. }
  50. TEST(RelatvivePointerTest, ZeroIsHere) {
  51. Json::Value json;
  52. json["A"] = 1;
  53. RelativePointer const rel("0");
  54. EXPECT_THAT(rel.inspect("/A"_jptr, JsonCppAdapter(json)),
  55. VariantWith<JsonCppAdapter>(JsonCppAdapter(json["A"])))
  56. << rel;
  57. }
  58. TEST(RelatvivePointerTest, CanWalkBackwards) {
  59. Json::Value json;
  60. json["A"] = 1;
  61. RelativePointer const rel("1");
  62. EXPECT_THAT(rel.inspect("/A"_jptr, JsonCppAdapter(json)),
  63. VariantWith<JsonCppAdapter>(JsonCppAdapter(json)))
  64. << rel;
  65. }
  66. TEST(RelatvivePointerTest, CanFetchKey) {
  67. Json::Value json;
  68. json["A"] = 1;
  69. RelativePointer const rel("0#");
  70. EXPECT_THAT(rel.inspect("/A"_jptr, JsonCppAdapter(json)), VariantWith<std::string>(Eq("A")))
  71. << rel;
  72. }
  73. TEST(RelatvivePointerTest, CanGoUpAndDown) {
  74. Json::Value json;
  75. json["A"] = 1;
  76. json["B"] = 2;
  77. RelativePointer const rel("1/B");
  78. EXPECT_THAT(rel.inspect("/A"_jptr, JsonCppAdapter(json)),
  79. VariantWith<JsonCppAdapter>(JsonCppAdapter(json["B"])))
  80. << rel;
  81. }
  82. template <typename T> class NumberFromStrTest : public Test {};
  83. using Integers = Types<char, size_t, int>;
  84. TYPED_TEST_SUITE(NumberFromStrTest, Integers);
  85. TEST(NumberTest, ULLFitsInInteger) {
  86. EXPECT_TRUE(fits_in_integer(9223372036854775807ULL));
  87. EXPECT_FALSE(fits_in_integer(9223372036854775808ULL));
  88. }
  89. TEST(NumberTest, DoubleDoesNotFitInIntegerWhenFractional) { EXPECT_FALSE(fits_in_integer(10.5)); }
  90. TEST(NumberTest, DoubleFitsInIntegerWhenWhole) { EXPECT_TRUE(fits_in_integer(10.0)); }
  91. TEST(NumberTest, DoubleOutOfIntegerRange) {
  92. EXPECT_FALSE(fits_in_integer(10000000000000000000.0));
  93. EXPECT_FALSE(fits_in_integer(-10000000000000000000.0));
  94. }
  95. TYPED_TEST(NumberFromStrTest, NumberParsesIntegers) { EXPECT_THAT(from_str<TypeParam>("10"), 10); }
  96. TYPED_TEST(NumberFromStrTest, NumberParsesNegativeIntegers) {
  97. if constexpr (std::is_signed_v<TypeParam>) {
  98. EXPECT_THAT(from_str<TypeParam>("-10"), -10);
  99. } else {
  100. EXPECT_THAT([] { from_str<TypeParam>("-10"); },
  101. ThrowsMessage<std::runtime_error>("Invalid argument"));
  102. }
  103. }
  104. TYPED_TEST(NumberFromStrTest, ThrowsOnPlusSign) {
  105. EXPECT_THAT([] { from_str<TypeParam>("+10"); },
  106. ThrowsMessage<std::runtime_error>("Invalid argument"));
  107. }
  108. TYPED_TEST(NumberFromStrTest, ThrowsOnTooManyChars) {
  109. EXPECT_THAT([] { from_str<TypeParam>("10 coconuts"); },
  110. ThrowsMessage<std::runtime_error>("NaN: 10 coconuts"));
  111. }
  112. TYPED_TEST(NumberFromStrTest, ThrowsOnOutOfRange) {
  113. EXPECT_THAT([] { from_str<TypeParam>("99999999999999999999999999999"); },
  114. ThrowsMessage<std::runtime_error>("Result too large"));
  115. }
  116. TEST(StringAdapterTest, IsStringy) {
  117. EXPECT_THAT(StringAdapter("").type(), Type::String);
  118. EXPECT_THAT(StringAdapter("lorem ipsum").as_string(), "lorem ipsum");
  119. }
  120. TEST(StringAdapterTest, DiesOnAccess) {
  121. EXPECT_THROW(StringAdapter("").as_boolean(), std::runtime_error);
  122. EXPECT_THROW(StringAdapter("").as_integer(), std::runtime_error);
  123. EXPECT_THROW(StringAdapter("").as_number(), std::runtime_error);
  124. EXPECT_THROW(StringAdapter("").as_array(), std::runtime_error);
  125. EXPECT_THROW(StringAdapter("").array_size(), std::runtime_error);
  126. EXPECT_THROW(StringAdapter("").as_object(), std::runtime_error);
  127. EXPECT_THROW(StringAdapter("").object_size(), std::runtime_error);
  128. }
  129. TEST(StringAdapterTest, DoesNotRunApplyArray) {
  130. StringAdapter("").apply_array([](auto const &) {
  131. ADD_FAILURE();
  132. return jvalidate::Status::Noop;
  133. });
  134. }
  135. TEST(StringAdapterTest, DoesNotRunApplyObject) {
  136. StringAdapter("").apply_object([](auto const &, auto const &) {
  137. ADD_FAILURE();
  138. return jvalidate::Status::Noop;
  139. });
  140. }
  141. TEST(UnsupportedArrayAdapterTest, Empty) {
  142. UnsupportedArrayAdapter<StringAdapter> array;
  143. EXPECT_THAT(array.size(), 0);
  144. EXPECT_THAT(array.begin(), array.end());
  145. }
  146. TEST(UnsupportedArrayAdapterTest, DiesWhenIndexed) {
  147. UnsupportedArrayAdapter<StringAdapter> array;
  148. EXPECT_THROW(array[0], std::runtime_error);
  149. }
  150. TEST(UnsupportedObjectAdapterTest, Empty) {
  151. UnsupportedObjectAdapter<StringAdapter> object;
  152. EXPECT_THAT(object.size(), 0);
  153. EXPECT_THAT(object.begin(), object.end());
  154. }
  155. TEST(UnsupportedObjectAdapterTest, DiesWhenIndexed) {
  156. UnsupportedObjectAdapter<StringAdapter> object;
  157. EXPECT_FALSE(object.contains(""));
  158. EXPECT_THROW(object[""], std::runtime_error);
  159. }
  160. #if JVALIDATE_HAS_ICU
  161. TEST(StringLengthTest, MultiCharLength) {
  162. // Dragon Emoji from non-bmp-regex test case
  163. EXPECT_THAT(length("\xF0\x9F\x90\xB2"), 1);
  164. }
  165. #endif
  166. #if !defined(JVALIDATE_MONOTEST)
  167. int main(int argc, char ** argv) {
  168. testing::InitGoogleMock(&argc, argv);
  169. return RUN_ALL_TESTS();
  170. }
  171. #endif