resolved: tests for dns_query_go() -- with and without network link

This commit is contained in:
James Coglan
2024-07-23 14:17:23 +01:00
parent 7d5ad4f88e
commit 16078b8172
+102
View File
@@ -3,6 +3,9 @@
#include "log.h"
#include "resolved-dns-query.h"
#include "resolved-dns-rr.h"
#include "resolved-dns-scope.h"
#include "resolved-dns-server.h"
#include "resolved-link.h"
#include "resolved-manager.h"
#include "tests.h"
@@ -614,4 +617,103 @@ TEST(dns_query_process_cname_many_success_match_multiple_cname) {
dns_resource_key_unref(key);
}
/* ================================================================
* dns_query_go()
* ================================================================ */
/* Testing this function is somewhat problematic since, in addition to setting up the state for query
* candidates, their scopes and transactions, it also directly initiates I/O to files and the network. In
* particular:
*
* - The very first thing it does is try to respond to the query by reading the system /etc/hosts file, which
* may be symlinked to a SystemD resource. Ideally we could test this without accessing global files.
*
* - dns_scope_get_dns_server() calls manager_get_dns_server(), which tries to read /etc/resolv.conf.
*
* - A potential solution to these issues would be to let these file paths be configured instead of
* hard-coded into the source.
*
* - dns_scope_good_domain(), by checking dns_scope_get_dns_server(), will not match with a scope that does
* not have a server configured, either on the scope's link (if it has one) or the manager's main/fallback
* server. Configuring a server means that dns_query_candidate_go() and then dns_transaction_go() will send
* UDP/TCP traffic to that server. Ideally we'd like to test that we can set up all the candidate and
* transaction state without actually causing any requests to be sent.
*/
static void dns_scope_freep(DnsScope **s) {
dns_scope_free(*s);
}
typedef struct GoConfig {
bool use_link;
} GoConfig;
static GoConfig mk_go_config(void) {
return (GoConfig) {
.use_link = false
};
}
static void exercise_dns_query_go(GoConfig *cfg) {
Manager manager = {};
Link *link = NULL;
_cleanup_(dns_server_unrefp) DnsServer *server = NULL;
_cleanup_(dns_scope_freep) DnsScope *scope = NULL;
_cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
_cleanup_(dns_query_freep) DnsQuery *query = NULL;
DnsProtocol protocol = DNS_PROTOCOL_DNS;
int family = AF_INET;
int flags = SD_RESOLVED_FLAGS_MAKE(protocol, family, false, false);
int ifindex;
union in_addr_union server_addr = { .in.s_addr = htobe32(0x7f000001) };
const char *server_name = "localhost";
uint16_t port = 53;
DnsServerType type;
if (cfg->use_link) {
ifindex = 1;
ASSERT_OK(link_new(&manager, &link, ifindex));
ASSERT_NOT_NULL(link);
type = DNS_SERVER_LINK;
} else {
ifindex = 0;
link = NULL;
type = DNS_SERVER_FALLBACK;
}
ASSERT_OK(sd_event_new(&manager.event));
ASSERT_NOT_NULL(manager.event);
ASSERT_OK(dns_server_new(&manager, &server, type, link, family, &server_addr,
port, ifindex, server_name, RESOLVE_CONFIG_SOURCE_DBUS));
ASSERT_NOT_NULL(server);
ASSERT_OK(dns_scope_new(&manager, &scope, link, protocol, family));
ASSERT_NOT_NULL(scope);
ASSERT_OK(dns_question_new_address(&question, AF_INET, "www.example.com", false));
ASSERT_NOT_NULL(question);
ASSERT_OK(dns_query_new(&manager, &query, question, question, NULL, ifindex, flags));
ASSERT_NOT_NULL(query);
ASSERT_OK(dns_query_go(query));
dns_server_unref(server);
sd_event_unref(manager.event);
}
TEST(dns_query_go) {
GoConfig cfg1 = mk_go_config();
exercise_dns_query_go(&cfg1);
GoConfig cfg2 = mk_go_config();
cfg2.use_link = true;
exercise_dns_query_go(&cfg2);
}
DEFINE_TEST_MAIN(LOG_DEBUG);