27#include "../../codec.h"
41static void test_issue149()
46 codec.load<Issue149V4Msg>();
47 codec.set_strict(
true);
49 bool v4_threw =
false;
56 codec.encode(&encoded, msg_in);
63 assert(v4_threw &&
"issue #149: v4 codec must throw OutOfRangeException for value == max");
64 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"issue #149: v4 encoding of max boundary value threw OutOfRangeException as expected" << std::endl;
66 codec.set_strict(
false);
69 codec.load<Issue149V5Msg>();
70 codec.set_strict(
true);
73 const float test_val = 0.05f;
74 const float resolution = 0.01f;
77 msg_in.set_a(test_val);
80 codec.encode(&encoded, msg_in);
82 Issue149V5Msg msg_out;
83 codec.decode(encoded, &msg_out);
85 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"issue #149: v5 encoding of max boundary value succeeded, decoded = "
86 << msg_out.a() << std::endl;
87 assert(std::abs(msg_out.a() - test_val) <= resolution / 2 &&
88 "issue #149: v5 decoded value too far from input for max boundary");
92int main(
int argc,
char* argv[])
95 for (
int i = 1; i < argc; ++i)
97 if (argv[i] && argv[i][0] ==
'-' && argv[i][1] ==
'v' && argv[i][2] ==
'\0')
101 dccl::dlog.
connect(verbose ? dccl::logger::ALL :
dccl::logger::WARN_PLUS, &std::cerr);
106 codec.load<FloatMsg>();
107 codec.info<FloatMsg>(&dccl::dlog);
110 const auto *field_ptr = FloatMsg::GetDescriptor()->FindFieldByName(
"f");
112 const auto &field = *field_ptr;
114 const auto &opts = field.options();
115 const auto &dccl_ext = opts.GetExtension(dccl::field);
117 auto res = std::numeric_limits<double>::quiet_NaN();
118 if (dccl_ext.has_precision()) {
119 res = std::pow(10.0, -dccl_ext.precision());
121 res = dccl_ext.resolution();
124 const auto tol = res/2;
125 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Tolerance for DCCL float = " << res <<
" / 2 = " << tol << std::endl;
127 const auto test_cases = std::array<float, 3>{{0.000001f, 0.010001f, 1.000001f}};
128 for (
const auto test_case : test_cases) {
129 auto msg_in = FloatMsg{};
130 msg_in.set_f(test_case);
132 auto encoded = std::string{};
133 codec.encode(&encoded, msg_in);
135 auto msg_out = FloatMsg{};
136 codec.decode(encoded, &msg_out);
138 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if encoded value " << msg_out.f() <<
" is close enough to " << test_case <<
"..." << std::endl;
139 assert(std::abs(test_case - msg_out.f()) < tol);
144 codec.load<NegativePrecisionFloatMsg>();
145 codec.info<NegativePrecisionFloatMsg>(&dccl::dlog);
148 const auto *field_ptr = NegativePrecisionFloatMsg::GetDescriptor()->FindFieldByName(
"f");
150 const auto &field = *field_ptr;
152 const auto &opts = field.options();
153 const auto &dccl_ext = opts.GetExtension(dccl::field);
155 auto res = std::numeric_limits<double>::quiet_NaN();
156 if (dccl_ext.has_precision()) {
157 res = std::pow(10.0, -dccl_ext.precision());
159 res = dccl_ext.resolution();
162 const auto tol = res/2;
163 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Tolerance for DCCL float = " << res <<
" / 2 = " << tol << std::endl;
165 const auto test_cases = std::array<float, 3>{{10.f, -10.f, 1.f}};
166 for (
const auto test_case : test_cases) {
167 auto msg_in = NegativePrecisionFloatMsg{};
168 msg_in.set_f(test_case);
170 auto encoded = std::string{};
171 codec.encode(&encoded, msg_in);
173 auto msg_out = NegativePrecisionFloatMsg{};
174 codec.decode(encoded, &msg_out);
176 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if encoded value " << msg_out.f() <<
" is close enough to " << test_case <<
"..." << std::endl;
177 assert(std::abs(test_case - msg_out.f()) < tol);
182 codec.load<PrecisionRangeFloatMsg>();
183 codec.info<PrecisionRangeFloatMsg>(&dccl::dlog);
186 auto resolutions = std::vector<double>{};
187 resolutions.resize(7);
188 for (
auto field_idx = 0ul; field_idx < 7; ++field_idx) {
189 const auto field_name =
"prec" + std::to_string(field_idx);
190 const auto *field_ptr = PrecisionRangeFloatMsg::GetDescriptor()->FindFieldByName(field_name);
192 const auto &field = *field_ptr;
194 const auto &opts = field.options();
195 const auto &dccl_ext = opts.GetExtension(dccl::field);
197 if (dccl_ext.has_precision()) {
198 resolutions[field_idx] = std::pow(10.0, -dccl_ext.precision());
200 resolutions[field_idx] = dccl_ext.resolution();
203 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Tolerance for DCCL float number " << field_idx <<
" is " << resolutions[field_idx] <<
" / 2 = " << resolutions[field_idx]/2 << std::endl;
206 for (
auto i = -100; i < 101; ++i) {
212 const auto test_val = 1000000+i;
213 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Testing encoding of " << test_val <<
" on a range of precisions..." << std::endl;
214 auto msg_in = PrecisionRangeFloatMsg{};
215 msg_in.set_prec0(test_val * resolutions[0]);
216 msg_in.set_prec1(test_val * resolutions[1]);
217 msg_in.set_prec2(test_val * resolutions[2]);
218 msg_in.set_prec3(test_val * resolutions[3]);
219 msg_in.set_prec4(test_val * resolutions[4]);
220 msg_in.set_prec5(test_val * resolutions[5]);
221 msg_in.set_prec6(test_val * resolutions[6]);
223 auto encoded = std::string{};
224 codec.encode(&encoded, msg_in);
226 auto msg_out = PrecisionRangeFloatMsg{};
227 codec.decode(encoded, &msg_out);
229 const auto diff0 = std::abs(msg_out.prec0() - msg_in.prec0());
230 const auto diff1 = std::abs(msg_out.prec1() - msg_in.prec1());
231 const auto diff2 = std::abs(msg_out.prec2() - msg_in.prec2());
232 const auto diff3 = std::abs(msg_out.prec3() - msg_in.prec3());
233 const auto diff4 = std::abs(msg_out.prec4() - msg_in.prec4());
234 const auto diff5 = std::abs(msg_out.prec5() - msg_in.prec5());
235 const auto diff6 = std::abs(msg_out.prec6() - msg_in.prec6());
236 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec0() <<
" is close enough to " << msg_in.prec0() <<
"...";
237 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff0 <<
"<=" << resolutions[0]/2 << std::endl;
238 assert(diff0 <= resolutions[0]/2);
239 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec1() <<
" is close enough to " << msg_in.prec1() <<
"...";
240 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff1 <<
"<=" << resolutions[1]/2 << std::endl;
241 assert(diff1 <= resolutions[1]/2);
242 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec2() <<
" is close enough to " << msg_in.prec2() <<
"...";
243 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff2 <<
"<=" << resolutions[2]/2 << std::endl;
244 assert(diff2 <= resolutions[2]/2);
245 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec3() <<
" is close enough to " << msg_in.prec3() <<
"...";
246 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff3 <<
"<=" << resolutions[3]/2 << std::endl;
247 assert(diff3 <= resolutions[3]/2);
248 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec4() <<
" is close enough to " << msg_in.prec4() <<
"...";
249 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff4 <<
"<=" << resolutions[4]/2 << std::endl;
250 assert(diff4 <= resolutions[4]/2);
251 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec5() <<
" is close enough to " << msg_in.prec5() <<
"...";
252 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff5 <<
"<=" << resolutions[5]/2 << std::endl;
253 assert(diff5 <= resolutions[5]/2);
254 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"Checking if " << msg_out.prec6() <<
" is close enough to " << msg_in.prec6() <<
"...";
255 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
" i.e. Difference " << diff6 <<
"<=" << resolutions[6]/2 << std::endl;
256 assert(diff6 <= resolutions[6]/2);
262 dccl::dlog.
is(dccl::logger::INFO) && dccl::dlog <<
"all tests passed" << std::endl;
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
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...
void connect(int verbosity_mask, Slot slot)
Connect the output of one or more given verbosities to a slot (function pointer or similar)
Dynamic Compact Control Language namespace.