Goby v2
test.cpp
1 // Copyright 2009-2018 Toby Schneider (http://gobysoft.org/index.wt/people/toby)
2 // GobySoft, LLC (2013-)
3 // Massachusetts Institute of Technology (2007-2014)
4 //
5 //
6 // This file is part of the Goby Underwater Autonomy Project Binaries
7 // ("The Goby Binaries").
8 //
9 // The Goby Binaries are free software: you can redistribute them and/or modify
10 // them under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // The Goby Binaries are distributed in the hope that they will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with Goby. If not, see <http://www.gnu.org/licenses/>.
21 
22 // tests custom message codec
23 // tests cryptography
24 
25 #include "goby/acomms/dccl.h"
26 #include "goby/common/time.h"
27 #include "goby/util/as.h"
28 #include "goby/util/binary.h"
29 #include "goby/util/sci.h"
30 #include "test.pb.h"
31 
32 using goby::acomms::operator<<;
33 using goby::acomms::Bitset;
34 
36 {
37  private:
38  unsigned size() { return (part() == goby::acomms::MessageHandler::HEAD) ? 0 : A_SIZE + B_SIZE; }
39  Bitset encode() { return Bitset(size()); }
40 
41  Bitset encode(const CustomMsg& msg)
42  {
43  if (part() == goby::acomms::MessageHandler::HEAD)
44  {
45  return encode();
46  }
47  else
48  {
49  Bitset a(A_SIZE, static_cast<unsigned long>(msg.a()));
50  Bitset b(B_SIZE, static_cast<unsigned long>(msg.b()));
51 
52  std::cout << "a: " << a << std::endl;
53  std::cout << "b: " << b << std::endl;
54 
55  a.append(b);
56  return a;
57  }
58  }
59 
60  CustomMsg decode(Bitset* bits)
61  {
62  if (part() == goby::acomms::MessageHandler::HEAD)
63  {
64  throw(goby::acomms::DCCLNullValueException());
65  }
66  else
67  {
68  Bitset a = *bits;
69  a.resize(A_SIZE);
70  Bitset b = *bits;
71  b >>= A_SIZE;
72  b.resize(B_SIZE);
73 
74  CustomMsg msg;
75  msg.set_a(a.to_ulong());
76  msg.set_b(b.to_ulong());
77  return msg;
78  }
79  }
80 
81  void validate() {}
82 
83  enum
84  {
85  A_SIZE = 32
86  };
87  enum
88  {
89  B_SIZE = 1
90  };
91 };
92 
94 {
95  private:
96  enum
97  {
98  REPEAT_STORAGE_BITS = 4
99  };
100  enum
101  {
102  MAX_REPEAT_SIZE = 1 << REPEAT_STORAGE_BITS
103  }; // 2^4
104 
105  goby::int32 max() { return DCCLFieldCodecBase::dccl_field_options().max(); }
106  goby::int32 min() { return DCCLFieldCodecBase::dccl_field_options().min(); }
107  goby::int32 max_repeat() { return DCCLFieldCodecBase::dccl_field_options().max_repeat(); }
108 
109  Bitset encode_repeated(const std::vector<goby::int32>& wire_values)
110  {
111  Bitset value_bits;
112  int repeat_size =
113  static_cast<int>(wire_values.size()) > max_repeat() ? max_repeat() : wire_values.size();
114 
115  std::cout << "repeat size is " << repeat_size << std::endl;
116 
117  for (int i = 0, n = repeat_size; i < n; ++i)
118  {
119  goby::int32 wire_value = wire_values[i];
120  wire_value -= min();
121  value_bits.append(Bitset(singular_size(), static_cast<unsigned long>(wire_value)));
122  }
123 
124  std::cout << value_bits << std::endl;
125  std::cout << Bitset(REPEAT_STORAGE_BITS, repeat_size) << std::endl;
126  Bitset out(REPEAT_STORAGE_BITS, repeat_size);
127  out.append(value_bits);
128  return out;
129  }
130 
131  std::vector<goby::int32> decode_repeated(Bitset* bits)
132  {
133  int repeat_size = bits->to_ulong();
134  std::cout << "repeat size is " << repeat_size << std::endl;
135  // grabs more bits to add to the MSBs of `bits`
136  bits->get_more_bits(repeat_size * singular_size());
137 
138  Bitset value_bits = *bits;
139  value_bits >>= REPEAT_STORAGE_BITS;
140 
141  std::vector<goby::int32> out;
142  for (int i = 0; i < repeat_size; ++i)
143  {
144  goby::int32 value = value_bits.to_ulong() & ((1 << singular_size()) - 1);
145  value += min();
146  out.push_back(value);
147  value_bits >>= singular_size();
148  }
149  return out;
150  }
151 
152  unsigned size_repeated(const std::vector<goby::int32>& field_values)
153  {
154  return REPEAT_STORAGE_BITS + field_values.size() * singular_size();
155  }
156 
157  unsigned singular_size() { return goby::util::ceil_log2((max() - min()) + 1); }
158 
159  unsigned max_size_repeated() { return REPEAT_STORAGE_BITS + max_repeat() * singular_size(); }
160 
161  unsigned min_size_repeated() { return REPEAT_STORAGE_BITS; }
162 
163  void validate()
164  {
165  DCCLFieldCodecBase::require(DCCLFieldCodecBase::dccl_field_options().has_min(),
166  "missing (dccl.field).min");
167  DCCLFieldCodecBase::require(DCCLFieldCodecBase::dccl_field_options().has_max(),
168  "missing (dccl.field).max");
169  DCCLFieldCodecBase::require(
170  DCCLFieldCodecBase::dccl_field_options().max_repeat() < MAX_REPEAT_SIZE,
171  "(dccl.field).max_repeat must be less than " +
172  goby::util::as<std::string>(static_cast<int>(MAX_REPEAT_SIZE)));
173  }
174 };
175 
176 int main(int argc, char* argv[])
177 {
178  goby::glog.add_stream(goby::common::logger::DEBUG3, &std::cerr);
179  goby::glog.set_name(argv[0]);
180 
182  goby::acomms::DCCLFieldCodecManager::add<CustomCodec>("custom_codec");
183  goby::acomms::DCCLFieldCodecManager::add<Int32RepeatedCodec>("int32_test_codec");
184 
186  cfg.set_crypto_passphrase("my_passphrase!");
187  codec->set_cfg(cfg);
188 
189  CustomMsg msg_in1;
190 
191  msg_in1.set_a(10);
192  msg_in1.set_b(true);
193 
194  codec->info(msg_in1.GetDescriptor(), &std::cout);
195  std::cout << "Message in:\n" << msg_in1.DebugString() << std::endl;
196  codec->validate(msg_in1.GetDescriptor());
197  std::cout << "Try encode..." << std::endl;
198  std::string bytes1;
199  codec->encode(&bytes1, msg_in1);
200  std::cout << "... got bytes (hex): " << goby::util::hex_encode(bytes1) << std::endl;
201  std::cout << "Try decode..." << std::endl;
202  boost::shared_ptr<google::protobuf::Message> msg_out1 =
203  codec->decode<boost::shared_ptr<google::protobuf::Message> >(bytes1);
204  std::cout << "... got Message out:\n" << msg_out1->DebugString() << std::endl;
205  assert(msg_in1.SerializeAsString() == msg_out1->SerializeAsString());
206 
207  CustomMsg2 msg_in2, msg_out2;
208 
209  msg_in2.mutable_msg()->CopyFrom(msg_in1);
210  msg_in2.add_c(30);
211  msg_in2.add_c(2);
212 
213  codec->info(msg_in2.GetDescriptor(), &std::cout);
214  std::cout << "Message in:\n" << msg_in2.DebugString() << std::endl;
215  codec->validate(msg_in2.GetDescriptor());
216  std::cout << "Try encode..." << std::endl;
217  std::string bytes2;
218  codec->encode(&bytes2, msg_in2);
219  std::cout << "... got bytes (hex): " << goby::util::hex_encode(bytes2) << std::endl;
220  std::cout << "Try decode..." << std::endl;
221  codec->decode(bytes2, &msg_out2);
222  std::cout << "... got Message out:\n" << msg_out2.DebugString() << std::endl;
223  assert(msg_in2.SerializeAsString() == msg_out2.SerializeAsString());
224 
225  std::cout << "all tests passed" << std::endl;
226 }
void set_name(const std::string &s)
Set the name of the application that the logger is serving.
Definition: flex_ostream.h:67
static DCCLCodec * get()
DCCLCodec is a singleton class; use this to get a pointer to the class.
Definition: dccl.h:124
common::FlexOstream glog
Access the Goby logger through this object.
void add_stream(logger::Verbosity verbosity=logger::VERBOSE, std::ostream *os=0)
Attach a stream object (e.g. std::cout, std::ofstream, ...) to the logger with desired verbosity...
Definition: flex_ostream.h:96
google::protobuf::int32 int32
a signed 32 bit integer