xref: /6.0.3/subjson/tests/t_path.cc (revision 5a685f44)
1/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3*     Copyright 2015 Couchbase, Inc
4*
5*   Licensed under the Apache License, Version 2.0 (the "License");
6*   you may not use this file except in compliance with the License.
7*   You may obtain a copy of the License at
8*
9*       http://www.apache.org/licenses/LICENSE-2.0
10*
11*   Unless required by applicable law or agreed to in writing, software
12*   distributed under the License is distributed on an "AS IS" BASIS,
13*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*   See the License for the specific language governing permissions and
15*   limitations under the License.
16*/
17#include "subdoc-tests-common.h"
18
19using std::string;
20using std::cerr;
21using std::endl;
22using Subdoc::Path;
23
24class PathTests : public ::testing::Test {};
25
26static void
27getComponentString(const Path& nj, int ix, string& out) {
28    const auto& comp = nj.get_component(ix);
29    out.assign(comp.pstr, comp.len);
30}
31static string
32getComponentString(const Path& nj, int ix) {
33    string tmp;
34    getComponentString(nj, ix, tmp);
35    return tmp;
36}
37static unsigned long
38getComponentNumber(const Path& nj, int ix) {
39    return nj.get_component(ix).idx;
40}
41
42TEST_F(PathTests, testBasic)
43{
44    Path ss;
45
46    string pth1("foo.bar.baz");
47    ASSERT_EQ(0, ss.parse(pth1));
48    ASSERT_EQ(4, ss.size());
49
50    ASSERT_EQ(JSONSL_PATH_ROOT, ss[0].ptype);
51    ASSERT_EQ(JSONSL_PATH_STRING, ss[1].ptype);
52    ASSERT_EQ(JSONSL_PATH_STRING, ss[2].ptype);
53    ASSERT_EQ(JSONSL_PATH_STRING, ss[3].ptype);
54
55
56    ASSERT_EQ("foo", getComponentString(ss, 1));
57    ASSERT_EQ("bar", getComponentString(ss, 2));
58    ASSERT_EQ("baz", getComponentString(ss, 3));
59
60    ss.clear();
61    pth1 = "....";
62    ASSERT_NE(0, ss.parse(pth1));
63}
64
65TEST_F(PathTests, testNumericIndices) {
66    Path ss;
67    string pth = "array[1].item[9]";
68
69    ASSERT_EQ(0, ss.parse(pth));
70    ASSERT_EQ(5, ss.size());
71
72    ASSERT_EQ(JSONSL_PATH_STRING, ss[1].ptype);
73    ASSERT_EQ("array", getComponentString(ss, 1));
74
75    ASSERT_EQ(JSONSL_PATH_NUMERIC, ss[2].ptype);
76    ASSERT_EQ(1, getComponentNumber(ss, 2));
77
78    ASSERT_EQ(JSONSL_PATH_STRING, ss[3].ptype);
79    ASSERT_EQ("item", getComponentString(ss, 3));
80
81    ASSERT_EQ(JSONSL_PATH_NUMERIC, ss[4].ptype);
82    ASSERT_EQ(9, getComponentNumber(ss, 4));
83
84    // Try again, using [] syntax
85    pth = "foo[0][0][0]";
86    ASSERT_EQ(0, ss.parse(pth));
87    ASSERT_EQ(5, ss.size());
88
89    pth = "[1][2][3]";
90    ASSERT_EQ(0, ss.parse(pth));
91    ASSERT_EQ(4, ss.size());
92}
93
94TEST_F(PathTests, testEscapes)
95{
96    Path ss;
97    string pth;
98
99    pth = "`simple`.`escaped`.`path`";
100    ASSERT_EQ(0, ss.parse(pth));
101    ASSERT_EQ("simple", getComponentString(ss, 1));
102    ASSERT_EQ("escaped", getComponentString(ss, 2));
103    ASSERT_EQ("path", getComponentString(ss, 3));
104
105    // Try something more complex
106    ss.clear();
107    pth = "escaped.`arr.idx`[9]";
108    ASSERT_EQ(0, ss.parse(pth));
109    ASSERT_EQ("escaped", getComponentString(ss, 1));
110    ASSERT_EQ("arr.idx", getComponentString(ss, 2));
111    ASSERT_EQ(9, getComponentNumber(ss, 3));
112
113    ss.clear();
114    pth = "`BACKTICK``HAPPY`.`CAMPER`";
115    ASSERT_EQ(0, ss.parse(pth));
116    ASSERT_EQ("BACKTICK`HAPPY", getComponentString(ss, 1));
117    ASSERT_EQ("CAMPER", getComponentString(ss, 2));
118}
119
120TEST_F(PathTests, testNegativePath) {
121    Path ss;
122    string pth;
123
124    pth = "foo[-1][-1][-1]";
125    ASSERT_EQ(0, ss.parse(pth));
126    ASSERT_EQ(5, ss.size());
127    ASSERT_TRUE(!!ss.components_s[2].is_neg);
128    ASSERT_TRUE(!!ss.components_s[3].is_neg);
129    ASSERT_TRUE(!!ss.components_s[4].is_neg);
130    ASSERT_TRUE(!!ss.has_negix);
131
132    ss.clear();
133    pth = "foo[-2]";
134    ASSERT_NE(0, ss.parse(pth));
135}
136
137TEST_F(PathTests, testInvalidSequence) {
138    Path ss;
139    string pth;
140
141    #if 0 /* TODO */
142    pth = "[1].[2].[3]";
143    ASSERT_NE(0, ss.parse(pth));
144    #endif
145
146    pth = "hello[0]world";
147    ASSERT_NE(0, ss.parse(pth));
148
149    pth = "[not][a][number]";
150    ASSERT_NE(0, ss.parse(pth));
151}
152
153TEST_F(PathTests, testJsonEscapes) {
154    Path ss;
155    string pth;
156
157    // Reject any path not considered valid as a JSON string. N1QL escapes
158    // are *only* for n1ql syntax tokens (like ., ], [, `)
159    pth = "\"invalid.path";
160    ASSERT_NE(0, ss.parse(pth));
161
162    pth = "\\" "\"quoted.path";
163    ASSERT_EQ(0, ss.parse(pth));
164}
165