detail_test.cxx 7.5 KB

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