summaryrefslogtreecommitdiff
path: root/libdhcp/tests/test_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdhcp/tests/test_client.c')
-rw-r--r--libdhcp/tests/test_client.c118
1 files changed, 118 insertions, 0 deletions
diff --git a/libdhcp/tests/test_client.c b/libdhcp/tests/test_client.c
new file mode 100644
index 0000000..90efd01
--- /dev/null
+++ b/libdhcp/tests/test_client.c
@@ -0,0 +1,118 @@
+/* libdhcp/tests/test_client.c - Tests for libdhcp client
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <string.h> /* for memcpy() */
+
+#include <libcr/coroutine.h>
+#include <libhw/generic/net.h>
+#include <libhw/host_alarmclock.h>
+
+#include <libdhcp/client.h>
+
+#include "test.h"
+
+/******************************************************************************/
+
+struct test_udp {
+};
+LO_IMPLEMENTATION_H(io_closer, struct test_udp, test_udp);
+LO_IMPLEMENTATION_C(io_closer, struct test_udp, test_udp, static);
+LO_IMPLEMENTATION_H(net_packet_conn, struct test_udp, test_udp);
+LO_IMPLEMENTATION_C(net_packet_conn, struct test_udp, test_udp, static);
+
+static ssize_t test_udp_sendto(struct test_udp *LM_UNUSED(self), void *LM_UNUSED(buf), size_t len, struct net_ip4_addr LM_UNUSED(node), uint16_t LM_UNUSED(port)) {
+ return len;
+}
+
+static ssize_t test_udp_recvfrom(struct test_udp *LM_UNUSED(self), void *buf, size_t len, struct net_ip4_addr *ret_node, uint16_t *ret_port) {
+ static const uint8_t resp_offer[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x02,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ static const uint8_t resp_ack[] = {0x02,0x01,0x06,0x00,0xE8,0x40,0xC6,0x79,0x00,0x01,0x80,0x00,0x00,0x00,0x00,0x00,0xC0,0xA8,0x0A,0x78,0xC0,0xA8,0x0A,0x01,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x82,0x53,0x63,0x35,0x01,0x05,0x36,0x04,0xC0,0xA8,0x0A,0x01,0x33,0x04,0x00,0x00,0xA8,0xC0,0x3A,0x04,0x00,0x00,0x54,0x60,0x3B,0x04,0x00,0x00,0x93,0xA8,0x01,0x04,0xFF,0xFF,0xFF,0x00,0x1C,0x04,0xC0,0xA8,0x0A,0xFF,0x03,0x04,0xC0,0xA8,0x0A,0x01,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+ static unsigned cnt = 0;
+ const void *resp;
+ size_t resp_len;
+ switch (cnt++) {
+ case 0: resp = resp_offer; resp_len = sizeof(resp_offer); break;
+ case 1: resp = resp_ack; resp_len = sizeof(resp_ack); break;
+ default: return -NET_ERECV_TIMEOUT;
+ }
+ test_assert(len >= resp_len);
+ memcpy(buf, resp, resp_len);
+ *ret_node = ((struct net_ip4_addr){{192,168,10,1}});
+ *ret_port = 67;
+ return resp_len;
+}
+
+static void test_udp_set_recv_deadline(struct test_udp *LM_UNUSED(self), uint64_t LM_UNUSED(ns_since_boot)) {
+ /* Do nothing? */
+}
+
+static int test_udp_close(struct test_udp *LM_UNUSED(self)) {
+ assert_notreached("not implemented");
+}
+
+/******************************************************************************/
+
+struct test_iface {
+ struct net_iface_config cfg;
+
+ struct test_udp conn;
+};
+LO_IMPLEMENTATION_H(net_iface, struct test_iface, test);
+LO_IMPLEMENTATION_C(net_iface, struct test_iface, test, static);
+
+static struct net_eth_addr test_hwaddr(struct test_iface *LM_UNUSED(self)) {
+ struct net_eth_addr ret = {{1, 2, 3, 4, 5, 6}};
+ return ret;
+}
+
+static void test_ifup(struct test_iface *LM_UNUSED(self), struct net_iface_config LM_UNUSED(cfg)) {
+ cr_exit();
+}
+
+static void test_ifdown(struct test_iface *LM_UNUSED(self)) {
+ assert_notreached("not implemented");
+}
+
+static bool test_arp_ping(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(addr)) {
+ return false;
+}
+
+static lo_interface net_stream_listener test_tcp_listen(struct test_iface *LM_UNUSED(self), uint16_t LM_UNUSED(local_port)) {
+ assert_notreached("not implemented");
+}
+
+static lo_interface net_stream_conn test_tcp_dial(struct test_iface *LM_UNUSED(self), struct net_ip4_addr LM_UNUSED(remote_node), uint16_t LM_UNUSED(remote_port)) {
+ assert_notreached("not implemented");
+}
+
+static lo_interface net_packet_conn test_udp_conn(struct test_iface *self, uint16_t local_port) {
+ bool once = false;
+ test_assert(local_port == 68);
+ test_assert(!once);
+ once = true;
+ return lo_box_test_udp_as_net_packet_conn(&self->conn);
+}
+
+/******************************************************************************/
+
+COROUTINE dhcp_cr(void *) {
+ cr_begin();
+ struct test_iface iface = {};
+ dhcp_client_main(lo_box_test_as_net_iface(&iface), "test-client");
+ cr_end();
+}
+
+int main() {
+ struct hostclock clock_monotonic = {
+ .clock_id = CLOCK_MONOTONIC,
+ };
+ bootclock = lo_box_hostclock_as_alarmclock(&clock_monotonic);
+
+ coroutine_add("dhcp", dhcp_cr, NULL);
+ coroutine_main();
+ return 0;
+}