DCCL v4
test.cpp
1 // Copyright 2019-2023:
2 // GobySoft, LLC (2013-)
3 // Community contributors (see AUTHORS file)
4 // File authors:
5 // Toby Schneider <toby@gobysoft.org>
6 //
7 //
8 // This file is part of the Dynamic Compact Control Language Library
9 // ("DCCL").
10 //
11 // DCCL is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU Lesser General Public License as published by
13 // the Free Software Foundation, either version 2.1 of the License, or
14 // (at your option) any later version.
15 //
16 // DCCL is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public License
22 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
23 // tests all protobuf types with _default codecs, repeat and non repeat
24 
25 #include <fstream>
26 
27 #include <google/protobuf/descriptor.pb.h>
28 
29 #include "../../binary.h"
30 #include "../../codec.h"
31 #include "test.pb.h"
32 using namespace dccl::test;
33 
34 void decode_check(const TestMsg& msg_in);
35 dccl::Codec codec;
36 
37 int main(int /*argc*/, char* /*argv*/ [])
38 {
39  dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
40 
41  codec.info<TestMsg>();
42  codec.load<TestMsg>();
43 
44  // enable strict mode
45  codec.set_strict(true);
46 
47  {
48  TestMsg msg_in;
49  msg_in.set_d(10.0);
50  msg_in.set_i(1000);
51  msg_in.set_s("foo");
52  msg_in.set_b(std::string(9, '1'));
53  msg_in.add_ri(1);
54  msg_in.add_ri(2);
55  msg_in.add_ri(3);
56 
57  decode_check(msg_in);
58  }
59 
60  // double out of range
61  try
62  {
63  TestMsg msg_in;
64  msg_in.set_d(150);
65  msg_in.set_i(1000);
66  msg_in.set_s("foo");
67  msg_in.set_b(std::string(9, '1'));
68 
69  decode_check(msg_in);
70  bool expected_out_of_range_exception = false;
71  assert(expected_out_of_range_exception);
72  }
73  catch (dccl::OutOfRangeException& e)
74  {
75  assert(e.field() == TestMsg::descriptor()->FindFieldByName("d"));
76  std::cout << "Caught (as expected) " << e.what() << std::endl;
77  }
78 
79  // int out of range
80  try
81  {
82  TestMsg msg_in;
83  msg_in.set_d(10.0);
84  msg_in.set_i(-30);
85  msg_in.set_s("foo");
86  msg_in.set_b(std::string(9, '1'));
87 
88  decode_check(msg_in);
89  bool expected_out_of_range_exception = false;
90  assert(expected_out_of_range_exception);
91  }
92  catch (dccl::OutOfRangeException& e)
93  {
94  assert(e.field() == TestMsg::descriptor()->FindFieldByName("i"));
95  std::cout << "Caught (as expected) " << e.what() << std::endl;
96  }
97 
98  // string (version 2) out of range
99  try
100  {
101  TestMsg msg_in;
102  msg_in.set_d(10.0);
103  msg_in.set_i(1000);
104  msg_in.set_s2("foobar1234546789");
105  msg_in.set_b(std::string(9, '1'));
106 
107  decode_check(msg_in);
108  bool expected_out_of_range_exception = false;
109  assert(expected_out_of_range_exception);
110  }
111  catch (dccl::OutOfRangeException& e)
112  {
113  assert(e.field() == TestMsg::descriptor()->FindFieldByName("s2"));
114  std::cout << "Caught (as expected) " << e.what() << std::endl;
115  }
116 
117  // string (version 3) out of range
118  try
119  {
120  TestMsg msg_in;
121  msg_in.set_d(10.0);
122  msg_in.set_i(1000);
123  msg_in.set_s("foobar1234546789");
124  msg_in.set_b(std::string(9, '1'));
125 
126  decode_check(msg_in);
127  bool expected_out_of_range_exception = false;
128  assert(expected_out_of_range_exception);
129  }
130  catch (dccl::OutOfRangeException& e)
131  {
132  assert(e.field() == TestMsg::descriptor()->FindFieldByName("s"));
133  std::cout << "Caught (as expected) " << e.what() << std::endl;
134  }
135 
136  // bytes out of range
137  try
138  {
139  TestMsg msg_in;
140  msg_in.set_d(10.0);
141  msg_in.set_i(1000);
142  msg_in.set_s("foo");
143  msg_in.set_b(std::string(12, '1'));
144 
145  decode_check(msg_in);
146  bool expected_out_of_range_exception = false;
147  assert(expected_out_of_range_exception);
148  }
149  catch (dccl::OutOfRangeException& e)
150  {
151  assert(e.field() == TestMsg::descriptor()->FindFieldByName("b"));
152  std::cout << "Caught (as expected) " << e.what() << std::endl;
153  }
154 
155  // var bytes out of range
156  try
157  {
158  TestMsg msg_in;
159  msg_in.set_d(10.0);
160  msg_in.set_i(1000);
161  msg_in.set_s("foo");
162  msg_in.set_vb(std::string(12, '1'));
163 
164  decode_check(msg_in);
165  bool expected_out_of_range_exception = false;
166  assert(expected_out_of_range_exception);
167  }
168  catch (dccl::OutOfRangeException& e)
169  {
170  assert(e.field() == TestMsg::descriptor()->FindFieldByName("vb"));
171  std::cout << "Caught (as expected) " << e.what() << std::endl;
172  }
173 
174  // repeat size out of range
175  try
176  {
177  TestMsg msg_in;
178  msg_in.set_d(10.0);
179  msg_in.set_i(1000);
180  msg_in.set_s("foo");
181  msg_in.set_b(std::string(9, '1'));
182  msg_in.add_ri(1);
183  msg_in.add_ri(2);
184  msg_in.add_ri(3);
185  msg_in.add_ri(4);
186 
187  decode_check(msg_in);
188  }
189  catch (dccl::OutOfRangeException& e)
190  {
191  assert(e.field() == TestMsg::descriptor()->FindFieldByName("ri"));
192  std::cout << "Caught (as expected) " << e.what() << std::endl;
193  }
194 
195  // disable strict mode
196  codec.set_strict(false);
197 
198  {
199  TestMsg msg_in;
200  msg_in.set_d(10.0);
201  msg_in.set_i(1000);
202  msg_in.set_s("foo");
203  msg_in.set_b(std::string(9, '1'));
204  msg_in.add_ri(1);
205  msg_in.add_ri(2);
206  msg_in.add_ri(3);
207 
208  decode_check(msg_in);
209  }
210 
211  // double out of range
212  {
213  TestMsg msg_in;
214  msg_in.set_d(150);
215  msg_in.set_i(1000);
216  msg_in.set_s("foo");
217  msg_in.set_b(std::string(9, '1'));
218 
219  decode_check(msg_in);
220  }
221 
222  // int out of range
223  {
224  TestMsg msg_in;
225  msg_in.set_d(10.0);
226  msg_in.set_i(-30);
227  msg_in.set_s("foo");
228  msg_in.set_b(std::string(9, '1'));
229 
230  decode_check(msg_in);
231  }
232 
233  // string (version 2) out of range
234  {
235  TestMsg msg_in;
236  msg_in.set_d(10.0);
237  msg_in.set_i(1000);
238  msg_in.set_s2("foobar1234546789");
239  msg_in.set_b(std::string(9, '1'));
240 
241  decode_check(msg_in);
242  }
243 
244  // string (version 3) out of range
245  {
246  TestMsg msg_in;
247  msg_in.set_d(10.0);
248  msg_in.set_i(1000);
249  msg_in.set_s("foobar1234546789");
250  msg_in.set_b(std::string(9, '1'));
251 
252  decode_check(msg_in);
253  }
254 
255  // bytes out of range
256  {
257  TestMsg msg_in;
258  msg_in.set_d(10.0);
259  msg_in.set_i(1000);
260  msg_in.set_s("foo");
261  msg_in.set_b(std::string(12, '1'));
262 
263  decode_check(msg_in);
264  }
265 
266  // var bytes out of range
267  {
268  TestMsg msg_in;
269  msg_in.set_d(10.0);
270  msg_in.set_i(1000);
271  msg_in.set_s("foo");
272  msg_in.set_vb(std::string(12, '1'));
273 
274  decode_check(msg_in);
275  }
276 
277  // repeat size out of range
278  {
279  TestMsg msg_in;
280  msg_in.set_d(10.0);
281  msg_in.set_i(1000);
282  msg_in.set_s("foo");
283  msg_in.set_b(std::string(9, '1'));
284  msg_in.add_ri(1);
285  msg_in.add_ri(2);
286  msg_in.add_ri(3);
287  msg_in.add_ri(4);
288 
289  decode_check(msg_in);
290  }
291 
292  std::cout << "all tests passed" << std::endl;
293 }
294 
295 void decode_check(const TestMsg& msg_in)
296 {
297  std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
298 
299  std::cout << "Try encode (in bounds)..." << std::endl;
300  std::string bytes;
301  codec.encode(&bytes, msg_in);
302  std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
303 
304  std::cout << "Try decode..." << std::endl;
305 
306  TestMsg msg_out;
307  codec.decode(bytes, &msg_out);
308 
309  std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl;
310 }
dccl::test
Unit test namespace.
Definition: test.cpp:44
dccl::Codec
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition: codec.h:62
dccl::Logger::connect
void connect(int verbosity_mask, Slot slot)
Connect the output of one or more given verbosities to a slot (function pointer or similar)
Definition: logger.h:214
dccl::hex_encode
void hex_encode(CharIterator begin, CharIterator end, std::string *out, bool upper_case=false)
Encodes a (little-endian) hexadecimal string from a byte string. Index 0 of begin is written to index...
Definition: binary.h:100
dccl::OutOfRangeException
Definition: exception.h:67