DCCL v4
Loading...
Searching...
No Matches
test.cpp
1// Copyright 2011-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7// Chris Murphy <cmurphy@aphysci.com>
8//
9//
10// This file is part of the Dynamic Compact Control Language Library
11// ("DCCL").
12//
13// DCCL is free software: you can redistribute it and/or modify
14// it under the terms of the GNU Lesser General Public License as published by
15// the Free Software Foundation, either version 2.1 of the License, or
16// (at your option) any later version.
17//
18// DCCL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU Lesser General Public License for more details.
22//
23// You should have received a copy of the GNU Lesser General Public License
24// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25// tests custom message codec
26// tests cryptography
27
28#include "../../codec.h"
29#include "test.pb.h"
30
31#include "../../binary.h"
32using namespace dccl::test;
33
34using dccl::operator<<;
35using dccl::Bitset;
36
37namespace dccl
38{
40namespace test
41{
42class CustomCodec : public dccl::TypedFixedFieldCodec<CustomMsg>
43{
44 private:
45 unsigned size() override { return (part() == dccl::HEAD) ? 0 : A_SIZE + B_SIZE; }
46 Bitset encode() override { return Bitset(size()); }
47
48 Bitset encode(const CustomMsg& msg) override
49 {
50 if (part() == dccl::HEAD)
51 {
52 return encode();
53 }
54 else
55 {
56 Bitset a(A_SIZE, static_cast<unsigned long>(msg.a()));
57 Bitset b(B_SIZE, static_cast<unsigned long>(msg.b()));
58
59 std::cout << "a: " << a << std::endl;
60 std::cout << "b: " << b << std::endl;
61
62 a.append(b);
63 return a;
64 }
65 }
66
67 CustomMsg decode(Bitset* bits) override
68 {
69 if (part() == dccl::HEAD)
70 {
72 }
73 else
74 {
75 Bitset a = *bits;
76 a.resize(A_SIZE);
77 Bitset b = *bits;
78 b >>= A_SIZE;
79 b.resize(B_SIZE);
80
81 CustomMsg msg;
82 msg.set_a(a.to_ulong());
83 msg.set_b(b.to_ulong());
84 return msg;
85 }
86 }
87
88 void validate() override {}
89
90 enum
91 {
92 A_SIZE = 32
93 };
94 enum
95 {
96 B_SIZE = 1
97 };
98};
99
101{
102 private:
103 enum
104 {
105 REPEAT_STORAGE_BITS = 4
106 };
107 enum
108 {
109 MAX_REPEAT_SIZE = 1 << REPEAT_STORAGE_BITS
110 }; // 2^4
111
112 dccl::int32 max() { return FieldCodecBase::dccl_field_options().max(); }
113 dccl::int32 min() { return FieldCodecBase::dccl_field_options().min(); }
114 dccl::int32 max_repeat() { return FieldCodecBase::dccl_field_options().max_repeat(); }
115
116 Bitset encode_repeated(const std::vector<dccl::int32>& wire_values) override
117 {
118 Bitset value_bits;
119 int repeat_size =
120 static_cast<int>(wire_values.size()) > max_repeat() ? max_repeat() : wire_values.size();
121
122 std::cout << "repeat size is " << repeat_size << std::endl;
123
124 for (int i = 0, n = repeat_size; i < n; ++i)
125 {
126 dccl::int32 wire_value = wire_values[i];
127 wire_value -= min();
128 value_bits.append(Bitset(singular_size(), static_cast<unsigned long>(wire_value)));
129 }
130
131 std::cout << value_bits << std::endl;
132 std::cout << Bitset(REPEAT_STORAGE_BITS, repeat_size) << std::endl;
133 Bitset out(REPEAT_STORAGE_BITS, repeat_size);
134 out.append(value_bits);
135 return out;
136 }
137
138 std::vector<dccl::int32> decode_repeated(Bitset* bits) override
139 {
140 int repeat_size = bits->to_ulong();
141 std::cout << "repeat size is " << repeat_size << std::endl;
142 // grabs more bits to add to the MSBs of `bits`
143 bits->get_more_bits(repeat_size * singular_size());
144
145 Bitset value_bits = *bits;
146 value_bits >>= REPEAT_STORAGE_BITS;
147
148 std::vector<dccl::int32> out;
149 for (int i = 0; i < repeat_size; ++i)
150 {
151 dccl::int32 value = value_bits.to_ulong() & ((1 << singular_size()) - 1);
152 value += min();
153 out.push_back(value);
154 value_bits >>= singular_size();
155 }
156 return out;
157 }
158
159 unsigned size_repeated(const std::vector<dccl::int32>& field_values) override
160 {
161 return REPEAT_STORAGE_BITS + field_values.size() * singular_size();
162 }
163
164 unsigned singular_size() { return dccl::ceil_log2((max() - min()) + 1); }
165
166 unsigned max_size_repeated() override
167 {
168 return REPEAT_STORAGE_BITS + max_repeat() * singular_size();
169 }
170
171 unsigned min_size_repeated() override { return REPEAT_STORAGE_BITS; }
172
173 void validate() override
174 {
176 "missing (dccl.field).min");
178 "missing (dccl.field).max");
180 FieldCodecBase::dccl_field_options().max_repeat() < MAX_REPEAT_SIZE,
181 "(dccl.field).max_repeat must be less than " +
182 std::to_string(static_cast<int>(MAX_REPEAT_SIZE)));
183 }
184};
185
186} // namespace test
187} // namespace dccl
188
189int main(int /*argc*/, char* /*argv*/ [])
190{
191 dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
192
193 dccl::Codec codec;
194 codec.manager().add<dccl::test::CustomCodec>("custom_codec");
195 codec.manager().add<dccl::test::Int32RepeatedCodec>("int32_test_codec");
196
197 codec.set_crypto_passphrase("my_passphrase!");
198
199 CustomMsg msg_in1;
200
201 msg_in1.set_a(10);
202 msg_in1.set_b(true);
203
204 codec.info(msg_in1.GetDescriptor(), &std::cout);
205 std::cout << "Message in:\n" << msg_in1.DebugString() << std::endl;
206 codec.load(msg_in1.GetDescriptor());
207 std::cout << "Try encode..." << std::endl;
208 std::string bytes1;
209 codec.encode(&bytes1, msg_in1);
210 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes1) << std::endl;
211 std::cout << "Try decode..." << std::endl;
212 std::shared_ptr<google::protobuf::Message> msg_out1 =
213 codec.decode<std::shared_ptr<google::protobuf::Message>>(bytes1);
214 std::cout << "... got Message out:\n" << msg_out1->DebugString() << std::endl;
215 assert(msg_in1.SerializeAsString() == msg_out1->SerializeAsString());
216
217 CustomMsg2 msg_in2, msg_out2;
218
219 msg_in2.mutable_msg()->CopyFrom(msg_in1);
220 msg_in2.add_c(30);
221 msg_in2.add_c(2);
222
223 codec.info(msg_in2.GetDescriptor(), &std::cout);
224 std::cout << "Message in:\n" << msg_in2.DebugString() << std::endl;
225 codec.load(msg_in2.GetDescriptor());
226 std::cout << "Try encode..." << std::endl;
227 std::string bytes2;
228 codec.encode(&bytes2, msg_in2);
229 std::cout << "... got bytes (hex): " << dccl::hex_encode(bytes2) << std::endl;
230 std::cout << "Try decode..." << std::endl;
231 codec.decode(bytes2, &msg_out2);
232 std::cout << "... got Message out:\n" << msg_out2.DebugString() << std::endl;
233 assert(msg_in2.SerializeAsString() == msg_out2.SerializeAsString());
234
235 std::cout << "all tests passed" << std::endl;
236}
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition bitset.h:420
Bitset & append(const Bitset &bits)
Adds the bitset to the big end.
Definition bitset.h:361
unsigned long to_ulong() const
Returns the value of the Bitset as an unsigned long integer. Equivalent to to<unsigned long>().
Definition bitset.h:275
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition codec.h:63
MessagePart part()
the part of the message currently being encoded (head or body)
void require(bool b, const std::string &description)
Essentially an assertion to be used in the validate() virtual method.
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
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
Exception used to signal null (non-existent) value within field codecs during decode.
Definition exception.h:62
Base class for "repeated" (multiple value) static-typed (no dccl::any) field encoders/decoders....
Base class for static-typed field encoders/decoders that use a fixed number of bits on the wire regar...
Unit test namespace.
Definition test.cpp:45
Dynamic Compact Control Language namespace.
Definition any.h:47
google::protobuf::int32 int32
a signed 32 bit integer
Definition common.h:58
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
unsigned ceil_log2(dccl::uint64 v)
Definition binary.h:178