]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test-resolved-etc-hosts: add tests for /etc/hosts parsing
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 31 Jul 2018 09:01:21 +0000 (11:01 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 1 Aug 2018 10:38:39 +0000 (12:38 +0200)
Calling 'build/test-resolved-etc-hosts filename' parses just that file.
This is useful to test against https://hosts.ubuntu101.co.za/hosts.

src/resolve/meson.build
src/resolve/resolved-etc-hosts.c
src/resolve/resolved-etc-hosts.h
src/resolve/test-resolved-etc-hosts.c [new file with mode: 0644]

index 6d03ebf7f48a71a2fdb2f400d5c6c87a68e120cf..f9c394e0a3136409bfe17a2c2e30346243e7821d 100644 (file)
@@ -192,6 +192,16 @@ tests += [
           libm],
          'ENABLE_RESOLVE'],
 
+        [['src/resolve/test-resolved-etc-hosts.c',
+          'src/resolve/resolved-etc-hosts.c',
+          'src/resolve/resolved-etc-hosts.h'],
+         [libsystemd_resolve_core,
+          libshared],
+         [libgcrypt,
+          libgpg_error,
+          libm],
+         'ENABLE_RESOLVE'],
+
         [['src/resolve/test-resolved-packet.c',
           dns_type_headers],
          [libsystemd_resolve_core,
index a400331b0dd4156bbf08dbd0a38f86561b5c9f38..7b381f0561f757c6ec4264509a4f1fd49b44ead3 100644 (file)
 /* Recheck /etc/hosts at most once every 2s */
 #define ETC_HOSTS_RECHECK_USEC (2*USEC_PER_SEC)
 
-typedef struct EtcHostsItem {
-        struct in_addr_data address;
-
-        char **names;
-} EtcHostsItem;
-
-typedef struct EtcHostsItemByName {
-        char *name;
-
-        struct in_addr_data **addresses;
-        size_t n_addresses, n_allocated;
-} EtcHostsItemByName;
-
 static inline void etc_hosts_item_free(EtcHostsItem *item) {
         strv_free(item->names);
         free(item);
@@ -36,7 +23,7 @@ static inline void etc_hosts_item_by_name_free(EtcHostsItemByName *item) {
         free(item);
 }
 
-static void etc_hosts_free(EtcHosts *hosts) {
+void etc_hosts_free(EtcHosts *hosts) {
         hosts->by_address = hashmap_free_with_destructor(hosts->by_address, etc_hosts_item_free);
         hosts->by_name = hashmap_free_with_destructor(hosts->by_name, etc_hosts_item_by_name_free);
 }
@@ -76,7 +63,7 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
                  * nothing. */
                 item = NULL;
         else {
-                /* If this is a normal address, then, simply add entry mapping it to the specified names */
+                /* If this is a normal address, then simply add entry mapping it to the specified names */
 
                 item = hashmap_get(hosts->by_address, &address);
                 if (!item) {
@@ -161,7 +148,7 @@ static int parse_line(EtcHosts *hosts, unsigned nr, const char *line) {
         return 0;
 }
 
-static int etc_hosts_parse(EtcHosts *hosts, FILE *f) {
+int etc_hosts_parse(EtcHosts *hosts, FILE *f) {
         _cleanup_(etc_hosts_free) EtcHosts t = {};
         char line[LINE_MAX];
         unsigned nr = 0;
index 0498ee3821225831fa5e9a75c07b756730e8de86..caf32a53ddae230c869f3a2bc0e1cfbc5d530106 100644 (file)
@@ -5,5 +5,21 @@
 #include "resolved-dns-question.h"
 #include "resolved-dns-answer.h"
 
+typedef struct EtcHostsItem {
+        struct in_addr_data address;
+
+        char **names;
+} EtcHostsItem;
+
+typedef struct EtcHostsItemByName {
+        char *name;
+
+        struct in_addr_data **addresses;
+        size_t n_addresses, n_allocated;
+} EtcHostsItemByName;
+
+int etc_hosts_parse(EtcHosts *hosts, FILE *f);
+void etc_hosts_free(EtcHosts *hosts);
+
 void manager_etc_hosts_flush(Manager *m);
 int manager_etc_hosts_lookup(Manager *m, DnsQuestion* q, DnsAnswer **answer);
diff --git a/src/resolve/test-resolved-etc-hosts.c b/src/resolve/test-resolved-etc-hosts.c
new file mode 100644 (file)
index 0000000..74a565f
--- /dev/null
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "log.h"
+#include "resolved-etc-hosts.h"
+
+static void test_parse_etc_hosts_system(void) {
+        _cleanup_fclose_ FILE *f = NULL;
+
+        f = fopen("/etc/hosts", "r");
+        if (!f) {
+                assert_se(errno == -ENOENT);
+                return;
+        }
+
+        _cleanup_(etc_hosts_free) EtcHosts hosts = {};
+        assert_se(etc_hosts_parse(&hosts, f) == 0);
+}
+
+static void test_parse_etc_hosts(const char *fname) {
+        _cleanup_(unlink_tempfilep) char
+                t[] = "/tmp/test-resolved-etc-hosts.XXXXXX";
+
+        int fd;
+        _cleanup_fclose_ FILE *f;
+
+        if (fname) {
+                f = fopen(fname, "r");
+                assert_se(f);
+        } else {
+                fd = mkostemp_safe(t);
+                assert_se(fd >= 0);
+
+                f = fdopen(fd, "r+");
+                fputs("1.2.3.4 some.where\n", f);
+                fputs("1.2.3.5 some.where\n", f);
+                fputs("::0 some.where some.other\n", f);
+                fputs("0.0.0.0 black.listed\n", f);
+                fputs("::5 some.where some.other foobar.foo.foo\n", f);
+                fputs("        \n", f);
+                fflush(f);
+                rewind(f);
+        }
+
+        _cleanup_(etc_hosts_free) EtcHosts hosts = {};
+        assert_se(etc_hosts_parse(&hosts, f) == 0);
+
+        if (fname)
+                return;
+                
+        EtcHostsItemByName *bn;
+        assert_se(bn = hashmap_get(hosts.by_name, "some.where"));
+        assert_se(bn->n_addresses == 3);
+        assert_se(bn->n_allocated >= 3);
+
+        assert_se(bn->addresses[0]->family == AF_INET);
+        assert_se(memcmp(&bn->addresses[0]->address.in,
+                         &(struct in_addr) { .s_addr = htobe32(0x01020304) }, 4) == 0);
+        assert_se(bn->addresses[1]->family == AF_INET);
+        assert_se(memcmp(&bn->addresses[1]->address.in,
+                         &(struct in_addr) { .s_addr = htobe32(0x01020305) }, 4) == 0);
+        assert_se(bn->addresses[2]->family == AF_INET6);
+        assert_se(memcmp(&bn->addresses[2]->address.in6,
+                         &(struct in6_addr) { .s6_addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5} }, 16 ) == 0);
+
+        assert_se(bn = hashmap_get(hosts.by_name, "some.other"));
+        assert_se(bn->n_addresses == 1);
+        assert_se(bn->n_allocated >= 1);
+        assert_se(bn->addresses[0]->family == AF_INET6);
+        assert_se(memcmp(&bn->addresses[0]->address.in6,
+                         &(struct in6_addr) { .s6_addr = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5} }, 16 ) == 0);
+}
+
+int main(int argc, char **argv) {
+        log_set_max_level(LOG_DEBUG);
+        log_parse_environment();
+        log_open();
+
+        if (argc == 1)
+                test_parse_etc_hosts_system();
+        test_parse_etc_hosts(argv[1]);
+
+        return 0;
+}