DCCL v4
test.cpp
1 // Copyright 2011-2017:
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"
32 using namespace dccl::test;
33 
34 using dccl::operator<<;
35 using dccl::Bitset;
36 
37 namespace dccl
38 {
40 namespace test
41 {
42 class 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 
189 int 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 }
dccl::test
Unit test namespace.
Definition: test.cpp:45
dccl::Bitset::to_ulong
unsigned long to_ulong() const
Returns the value of the Bitset as an unsigned long integer. Equivalent to to<unsigned long>().
Definition: bitset.h:274
dccl::Bitset::get_more_bits
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition: bitset.h:419
dccl
Dynamic Compact Control Language namespace.
Definition: any.h:49
dccl::TypedFixedFieldCodec
Base class for static-typed field encoders/decoders that use a fixed number of bits on the wire regar...
Definition: field_codec_fixed.h:37
dccl::FieldCodecBase::require
void require(bool b, const std::string &description)
Essentially an assertion to be used in the validate() virtual method.
Definition: field_codec.h:349
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::ceil_log2
unsigned ceil_log2(dccl::uint64 v)
Definition: binary.h:178
dccl::Bitset::append
Bitset & append(const Bitset &bits)
Adds the bitset to the big end.
Definition: bitset.h:360
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::NullValueException
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:62
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:41
dccl::RepeatedTypedFieldCodec
Base class for "repeated" (multiple value) static-typed (no dccl::any) field encoders/decoders....
Definition: field_codec_typed.h:224
dccl::test::CustomCodec
Definition: test.cpp:42
dccl::test::Int32RepeatedCodec
Definition: test.cpp:100
dccl::int32
google::protobuf::int32 int32
a signed 32 bit integer
Definition: common.h:58
dccl::FieldCodecBase::dccl_field_options
dccl::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
Definition: field_codec.h:335