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 #include "goby/acomms/acomms_constants.h"
23 #include "goby/acomms/connect.h"
24 #include "goby/acomms/queue.h"
25 #include "goby/common/logger.h"
26 #include "goby/util/binary.h"
27 #include "test.pb.h"
28 
29 // tests "encode_on_demand" functionality
30 
31 using goby::acomms::operator<<;
32 
33 int receive_count = 0;
34 int encode_on_demand_count = 0;
35 bool handle_ack_called = false;
36 int goby_message_qsize = 0;
37 int last_decoded_count = 0;
38 std::deque<int> decode_order;
39 //GobyMessage msg_in1, msg_in2;
41 const int MY_MODEM_ID = 1;
42 bool provide_data = true;
43 
44 void handle_encode_on_demand(const goby::acomms::protobuf::ModemTransmission& request_msg,
45  google::protobuf::Message* data_msg);
46 
47 void qsize(goby::acomms::protobuf::QueueSize size);
48 
49 void handle_receive(const google::protobuf::Message& msg);
50 
51 void request_test(int request_bytes, int expected_encode_requests, int expected_messages_sent);
52 
53 int main(int argc, char* argv[])
54 {
55  goby::glog.add_stream(goby::common::logger::DEBUG3, &std::cerr);
56  goby::glog.set_name(argv[0]);
57 
59 
61  cfg.set_modem_id(MY_MODEM_ID);
62  goby::acomms::protobuf::QueuedMessageEntry* entry = cfg.add_message_entry();
63  entry->set_protobuf_name("GobyMessage");
64  entry->set_newest_first(true);
65  entry->add_manipulator(goby::acomms::protobuf::ON_DEMAND);
66  cfg.set_on_demand_skew_seconds(0.1);
67 
68  q_manager.set_cfg(cfg);
69 
70  goby::glog << q_manager << std::endl;
71 
73  goby::acomms::connect(&q_manager.signal_data_on_demand, &handle_encode_on_demand);
74  goby::acomms::connect(&q_manager.signal_receive, &handle_receive);
75 
76  // we want to test requesting for a message slightly larger than the expected size
77  decode_order.push_back(0);
78  request_test(codec->size(GobyMessage()) + 1, 2, 1);
79  assert(decode_order.empty());
80 
81  // no lag so it should be the *already* encoded message
82  decode_order.push_back(1);
83  request_test(codec->size(GobyMessage()), 0, 1);
84  assert(decode_order.empty());
85 
86  // nothing in the queue so we'll try this again
87  decode_order.push_back(2);
88  decode_order.push_back(3);
89  request_test(codec->size(GobyMessage()) * 2 + 1, 3, 2);
90  assert(decode_order.empty());
91 
92  // 0.2 seconds > 0.1 seconds
93  usleep(2e5);
94  // 4 is too old so a new request made
95  decode_order.push_back(5);
96  request_test(codec->size(GobyMessage()), 1, 1);
97  assert(decode_order.empty());
98 
99  // we won't provide data this time so the old message in the queue (4) should be sent
100  provide_data = false;
101  decode_order.push_back(4);
102  request_test(codec->size(GobyMessage()), 1, 1);
103  assert(decode_order.empty());
104 
105  std::cout << "all tests passed" << std::endl;
106 }
107 
108 void request_test(int request_bytes, int expected_encode_requests, int expected_messages_sent)
109 {
110  int starting_qsize = goby_message_qsize;
111  int starting_encode_count = encode_on_demand_count;
112 
114  transmit_msg.set_max_frame_bytes(request_bytes);
115  transmit_msg.set_max_num_frames(1);
116 
117  q_manager.handle_modem_data_request(&transmit_msg);
118  std::cout << "requesting data, got: " << transmit_msg << std::endl;
119 
120  // once for each one that fits, twice for the one that doesn't
121  assert(encode_on_demand_count - starting_encode_count == expected_encode_requests);
122 
123  std::cout << "\tdata as hex: " << goby::util::hex_encode(transmit_msg.frame(0)) << std::endl;
124 
125  assert(transmit_msg.src() == MY_MODEM_ID);
126  assert(transmit_msg.dest() == goby::acomms::BROADCAST_ID);
127  assert(transmit_msg.ack_requested() == false);
128 
129  if (provide_data)
130  assert(goby_message_qsize ==
131  starting_qsize + expected_encode_requests - expected_messages_sent);
132  else
133  assert(goby_message_qsize == starting_qsize - expected_messages_sent);
134 
135  q_manager.handle_modem_receive(transmit_msg);
136 }
137 
138 void handle_encode_on_demand(const goby::acomms::protobuf::ModemTransmission& request_msg,
139  google::protobuf::Message* data_msg)
140 {
141  GobyMessage msg;
142 
143  if (provide_data)
144  msg.set_telegram(encode_on_demand_count);
145 
146  std::cout << "encoded on demand: " << msg << std::endl;
147 
148  // put our message into the data_msg for return
149  data_msg->CopyFrom(msg);
150  ++encode_on_demand_count;
151 }
152 
153 void qsize(goby::acomms::protobuf::QueueSize size) { goby_message_qsize = size.size(); }
154 
155 void handle_receive(const google::protobuf::Message& in_msg)
156 {
157  GobyMessage msg;
158  msg.CopyFrom(in_msg);
159 
160  std::cout << "Received: " << msg << std::endl;
161  ++receive_count;
162  assert(decode_order.front() == msg.telegram());
163  decode_order.pop_front();
164 }
provides an API to the goby-acomms Queuing Library.
Definition: queue_manager.h:49
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
boost::signals2::signal< void(const protobuf::ModemTransmission &request_msg, google::protobuf::Message *data_msg)> signal_data_on_demand
Forwards the data request to the application layer. This advanced feature is used when queue...
boost::signals2::signal< void(const google::protobuf::Message &msg)> signal_receive
Signals when a DCCL message is received.
void handle_modem_data_request(protobuf::ModemTransmission *msg)
Finds data to send to the modem.
void handle_modem_receive(const protobuf::ModemTransmission &message)
Receive incoming data from the modem.
const int BROADCAST_ID
special modem id for the broadcast destination - no one is assigned this address. Analogous to 192...
void connect(Signal *signal, Slot slot)
connect a signal to a slot (e.g. function pointer)
Definition: connect.h:36
common::FlexOstream glog
Access the Goby logger through this object.
void set_cfg(const protobuf::QueueManagerConfig &cfg)
Set (and overwrite completely if present) the current configuration. (protobuf::QueueManagerConfig de...
boost::signals2::signal< void(protobuf::QueueSize size)> signal_queue_size_change
Signals when any queue changes size (message is popped or pushed)
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