DCCL v4
test.cpp
1 // Copyright 2011-2023:
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 //
8 //
9 // This file is part of the Dynamic Compact Control Language Library
10 // ("DCCL").
11 //
12 // DCCL is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU Lesser General Public License as published by
14 // the Free Software Foundation, either version 2.1 of the License, or
15 // (at your option) any later version.
16 //
17 // DCCL is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public License
23 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24 // tests usage of Legacy CCL
25 
26 #include "../../ccl/ccl_compatibility.h"
27 #include "../../codec.h"
28 #include "../../field_codec.h"
29 #include "test.pb.h"
30 
31 using namespace dccl::test;
32 
33 using dccl::operator<<;
34 
35 bool double_cmp(double a, double b, int precision)
36 {
37  int a_whole = a;
38  int b_whole = b;
39 
40  int a_part = (a - a_whole) * pow(10.0, precision);
41  int b_part = (b - b_whole) * pow(10.0, precision);
42 
43  return (a_whole == b_whole) && (a_part == b_part);
44 }
45 
46 template <typename N> void check_normal_dccl(dccl::Codec& codec)
47 {
48  codec.load<N>();
49  codec.info<N>(&dccl::dlog);
50  N normal_msg, normal_msg_out;
51  normal_msg.set_a(123);
52  normal_msg.set_b(321);
53 
54  std::string encoded;
55  codec.encode(&encoded, normal_msg);
56  std::cout << dccl::hex_encode(encoded) << std::endl;
57  assert(dccl::hex_encode(encoded).substr(0, 2) == "20");
58  codec.decode(encoded, &normal_msg_out);
59 
60  assert(normal_msg.SerializeAsString() == normal_msg_out.SerializeAsString());
61 }
62 
63 int main(int /*argc*/, char* /*argv*/ [])
64 {
65  dccl::dlog.connect(dccl::logger::ALL, &std::cerr);
66 
67  dccl::Codec codec("dccl.ccl.id", DCCL_CCL_COMPAT_NAME);
68 
69  check_normal_dccl<NormalDCCL1Byte>(codec);
70  check_normal_dccl<NormalDCCL2Byte>(codec);
71 
72  codec.info<dccl::legacyccl::protobuf::CCLMDATState>(&dccl::dlog);
73 
74  dccl::legacyccl::protobuf::CCLMDATState state_in, state_out;
75  std::string test_state_encoded =
76  "0e86fa11ad20c9011b4432bf47d10000002401042f0e7d87fa111620c95a200a";
77  codec.decode(dccl::hex_decode(test_state_encoded), &state_out);
78  state_in.set_latitude(25.282416667);
79  state_in.set_longitude(-77.164266667);
80  state_in.set_fix_age(4);
81 
82  auto now = std::chrono::system_clock::now();
83  std::time_t now_time_t = std::chrono::system_clock::to_time_t(now);
84  std::tm input_tm = *std::gmtime(&now_time_t); // get current year
85  input_tm.tm_mon = 2; // zero indexed March
86  input_tm.tm_mday = 4;
87  input_tm.tm_hour = 17;
88  input_tm.tm_min = 1;
89  input_tm.tm_sec = 44;
90  input_tm.tm_isdst = -1;
91  std::time_t time_date = timegm(&input_tm);
92 
93  state_in.set_time_date(dccl::legacyccl::TimeDateCodec::to_uint64_time(time_date));
94  state_in.set_heading(270);
95  state_in.set_depth(2323);
96  state_in.set_mission_mode(dccl::legacyccl::protobuf::CCLMDATState::NORMAL);
97  state_in.set_faults(dccl::hex_decode("00000024"));
98  state_in.set_faults_2(dccl::hex_decode("01"));
99  state_in.set_mission_leg(4);
100  state_in.set_est_velocity(1.88);
101  state_in.set_objective_index(dccl::hex_decode("0E"));
102  state_in.set_watts(500);
103  state_in.set_lat_goal(25.282440815262891);
104  state_in.set_lon_goal(-77.167505880296929);
105  state_in.set_battery_percent(90);
106  state_in.mutable_gfi_pitch_oil()->set_gfi(0);
107  state_in.mutable_gfi_pitch_oil()->set_pitch(6);
108  state_in.mutable_gfi_pitch_oil()->set_oil(55);
109 
110  assert(double_cmp(state_in.latitude(), state_out.latitude(), 4));
111  assert(double_cmp(state_in.longitude(), state_out.longitude(), 4));
112  assert(state_in.fix_age() == state_out.fix_age());
113  assert(state_in.time_date() == state_out.time_date());
114  assert(dccl::round(state_in.heading(), 0) == dccl::round(state_out.heading(), 0));
115  assert(double_cmp(state_in.depth(), state_out.depth(), 1));
116  assert(state_in.mission_mode() == state_out.mission_mode());
117 
118  // test the dynamically generated message
119  std::shared_ptr<google::protobuf::Message> state_in_2 =
121  dccl::legacyccl::protobuf::CCLMDATState::descriptor());
122  state_in_2->CopyFrom(state_in);
123 
124  std::string state_encoded;
125  codec.encode(&state_encoded, *state_in_2);
126 
128  codec.decode(state_encoded, &state_out_2);
129 
130  std::cout << "in:" << state_in << std::endl;
131  std::cout << test_state_encoded << std::endl;
132  std::cout << dccl::hex_encode(state_encoded) << std::endl;
133  std::cout << std::setprecision(16) << state_out.lon_goal() << std::endl;
134  std::cout << "out:" << state_out << std::endl;
135  std::cout << "out2: " << state_out_2 << std::endl;
136 
137  assert(state_out.SerializeAsString() == state_out_2.SerializeAsString());
138  assert(test_state_encoded == dccl::hex_encode(state_encoded));
139 
140  std::cout << dccl::hex_encode(state_out.faults()) << std::endl;
141  std::cout << dccl::hex_encode(state_out.faults_2()) << std::endl;
142 
143  codec.info<dccl::legacyccl::protobuf::CCLMDATRedirect>(&dccl::dlog);
144 
145  dccl::legacyccl::protobuf::CCLMDATRedirect redirect_in, redirect_out;
146  std::string test_redirect_encoded =
147  "07522cf9113d20c99964003d6464003d640be60014142035f911ef21c9000000";
148  codec.decode(dccl::hex_decode(test_redirect_encoded), &redirect_out);
149  redirect_in.set_message_number(82);
150  redirect_in.set_latitude(25.274995002149939);
151  redirect_in.set_longitude(-77.166669030984522);
152  redirect_in.set_transit_vertical_mode(dccl::legacyccl::protobuf::CCLMDATRedirect::ALTITUDE);
153  redirect_in.set_transit_thrust_mode(
154  dccl::legacyccl::protobuf::CCLMDATRedirect::METERS_PER_SECOND);
155  redirect_in.set_survey_vertical_mode(dccl::legacyccl::protobuf::CCLMDATRedirect::ALTITUDE);
156  redirect_in.set_survey_thrust_mode(
157  dccl::legacyccl::protobuf::CCLMDATRedirect::METERS_PER_SECOND);
158 
159  redirect_in.set_depth_goal_transit(10.0);
160  redirect_in.set_speed_transit(2.0333333);
161  redirect_in.set_device_cmd_transit(100);
162 
163  redirect_in.set_depth_goal_survey(10.0);
164  redirect_in.set_speed_survey(2.0333333);
165  redirect_in.set_device_cmd_survey(100);
166 
167  redirect_in.set_num_rows(11);
168  redirect_in.set_row_length(230);
169  redirect_in.set_spacing_0(20);
170  redirect_in.set_spacing_1(20);
171  redirect_in.set_heading(45.176472);
172 
173  redirect_in.set_lat_start(25.275183333);
174  redirect_in.set_lon_start(-77.15735);
175 
176  redirect_in.set_spare(std::string(3, '\0'));
177 
178  std::string redirect_encoded;
179  codec.encode(&redirect_encoded, redirect_in);
180 
182  codec.decode(redirect_encoded, &redirect_out_2);
183 
184  std::cout << "in:" << redirect_in << std::endl;
185  std::cout << test_redirect_encoded << std::endl;
186  std::cout << dccl::hex_encode(redirect_encoded) << std::endl;
187  std::cout << "out:" << redirect_out << std::endl;
188  std::cout << "out2: " << redirect_out_2 << std::endl;
189 
190  assert(redirect_out.SerializeAsString() == redirect_out_2.SerializeAsString());
191  assert(test_redirect_encoded == dccl::hex_encode(redirect_encoded));
192 
193  codec.info<dccl::legacyccl::protobuf::CCLMDATEmpty>(&dccl::dlog);
194  codec.info<dccl::legacyccl::protobuf::CCLMDATBathy>(&dccl::dlog);
195  codec.info<dccl::legacyccl::protobuf::CCLMDATCTD>(&dccl::dlog);
196  codec.info<dccl::legacyccl::protobuf::CCLMDATError>(&dccl::dlog);
197  codec.info<dccl::legacyccl::protobuf::CCLMDATCommand>(&dccl::dlog);
198 
199  std::cout << "all tests passed" << std::endl;
200 }
dccl::test
Unit test namespace.
Definition: test.cpp:44
dccl::legacyccl::protobuf::CCLMDATRedirect
Definition: ccl.pb.h:344
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::legacyccl::protobuf::CCLMDATEmpty
Definition: ccl.pb.h:221
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::legacyccl::protobuf::CCLMDATCommand
Definition: ccl.pb.h:1131
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::legacyccl::protobuf::CCLMDATBathy
Definition: ccl.pb.h:734
dccl::legacyccl::protobuf::CCLMDATState
Definition: ccl.pb.h:1518
dccl::DynamicProtobufManager::new_protobuf_message
static GoogleProtobufMessagePointer new_protobuf_message(const std::string &protobuf_type_name, bool user_pool_first=false)
Create a new (empty) Google Protobuf message of a given type by name.
Definition: dynamic_protobuf_manager.h:76
dccl::legacyccl::protobuf::CCLMDATCTD
Definition: ccl.pb.h:909
dccl::hex_decode
void hex_decode(const std::string &in, std::string *out)
Decodes a (little-endian) hexadecimal string to a byte string. Index 0 and 1 (first byte) of in are w...
Definition: binary.h:51
dccl::legacyccl::protobuf::CCLMDATError
Definition: ccl.pb.h:1865