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