Hello everyone,

we have merged support for multiple IPv6 addresses to our release in
RHEL. We tried to ensure it does not break anything and we failed.

I made already some dnsmasq tests in separate repository [1], running in
network namespaces. There are two kinds of tests. Simple shell backed
bats tests in bash. bats and bash packages are required to run them.
Second kind are few tests in beakerlib [2], which is test framework used
in Fedora and RHEL testing. They exist and can test few things.

But now, I have accomplished creating few unit tests [3] for dnsmasq.
They are kind of hack, but they should allow basic testing of options
working. I used cmocka library. Dnsmasq is not very well prepared for
unit testing, but some parts can be tested. It is much easier to test
just code, without providing fake network configuration. I want to use
it to ensure no change in DHCP breaks expected behaviour. It is much
easier to prepare code changes than full fledged functional test,
emulating real request over network.

I would love if you could try it and tell me what you think about it. I
am attaching squished patch, separate commits are at our github [3]. If
someone would like to add some test, please create a pull request!

If you would like to try it:
git clone -b unittests https://github.com/InfrastructureServices/dnsmasq.git
cd dnsmasq
make
cd tests
make
./option_test
./dhcp_test

Since these are related to dnsmasq internals, I think merge to master
would be nice eventually. Some parts of dnsmasq should be adjusted for
easier testing, I have to prepare some changes. It might be starting
block to ensure new releases do not break existing functionality.

Any opinions would be appreciated too.

Cheers,
Petr

1. https://github.com/InfrastructureServices/dnsmasq-tests
2. https://github.com/beakerlib/beakerlib
3. https://github.com/InfrastructureServices/dnsmasq/tree/unittests/tests
-- 
Petr Menšík
Software Engineer
Red Hat, http://www.redhat.com/
email: pemen...@redhat.com
PGP: DFCF908DB7C87E8E529925BC4931CA5B6C9FC5CB
>From 9395cc84f93c63573ba28e4e349c44adb5dbb34d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemen...@redhat.com>
Date: Mon, 4 May 2020 16:26:17 +0200
Subject: [PATCH] Create unittests with dhcp and option tests
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Squashed commit of the following:

commit 715c420bf069a6c4fce2238816ff2c3fe371c4c8
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 16:00:31 2020 +0200

    Add mixed DHCP test entries for both IPv4 and IPv6

    Ensure it works also with both ways.

commit c288ca9651ab0f1b777cc938c8e175f55e3819c2
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 15:42:45 2020 +0200

    Merge all objs and add licenses

    Stop using workarounds for option test, use full objects from dnsmasq,
    without few exceptions.

    Updated also all files to include license headers.

commit 33cdd6a312947cdc7d83f0cbf59d22ffd1ccd036
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 15:20:09 2020 +0200

    Add starting parameters to dnsmasq

    Ensures dnsmasq does not read configuration from the system.

commit 2aed21f9aa1fe42d94bb67d1b0fe630a56096c91
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 15:04:35 2020 +0200

    Fix dhcp test

    Prepare two basic tests for ipv4 parsing and ipv6 parsing in separate
    configuration. Check mac-assigned configuration gets different hostname
    than just hostname matched entry.

commit 4ccf8a664abad1e5079f6422f50fe3500152bbf2
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 15:03:21 2020 +0200

    Do not optimize, fix multiple tests in one file

commit 6408f8d8af43b5727828571fe5d78c69fbd1361f
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 11:22:47 2020 +0200

    Add rule to create cscope

commit 2568d4b18286b6c5d844604fb1fad2631e9378e4
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 11:22:36 2020 +0200

    Add gitignore file

commit d687698363709b872c80f9c6e0d5ae5c7c27cdac
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 11:22:20 2020 +0200

    Create dhcp_test

    Use most of source files with exception of dnsmasq.o.
    Solve undefined symbols with fake test commands.

    Currently compiles, but crashes.

commit e0e686a9106a78c8ecdc0b0a8d42bdcbdbf7f617
Author: Petr Menšík <pemen...@redhat.com>
Date:   Mon May 4 11:22:04 2020 +0200

    Add first basic option test

commit 10e9cf5d0b589af839dd806c6cf7e87ca2e310ce
Author: Petr Menšík <pemen...@redhat.com>
Date:   Sat May 2 10:28:44 2020 +0200

    Basic core for unit tests

    Have to fix yet pending unresolved symbols.
---
 Makefile            |   2 +-
 tests/.gitignore    |   3 +
 tests/Makefile      |  51 +++++++
 tests/dhcp_test.c   | 315 ++++++++++++++++++++++++++++++++++++++++++++
 tests/option_test.c |  47 +++++++
 tests/test.h        |  28 ++++
 tests/testcore.c    |  35 +++++
 tests/testlib.c     |  85 ++++++++++++
 8 files changed, 565 insertions(+), 1 deletion(-)
 create mode 100644 tests/.gitignore
 create mode 100644 tests/Makefile
 create mode 100644 tests/dhcp_test.c
 create mode 100644 tests/option_test.c
 create mode 100644 tests/test.h
 create mode 100644 tests/testcore.c
 create mode 100644 tests/testlib.c

diff --git a/Makefile b/Makefile
index 78e25f0..e390745 100644
--- a/Makefile
+++ b/Makefile
@@ -24,7 +24,7 @@ MANDIR        = $(PREFIX)/share/man
 LOCALEDIR     = $(PREFIX)/share/locale
 BUILDDIR      = $(SRC)
 DESTDIR       = 
-CFLAGS        = -Wall -W -O2
+CFLAGS        = -Wall -W -O2 -ggdb
 LDFLAGS       = 
 COPTS         = 
 RPM_OPT_FLAGS = 
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644
index 0000000..7e4b5f2
--- /dev/null
+++ b/tests/.gitignore
@@ -0,0 +1,3 @@
+*.o
+*_test
+cscope.out
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644
index 0000000..f8606ea
--- /dev/null
+++ b/tests/Makefile
@@ -0,0 +1,51 @@
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 dated June, 1991, or
+# (at your option) version 3 dated 29 June, 2007.
+#
+# 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 <http://www.gnu.org/licenses/>.
+
+# Do not optimize too much. dnsmasq object files are optimized already
+# but tests need easier debugging by default
+CFLAGS=-O0 -Wall -ggdb
+SRC=../src
+CPPFLAGS=-I$(SRC)
+LIBS=-lcmocka
+
+DNSMASQ_OBJS=$(SRC)/option.o $(SRC)/log.o $(SRC)/util.o $(SRC)/poll.o \
+		  $(SRC)/cache.o $(SRC)/network.o $(SRC)/netlink.o $(SRC)/dhcp-common.o \
+		  $(SRC)/dhcp.o $(SRC)/dhcp6.o $(SRC)/rfc2131.o $(SRC)/rfc3315.o \
+		  $(SRC)/rfc1035.o $(SRC)/forward.o $(SRC)/loop.o $(SRC)/lease.o \
+		  $(SRC)/domain.o $(SRC)/radv.o $(SRC)/outpacket.o $(SRC)/arp.o $(SRC)/blockdata.o \
+		  $(SRC)/edns0.o $(SRC)/dump.o
+TESTCORE=testcore.o testlib.o
+TESTCORE_SRCS=test.h testcore.c testlib.c
+
+TEST_OBJS=option_test.o dhcp_test.o
+TEST_SRCS=option_test.c dhcp_test.c
+TESTS=option_test dhcp_test
+
+all: $(TESTS)
+
+option_test: option_test.o $(TESTCORE) $(DNSMASQ_OBJS)
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
+
+dhcp_test: dhcp_test.o $(TESTCORE) $(DNSMASQ_OBJS)
+	$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $+ $(LIBS)
+
+clean:
+	rm -f $(TESTCORE) $(TEST_OBJS) $(TESTS)
+
+cscope.out: $(TESTCORE_SRCS) $(TEST_SRCS)
+	cscope -R -b -s $(SRC)
+
+tags: cscope.out
+
+%.o: %.c
+	$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
diff --git a/tests/dhcp_test.c b/tests/dhcp_test.c
new file mode 100644
index 0000000..d01da9e
--- /dev/null
+++ b/tests/dhcp_test.c
@@ -0,0 +1,315 @@
+// vim: sts=2
+/*
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
+/* DHCP protocol definitions and configuration lookup tests.
+ *
+ * Because dnsmasq uses die() function to report failures,
+ * unsupported options cannot be tested now. */
+
+#include "test.h"
+
+#if 0
+/* dhcp-range, stored in daemon->dhcp */
+/*
+(gdb) p *context
+$23 = {
+  lease_time = 3600,
+  addr_epoch = 0,
+  netmask = {
+    s_addr = 16777215
+  },
+  broadcast = {
+    s_addr = 4279246508
+  },
+  local = {
+    s_addr = 17833644
+  },
+  router = {
+    s_addr = 17833644
+  },
+  start = {
+    s_addr = 84942508
+  },
+  end = {
+    s_addr = 504372908
+  },
+  start6 = {
+    __in6_u = {
+      __u6_addr8 = '\000' <repeats 15 times>,
+      __u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0},
+      __u6_addr32 = {0, 0, 0, 0}
+    }
+  },
+  end6 = {
+    __in6_u = {
+      __u6_addr8 = '\000' <repeats 15 times>,
+      __u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0},
+      __u6_addr32 = {0, 0, 0, 0}
+    }
+  },
+  local6 = {
+    __in6_u = {
+      __u6_addr8 = '\000' <repeats 15 times>,
+      __u6_addr16 = {0, 0, 0, 0, 0, 0, 0, 0},
+      __u6_addr32 = {0, 0, 0, 0}
+    }
+  },
+  prefix = 0,
+  if_index = 0,
+  valid = 0,
+  preferred = 0,
+  saved_valid = 0,
+  ra_time = 0,
+  ra_short_period_start = 0,
+  address_lost_time = 0,
+  template_interface = 0x0,
+  flags = 0,
+  netid = {
+    net = 0x0,
+    next = 0x0
+  },
+  filter = 0x0,
+  next = 0x0,
+  current = 0x0
+}
+*/
+
+/* Request from dhclient over IPv4 */
+/*
+(gdb) p hwaddr[0]
+$8 = 58 ':'
+(gdb) p hwaddr[1]
+$9 = 26 '\032'
+(gdb) p hwaddr[2]
+$10 = 162 '\242'
+(gdb) p hwaddr[3]
+$11 = 54 '6'
+(gdb) p hwaddr[4]
+$12 = 37 '%'
+(gdb) p hwaddr[5]
+$13 = 73 'I'
+(gdb) p hwaddr[6]
+$14 = 0 '\000'
+
+#0  find_config (configs=0x0, context=context@entry=0x55f4f6004750, clid=clid@entry=0x0, clid_len=clid_len@entry=0,
+    hwaddr=hwaddr@entry=0x55f4f60061cc ":\032\242\066%I", hw_len=6, hw_type=1, hostname=0x0, tags=0x7fffc9d51240)
+    at dhcp-common.c:382
+
+(gdb) p /x *(struct dhcp_packet *)dnsmasq_daemon->dhcp_packet.iov_base
+$18 = {
+  op = 0x2,
+  htype = 0x1,
+  hlen = 0x6,
+  hops = 0x0,
+  xid = 0x31505f32,
+  secs = 0x0,
+  flags = 0x0,
+  ciaddr = {
+    s_addr = 0x0
+  },
+  yiaddr = {
+    s_addr = 0x0
+  },
+  siaddr = {
+    s_addr = 0x0
+  },
+  giaddr = {
+    s_addr = 0x0
+  },
+  chaddr = {0x3a, 0x1a, 0xa2, 0x36, 0x25, 0x49, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
+  sname = {0x0 <repeats 64 times>},
+  file = {0x0 <repeats 128 times>},
+  options = {0x63, 0x82, 0x53, 0x63, 0x35, 0x1, 0x3, 0x32, 0x4, 0xac, 0x1e, 0x10, 0x1d, 0x37, 0xd, 0x1, 0x1c, 0x2, 0x79, 0xf,
+    0x6, 0xc, 0x28, 0x29, 0x2a, 0x1a, 0x77, 0x3, 0xff, 0x0 <repeats 283 times>}
+}
+*/
+#endif
+#if 0
+  iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
+			   now, unicast_dest, loopback, &is_inform, pxe_fd, iface_addr, recvtime);
+#endif
+#if 0
+  struct dhcp_packet pkt_data = {
+	  .op=2, .htype=1, .hlen=6, .hops=0,
+	  .xid=0x31505f32,
+	  .secs=0, .flags=0,
+	  { INADDR_ANY },
+	  { INADDR_ANY },
+	  { INADDR_ANY },
+	  { INADDR_ANY },
+	  .chaddr = {0x3a, 0x1a, 0xa2, 0x36, 0x25, 0x49, 0x0, },
+	  .sname = {0, },
+	  .file =  {0, },
+	  .options = { 0x63, 0x82, 0x53, 0x63, 0x35, 0x1, 0x3, 0x32, 0x4, 0xac, 0x1e, 0x10, 0x1d, 0x37, 0xd,
+		  0x1, 0x1c, 0x2, 0x79, 0xf, 0x6, 0xc, 0x28, 0x29, 0x2a, 0x1a, 0x77, 0x3, 0xff, 0x0, },
+  };
+  unsigned char hwaddr[] = { 58, 26, 126, 54, 37, 73, 0 };
+#endif
+
+static void test_dhcp_ipv4(void **state)
+{
+  char *argv[] = {
+	  ARGV_START,
+	  "--dhcp-range=192.168.1.5,192.168.1.10,10",
+	  "--dhcp-host=11:22:33:44:55:66,192.168.1.12,mac-host",
+	  "--dhcp-host=192.168.1.13,only-host",
+  };
+
+  unsigned char *clid = NULL;
+  int clid_len = 0;
+  struct dhcp_context *context;
+  struct dhcp_config *config = NULL;
+  struct hwaddr_config defined_client = {
+	6, 1, { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x0 }, 0, NULL,
+  };
+  struct hwaddr_config undefined_client = {
+	6, 1, { 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x0 }, 0, NULL,
+  };
+
+  (void) state;
+
+  testcore_main(ARRAY_SIZE(argv), argv);
+
+  context = daemon->dhcp;
+
+  assert_true(context);
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       defined_client.hwaddr, defined_client.hwaddr_len,
+		       defined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "mac-host");
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_false(config);
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, "only-host", NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "only-host");
+  assert_false(config->hwaddr);
+}
+
+static void test_dhcp_ipv6(void **state)
+{
+  char *argv[] = {
+	  ARGV_START,
+	  "--dhcp-range=fd27:807d:181c:fb81::d000,fd27:807d:181c:fb81::dfff,64,10",
+	  "--dhcp-host=11:22:33:44:55:66,[fd27:807d:181c:fb81::d12],mac-host",
+	  "--dhcp-host=[fd27:807d:181c:fb81::d13],only-host",
+  };
+
+  unsigned char *clid = NULL;
+  int clid_len = 0;
+  struct dhcp_context *context;
+  struct dhcp_config *config = NULL;
+  struct hwaddr_config defined_client = {
+	6, 1, { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x0 }, 0, NULL,
+  };
+  struct hwaddr_config undefined_client = {
+	6, 1, { 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x0 }, 0, NULL,
+  };
+
+  testcore_main(ARRAY_SIZE(argv), argv);
+
+  context = daemon->dhcp6;
+
+  assert_true(context);
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       defined_client.hwaddr, defined_client.hwaddr_len,
+		       defined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "mac-host");
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_false(config);
+  config = find_config(daemon->dhcp_conf, context, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, "only-host", NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "only-host");
+  assert_false(config->hwaddr);
+}
+
+static void test_dhcp_mixed(void **state)
+{
+  char *argv[] = {
+	  ARGV_START,
+	  "--dhcp-range=192.168.1.5,192.168.1.10,10",
+	  "--dhcp-host=11:22:33:44:55:66,192.168.1.12,mac-host4",
+	  "--dhcp-host=192.168.1.13,only-host",
+	  "--dhcp-range=fd27:807d:181c:fb81::d000,fd27:807d:181c:fb81::dfff,64,10",
+	  "--dhcp-host=11:22:33:44:55:66,[fd27:807d:181c:fb81::d12],mac-host6",
+	  "--dhcp-host=[fd27:807d:181c:fb81::d13],only-host",
+  };
+  unsigned char *clid = NULL;
+  int clid_len = 0;
+  struct dhcp_config *config = NULL;
+  struct hwaddr_config defined_client = {
+	6, 1, { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x0 }, 0, NULL,
+  };
+  struct hwaddr_config undefined_client = {
+	6, 1, { 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x0 }, 0, NULL,
+  };
+
+  testcore_main(ARRAY_SIZE(argv), argv);
+
+  assert_true(daemon->dhcp);
+  assert_true(daemon->dhcp6);
+  config = find_config(daemon->dhcp_conf, daemon->dhcp, clid, clid_len,
+		       defined_client.hwaddr, defined_client.hwaddr_len,
+		       defined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "mac-host4");
+  config = find_config(daemon->dhcp_conf, daemon->dhcp6, clid, clid_len,
+		       defined_client.hwaddr, defined_client.hwaddr_len,
+		       defined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR6);
+  assert_true(config);
+  assert_string_equal(config->hostname, "mac-host6");
+  config = find_config(daemon->dhcp_conf, daemon->dhcp, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR);
+  assert_false(config);
+  config = find_config(daemon->dhcp_conf, daemon->dhcp6, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, NULL, NULL, CONFIG_ADDR6);
+  assert_false(config);
+  config = find_config(daemon->dhcp_conf, daemon->dhcp, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, "only-host", NULL, CONFIG_ADDR);
+  assert_true(config);
+  assert_string_equal(config->hostname, "only-host");
+  assert_false(config->hwaddr);
+  config = find_config(daemon->dhcp_conf, daemon->dhcp6, clid, clid_len,
+		       undefined_client.hwaddr, undefined_client.hwaddr_len,
+		       undefined_client.hwaddr_type, "only-host", NULL, CONFIG_ADDR6);
+  assert_true(config);
+  assert_string_equal(config->hostname, "only-host");
+  assert_false(config->hwaddr);
+}
+
+
+int main(int argc, char *argv[])
+{
+  const struct CMUnitTest tests[] = {
+    cmocka_unit_test(test_dhcp_ipv4),
+    cmocka_unit_test(test_dhcp_ipv6),
+    cmocka_unit_test(test_dhcp_mixed),
+  };
+
+  return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/option_test.c b/tests/option_test.c
new file mode 100644
index 0000000..8b31de4
--- /dev/null
+++ b/tests/option_test.c
@@ -0,0 +1,47 @@
+// vim: sts=2
+/*
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+/* Basic checks for generic options */
+#include "test.h"
+
+/* Because dnsmasq uses die() function to report failures,
+ * unsupported options cannot be tested now. */
+
+static void test_option(void **state)
+{
+  char *argv[] = {
+	  ARGV_START,
+	  "--user=dnsmasq",
+	  "--group=dnsmasq",
+	  "--domain=test",
+	  "--log-queries",
+  };
+  (void) state;
+
+  testcore_main(ARRAY_SIZE(argv), argv);
+  assert_string_equal(daemon->username, "dnsmasq");
+  assert_string_equal(daemon->groupname, "dnsmasq");
+  assert_true(option_bool(OPT_LOG));
+  assert_false(option_bool(OPT_EXTRALOG));
+}
+
+int main(int argc, char *argv[])
+{
+  const struct CMUnitTest tests[] = {
+    cmocka_unit_test(test_option),
+  };
+  
+  return cmocka_run_group_tests(tests, NULL, NULL);
+}
diff --git a/tests/test.h b/tests/test.h
new file mode 100644
index 0000000..cc21113
--- /dev/null
+++ b/tests/test.h
@@ -0,0 +1,28 @@
+// vim: sts=2
+/*
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dnsmasq.h"
+
+#include <setjmp.h>
+#include <cmocka.h>
+
+
+#define ARRAY_SIZE(a)  (sizeof(a)/sizeof((a)[0]))
+#define ARGV_START "dnsmasq", "-C", "/dev/null"
+
+void testcore_main(int argc, char **argv);
diff --git a/tests/testcore.c b/tests/testcore.c
new file mode 100644
index 0000000..8168882
--- /dev/null
+++ b/tests/testcore.c
@@ -0,0 +1,35 @@
+// vim: sts=2
+#include "test.h"
+#include <unistd.h>
+
+struct daemon *daemon = NULL;
+
+/* basic initialization taken from dnsmasq.c */
+void testcore_main(int argc, char **argv)
+{
+  rand_init();
+
+  if (daemon)
+    free(daemon);
+  optind=1;
+  read_opts(argc, argv, "unittest");
+
+#ifdef HAVE_LINUX_NETWORK
+  daemon->kernel_version = kernel_version();
+#endif
+
+  if (daemon->edns_pktsz < PACKETSZ)
+    daemon->edns_pktsz = PACKETSZ;
+
+  /* Min buffer size: we check after adding each record, so there must be 
+     memory for the largest packet, and the largest record so the
+     min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
+     This might be increased is EDNS packet size if greater than the minimum. */ 
+  daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
+  daemon->packet = safe_malloc(daemon->packet_buff_sz);
+  
+  daemon->addrbuff = safe_malloc(ADDRSTRLEN);
+  if (option_bool(OPT_EXTRALOG))
+    daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
+
+}
diff --git a/tests/testlib.c b/tests/testlib.c
new file mode 100644
index 0000000..7301bbc
--- /dev/null
+++ b/tests/testlib.c
@@ -0,0 +1,85 @@
+// vim: sts=2
+/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 dated June, 1991, or
+   (at your option) version 3 dated 29 June, 2007.
+
+   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 <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Generic required calls, faking original functions without functional body.
+ */
+#include "dnsmasq.h"
+
+/* inotify.c */
+#ifdef HAVE_INOTIFY
+void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
+{}
+#endif
+
+/* dnsmasq.c */
+void send_event(int fd, int event, int data, char *msg)
+{}
+void queue_event(int event)
+{}
+int icmp_ping(struct in_addr addr)
+{
+  return 0;
+}
+void send_alarm(time_t event, time_t now)
+{}
+int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
+{
+  return 0;
+}
+
+/* ipset.c / tables.c */
+int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove)
+{
+  return -1;
+}
+
+/* rrfilter.c */
+size_t rrfilter(struct dns_header *header, size_t plen, int mode)
+{
+  return plen;
+}
+
+/* auth.c */
+size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, 
+		   int local_query, int do_bit, int have_pseudoheader) 
+{
+  return 0;
+}
+int in_zone(struct auth_zone *zone, char *name, char **cut)
+{
+  return 0;
+}
+
+/* slaac.c */
+time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
+{
+  return 0;
+}
+
+void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
+{}
+void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases)
+{}
+
+/* helper.c */
+#ifdef HAVE_SCRIPT
+void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t now)
+{}
+void queue_arp(int action, unsigned char *mac, int maclen, int family, union all_addr *addr)
+{}
+#endif
-- 
2.21.1

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Dnsmasq-discuss mailing list
Dnsmasq-discuss@lists.thekelleys.org.uk
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

Reply via email to