From: Zbigniew Jędrzejewski-Szmek Date: Tue, 31 Jul 2018 09:01:21 +0000 (+0200) Subject: test-resolved-etc-hosts: add tests for /etc/hosts parsing X-Git-Tag: v240~874^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=78fc21a11a5ac7e090b309ed89b264dddba3a122;p=thirdparty%2Fsystemd.git test-resolved-etc-hosts: add tests for /etc/hosts parsing Calling 'build/test-resolved-etc-hosts filename' parses just that file. This is useful to test against https://hosts.ubuntu101.co.za/hosts. --- diff --git a/src/resolve/meson.build b/src/resolve/meson.build index 6d03ebf7f48..f9c394e0a31 100644 --- a/src/resolve/meson.build +++ b/src/resolve/meson.build @@ -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, diff --git a/src/resolve/resolved-etc-hosts.c b/src/resolve/resolved-etc-hosts.c index a400331b0dd..7b381f0561f 100644 --- a/src/resolve/resolved-etc-hosts.c +++ b/src/resolve/resolved-etc-hosts.c @@ -12,19 +12,6 @@ /* 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; diff --git a/src/resolve/resolved-etc-hosts.h b/src/resolve/resolved-etc-hosts.h index 0498ee38212..caf32a53dda 100644 --- a/src/resolve/resolved-etc-hosts.h +++ b/src/resolve/resolved-etc-hosts.h @@ -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 index 00000000000..74a565fae71 --- /dev/null +++ b/src/resolve/test-resolved-etc-hosts.c @@ -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; +}