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 
18 #include <gtest/gtest.h>
19 #include "subdoc/uescape.h"
20 
21 using std::string;
22 using Subdoc::UescapeConverter;
23 
24 typedef UescapeConverter::Status Status;
25 
26 class UescapeTests : public ::testing::Test {
27 };
28 
TEST_F(UescapeTests, testBasic)29 TEST_F(UescapeTests, testBasic) {
30     string in("nothing here"), out;
31     auto rv = UescapeConverter::convert(in, out);
32     ASSERT_EQ(in, out);
33     ASSERT_TRUE(rv);
34 
35     out.clear();
36     in = "simple\\u0020space";
37     rv = UescapeConverter::convert(in, out);
38     ASSERT_TRUE(rv);
39     ASSERT_EQ(out, "simple space");
40 
41     out.clear();
42     in = "\\u0000NUL";
43     rv = UescapeConverter::convert(in, out);
44     ASSERT_FALSE(rv);
45     ASSERT_EQ(Status::EMBEDDED_NUL, rv.code());
46 }
47 
TEST_F(UescapeTests, testSurrogates)48 TEST_F(UescapeTests, testSurrogates) {
49     // http://www.fileformat.info/info/unicode/char/1d11e/index.htm
50     string in("Clef\\uD834\\uDD1E"), out;
51     // The way it's encoded in UTF8
52     string exp("Clef\xf0\x9d\x84\x9e");
53 
54     auto rv = UescapeConverter::convert(in, out);
55     ASSERT_TRUE(rv);
56     ASSERT_EQ(exp, out);
57 
58     out.clear();
59     in = "Clef\\uD834";
60     rv = UescapeConverter::convert(in, out);
61     ASSERT_FALSE(rv);
62     ASSERT_EQ(Status::INCOMPLETE_SURROGATE, rv.code());
63 
64     in = "Clef\\uD834\\u0020";
65     out.clear();
66     rv = UescapeConverter::convert(in, out);
67     ASSERT_FALSE(rv);
68     ASSERT_EQ(Status::INVALID_SURROGATE, rv.code());
69 }
70 
TEST_F(UescapeTests, testInvalidHex)71 TEST_F(UescapeTests, testInvalidHex) {
72     string in("\\uTTTT"), out;
73     auto rv = UescapeConverter::convert(in, out);
74     ASSERT_FALSE(rv);
75     ASSERT_EQ(Status::INVALID_HEXCHARS, rv.code());
76 
77     for (size_t ii = 1; ii < 4; ++ii) {
78         in = "\\u";
79         for (size_t jj = 0; jj < ii; jj++) {
80             in += '3';
81         }
82         rv = UescapeConverter::convert(in, out);
83         ASSERT_FALSE(rv) << "Fails with uescape of " << ii << " length";
84         ASSERT_EQ(Status::INVALID_HEXCHARS, rv.code());
85     }
86 }
87