1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2014 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 #include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
32 #include <google/protobuf/testing/googletest.h>
33 #include <gtest/gtest.h>
34
35 namespace google {
36 namespace protobuf {
37 namespace compiler {
38 namespace objectivec {
39 namespace {
40
TEST(ObjCHelper,TextFormatDecodeData_DecodeDataForString_RawStrings)41 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
42 string input_for_decode("abcdefghIJ");
43 string desired_output_for_decode;
44 string expected;
45 string result;
46
47 // Different data, can't transform.
48
49 desired_output_for_decode = "zbcdefghIJ";
50 expected = string("\0zbcdefghIJ\0", 12);
51 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
52 desired_output_for_decode);
53 EXPECT_EQ(expected, result);
54
55 desired_output_for_decode = "abcdezghIJ";
56 expected = string("\0abcdezghIJ\0", 12);
57 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
58 desired_output_for_decode);
59 EXPECT_EQ(expected, result);
60
61 // Shortened data, can't transform.
62
63 desired_output_for_decode = "abcdefghI";
64 expected = string("\0abcdefghI\0", 11);
65 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
66 desired_output_for_decode);
67 EXPECT_EQ(expected, result);
68
69 // Extra data, can't transform.
70
71 desired_output_for_decode = "abcdefghIJz";
72 expected = string("\0abcdefghIJz\0", 13);
73 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
74 desired_output_for_decode);
75 EXPECT_EQ(expected, result);
76 }
77
TEST(ObjCHelper,TextFormatDecodeData_DecodeDataForString_ByteCodes)78 TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
79 string input_for_decode("abcdefghIJ");
80 string desired_output_for_decode;
81 string expected;
82 string result;
83
84 desired_output_for_decode = "abcdefghIJ";
85 expected = string("\x0A\x0", 2);
86 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
87 desired_output_for_decode);
88 EXPECT_EQ(expected, result);
89
90 desired_output_for_decode = "_AbcdefghIJ";
91 expected = string("\xCA\x0", 2);
92 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
93 desired_output_for_decode);
94 EXPECT_EQ(expected, result);
95
96 desired_output_for_decode = "ABCD__EfghI_j";
97 expected = string("\x64\x80\xC5\xA1\x0", 5);
98 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
99 desired_output_for_decode);
100 EXPECT_EQ(expected, result);
101
102 // Long name so multiple decode ops are needed.
103
104 input_for_decode =
105 "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
106 desired_output_for_decode =
107 "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
108 expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
109 result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
110 desired_output_for_decode);
111 EXPECT_EQ(expected, result);
112 }
113
114 // Death tests do not work on Windows as of yet.
115 #ifdef PROTOBUF_HAS_DEATH_TEST
TEST(ObjCHelperDeathTest,TextFormatDecodeData_DecodeDataForString_Failures)116 TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
117 // Empty inputs.
118
119 EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""),
120 ::testing::KilledBySignal(SIGABRT),
121 "error: got empty string for making TextFormat data, input:");
122 EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""),
123 ::testing::KilledBySignal(SIGABRT),
124 "error: got empty string for making TextFormat data, input:");
125 EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"),
126 ::testing::KilledBySignal(SIGABRT),
127 "error: got empty string for making TextFormat data, input:");
128
129 // Null char in the string.
130
131 string str_with_null_char("ab\0c", 4);
132 EXPECT_EXIT(
133 TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
134 ::testing::KilledBySignal(SIGABRT),
135 "error: got a null char in a string for making TextFormat data, input:");
136 EXPECT_EXIT(
137 TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
138 ::testing::KilledBySignal(SIGABRT),
139 "error: got a null char in a string for making TextFormat data, input:");
140 }
141 #endif // PROTOBUF_HAS_DEATH_TEST
142
TEST(ObjCHelper,TextFormatDecodeData_RawStrings)143 TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
144 TextFormatDecodeData decode_data;
145
146 // Different data, can't transform.
147 decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
148 decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
149 // Shortened data, can't transform.
150 decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
151 // Extra data, can't transform.
152 decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
153
154 EXPECT_EQ(4, decode_data.num_entries());
155
156 uint8 expected_data[] = {
157 0x4,
158 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
159 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
160 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
161 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
162 };
163 string expected((const char*)expected_data, sizeof(expected_data));
164
165 EXPECT_EQ(expected, decode_data.Data());
166 }
167
TEST(ObjCHelper,TextFormatDecodeData_ByteCodes)168 TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
169 TextFormatDecodeData decode_data;
170
171 decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
172 decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
173 decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
174 decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
175 decode_data.AddString(1000,
176 "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
177 "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
178
179 EXPECT_EQ(5, decode_data.num_entries());
180
181 uint8 expected_data[] = {
182 0x5,
183 // All as is (00 op)
184 0x1, 0x0A, 0x0,
185 // Underscore, upper + 9 (10 op)
186 0x3, 0xCA, 0x0,
187 // Upper + 3 (10 op), underscore, upper + 5 (10 op)
188 0x2, 0x44, 0xC6, 0x0,
189 // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
190 // underscore, lower + 0 (01 op)
191 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
192 // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
193 // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
194 // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
195 // op),
196 // underscore, as is + 3 (00 op)
197 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
198 };
199 string expected((const char*)expected_data, sizeof(expected_data));
200
201 EXPECT_EQ(expected, decode_data.Data());
202 }
203
204
205 // Death tests do not work on Windows as of yet.
206 #ifdef PROTOBUF_HAS_DEATH_TEST
TEST(ObjCHelperDeathTest,TextFormatDecodeData_Failures)207 TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
208 TextFormatDecodeData decode_data;
209
210 // Empty inputs.
211
212 EXPECT_EXIT(decode_data.AddString(1, "", ""),
213 ::testing::KilledBySignal(SIGABRT),
214 "error: got empty string for making TextFormat data, input:");
215 EXPECT_EXIT(decode_data.AddString(1, "a", ""),
216 ::testing::KilledBySignal(SIGABRT),
217 "error: got empty string for making TextFormat data, input:");
218 EXPECT_EXIT(decode_data.AddString(1, "", "a"),
219 ::testing::KilledBySignal(SIGABRT),
220 "error: got empty string for making TextFormat data, input:");
221
222 // Null char in the string.
223
224 string str_with_null_char("ab\0c", 4);
225 EXPECT_EXIT(
226 decode_data.AddString(1, str_with_null_char, "def"),
227 ::testing::KilledBySignal(SIGABRT),
228 "error: got a null char in a string for making TextFormat data, input:");
229 EXPECT_EXIT(
230 decode_data.AddString(1, "def", str_with_null_char),
231 ::testing::KilledBySignal(SIGABRT),
232 "error: got a null char in a string for making TextFormat data, input:");
233
234 // Duplicate keys
235
236 decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
237 decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
238 decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
239 EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"),
240 ::testing::KilledBySignal(SIGABRT),
241 "error: duplicate key \\(2\\) making TextFormat data, input:");
242 }
243 #endif // PROTOBUF_HAS_DEATH_TEST
244
245 // TODO(thomasvl): Should probably add some unittests for all the special cases
246 // of name mangling (class name, field name, enum names). Rather than doing
247 // this with an ObjC test in the objectivec directory, we should be able to
248 // use src/google/protobuf/compiler/importer* (like other tests) to support a
249 // virtual file system to feed in protos, once we have the Descriptor tree, the
250 // tests could use the helper methods for generating names and validate the
251 // right things are happening.
252
253 } // namespace
254 } // namespace objectivec
255 } // namespace compiler
256 } // namespace protobuf
257 } // namespace google
258