1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc. All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7
8
9 #include <cstdint>
10 #include <string>
11
12 #include <gtest/gtest.h>
13 #include "google/protobuf/compiler/objectivec/tf_decode_data.h"
14
15 // Must be included last
16 #include "google/protobuf/port_def.inc"
17
18 namespace google {
19 namespace protobuf {
20 namespace compiler {
21 namespace objectivec {
22
23 namespace {
24
TEST(ObjCHelper,TextFormatDecodeData_DecodeDataForString_RawStrings)25 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
26 std::string input_for_decode("abcdefghIJ");
27 std::string desired_output_for_decode;
28 std::string expected;
29 std::string result;
30
31 // Different data, can't transform.
32
33 desired_output_for_decode = "zbcdefghIJ";
34 expected = std::string("\0zbcdefghIJ\0", 12);
35 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
36 desired_output_for_decode);
37 EXPECT_EQ(expected, result);
38
39 desired_output_for_decode = "abcdezghIJ";
40 expected = std::string("\0abcdezghIJ\0", 12);
41 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
42 desired_output_for_decode);
43 EXPECT_EQ(expected, result);
44
45 // Shortened data, can't transform.
46
47 desired_output_for_decode = "abcdefghI";
48 expected = std::string("\0abcdefghI\0", 11);
49 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
50 desired_output_for_decode);
51 EXPECT_EQ(expected, result);
52
53 // Extra data, can't transform.
54
55 desired_output_for_decode = "abcdefghIJz";
56 expected = std::string("\0abcdefghIJz\0", 13);
57 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
58 desired_output_for_decode);
59 EXPECT_EQ(expected, result);
60 }
61
TEST(ObjCHelper,TextFormatDecodeData_DecodeDataForString_ByteCodes)62 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
63 std::string input_for_decode("abcdefghIJ");
64 std::string desired_output_for_decode;
65 std::string expected;
66 std::string result;
67
68 desired_output_for_decode = "abcdefghIJ";
69 expected = std::string("\x0A\x0", 2);
70 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
71 desired_output_for_decode);
72 EXPECT_EQ(expected, result);
73
74 desired_output_for_decode = "_AbcdefghIJ";
75 expected = std::string("\xCA\x0", 2);
76 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
77 desired_output_for_decode);
78 EXPECT_EQ(expected, result);
79
80 desired_output_for_decode = "ABCD__EfghI_j";
81 expected = std::string("\x64\x80\xC5\xA1\x0", 5);
82 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
83 desired_output_for_decode);
84 EXPECT_EQ(expected, result);
85
86 // Long name so multiple decode ops are needed.
87
88 input_for_decode =
89 "longFieldNameIsLoooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
90 "ooooooooooooooooong1000";
91 desired_output_for_decode =
92 "long_field_name_is_"
93 "looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
94 "oong_1000";
95 expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
96 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
97 desired_output_for_decode);
98 EXPECT_EQ(expected, result);
99 }
100
101 // Death tests do not work on Windows as of yet.
102 #if GTEST_HAS_DEATH_TEST
TEST(ObjCHelperDeathTest,TextFormatDecodeData_DecodeDataForString_Failures)103 TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
104 // Empty inputs.
105
106 EXPECT_DEATH(TextFormatDecodeData::DecodeDataForString("", ""),
107 "error: got empty string for making TextFormat data, input:");
108 EXPECT_DEATH(TextFormatDecodeData::DecodeDataForString("a", ""),
109 "error: got empty string for making TextFormat data, input:");
110 EXPECT_DEATH(TextFormatDecodeData::DecodeDataForString("", "a"),
111 "error: got empty string for making TextFormat data, input:");
112
113 // Null char in the string.
114
115 std::string str_with_null_char("ab\0c", 4);
116 EXPECT_DEATH(
117 TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
118 "error: got a null char in a string for making TextFormat data, input:");
119 EXPECT_DEATH(
120 TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
121 "error: got a null char in a string for making TextFormat data, input:");
122 }
123 #endif // PROTOBUF_HAS_DEATH_TEST
124
TEST(ObjCHelper,TextFormatDecodeData_RawStrings)125 TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
126 TextFormatDecodeData decode_data;
127
128 // Different data, can't transform.
129 decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
130 decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
131 // Shortened data, can't transform.
132 decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
133 // Extra data, can't transform.
134 decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
135
136 EXPECT_EQ(4, decode_data.num_entries());
137
138 uint8_t expected_data[] = {
139 // clang-format off
140 0x4,
141 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
142 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
143 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
144 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
145 // clang-format on
146 };
147 std::string expected((const char*)expected_data, sizeof(expected_data));
148
149 EXPECT_EQ(expected, decode_data.Data());
150 }
151
TEST(ObjCHelper,TextFormatDecodeData_ByteCodes)152 TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
153 TextFormatDecodeData decode_data;
154
155 decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
156 decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
157 decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
158 decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
159 decode_data.AddString(1000,
160 "longFieldNameIsLoooooooooooooooooooooooooooooooooooooo"
161 "ooooooooooooooooooooooooooooooooooong1000",
162 "long_field_name_is_"
163 "looooooooooooooooooooooooooooooooooooooooooooooooooooo"
164 "oooooooooooooooooooong_1000");
165
166 EXPECT_EQ(5, decode_data.num_entries());
167
168 // clang-format off
169 uint8_t expected_data[] = {
170 0x5,
171 // All as is (00 op)
172 0x1, 0x0A, 0x0,
173 // Underscore, upper + 9 (10 op)
174 0x3, 0xCA, 0x0,
175 // Upper + 3 (10 op), underscore, upper + 5 (10 op)
176 0x2, 0x44, 0xC6, 0x0,
177 // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
178 // underscore, lower + 0 (01 op)
179 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
180 // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
181 // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
182 // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
183 // op),
184 // underscore, as is + 3 (00 op)
185 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
186 };
187 // clang-format on
188 std::string expected((const char*)expected_data, sizeof(expected_data));
189
190 EXPECT_EQ(expected, decode_data.Data());
191 }
192
193 #if GTEST_HAS_DEATH_TEST
TEST(ObjCHelperDeathTest,TextFormatDecodeData_Failures)194 TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
195 TextFormatDecodeData decode_data;
196
197 // Empty inputs.
198
199 EXPECT_DEATH(decode_data.AddString(1, "", ""),
200 "error: got empty string for making TextFormat data, input:");
201 EXPECT_DEATH(decode_data.AddString(1, "a", ""),
202 "error: got empty string for making TextFormat data, input:");
203 EXPECT_DEATH(decode_data.AddString(1, "", "a"),
204 "error: got empty string for making TextFormat data, input:");
205
206 // Null char in the string.
207
208 std::string str_with_null_char("ab\0c", 4);
209 EXPECT_DEATH(
210 decode_data.AddString(1, str_with_null_char, "def"),
211 "error: got a null char in a string for making TextFormat data, input:");
212 EXPECT_DEATH(
213 decode_data.AddString(1, "def", str_with_null_char),
214 "error: got a null char in a string for making TextFormat data, input:");
215
216 // Duplicate keys
217
218 decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
219 decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
220 decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
221 EXPECT_DEATH(decode_data.AddString(2, "xyz", "x_yz"),
222 "error: duplicate key \\(2\\) making TextFormat data, input:");
223 }
224 #endif // PROTOBUF_HAS_DEATH_TEST
225
226 } // namespace
227
228 } // namespace objectivec
229 } // namespace compiler
230 } // namespace protobuf
231 } // namespace google
232
233 #include "google/protobuf/port_undef.inc"
234