fix coverage, unit test allocators and equality

This commit is contained in:
Steve Hanson 2021-06-09 10:31:09 +01:00
parent 18ab3b16bc
commit 3df804c128
5 changed files with 579 additions and 544 deletions

View File

@ -530,7 +530,9 @@ public:
// For use with JSON pointers into JSON schema documents. // For use with JSON pointers into JSON schema documents.
/*! /*!
\param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root. \param root Root value of a DOM sub-tree to be resolved. It can be any value other than document root.
\param rootUri Root URI
\param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token. \param unresolvedTokenIndex If the pointer cannot resolve a token in the pointer, this parameter can obtain the index of unresolved token.
\param allocator Allocator for Uris
\return Uri if it can be resolved. Otherwise null. \return Uri if it can be resolved. Otherwise null.
\note \note
@ -541,10 +543,10 @@ public:
Use unresolvedTokenIndex to retrieve the token index. Use unresolvedTokenIndex to retrieve the token index.
*/ */
UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0) const { UriType GetUri(ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
static const Ch kIdString[] = { 'i', 'd', '\0' }; static const Ch kIdString[] = { 'i', 'd', '\0' };
static const ValueType kIdValue(kIdString, 2); static const ValueType kIdValue(kIdString, 2);
UriType base = rootUri; UriType base = UriType(rootUri, allocator);
RAPIDJSON_ASSERT(IsValid()); RAPIDJSON_ASSERT(IsValid());
ValueType* v = &root; ValueType* v = &root;
for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) { for (const Token *t = tokens_; t != tokens_ + tokenCount_; ++t) {
@ -554,7 +556,7 @@ public:
// See if we have an id, and if so resolve with the current base // See if we have an id, and if so resolve with the current base
typename ValueType::MemberIterator m = v->FindMember(kIdValue); typename ValueType::MemberIterator m = v->FindMember(kIdValue);
if (m != v->MemberEnd() && (m->value).IsString()) { if (m != v->MemberEnd() && (m->value).IsString()) {
UriType here = UriType(m->value, allocator_).Resolve(base, allocator_); UriType here = UriType(m->value, allocator).Resolve(base, allocator);
base = here; base = here;
} }
m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length))); m = v->FindMember(GenericValue<EncodingType>(GenericStringRef<Ch>(t->name, t->length)));
@ -575,13 +577,13 @@ public:
// Error: unresolved token // Error: unresolved token
if (unresolvedTokenIndex) if (unresolvedTokenIndex)
*unresolvedTokenIndex = static_cast<size_t>(t - tokens_); *unresolvedTokenIndex = static_cast<size_t>(t - tokens_);
return UriType(allocator_); return UriType(allocator);
} }
return base; return base;
} }
UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0) const { UriType GetUri(const ValueType& root, const UriType& rootUri, size_t* unresolvedTokenIndex = 0, Allocator* allocator = 0) const {
return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex); return GetUri(const_cast<ValueType&>(root), rootUri, unresolvedTokenIndex, allocator);
} }

View File

@ -1741,7 +1741,7 @@ private:
// Changed by PR #1393 // Changed by PR #1393
void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) { void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) {
if (v.GetType() == kObjectType) { if (v.GetType() == kObjectType) {
UriType newid = CreateSchema(schema, pointer, v, document, id); UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_);
for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr) for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid); CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid);
@ -1790,7 +1790,7 @@ private:
SizeType len = itr->value.GetStringLength(); SizeType len = itr->value.GetStringLength();
if (len > 0) { if (len > 0) {
// First resolve $ref against the in-scope id // First resolve $ref against the in-scope id
UriType scopeId = id; UriType scopeId = UriType(id, allocator_);
UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_); UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_);
// See if the resolved $ref minus the fragment matches a resolved id in this document // See if the resolved $ref minus the fragment matches a resolved id in this document
// Search from the root. Returns the subschema in the document and its absolute JSON pointer. // Search from the root. Returns the subschema in the document and its absolute JSON pointer.
@ -1838,7 +1838,8 @@ private:
if (pointer.IsValid() && !IsCyclicRef(pointer)) { if (pointer.IsValid() && !IsCyclicRef(pointer)) {
// Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
// TODO: cache pointer <-> id mapping // TODO: cache pointer <-> id mapping
scopeId = pointer.GetUri(document, docId_); size_t unresolvedTokenIndex;
scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
CreateSchema(schema, pointer, *pv, document, scopeId); CreateSchema(schema, pointer, *pv, document, scopeId);
return true; return true;
} }
@ -1855,7 +1856,8 @@ private:
//pointer.StringifyUriFragment(sb); //pointer.StringifyUriFragment(sb);
// Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
// TODO: cache pointer <-> id mapping // TODO: cache pointer <-> id mapping
scopeId = pointer.GetUri(document, docId_); size_t unresolvedTokenIndex;
scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
CreateSchema(schema, pointer, *pv, document, scopeId); CreateSchema(schema, pointer, *pv, document, scopeId);
return true; return true;
} }
@ -1879,8 +1881,8 @@ private:
ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const { ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const {
SizeType i = 0; SizeType i = 0;
ValueType* resval = 0; ValueType* resval = 0;
UriType tempuri = finduri; UriType tempuri = UriType(finduri, allocator_);
UriType localuri = baseuri; UriType localuri = UriType(baseuri, allocator_);
if (doc.GetType() == kObjectType) { if (doc.GetType() == kObjectType) {
// Establish the base URI of this object // Establish the base URI of this object
typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString()); typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString());

View File

@ -659,6 +659,7 @@ static const char kJsonIds[] = "{\n"
TEST(Pointer, GetUri) { TEST(Pointer, GetUri) {
CrtAllocator allocator;
Document d; Document d;
d.Parse(kJsonIds); d.Parse(kJsonIds);
Pointer::UriType doc("http://doc"); Pointer::UriType doc("http://doc");
@ -677,15 +678,16 @@ TEST(Pointer, GetUri) {
EXPECT_TRUE(Pointer("/jbo").GetUri(d, doc) == root); EXPECT_TRUE(Pointer("/jbo").GetUri(d, doc) == root);
EXPECT_TRUE(Pointer("/jbo/child").GetUri(d, doc) == root); // id not string EXPECT_TRUE(Pointer("/jbo/child").GetUri(d, doc) == root); // id not string
EXPECT_TRUE(Pointer("/abc").GetUri(d, doc) == empty); // Out of boundary
size_t unresolvedTokenIndex; size_t unresolvedTokenIndex;
EXPECT_TRUE(Pointer("/foo/3").GetUri(d, doc, &unresolvedTokenIndex) == empty); // Out of boundary EXPECT_TRUE(Pointer("/abc").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
EXPECT_EQ(0u, unresolvedTokenIndex);
EXPECT_TRUE(Pointer("/foo/3").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // Out of boundary
EXPECT_EQ(1u, unresolvedTokenIndex); EXPECT_EQ(1u, unresolvedTokenIndex);
EXPECT_TRUE(Pointer("/foo/a").GetUri(d, doc, &unresolvedTokenIndex) == empty); // "/foo" is an array, cannot query by "a" EXPECT_TRUE(Pointer("/foo/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo" is an array, cannot query by "a"
EXPECT_EQ(1u, unresolvedTokenIndex); EXPECT_EQ(1u, unresolvedTokenIndex);
EXPECT_TRUE(Pointer("/foo/0/0").GetUri(d, doc, &unresolvedTokenIndex) == empty); // "/foo/0" is an string, cannot further query EXPECT_TRUE(Pointer("/foo/0/0").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
EXPECT_EQ(2u, unresolvedTokenIndex); EXPECT_EQ(2u, unresolvedTokenIndex);
EXPECT_TRUE(Pointer("/foo/0/a").GetUri(d, doc, &unresolvedTokenIndex) == empty); // "/foo/0" is an string, cannot further query EXPECT_TRUE(Pointer("/foo/0/a").GetUri(d, doc, &unresolvedTokenIndex, &allocator) == empty); // "/foo/0" is an string, cannot further query
EXPECT_EQ(2u, unresolvedTokenIndex); EXPECT_EQ(2u, unresolvedTokenIndex);
Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } }; Pointer::Token tokens[] = { { "foo ...", 3, kPointerInvalidIndex } };

View File

@ -619,6 +619,35 @@ res = ref.Resolve(base);
EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s/../x") == 0); EXPECT_TRUE(StrCmp(res.GetString(), L"http://a/b/c/g#s/../x") == 0);
} }
TEST(Uri, Equals) {
typedef GenericUri<Value> UriType;
UriType a = UriType("http://a/a#a");
UriType b = UriType("http://a/a#b");
UriType c = a;
EXPECT_TRUE(a == a);
EXPECT_TRUE(a == c);
EXPECT_TRUE(a != b);
}
TEST(Uri, Match) {
typedef GenericUri<Value> UriType;
UriType a = UriType("http://a/a#a");
UriType b = UriType("http://a/a#b");
UriType c = a;
UriType d;
EXPECT_TRUE(a.Match(a));
EXPECT_TRUE(a.Match(c));
EXPECT_FALSE(a.Match(b));
EXPECT_FALSE(a.Match(b, true));
EXPECT_TRUE(a.Match(b, false)); // Base Uri same
EXPECT_FALSE(a.Match(d));
EXPECT_FALSE(d.Match(a));
}
#if defined(_MSC_VER) || defined(__clang__) #if defined(_MSC_VER) || defined(__clang__)
RAPIDJSON_DIAG_POP RAPIDJSON_DIAG_POP
#endif #endif