| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- // Copyright (C) 2011 Milo Yip
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- #include "unittest.h"
- #include "rapidjson/pointer.h"
- #include "rapidjson/stringbuffer.h"
- #include <sstream>
- using namespace rapidjson;
- static const char kJson[] = "{\n"
- " \"foo\":[\"bar\", \"baz\"],\n"
- " \"\" : 0,\n"
- " \"a/b\" : 1,\n"
- " \"c%d\" : 2,\n"
- " \"e^f\" : 3,\n"
- " \"g|h\" : 4,\n"
- " \"i\\\\j\" : 5,\n"
- " \"k\\\"l\" : 6,\n"
- " \" \" : 7,\n"
- " \"m~n\" : 8\n"
- "}";
- TEST(Pointer, Parse) {
- {
- Pointer p("");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(0, p.GetTokenCount());
- }
- {
- Pointer p("/foo");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_EQ(3, p.GetTokens()[0].length);
- EXPECT_STREQ("foo", p.GetTokens()[0].name);
- }
- {
- Pointer p("/foo/0");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(2, p.GetTokenCount());
- EXPECT_EQ(3, p.GetTokens()[0].length);
- EXPECT_STREQ("foo", p.GetTokens()[0].name);
- EXPECT_EQ(1, p.GetTokens()[1].length);
- EXPECT_STREQ("0", p.GetTokens()[1].name);
- EXPECT_EQ(0, p.GetTokens()[1].index);
- }
- {
- // Unescape ~1
- Pointer p("/a~1b");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_EQ(3, p.GetTokens()[0].length);
- EXPECT_STREQ("a/b", p.GetTokens()[0].name);
- }
- {
- // Unescape ~0
- Pointer p("/m~0n");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_EQ(3, p.GetTokens()[0].length);
- EXPECT_STREQ("m~n", p.GetTokens()[0].name);
- }
- {
- // empty name
- Pointer p("/");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_EQ(0, p.GetTokens()[0].length);
- EXPECT_STREQ("", p.GetTokens()[0].name);
- }
- {
- // empty and non-empty name
- Pointer p("//a");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(2, p.GetTokenCount());
- EXPECT_EQ(0, p.GetTokens()[0].length);
- EXPECT_STREQ("", p.GetTokens()[0].name);
- EXPECT_EQ(1, p.GetTokens()[1].length);
- EXPECT_STREQ("a", p.GetTokens()[1].name);
- }
- {
- // Null characters
- Pointer p("/\0\0", 3);
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_EQ(2, p.GetTokens()[0].length);
- EXPECT_EQ('\0', p.GetTokens()[0].name[0]);
- EXPECT_EQ('\0', p.GetTokens()[0].name[1]);
- EXPECT_EQ('\0', p.GetTokens()[0].name[2]);
- }
- {
- // Valid index
- Pointer p("/123");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_STREQ("123", p.GetTokens()[0].name);
- EXPECT_EQ(123, p.GetTokens()[0].index);
- }
- {
- // Invalid index (with leading zero)
- Pointer p("/01");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_STREQ("01", p.GetTokens()[0].name);
- EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index);
- }
- if (sizeof(SizeType) == 4) {
- // Invalid index (overflow)
- Pointer p("/4294967296");
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(1, p.GetTokenCount());
- EXPECT_STREQ("4294967296", p.GetTokens()[0].name);
- EXPECT_EQ(Pointer::kInvalidIndex, p.GetTokens()[0].index);
- }
- }
- TEST(Pointer, Stringify) {
- // Test by roundtrip
- const char* sources[] = {
- "",
- "/foo",
- "/foo/0",
- "/",
- "/a~1b",
- "/c%d",
- "/e^f",
- "/g|h",
- "/i\\j",
- "/k\"l",
- "/ ",
- "/m~0n"
- };
- for (size_t i = 0; i < sizeof(sources) / sizeof(sources[0]); i++) {
- Pointer p(sources[i]);
- StringBuffer s;
- p.Stringify(s);
- EXPECT_STREQ(sources[i], s.GetString());
- }
- }
- // Construct a Pointer with static tokens, no dynamic allocation involved.
- #define NAME(s) { s, sizeof(s) / sizeof(s[0]) - 1, Pointer::kInvalidIndex }
- #define INDEX(i) { #i, sizeof(#i) - 1, i }
- static const Pointer::Token kTokens[] = { NAME("foo"), INDEX(0) }; // equivalent to "/foo/0"
- #undef NAME
- #undef INDEX
- TEST(Pointer, ConstructorWithToken) {
- Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
- EXPECT_TRUE(p.IsValid());
- EXPECT_EQ(2, p.GetTokenCount());
- EXPECT_EQ(3, p.GetTokens()[0].length);
- EXPECT_STREQ("foo", p.GetTokens()[0].name);
- EXPECT_EQ(1, p.GetTokens()[1].length);
- EXPECT_STREQ("0", p.GetTokens()[1].name);
- EXPECT_EQ(0, p.GetTokens()[1].index);
- }
- TEST(Pointer, CopyConstructor) {
- {
- Pointer p("/foo/0");
- Pointer q(p);
- EXPECT_TRUE(q.IsValid());
- EXPECT_EQ(2, q.GetTokenCount());
- EXPECT_EQ(3, q.GetTokens()[0].length);
- EXPECT_STREQ("foo", q.GetTokens()[0].name);
- EXPECT_EQ(1, q.GetTokens()[1].length);
- EXPECT_STREQ("0", q.GetTokens()[1].name);
- EXPECT_EQ(0, q.GetTokens()[1].index);
- }
- // Static tokens
- {
- Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
- Pointer q(p);
- EXPECT_TRUE(q.IsValid());
- EXPECT_EQ(2, q.GetTokenCount());
- EXPECT_EQ(3, q.GetTokens()[0].length);
- EXPECT_STREQ("foo", q.GetTokens()[0].name);
- EXPECT_EQ(1, q.GetTokens()[1].length);
- EXPECT_STREQ("0", q.GetTokens()[1].name);
- EXPECT_EQ(0, q.GetTokens()[1].index);
- }
- }
- TEST(Pointer, Assignment) {
- {
- Pointer p("/foo/0");
- Pointer q;
- q = p;
- EXPECT_TRUE(q.IsValid());
- EXPECT_EQ(2, q.GetTokenCount());
- EXPECT_EQ(3, q.GetTokens()[0].length);
- EXPECT_STREQ("foo", q.GetTokens()[0].name);
- EXPECT_EQ(1, q.GetTokens()[1].length);
- EXPECT_STREQ("0", q.GetTokens()[1].name);
- EXPECT_EQ(0, q.GetTokens()[1].index);
- }
- // Static tokens
- {
- Pointer p(kTokens, sizeof(kTokens) / sizeof(kTokens[0]));
- Pointer q;
- q = p;
- EXPECT_TRUE(q.IsValid());
- EXPECT_EQ(2, q.GetTokenCount());
- EXPECT_EQ(3, q.GetTokens()[0].length);
- EXPECT_STREQ("foo", q.GetTokens()[0].name);
- EXPECT_EQ(1, q.GetTokens()[1].length);
- EXPECT_STREQ("0", q.GetTokens()[1].name);
- EXPECT_EQ(0, q.GetTokens()[1].index);
- }
- }
- TEST(Pointer, Create) {
- Document d;
- EXPECT_EQ(&d, &Pointer("").Create(d, d.GetAllocator()));
- EXPECT_EQ(&d["foo"], &Pointer("/foo").Create(d, d.GetAllocator()));
- EXPECT_EQ(&d["foo"][0], &Pointer("/foo/0").Create(d, d.GetAllocator()));
- }
- TEST(Pointer, Get) {
- Document d;
- d.Parse(kJson);
- EXPECT_EQ(&d, Pointer("").Get(d));
- EXPECT_EQ(&d["foo"], Pointer("/foo").Get(d));
- EXPECT_EQ(&d["foo"][0], Pointer("/foo/0").Get(d));
- EXPECT_EQ(&d[""], Pointer("/").Get(d));
- EXPECT_EQ(&d["a/b"], Pointer("/a~1b").Get(d));
- EXPECT_EQ(&d["c%d"], Pointer("/c%d").Get(d));
- EXPECT_EQ(&d["e^f"], Pointer("/e^f").Get(d));
- EXPECT_EQ(&d["g|h"], Pointer("/g|h").Get(d));
- EXPECT_EQ(&d["i\\j"], Pointer("/i\\j").Get(d));
- EXPECT_EQ(&d["k\"l"], Pointer("/k\"l").Get(d));
- EXPECT_EQ(&d[" "], Pointer("/ ").Get(d));
- EXPECT_EQ(&d["m~n"], Pointer("/m~0n").Get(d));
- }
- TEST(Pointer, GetWithDefault) {
- Document d;
- d.Parse(kJson);
- Document::AllocatorType& a = d.GetAllocator();
- const Value v("qux");
- EXPECT_TRUE(Value("bar") == Pointer("/foo/0").GetWithDefault(d, v, a));
- EXPECT_TRUE(Value("baz") == Pointer("/foo/1").GetWithDefault(d, v, a));
- EXPECT_TRUE(Value("qux") == Pointer("/foo/2").GetWithDefault(d, v, a));
- }
- TEST(Pointer, Set) {
- Document d;
- d.Parse(kJson);
- Document::AllocatorType& a = d.GetAllocator();
-
- Pointer("/foo/0").Set(d, Value(123).Move(), a);
- EXPECT_EQ(123, d["foo"][0].GetInt());
- Pointer("/foo/2").Set(d, Value(456).Move(), a);
- EXPECT_EQ(456, d["foo"][2].GetInt());
- }
- TEST(Pointer, Swap) {
- Document d;
- d.Parse(kJson);
- Document::AllocatorType& a = d.GetAllocator();
- Pointer("/foo/0").Swap(d, *Pointer("/foo/1").Get(d), a);
- EXPECT_STREQ("baz", d["foo"][0].GetString());
- EXPECT_STREQ("bar", d["foo"][1].GetString());
- }
|