Attention is currently required from: plaisthos.
Hello plaisthos,
I'd like you to do a code review.
Please visit
http://gerrit.openvpn.net/c/openvpn/+/1946?usp=email
to review the following change.
Change subject: tests: add a unit test driver for route.c
......................................................................
tests: add a unit test driver for route.c
route.c has no unit test coverage at all, so there is nowhere to put a
test when touching it. Add a driver and cover the pure helpers it
already exports: the special address predicate, both netmask-to-netbits
conversions, and the IPv6 prefix host-bit masking.
The two conversions disagree on a full-length netmask, where
netmask_to_netbits() reports -1 and netmask_to_netbits2() reports 32.
That is deliberate, callers use the -1 to tell a host route from a
network route, so pin it down rather than leave it to be "fixed" later.
The platform routing calls and the handful of socket helpers route.c
references are stubbed in the test itself rather than linked in. That
keeps the dependency list short, and it makes certain a test can never
reach the real routing table.
Change-Id: I9085c55a7efefd31839b00ec8ec9a6f085574dde
Signed-off-by: Charlie Vigue <[email protected]>
---
M CMakeLists.txt
M tests/unit_tests/openvpn/Makefile.am
A tests/unit_tests/openvpn/test_route.c
3 files changed, 254 insertions(+), 0 deletions(-)
git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/46/1946/1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4eda75b..bf4a0de 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -676,6 +676,7 @@
"test_packet_id"
"test_pkt"
"test_provider"
+ "test_route"
"test_socket"
"test_ssl"
"test_user_pass"
@@ -900,6 +901,18 @@
src/openvpn/base64.c
)
+ target_link_libraries(test_route PUBLIC ${RESOLV_LIBRARIES})
+ target_sources(test_route PRIVATE
+ tests/unit_tests/openvpn/mock_get_random.c
+ tests/unit_tests/openvpn/mock_management.c
+ tests/unit_tests/openvpn/mock_win32_execve.c
+ src/openvpn/env_set.c
+ src/openvpn/otime.c
+ src/openvpn/route.c
+ src/openvpn/run_command.c
+ src/openvpn/socket_util.c
+ )
+
target_link_libraries(test_socket PUBLIC ${RESOLV_LIBRARIES})
target_sources(test_socket PRIVATE
tests/unit_tests/openvpn/mock_get_random.c
diff --git a/tests/unit_tests/openvpn/Makefile.am
b/tests/unit_tests/openvpn/Makefile.am
index f2c7a0d..eb1ff52 100644
--- a/tests/unit_tests/openvpn/Makefile.am
+++ b/tests/unit_tests/openvpn/Makefile.am
@@ -19,6 +19,7 @@
pkt_testdriver \
provider_testdriver \
push_update_msg_testdriver \
+ route_testdriver \
socket_testdriver \
ssl_testdriver \
user_pass_testdriver
@@ -420,3 +421,18 @@
$(top_srcdir)/src/openvpn/env_set.c \
$(top_srcdir)/src/openvpn/run_command.c \
$(top_srcdir)/src/openvpn/socket_util.c
+
+route_testdriver_CFLAGS = -I$(top_srcdir)/src/openvpn
-I$(top_srcdir)/src/compat @TEST_CFLAGS@
+route_testdriver_LDFLAGS = @TEST_LDFLAGS@ -L$(top_srcdir)/src/openvpn
+route_testdriver_SOURCES = test_route.c \
+ mock_msg.c test_common.h \
+ mock_get_random.c \
+ mock_management.c \
+ $(top_srcdir)/src/openvpn/route.c \
+ $(top_srcdir)/src/openvpn/buffer.c \
+ $(top_srcdir)/src/openvpn/env_set.c \
+ $(top_srcdir)/src/openvpn/otime.c \
+ $(top_srcdir)/src/openvpn/platform.c \
+ $(top_srcdir)/src/openvpn/run_command.c \
+ $(top_srcdir)/src/openvpn/socket_util.c \
+ $(top_srcdir)/src/openvpn/win32-util.c
diff --git a/tests/unit_tests/openvpn/test_route.c
b/tests/unit_tests/openvpn/test_route.c
new file mode 100644
index 0000000..db039c1
--- /dev/null
+++ b/tests/unit_tests/openvpn/test_route.c
@@ -0,0 +1,225 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2026 OpenVPN Inc <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "syshead.h"
+
+#include "test_common.h"
+
+#include "route.h"
+#include "networking.h"
+
+/* Stubs for functions route.c references but that no test here reaches.
+ * They assert rather than return quietly, so a test straying onto one
+ * fails loudly instead of silently doing nothing.
+ */
+struct argv
+argv_new(void)
+{
+ assert_true(0);
+ struct argv a = { 0 };
+ return a;
+}
+
+void
+argv_free(struct argv *a)
+{
+ assert_true(0);
+}
+
+bool
+get_ipv6_addr(const char *prefix_str, struct in6_addr *network, unsigned int
*netbits,
+ msglvl_t msglevel)
+{
+ assert_true(0);
+ return false;
+}
+
+in_addr_t
+getaddr(unsigned int flags, const char *hostname, int resolve_retry, bool
*succeeded,
+ struct signal_info *sig_info)
+{
+ assert_true(0);
+ return 0;
+}
+
+/* The routing table is never touched by these tests; stub the platform
+ * layer out so that a mistake cannot reach the system routing table.
+ */
+int
+net_route_v4_add(openvpn_net_ctx_t *ctx, const in_addr_t *dst, int prefixlen,
const in_addr_t *gw,
+ const openvpn_net_iface_t *iface, uint32_t table, int metric)
+{
+ assert_true(0);
+ return -1;
+}
+
+int
+net_route_v6_add(openvpn_net_ctx_t *ctx, const struct in6_addr *dst, int
prefixlen,
+ const struct in6_addr *gw, const openvpn_net_iface_t *iface,
uint32_t table,
+ int metric)
+{
+ assert_true(0);
+ return -1;
+}
+
+int
+net_route_v4_del(openvpn_net_ctx_t *ctx, const in_addr_t *dst, int prefixlen,
const in_addr_t *gw,
+ const openvpn_net_iface_t *iface, uint32_t table, int metric)
+{
+ assert_true(0);
+ return -1;
+}
+
+int
+net_route_v6_del(openvpn_net_ctx_t *ctx, const struct in6_addr *dst, int
prefixlen,
+ const struct in6_addr *gw, const openvpn_net_iface_t *iface,
uint32_t table,
+ int metric)
+{
+ assert_true(0);
+ return -1;
+}
+
+int
+net_route_v4_best_gw(openvpn_net_ctx_t *ctx, const in_addr_t *dst, in_addr_t
*best_gw,
+ openvpn_net_iface_t *best_iface)
+{
+ assert_true(0);
+ return -1;
+}
+
+int
+net_route_v6_best_gw(openvpn_net_ctx_t *ctx, const struct in6_addr *dst,
struct in6_addr *best_gw,
+ openvpn_net_iface_t *best_iface)
+{
+ assert_true(0);
+ return -1;
+}
+
+struct signal_info siginfo_static; /* GLOBAL */
+
+int
+signal_reset(struct signal_info *si, int signum)
+{
+ assert_true(0);
+ return 0;
+}
+
+static void
+test_is_special_addr(void **state)
+{
+ assert_true(is_special_addr("net_gateway"));
+ assert_true(is_special_addr("vpn_gateway"));
+ assert_true(is_special_addr("remote_host"));
+
+ assert_false(is_special_addr("10.0.0.1"));
+ assert_false(is_special_addr("default"));
+ assert_false(is_special_addr(NULL));
+}
+
+static void
+test_netmask_to_netbits(void **state)
+{
+ int netbits;
+
+ assert_true(netmask_to_netbits(0x0a000000, 0xff000000, &netbits)); /* 10/8
*/
+ assert_int_equal(netbits, 8);
+
+ assert_true(netmask_to_netbits(0xc0a80100, 0xffffff00, &netbits)); /*
192.168.1/24 */
+ assert_int_equal(netbits, 24);
+
+ assert_true(netmask_to_netbits(0x00000000, 0x00000000, &netbits)); /*
default route */
+ assert_int_equal(netbits, 0);
+
+ /* a full-length mask reports -1 rather than 32, which is what callers
+ * use to tell "host route" from "network route"
+ */
+ assert_true(netmask_to_netbits(0x0a010203, 0xffffffff, &netbits));
+ assert_int_equal(netbits, -1);
+
+ /* host bits set in the network part */
+ assert_false(netmask_to_netbits(0x0a000001, 0xff000000, &netbits));
+
+ /* not a contiguous netmask */
+ assert_false(netmask_to_netbits(0x0a000000, 0xff00ff00, &netbits));
+}
+
+static void
+test_netmask_to_netbits2(void **state)
+{
+ assert_int_equal(netmask_to_netbits2(0xff000000), 8);
+ assert_int_equal(netmask_to_netbits2(0xffffff00), 24);
+ assert_int_equal(netmask_to_netbits2(0x00000000), 0);
+
+ /* unlike netmask_to_netbits(), this one reports a full-length mask as 32
*/
+ assert_int_equal(netmask_to_netbits2(0xffffffff), 32);
+
+ assert_int_equal(netmask_to_netbits2(0xff00ff00), -1);
+}
+
+static void
+assert_clear_host_bits(const char *addr, unsigned int netbits, const char
*expected)
+{
+ struct route_ipv6 r6;
+ struct in6_addr want;
+
+ CLEAR(r6);
+ assert_int_equal(inet_pton(AF_INET6, addr, &r6.network), 1);
+ assert_int_equal(inet_pton(AF_INET6, expected, &want), 1);
+ r6.netbits = netbits;
+
+ route_ipv6_clear_host_bits(&r6);
+ assert_memory_equal(&r6.network, &want, sizeof(struct in6_addr));
+}
+
+static void
+test_route_ipv6_clear_host_bits(void **state)
+{
+ /* whole bytes cleared */
+ assert_clear_host_bits("2001:db8::1", 64, "2001:db8::");
+ assert_clear_host_bits("2001:db8:dead:beef::1", 32, "2001:db8::");
+
+ /* a prefix that does not fall on a byte boundary */
+ assert_clear_host_bits("2001:db8:0:00ff::1", 60, "2001:db8:0:00f0::");
+ assert_clear_host_bits("2001:db8::ffff", 121, "2001:db8::ff80");
+
+ /* nothing to clear, and everything to clear */
+ assert_clear_host_bits("2001:db8::1", 128, "2001:db8::1");
+ assert_clear_host_bits("2001:db8::1", 0, "::");
+}
+
+const struct CMUnitTest route_tests[] = {
+ cmocka_unit_test(test_is_special_addr),
+ cmocka_unit_test(test_netmask_to_netbits),
+ cmocka_unit_test(test_netmask_to_netbits2),
+ cmocka_unit_test(test_route_ipv6_clear_host_bits),
+};
+
+int
+main(void)
+{
+ openvpn_unit_test_setup();
+ return cmocka_run_group_tests(route_tests, NULL, NULL);
+}
--
To view, visit http://gerrit.openvpn.net/c/openvpn/+/1946?usp=email
To unsubscribe, or for help writing mail filters, visit
http://gerrit.openvpn.net/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: openvpn
Gerrit-Branch: master
Gerrit-Change-Id: I9085c55a7efefd31839b00ec8ec9a6f085574dde
Gerrit-Change-Number: 1946
Gerrit-PatchSet: 1
Gerrit-Owner: chugly <[email protected]>
Gerrit-Reviewer: plaisthos <[email protected]>
Gerrit-CC: openvpn-devel <[email protected]>
Gerrit-Attention: plaisthos <[email protected]>
_______________________________________________
Openvpn-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openvpn-devel