mavtables  0.2.1
MAVLink router and firewall.
test_GoTo.cpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #include <catch.hpp>
19 #include <fakeit.hpp>
20 
21 #include "Action.hpp"
22 #include "Chain.hpp"
23 #include "GoTo.hpp"
24 #include "If.hpp"
25 #include "MAVAddress.hpp"
26 #include "Packet.hpp"
27 #include "PacketVersion1.hpp"
28 #include "PacketVersion2.hpp"
29 #include "Rule.hpp"
30 #include "utility.hpp"
31 
32 #include "common.hpp"
33 #include "common_Packet.hpp"
34 #include "common_Rule.hpp"
35 
36 
37 TEST_CASE("GoTo's are constructable.", "[GoTo]")
38 {
39  fakeit::Mock<Chain> mock;
40  std::shared_ptr<Chain> chain = mock_shared(mock);
41  SECTION("Without a condition (match all packet/address combinations) or a "
42  "priority.")
43  {
44  REQUIRE_NOTHROW(GoTo(chain));
45  }
46  SECTION("Without a condition (match all packet/address combinations) but "
47  "with a priority.")
48  {
49  REQUIRE_NOTHROW(GoTo(chain, 3));
50  }
51  SECTION("With a condition and without a priority.")
52  {
53  REQUIRE_NOTHROW(GoTo(chain, If()));
54  REQUIRE_NOTHROW(GoTo(chain, If().type("PING")));
55  REQUIRE_NOTHROW(GoTo(chain, If().from("192.168")));
56  REQUIRE_NOTHROW(GoTo(chain, If().to("172.16")));
57  }
58  SECTION("With both a condition and a priority.")
59  {
60  REQUIRE_NOTHROW(GoTo(chain, 3, If()));
61  REQUIRE_NOTHROW(GoTo(chain, 3, If().type("PING")));
62  REQUIRE_NOTHROW(GoTo(chain, 3, If().from("192.168")));
63  REQUIRE_NOTHROW(GoTo(chain, 3, If().to("172.16")));
64  }
65  SECTION("Ensures the chain's shared pointer is not null.")
66  {
67  REQUIRE_THROWS_AS(GoTo(nullptr), std::invalid_argument);
68  REQUIRE_THROWS_AS(GoTo(nullptr, 3), std::invalid_argument);
69  REQUIRE_THROWS_AS(
70  GoTo(nullptr, 3, If().type("PING")), std::invalid_argument);
71  REQUIRE_THROWS_WITH(GoTo(nullptr), "Given chain pointer is null.");
72  REQUIRE_THROWS_WITH(GoTo(nullptr, 3), "Given chain pointer is null.");
73  REQUIRE_THROWS_WITH(
74  GoTo(nullptr, 3, If().type("PING")),
75  "Given chain pointer is null.");
76  }
77 }
78 
79 
80 TEST_CASE("GoTo's are comparable.", "[GoTo]")
81 {
82  fakeit::Mock<Chain> mock1;
83  fakeit::Mock<Chain> mock2;
84  std::shared_ptr<Chain> chain1 = mock_shared(mock1);
85  std::shared_ptr<Chain> chain2 = mock_shared(mock2);
86  SECTION("with ==")
87  {
88  REQUIRE(GoTo(chain1) == GoTo(chain1));
89  REQUIRE(
90  GoTo(chain1, If().type("PING")) == GoTo(chain1, If().type("PING")));
91  REQUIRE(GoTo(chain1, 3) == GoTo(chain1, 3));
92  REQUIRE(
93  GoTo(chain1, 3, If().type("PING")) ==
94  GoTo(chain1, 3, If().type("PING")));
95  REQUIRE_FALSE(GoTo(chain1) == GoTo(chain2));
96  REQUIRE_FALSE(
97  GoTo(chain1, If().type("PING")) ==
98  GoTo(chain1, If().type("SET_MODE")));
99  REQUIRE_FALSE(GoTo(chain1, If().type("PING")) == GoTo(chain1, If()));
100  REQUIRE_FALSE(GoTo(chain1, If().type("PING")) == GoTo(chain1));
101  REQUIRE_FALSE(GoTo(chain1, 3) == GoTo(chain1, -3));
102  REQUIRE_FALSE(GoTo(chain1, 3) == GoTo(chain1));
103  }
104  SECTION("with !=")
105  {
106  REQUIRE(GoTo(chain1, If().type("PING")) != GoTo(chain1));
107  REQUIRE(GoTo(chain1, If().type("PING")) != GoTo(chain1, If()));
108  REQUIRE(
109  GoTo(chain1, If().type("PING")) !=
110  GoTo(chain1, If().type("SET_MODE")));
111  REQUIRE(GoTo(chain1, 3) != GoTo(chain1, -3));
112  REQUIRE(GoTo(chain1, 3) != GoTo(chain1));
113  REQUIRE(GoTo(chain1) != GoTo(chain2));
114  REQUIRE_FALSE(GoTo(chain1) != GoTo(chain1));
115  REQUIRE_FALSE(
116  GoTo(chain1, If().type("PING")) != GoTo(chain1, If().type("PING")));
117  REQUIRE_FALSE(GoTo(chain1, 3) != GoTo(chain1, 3));
118  REQUIRE_FALSE(
119  GoTo(chain1, 3, If().type("PING")) !=
120  GoTo(chain1, 3, If().type("PING")));
121  }
122 }
123 
124 
125 TEST_CASE("GoTo's 'action' method determines what to do with a "
126  "packet/address combination.", "[GoTo]")
127 {
128  fakeit::Mock<Chain> accept_mock;
129  fakeit::When(Method(accept_mock, action)).AlwaysReturn(
131  std::shared_ptr<Chain> accept_chain = mock_shared(accept_mock);
132  fakeit::Mock<Chain> reject_mock;
133  fakeit::When(Method(reject_mock, action)).AlwaysReturn(
135  std::shared_ptr<Chain> reject_chain = mock_shared(reject_mock);
136  fakeit::Mock<Chain> continue_mock;
137  fakeit::When(Method(continue_mock, action)).AlwaysReturn(
139  std::shared_ptr<Chain> continue_chain = mock_shared(continue_mock);
140  fakeit::Mock<Chain> default_mock;
141  fakeit::When(Method(default_mock, action)).AlwaysReturn(
143  std::shared_ptr<Chain> default_chain = mock_shared(default_mock);
144  fakeit::Mock<Chain> accept10_mock;
145  fakeit::When(Method(accept10_mock, action)).AlwaysReturn(
146  Action::make_accept(10));
147  std::shared_ptr<Chain> accept10_chain = mock_shared(accept10_mock);
148  auto ping = packet_v2::Packet(to_vector(PingV2()));
149  SECTION("Check call to chain's action method.")
150  {
151  REQUIRE(GoTo(std::make_shared<TestChain>()).action(
152  ping, MAVAddress("192.168")) == Action::make_accept());
153  fakeit::Mock<Chain> mock;
154  fakeit::When(Method(mock, action)).AlwaysReturn(Action::make_accept());
155  std::shared_ptr<Chain> chain = mock_shared(mock);
156  MAVAddress address("192.168");
157  GoTo(chain).action(ping, address);
158  fakeit::Verify(
159  Method(mock, action).Matching([&](auto & a, auto & b)
160  {
161  return a == ping && b == MAVAddress("192.168");
162  })).Once();
163  }
164  SECTION("Delegates to the contained chain if there is no conditional.")
165  {
166  // Without priority.
167  REQUIRE(
168  GoTo(accept_chain).action(ping, MAVAddress("192.168")) ==
170  REQUIRE(
171  GoTo(reject_chain).action(ping, MAVAddress("192.168")) ==
173  REQUIRE(
174  GoTo(continue_chain).action(ping, MAVAddress("192.168")) ==
176  REQUIRE(
177  GoTo(default_chain).action(ping, MAVAddress("192.168")) ==
179  // With priority (adds priority).
180  REQUIRE(
181  GoTo(accept_chain, 3).action(ping, MAVAddress("192.168")) ==
183  // Priority already set (no override).
184  REQUIRE(
185  GoTo(accept10_chain, 3).action(ping, MAVAddress("192.168")) ==
186  Action::make_accept(10));
187  }
188  SECTION("Delegates to the contained chain if the conditional is a match.")
189  {
190  // Without priority.
191  REQUIRE(
192  GoTo(accept_chain, If().to("192.168")).action(
193  ping, MAVAddress("192.168")) == Action::make_accept());
194  REQUIRE(
195  GoTo(reject_chain, If().to("192.168")).action(
196  ping, MAVAddress("192.168")) == Action::make_reject());
197  REQUIRE(
198  GoTo(continue_chain, If().to("192.168")).action(
199  ping, MAVAddress("192.168")) == Action::make_default());
200  REQUIRE(
201  GoTo(default_chain, If().to("192.168")).action(
202  ping, MAVAddress("192.168")) == Action::make_default());
203  // With priority (adds priority).
204  REQUIRE(
205  GoTo(accept_chain, 3, If().to("192.168")).action(
206  ping, MAVAddress("192.168")) == Action::make_accept(3));
207  // Priority already set (no override).
208  REQUIRE(
209  GoTo(accept10_chain, 3, If().to("192.168")).action(
210  ping, MAVAddress("192.168")) == Action::make_accept(10));
211  }
212  SECTION("Returns the continue action if the conditional does not match.")
213  {
214  // Without priority.
215  REQUIRE(
216  GoTo(accept_chain, If().to("172.16")).action(
217  ping, MAVAddress("192.168")) == Action::make_continue());
218  // With priority.
219  REQUIRE(
220  GoTo(accept_chain, 3, If().to("172.16")).action(
221  ping, MAVAddress("192.168")) == Action::make_continue());
222  }
223 }
224 
225 
226 TEST_CASE("GoTo's are printable (without a condition or a priority).", "[GoTo]")
227 {
228  auto chain = std::make_shared<TestChain>();
229  auto ping = packet_v2::Packet(to_vector(PingV2()));
230  GoTo goto_(chain);
232  SECTION("By direct type.")
233  {
234  REQUIRE(str(goto_) == "goto test_chain");
235  }
236  SECTION("By polymorphic type.")
237  {
238  REQUIRE(str(rule) == "goto test_chain");
239  }
240 }
241 
242 
243 TEST_CASE("GoTo's are printable (without a condition but with a priority).",
244  "[GoTo]")
245 {
246  auto chain = std::make_shared<TestChain>();
247  auto ping = packet_v2::Packet(to_vector(PingV2()));
248  GoTo goto_(chain, -3);
249  Rule &rule = goto_;
250  SECTION("By direct type.")
251  {
252  REQUIRE(str(goto_) == "goto test_chain with priority -3");
253  }
254  SECTION("By polymorphic type.")
255  {
256  REQUIRE(str(rule) == "goto test_chain with priority -3");
257  }
258 }
259 
260 
261 TEST_CASE("GoTo's are printable (with a condition but without a priority).",
262  "[GoTo]")
263 {
264  auto chain = std::make_shared<TestChain>();
265  auto ping = packet_v2::Packet(to_vector(PingV2()));
266  GoTo goto_(chain, If().type("PING").from("192.168/8").to("172.16/4"));
267  Rule &rule = goto_;
268  SECTION("By direct type.")
269  {
270  REQUIRE(
271  str(goto_) == "goto test_chain if PING from 192.168/8 to 172.16/4");
272  }
273  SECTION("By polymorphic type.")
274  {
275  REQUIRE(
276  str(rule) == "goto test_chain if PING from 192.168/8 to 172.16/4");
277  }
278 }
279 
280 
281 TEST_CASE("GoTo's are printable (with a condition and a priority).", "[GoTo]")
282 {
283  auto chain = std::make_shared<TestChain>();
284  auto ping = packet_v2::Packet(to_vector(PingV2()));
285  GoTo goto_(chain, -3, If().type("PING").from("192.168/8").to("172.16/4"));
286  Rule &rule = goto_;
287  SECTION("By direct type.")
288  {
289  REQUIRE(
290  str(goto_) ==
291  "goto test_chain with priority -3 "
292  "if PING from 192.168/8 to 172.16/4");
293  }
294  SECTION("By polymorphic type.")
295  {
296  REQUIRE(
297  str(rule) ==
298  "goto test_chain with priority -3 "
299  "if PING from 192.168/8 to 172.16/4");
300  }
301 }
302 
303 
304 TEST_CASE("GoTo's 'clone' method returns a polymorphic copy.", "[GoTo]")
305 {
306  auto chain = std::make_shared<TestChain>();
307  SECTION("Without a priority.")
308  {
309  GoTo goto_(chain, If().type("PING"));
310  Rule &rule = goto_;
311  std::unique_ptr<Rule> polymorphic_copy = rule.clone();
312  REQUIRE(goto_ == *polymorphic_copy);
313  }
314  SECTION("With a priority.")
315  {
316  GoTo goto_(chain, 3, If().type("PING"));
317  Rule &rule = goto_;
318  std::unique_ptr<Rule> polymorphic_copy = rule.clone();
319  REQUIRE(goto_ == *polymorphic_copy);
320  }
321 }
static Action make_reject()
Definition: Action.cpp:113
std::string str(const T &object)
Definition: utility.hpp:128
Rule & rule
Definition: test_GoTo.cpp:231
Definition: If.hpp:35
TEST_CASE("GoTo's are constructable.", "[GoTo]")
Definition: test_GoTo.cpp:37
static Action make_accept(std::optional< int > priority={})
Definition: Action.cpp:100
virtual std::unique_ptr< Rule > clone() const =0
virtual Action action(const Packet &packet, const MAVAddress &address) const
Definition: GoTo.cpp:120
auto ping
Definition: test_GoTo.cpp:229
static Action make_continue()
Definition: Action.cpp:126
GoTo goto_(chain)
static Action make_default()
Definition: Action.cpp:140
Definition: Rule.hpp:38
std::shared_ptr< T > mock_shared(fakeit::Mock< T > &mock)
Definition: common.hpp:33
Definition: GoTo.hpp:44