DCCL v4
test.cpp
1 // Copyright 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 <thread>
26 
27 #include "../../arithmetic/field_codec_arithmetic.h"
28 #include "../../codec.h"
29 #include "test.pb.h"
30 #include "test_arithmetic.pb.h"
31 
32 using namespace dccl::test;
33 
34 void arithmetic_run_test(dccl::Codec& codec, dccl::arith::protobuf::ArithmeticModel& model,
35  const google::protobuf::Message& msg_in, bool set_model = true)
36 {
37  if (set_model)
38  {
39  model.set_name("model");
40  dccl::arith::ModelManager::set_model(codec, model);
41  }
42 
43  codec.load(msg_in.GetDescriptor());
44  codec.info(msg_in.GetDescriptor());
45 
46  // std::cout << "Message in:\n" << msg_in.DebugString() << std::endl;
47 
48  // std::cout << "Try encode..." << std::endl;
49  std::string bytes;
50  codec.encode(&bytes, msg_in);
51  // std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes) << std::endl;
52 
53  // std::cout << "Try decode..." << std::endl;
54 
55  std::shared_ptr<google::protobuf::Message> msg_out(msg_in.New());
56  codec.decode(bytes, msg_out.get());
57 
58  // std::cout << "... got Message out:\n" << msg_out->DebugString() << std::endl;
59 
60  assert(msg_in.SerializeAsString() == msg_out->SerializeAsString());
61 }
62 
63 void decode_check(dccl::Codec& codec, const std::string& encoded, TestMsg msg_in);
64 void run(int thread, int num_iterations);
65 int main(int /*argc*/, char* /*argv*/ [])
66 {
67  {
68  std::thread t1([]() { run(1, 100); });
69  std::thread t2([]() { run(2, 100); });
70  std::thread t3([]() { run(3, 100); });
71  std::thread t4([]() { run(4, 100); });
72  std::thread t5([]() { run(5, 100); });
73  std::thread t6([]() { run(6, 100); });
74  std::thread t7([]() { run(7, 100); });
75  std::thread t8([]() { run(8, 100); });
76  std::thread t9([]() { run(9, 100); });
77  std::thread t10([]() { run(10, 100); });
78  t1.join();
79  t2.join();
80  t3.join();
81  t4.join();
82  t5.join();
83  t6.join();
84  t7.join();
85  t8.join();
86  t9.join();
87  t10.join();
88  }
89 
90  dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
91  {
92  std::thread t1([]() { run(1, 10); });
93  std::thread t2([]() { run(2, 10); });
94  std::thread t3([]() { run(3, 10); });
95  std::thread t4([]() { run(4, 10); });
96  std::thread t5([]() { run(5, 10); });
97  std::thread t6([]() { run(6, 10); });
98  std::thread t7([]() { run(7, 10); });
99  std::thread t8([]() { run(8, 10); });
100  std::thread t9([]() { run(9, 10); });
101  std::thread t10([]() { run(10, 10); });
102  t1.join();
103  t2.join();
104  t3.join();
105  t4.join();
106  t5.join();
107  t6.join();
108  t7.join();
109  t8.join();
110  t9.join();
111  t10.join();
112  }
113 
114  std::cout << "all tests passed" << std::endl;
115 }
116 
117 void run(int thread, int num_iterations)
118 {
119  dccl::Codec codec;
120  codec.load_library(DCCL_ARITHMETIC_NAME);
121  codec.load<TestMsg>();
122  for (int m = 0; m < num_iterations; ++m)
123  {
124  std::cout << "Thread " << thread << ", it: " << m << std::endl;
125  codec.info<TestMsg>();
126  TestMsg msg_in;
127  int i = 0;
128  msg_in.set_double_default_optional(++i + 0.1);
129  msg_in.set_float_default_optional(++i + 0.2);
130 
131  msg_in.set_int32_default_optional(++i);
132  msg_in.set_int64_default_optional(-++i);
133  msg_in.set_uint32_default_optional(++i);
134  msg_in.set_uint64_default_optional(++i);
135  msg_in.set_sint32_default_optional(-++i);
136  msg_in.set_sint64_default_optional(++i);
137  msg_in.set_fixed32_default_optional(++i);
138  msg_in.set_fixed64_default_optional(++i);
139  msg_in.set_sfixed32_default_optional(++i);
140  msg_in.set_sfixed64_default_optional(-++i);
141 
142  msg_in.set_bool_default_optional(true);
143 
144  msg_in.set_string_default_optional("abc123");
145  msg_in.set_bytes_default_optional(dccl::hex_decode("00112233aabbcc1234"));
146 
147  msg_in.set_enum_default_optional(ENUM_C);
148  msg_in.mutable_msg_default_optional()->set_val(++i + 0.3);
149  msg_in.mutable_msg_default_optional()->mutable_msg()->set_val(++i);
150 
151  msg_in.set_double_default_required(++i + 0.1);
152  msg_in.set_float_default_required(++i + 0.2);
153 
154  msg_in.set_int32_default_required(++i);
155  msg_in.set_int64_default_required(-++i);
156  msg_in.set_uint32_default_required(++i);
157  msg_in.set_uint64_default_required(++i);
158  msg_in.set_sint32_default_required(-++i);
159  msg_in.set_sint64_default_required(++i);
160  msg_in.set_fixed32_default_required(++i);
161  msg_in.set_fixed64_default_required(++i);
162  msg_in.set_sfixed32_default_required(++i);
163  msg_in.set_sfixed64_default_required(-++i);
164 
165  msg_in.set_bool_default_required(true);
166 
167  msg_in.set_string_default_required("abc123");
168  msg_in.set_bytes_default_required(dccl::hex_decode("00112233aabbcc1234"));
169 
170  msg_in.set_enum_default_required(ENUM_C);
171  msg_in.mutable_msg_default_required()->set_val(++i + 0.3);
172  msg_in.mutable_msg_default_required()->mutable_msg()->set_val(++i);
173 
174  for (int j = 0; j < 2; ++j)
175  {
176  msg_in.add_double_default_repeat(++i + 0.1);
177  msg_in.add_float_default_repeat(++i + 0.2);
178 
179  msg_in.add_int32_default_repeat(++i);
180  msg_in.add_int64_default_repeat(-++i);
181  msg_in.add_uint32_default_repeat(++i);
182  msg_in.add_uint64_default_repeat(++i);
183  msg_in.add_sint32_default_repeat(-++i);
184  msg_in.add_sint64_default_repeat(++i);
185  msg_in.add_fixed32_default_repeat(++i);
186  msg_in.add_fixed64_default_repeat(++i);
187  msg_in.add_sfixed32_default_repeat(++i);
188  msg_in.add_sfixed64_default_repeat(-++i);
189 
190  msg_in.add_bool_default_repeat(true);
191 
192  msg_in.add_string_default_repeat("abc123");
193 
194  if (j)
195  msg_in.add_bytes_default_repeat(dccl::hex_decode("00aabbcc"));
196  else
197  msg_in.add_bytes_default_repeat(dccl::hex_decode("ffeedd12"));
198 
199  msg_in.add_enum_default_repeat(static_cast<Enum1>((++i % 3) + 1));
200  EmbeddedMsg1* em_msg = msg_in.add_msg_default_repeat();
201  em_msg->set_val(++i + 0.3);
202  em_msg->mutable_msg()->set_val(++i);
203  }
204 
205  std::string bytes;
206  codec.encode(&bytes, msg_in);
207 
208  decode_check(codec, bytes, msg_in);
209 
210  // test case from Practical Implementations of Arithmetic Coding by Paul G. Howard and Je rey Scott Vitter
211  {
213 
214  model.set_eof_frequency(4); // "a"
215 
216  model.add_value_bound(0);
217  model.add_frequency(5); // "b"
218 
219  model.add_value_bound(1);
220  model.add_frequency(1); // "EOF"
221 
222  model.add_value_bound(2);
223 
224  model.set_out_of_range_frequency(0);
225 
226  dccl::test::arith::ArithmeticDoubleTestMsg msg_in;
227 
228  msg_in.add_value(0); // b
229  msg_in.add_value(0); // b
230  msg_in.add_value(0); // b
231  msg_in.add_value(1); // "EOF"
232 
233  arithmetic_run_test(codec, model, msg_in);
234  }
235  }
236 }
237 
238 void decode_check(dccl::Codec& codec, const std::string& encoded, TestMsg msg_in)
239 {
240  TestMsg msg_out;
241  codec.decode(encoded, &msg_out);
242 
243  // std::cout << "... got Message out:\n" << msg_out.DebugString() << std::endl;
244 
245  // truncate to "max_length" as codec should do
246  msg_in.set_string_default_repeat(0, "abc1");
247  msg_in.set_string_default_repeat(1, "abc1");
248 
249  assert(msg_in.SerializeAsString() == msg_out.SerializeAsString());
250 }
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::arith::protobuf::ArithmeticModel
Definition: arithmetic.pb.h:73
Message
dccl::hex_decode
void hex_decode(const std::string &in, std::string *out)
Decodes a (little-endian) hexadecimal string to a byte string. Index 0 and 1 (first byte) of in are w...
Definition: binary.h:51