DCCL v5
Loading...
Searching...
No Matches
test.cpp
1// Copyright 2019-2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Kyle Guilbert <kguilbert@aphysci.com>
6// Toby Schneider <toby@gobysoft.org>
7//
8//
9// This file is part of the Dynamic Compact Control Language Library
10// ("DCCL").
11//
12// DCCL is free software: you can redistribute it and/or modify
13// it under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// DCCL is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24// tests required versus optional encoding of fields using a presence bit
25
26#include "../../codec.h"
27#include "test/dccl_presence/test.pb.h"
28using namespace dccl::test;
29
30void test1(dccl::Codec&);
31void test2(dccl::Codec&);
32
33void test3(dccl::Codec& codec);
34
35int main(int argc, char* argv[])
36{
37 bool verbose = false;
38 for (int i = 1; i < argc; ++i)
39 {
40 if (argv[i] && argv[i][0] == '-' && argv[i][1] == 'v' && argv[i][2] == '\0')
41 verbose = true;
42 }
43
44 dccl::dlog.connect(verbose ? dccl::logger::ALL : dccl::logger::WARN_PLUS, &std::cerr);
45
46 dccl::Codec codec;
47 codec.load<PresenceMsg>();
48 codec.info<PresenceMsg>(&dccl::dlog);
49 test1(codec);
50 test2(codec);
51
52 codec.load<PresenceMsgV3>();
53 codec.info<PresenceMsgV3>(&dccl::dlog);
54 test3(codec);
55
56 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << "all tests passed" << std::endl;
57}
58
59// optional fields all left empty
60void test1(dccl::Codec& codec)
61{
62 PresenceMsg msg_in;
63
64 msg_in.set_req_i32(-100);
65 msg_in.set_req_i64(65535);
66 msg_in.set_req_ui32(1022);
67 msg_in.set_req_ui64(101);
68 msg_in.set_req_float(900.12345);
69 msg_in.set_req_double(900.12345678);
70 msg_in.set_req_enum(ENUM2_C);
71
72 std::string encoded;
73 codec.encode(&encoded, msg_in);
74
75 assert(encoded.size() == 17);
76
77 PresenceMsg msg_out;
78 codec.decode(encoded, &msg_out);
79
80 assert(msg_in.req_i32() == msg_out.req_i32());
81 assert(msg_in.req_i64() == msg_out.req_i64());
82 assert(msg_in.req_ui32() == msg_out.req_ui32());
83 assert(msg_in.req_ui64() == msg_out.req_ui64());
84 assert(fabsf(msg_in.req_float() - msg_out.req_float()) < 1e-4);
85 assert(fabs(msg_in.req_double() - msg_out.req_double()) < 1e-7);
86 assert(msg_in.req_enum() == msg_out.req_enum());
87
88 assert(!msg_out.has_opt_i32());
89 assert(!msg_out.has_opt_i64());
90 assert(!msg_out.has_opt_ui32());
91 assert(!msg_out.has_opt_ui64());
92 assert(!msg_out.has_opt_float());
93 assert(!msg_out.has_opt_double());
94 assert(!msg_out.has_opt_enum());
95
96 assert(msg_out.repeat_i32_size() == 0);
97 assert(msg_out.repeat_enum_size() == 0);
98
99 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << "test1 passed" << std::endl;
100}
101
102// all fields populated
103void test2(dccl::Codec& codec)
104{
105 PresenceMsg msg_in;
106
107 msg_in.set_req_i32(500);
108 msg_in.set_req_i64(0);
109 msg_in.set_req_ui32(0);
110 msg_in.set_req_ui64(100);
111 msg_in.set_req_float(-900.12345);
112 msg_in.set_req_double(-900.12345678);
113 msg_in.set_req_enum(ENUM2_A);
114
115 msg_in.set_opt_i32(-100);
116 msg_in.set_opt_i64(65535);
117 msg_in.set_opt_ui32(0);
118 msg_in.set_opt_ui64(1123);
119 msg_in.set_opt_float(-900.12345);
120 msg_in.set_opt_double(900.12345678);
121 msg_in.set_opt_enum(ENUM2_A);
122 msg_in.set_opt_bool(true);
123 msg_in.set_opt_str("ABCDE");
124 msg_in.set_opt_bytes("XY");
125
126 msg_in.add_repeat_i32(500);
127 msg_in.add_repeat_enum(ENUM2_A);
128 msg_in.add_repeat_enum(ENUM2_B);
129 msg_in.add_repeat_enum(ENUM2_C);
130
131 std::string encoded;
132 codec.encode(&encoded, msg_in);
133
134 assert(encoded.size() == 41);
135
136 PresenceMsg msg_out;
137 codec.decode(encoded, &msg_out);
138
139 assert(msg_in.req_i32() == msg_out.req_i32());
140 assert(msg_in.req_i64() == msg_out.req_i64());
141 assert(msg_in.req_ui32() == msg_out.req_ui32());
142 assert(msg_in.req_ui64() == msg_out.req_ui64());
143 assert(fabsf(msg_in.req_float() - msg_out.req_float()) < 1e-4);
144 assert(fabs(msg_in.req_double() - msg_out.req_double()) < 1e-7);
145 assert(msg_in.req_enum() == msg_out.req_enum());
146
147 assert(msg_out.has_opt_i32());
148 assert(msg_out.has_opt_i64());
149 assert(msg_out.has_opt_ui32());
150 assert(msg_out.has_opt_ui64());
151 assert(msg_out.has_opt_float());
152 assert(msg_out.has_opt_double());
153 assert(msg_out.has_opt_enum());
154
155 assert(msg_in.opt_i32() == msg_out.opt_i32());
156 assert(msg_in.opt_i64() == msg_out.opt_i64());
157 assert(msg_in.opt_ui32() == msg_out.opt_ui32());
158 assert(msg_in.opt_ui64() == msg_out.opt_ui64());
159 assert(fabsf(msg_in.opt_float() - msg_out.opt_float()) < 1e-4);
160 assert(fabs(msg_in.opt_double() - msg_out.opt_double()) < 1e-7);
161 assert(msg_in.opt_enum() == msg_out.opt_enum());
162
163 assert(msg_in.repeat_i32_size() == msg_out.repeat_i32_size());
164 assert(std::equal(msg_in.repeat_i32().begin(), msg_in.repeat_i32().end(),
165 msg_out.repeat_i32().begin()));
166 assert(msg_in.repeat_enum_size() == msg_out.repeat_enum_size());
167 assert(std::equal(msg_in.repeat_enum().begin(), msg_in.repeat_enum().end(),
168 msg_out.repeat_enum().begin()));
169
170 dccl::dlog.is(dccl::logger::INFO) && dccl::dlog << "test2 passed" << std::endl;
171}
172
173// Codec version 3 round trip. The v3 presence codec wraps the v2 field codecs,
174// a combination the version 5 cases above never instantiate. Sizes differ
175// between codec versions, so this checks the values survive rather than
176// pinning an encoded length.
177void test3(dccl::Codec& codec)
178{
179 PresenceMsgV3 msg_in;
180
181 msg_in.set_req_i32(-100);
182 msg_in.set_req_i64(65535);
183 msg_in.set_req_ui32(1022);
184 msg_in.set_req_ui64(101);
185 msg_in.set_req_float(900.12345);
186 msg_in.set_req_double(900.12345678);
187 msg_in.set_req_enum(ENUM2_C);
188
189 // once with every optional field absent, once with them all present
190 for (int pass = 0; pass < 2; ++pass)
191 {
192 if (pass == 1)
193 {
194 msg_in.set_opt_i32(-50);
195 msg_in.set_opt_i64(1000);
196 msg_in.set_opt_ui32(500);
197 msg_in.set_opt_ui64(500);
198 msg_in.set_opt_float(-12.5);
199 msg_in.set_opt_double(-12.5);
200 msg_in.set_opt_enum(ENUM2_A);
201 msg_in.set_opt_bool(true);
202 msg_in.set_opt_str("abc");
203 msg_in.set_opt_bytes("\x01\x02");
204 msg_in.add_repeat_i32(1);
205 msg_in.add_repeat_i32(2);
206 msg_in.add_repeat_enum(ENUM2_B);
207 }
208
209 std::string encoded;
210 codec.encode(&encoded, msg_in);
211
212 PresenceMsgV3 msg_out;
213 codec.decode(encoded, &msg_out);
214
215 assert(msg_in.req_i32() == msg_out.req_i32());
216 assert(msg_in.req_i64() == msg_out.req_i64());
217 assert(msg_in.req_ui32() == msg_out.req_ui32());
218 assert(msg_in.req_ui64() == msg_out.req_ui64());
219 assert(fabsf(msg_in.req_float() - msg_out.req_float()) < 1e-4);
220 assert(fabs(msg_in.req_double() - msg_out.req_double()) < 1e-7);
221 assert(msg_in.req_enum() == msg_out.req_enum());
222
223 // absent optionals must stay absent, present ones must survive
224 assert(msg_in.has_opt_i32() == msg_out.has_opt_i32());
225 assert(msg_in.opt_i32() == msg_out.opt_i32());
226 assert(msg_in.opt_i64() == msg_out.opt_i64());
227 assert(msg_in.opt_ui32() == msg_out.opt_ui32());
228 assert(msg_in.opt_ui64() == msg_out.opt_ui64());
229 assert(fabsf(msg_in.opt_float() - msg_out.opt_float()) < 1e-4);
230 assert(fabs(msg_in.opt_double() - msg_out.opt_double()) < 1e-7);
231 assert(msg_in.opt_enum() == msg_out.opt_enum());
232 assert(msg_in.opt_bool() == msg_out.opt_bool());
233 assert(msg_in.opt_str() == msg_out.opt_str());
234 assert(msg_in.opt_bytes() == msg_out.opt_bytes());
235 assert(msg_in.repeat_i32_size() == msg_out.repeat_i32_size());
236 assert(msg_in.repeat_enum_size() == msg_out.repeat_enum_size());
237 }
238}
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition codec.h:61
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Definition logger.h:191
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:213
Unit test namespace.
Definition test.cpp:45
Dynamic Compact Control Language namespace.
Definition any.h:28