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 
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition: codec.h:56
Bitset & append(const Bitset &bits)
Adds the bitset to the big end.
Definition: bitset.h:381
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::DCCLFieldOptions dccl_field_options() const
Get the DCCL field option extension value for the current field.
Definition: field_codec.h:317
Exception used to signal null (non-existent) value within field codecs during decode.
Definition: exception.h:39
void load()
All messages must be explicited loaded and validated (size checks, option extensions checks...
Definition: codec.h:96
void require(bool b, const std::string &description)
Essentially an assertion to be used in the validate() virtual method.
Definition: field_codec.h:331
Base class for "repeated" (multiple value) static-typed (no boost::any) field encoders/decoders. Use TypedFixedFieldCodec if your codec is fixed length (always uses the same number of bits on the wire). Use TypedFieldCodec if your fields are always singular ("optional" or "required"). Singular fields are default implemented in this codec by calls to the equivalent repeated function with an empty or single valued vector.
unsigned ceil_log2(dccl::uint64 v)
Definition: binary.h:178
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition: bitset.h:447
void info(std::ostream *os=0) const
Writes a human readable summary (including field sizes) of the provided DCCL type to the stream provi...
Definition: codec.h:139
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
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:98
Dynamic Compact Control Language namespace.
void set_crypto_passphrase(const std::string &passphrase, const std::set< unsigned > &do_not_encrypt_ids_=std::set< unsigned >())
Set a passphrase to be used when encoded messages to encrypt them and to decrypt messages after decod...
Definition: codec.cpp:601
Base class for static-typed field encoders/decoders that use a fixed number of bits on the wire regar...
Unit test namespace.
Definition: test.pb.h:36
CharIterator decode(CharIterator begin, CharIterator end, google::protobuf::Message *msg, bool header_only=false)
Decode a DCCL message when the type is known at compile time.
Definition: codec.h:405
google::protobuf::int32 int32
a signed 32 bit integer
Definition: common.h:57
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy...
Definition: bitset.h:38
void encode(std::string *bytes, const google::protobuf::Message &msg, bool header_only=false)
Encodes a DCCL message.
Definition: codec.cpp:266