]> git.tdb.fi Git - libs/net.git/blob - tests/protocol.cpp
Add a dynamic receiver class for more flexible packet handling
[libs/net.git] / tests / protocol.cpp
1 #include <msp/net/protocol.h>
2 #include <msp/test/test.h>
3
4 using namespace std;
5 using namespace Msp;
6
7 class ProtocolTests: public Test::RegisteredTest<ProtocolTests>
8 {
9 public:
10         ProtocolTests();
11
12         static const char *get_name() { return "Protocol"; }
13
14 private:
15         void hash_match();
16         void buffer_overflow();
17         void truncated_packet();
18         void stub_header();
19
20         template<typename P>
21         void transmit(const P &, P &, size_t);
22
23         void transmit_int();
24         void transmit_string();
25         void transmit_array();
26         void transmit_composite();
27 };
28
29
30 class Protocol: public Msp::Net::Protocol
31 {
32 public:
33         Protocol();
34 };
35
36 struct Packet1
37 {
38         uint32_t value;
39 };
40
41 struct Packet2
42 {
43         std::string value;
44 };
45
46 struct Packet3
47 {
48         std::vector<uint32_t> values;
49 };
50
51 struct Packet4
52 {
53         Packet2 sub1;
54         std::vector<Packet3> sub2;
55 };
56
57 Protocol::Protocol()
58 {
59         add<Packet1>(&Packet1::value);
60         add<Packet2>(&Packet2::value);
61         add<Packet3>(&Packet3::values);
62         add<Packet4>(&Packet4::sub1, &Packet4::sub2);
63 }
64
65 template<typename T>
66 class Receiver: public Net::PacketReceiver<T>
67 {
68 private:
69         T &storage;
70
71 public:
72         Receiver(T &s): storage(s) { }
73
74         void receive(const T &p) override { storage = p; }
75 };
76
77
78 ProtocolTests::ProtocolTests()
79 {
80         add(&ProtocolTests::hash_match, "Hash match");
81         add(&ProtocolTests::buffer_overflow, "Serialization buffer overflow").expect_throw<Net::buffer_error>();
82         add(&ProtocolTests::truncated_packet, "Truncated packet").expect_throw<Net::bad_packet>();
83         add(&ProtocolTests::stub_header, "Stub header");
84         add(&ProtocolTests::transmit_int, "Integer transmission");
85         add(&ProtocolTests::transmit_string, "String transmission");
86         add(&ProtocolTests::transmit_array, "Array transmission");
87         add(&ProtocolTests::transmit_composite, "Composite transmission");
88 }
89
90 void ProtocolTests::hash_match()
91 {
92         Protocol proto1;
93         Protocol proto2;
94         EXPECT_EQUAL(proto1.get_hash(), proto2.get_hash());
95 }
96
97 void ProtocolTests::buffer_overflow()
98 {
99         Protocol proto;
100         Packet1 pkt = { 42 };
101         char buffer[7];
102         proto.serialize(pkt, buffer, sizeof(buffer));
103 }
104
105 void ProtocolTests::truncated_packet()
106 {
107         Protocol proto;
108         Packet1 pkt = { 42 };
109         char buffer[16];
110         size_t len = proto.serialize(pkt, buffer, sizeof(buffer));
111         Receiver<Packet1> recv(pkt);
112         proto.dispatch(recv, buffer, len-1);
113 }
114
115 void ProtocolTests::stub_header()
116 {
117         Protocol proto;
118         char buffer[3] = { 4, 0, 1 };
119         size_t len = proto.get_packet_size(buffer, sizeof(buffer));
120         EXPECT_EQUAL(len, 0);
121 }
122
123 template<typename P>
124 void ProtocolTests::transmit(const P &pkt, P &rpkt, size_t expected_length)
125 {
126         Protocol proto;
127         char buffer[128];
128         size_t len = proto.serialize(pkt, buffer, sizeof(buffer));
129         EXPECT_EQUAL(len, expected_length);
130
131         size_t rlen = proto.get_packet_size(buffer, sizeof(buffer));
132         EXPECT_EQUAL(rlen, len);
133
134         Receiver<P> recv(rpkt);
135         size_t dlen = proto.dispatch(recv, buffer, sizeof(buffer));
136         EXPECT_EQUAL(dlen, len);
137 }
138
139 void ProtocolTests::transmit_int()
140 {
141         Packet1 pkt = { 42 };
142         Packet1 rpkt;
143         transmit(pkt, rpkt, 8);
144         EXPECT_EQUAL(rpkt.value, 42);
145 }
146
147 void ProtocolTests::transmit_string()
148 {
149         Packet2 pkt = { "Hello" };
150         Packet2 rpkt;
151         transmit(pkt, rpkt, 11);
152         EXPECT_EQUAL(rpkt.value, "Hello");
153 }
154
155 void ProtocolTests::transmit_array()
156 {
157         Packet3 pkt = {{ 2, 3, 5, 7, 11 }};
158         Packet3 rpkt;
159         transmit(pkt, rpkt, 26);
160         EXPECT_EQUAL(rpkt.values.size(), 5);
161         for(size_t i=0; i<pkt.values.size(); ++i)
162                 EXPECT_EQUAL(rpkt.values[i], pkt.values[i]);
163 }
164
165 void ProtocolTests::transmit_composite()
166 {
167         Packet4 pkt = { "Don't panic", { }};
168         pkt.sub2.emplace_back(Packet3{{ 2, 3, 5, 7, 11 }});
169         pkt.sub2.emplace_back(Packet3{{ 20, 10, 5, 16, 8, 4, 2, 1 }});
170         Packet4 rpkt;
171         transmit(pkt, rpkt, 75);
172         EXPECT_EQUAL(rpkt.sub1.value, "Don't panic");
173         EXPECT_EQUAL(rpkt.sub2.size(), 2);
174         EXPECT_EQUAL(rpkt.sub2[0].values.size(), 5);
175         EXPECT_EQUAL(rpkt.sub2[1].values.size(), 8);
176         for(size_t i=0; i<pkt.sub2.size(); ++i)
177                 for(size_t j=0; j<pkt.sub2[i].values.size(); ++j)       
178                         EXPECT_EQUAL(rpkt.sub2[i].values[j], pkt.sub2[i].values[j]);
179 }