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 usage of a custom DCCL ID codec
23 
24 #include "dccl/codec.h"
25 #include "dccl/field_codec_id.h"
26 #include "test.pb.h"
27 using namespace dccl::test;
28 
29 using dccl::operator<<;
30 
31 namespace dccl {
32 namespace test {
33 
34 // If "user_id" is set via UserCustomIdRAII, use that, fall back to using the
35 // default ID Codec
37 private:
38  dccl::Bitset encode(const dccl::uint32 &wire_value) {
39  return user_id_set ? encode() : DefaultIdentifierCodec::encode(wire_value);
40  }
41 
42  dccl::Bitset encode() {
43  return user_id_set ? dccl::Bitset() : DefaultIdentifierCodec::encode();
44  }
45 
46  unsigned size() { return user_id_set ? 0 : DefaultIdentifierCodec::size(); }
47 
48  unsigned size(const dccl::uint32 &wire_value) {
49  return user_id_set ? 0 : DefaultIdentifierCodec::size(wire_value);
50  }
51 
52  unsigned min_size() {
53  return user_id_set ? 0 : DefaultIdentifierCodec::min_size();
54  }
55 
56  unsigned max_size() {
57  return user_id_set ? 0 : DefaultIdentifierCodec::max_size();
58  }
59 
60  // pass the current ID back
61  dccl::uint32 decode(dccl::Bitset *bits) {
62  return user_id_set ? user_id : DefaultIdentifierCodec::decode(bits);
63  }
64 
65  void validate() {
66  if (!user_id_set)
68  }
69 
70  friend struct UserCustomIdRAII;
71  static dccl::uint32 user_id;
72  static bool user_id_set;
73 };
74 
75 // RAII-based tool for setting the current DCCL ID within the scope of this
76 // object's lifetime. Any actions (load, info, encode, decode, etc.) will
77 // use this DCCL ID for the duration of this lifetime.
80  UserCustomIdCodec::user_id = id;
81  UserCustomIdCodec::user_id_set = true;
82  }
83  ~UserCustomIdRAII() {
84  UserCustomIdCodec::user_id = 0;
85  UserCustomIdCodec::user_id_set = false;
86  }
87 };
88 } // namespace test
89 } // namespace dccl
90 
91 bool dccl::test::UserCustomIdCodec::user_id_set = false;
92 dccl::uint32 dccl::test::UserCustomIdCodec::user_id = 0;
93 
94 int main(int argc, char *argv[]) {
95  dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
96 
97  {
98  dccl::FieldCodecManager::add<dccl::test::UserCustomIdCodec>(
99  "user_id_codec");
100  dccl::Codec codec("user_id_codec");
101 
102  // load TestMessageA as DCCL ID 1
103  {
104  dccl::test::UserCustomIdRAII scoped_user_id(1);
105  codec.load<TestMessageA>();
106  codec.info<TestMessageA>(&dccl::dlog);
107  }
108  // load TestMessageA as DCCL ID 2
109  {
110  dccl::test::UserCustomIdRAII scoped_user_id(2);
111  codec.load<TestMessageA>();
112  codec.info<TestMessageA>(&dccl::dlog);
113  }
114 
115  // load TestMessageB as DCCL ID 3
116  {
117  dccl::test::UserCustomIdRAII scoped_user_id(3);
118  codec.load<TestMessageB>();
119  codec.info<TestMessageB>(&dccl::dlog);
120  }
121 
122  // load TestMessageA using default ID codec
123  {
124  codec.load<TestMessageA>();
125  codec.info<TestMessageA>(&dccl::dlog);
126  }
127 
128  // one byte as the UserCustomIdCodec doesn't use any bytes on the wire
129  unsigned byte_size_user_specified = 1;
130  TestMessageA a1;
131  a1.set_a(10);
132 
133  TestMessageA a2;
134  a2.set_a(20);
135 
136  TestMessageB b;
137  b.set_b(30);
138 
139  // one byte for the data, one byte for the ID
140  unsigned byte_size_default = 2;
141  TestMessageA a_default;
142  a_default.set_a(40);
143 
144  // encode/decode using user-specified DCCL ID
145  {
146  dccl::test::UserCustomIdRAII scoped_user_id(1);
147  std::string bytes;
148 
149  std::cout << "A1: " << a1.ShortDebugString() << std::endl;
150  assert(codec.size(a1) == byte_size_user_specified);
151  codec.encode(&bytes, a1);
152  assert(bytes.size() == byte_size_user_specified);
153  TestMessageA a1_out;
154  codec.decode(bytes, &a1_out);
155  std::cout << "A1 decoded: " << a1_out.ShortDebugString() << std::endl;
156  assert(a1_out.SerializeAsString() == a1.SerializeAsString());
157  }
158 
159  {
160  dccl::test::UserCustomIdRAII scoped_user_id(2);
161  std::string bytes;
162  std::cout << "A2: " << a2.ShortDebugString() << std::endl;
163  assert(codec.size(a2) == byte_size_user_specified);
164  codec.encode(&bytes, a2);
165  assert(bytes.size() == byte_size_user_specified);
166  TestMessageA a2_out;
167  codec.decode(bytes, &a2_out);
168  std::cout << "A2 decoded: " << a2_out.ShortDebugString() << std::endl;
169  assert(a2_out.SerializeAsString() == a2.SerializeAsString());
170  }
171 
172  {
173  dccl::test::UserCustomIdRAII scoped_user_id(3);
174  std::string bytes;
175  std::cout << "B: " << b.ShortDebugString() << std::endl;
176  assert(codec.size(b) == byte_size_user_specified);
177  codec.encode(&bytes, b);
178  assert(bytes.size() == byte_size_user_specified);
179  TestMessageA b_out;
180  codec.decode(bytes, &b_out);
181  std::cout << "B decoded: " << b_out.ShortDebugString() << std::endl;
182  assert(b_out.SerializeAsString() == b.SerializeAsString());
183  }
184 
185  // encode/decode using default DCCL ID
186  {
187  std::string bytes;
188 
189  std::cout << "A Default: " << a_default.ShortDebugString() << std::endl;
190  assert(codec.size(a_default) == byte_size_default);
191  codec.encode(&bytes, a_default);
192  assert(bytes.size() == byte_size_default);
193  TestMessageA a_default_out;
194  codec.decode(bytes, &a_default_out);
195  std::cout << "A Default decoded: " << a_default_out.ShortDebugString()
196  << std::endl;
197  assert(a_default_out.SerializeAsString() ==
198  a_default.SerializeAsString());
199  }
200  }
201 
202  std::cout << "all tests passed" << std::endl;
203 }
The Dynamic CCL enCODer/DECoder. This is the main class you will use to load, encode and decode DCCL ...
Definition: codec.h:56
virtual uint32 decode(Bitset *bits)
Decode a field. If the field is empty (i.e. was encoded using the zero-argument encode()), throw NullValueException to indicate this.
virtual Bitset encode()
Encode an empty field.
virtual unsigned size()
Calculate the size (in bits) of an empty field.
virtual unsigned min_size()
Calculate minimum size of the field in bits.
google::protobuf::uint32 uint32
an unsigned 32 bit integer
Definition: common.h:55
virtual void validate()
Validate a field. Use require() inside your overloaded validate() to assert requirements or throw Exc...
Provides the default 1 byte or 2 byte DCCL ID codec.
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
Dynamic Compact Control Language namespace.
virtual unsigned max_size()
Calculate maximum size of the field in bits.
Unit test namespace.
Definition: test.cpp:44
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy...
Definition: bitset.h:38