1/*	$NetBSD: plugin_test.c,v 1.2 2024/02/21 22:52:51 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16#include <inttypes.h>
17#include <limits.h>
18#include <sched.h> /* IWYU pragma: keep */
19#include <setjmp.h>
20#include <stdarg.h>
21#include <stdbool.h>
22#include <stddef.h>
23#include <stdlib.h>
24#include <string.h>
25
26#define UNIT_TESTING
27#include <cmocka.h>
28
29#include <isc/attributes.h>
30#include <isc/dir.h>
31#include <isc/mem.h>
32#include <isc/result.h>
33#include <isc/types.h>
34#include <isc/util.h>
35
36noreturn void
37_fail(const char *const file, const int line);
38
39#include <ns/hooks.h>
40
41#include <tests/ns.h>
42
43/*%
44 * Structure containing parameters for run_full_path_test().
45 */
46typedef struct {
47	const ns_test_id_t id; /* libns test identifier */
48	const char *input;     /* source string - plugin name or path
49				* */
50	size_t output_size;    /* size of target char array to
51				* allocate */
52	isc_result_t result;   /* expected return value */
53	const char *output;    /* expected output string */
54} ns_plugin_expandpath_test_params_t;
55
56/*%
57 * Perform a single ns_plugin_expandpath() check using given parameters.
58 */
59static void
60run_full_path_test(const ns_plugin_expandpath_test_params_t *test,
61		   void **state) {
62	char **target = (char **)state;
63	isc_result_t result;
64
65	REQUIRE(test != NULL);
66	REQUIRE(test->id.description != NULL);
67	REQUIRE(test->input != NULL);
68	REQUIRE(test->result != ISC_R_SUCCESS || test->output != NULL);
69
70	/*
71	 * Prepare a target buffer of given size.  Store it in 'state' so that
72	 * it can get cleaned up by _teardown() if the test fails.
73	 */
74	*target = isc_mem_allocate(mctx, test->output_size);
75
76	/*
77	 * Call ns_plugin_expandpath().
78	 */
79	result = ns_plugin_expandpath(test->input, *target, test->output_size);
80
81	/*
82	 * Check return value.
83	 */
84	if (result != test->result) {
85		fail_msg("# test \"%s\" on line %d: "
86			 "expected result %d (%s), got %d (%s)",
87			 test->id.description, test->id.lineno, test->result,
88			 isc_result_totext(test->result), result,
89			 isc_result_totext(result));
90	}
91
92	/*
93	 * Check output string if return value indicates success.
94	 */
95	if (result == ISC_R_SUCCESS && strcmp(*target, test->output) != 0) {
96		fail_msg("# test \"%s\" on line %d: "
97			 "expected output \"%s\", got \"%s\"",
98			 test->id.description, test->id.lineno, test->output,
99			 *target);
100	}
101
102	isc_mem_free(mctx, *target);
103}
104
105/* test ns_plugin_expandpath() */
106ISC_RUN_TEST_IMPL(ns_plugin_expandpath) {
107	size_t i;
108
109	const ns_plugin_expandpath_test_params_t tests[] = {
110		{
111			NS_TEST_ID("correct use with an absolute path"),
112			.input = "/usr/lib/named/foo.so",
113			.output_size = PATH_MAX,
114			.result = ISC_R_SUCCESS,
115			.output = "/usr/lib/named/foo.so",
116		},
117		{
118			NS_TEST_ID("correct use with a relative path"),
119			.input = "../../foo.so",
120			.output_size = PATH_MAX,
121			.result = ISC_R_SUCCESS,
122			.output = "../../foo.so",
123		},
124		{
125			NS_TEST_ID("correct use with a filename"),
126			.input = "foo.so",
127			.output_size = PATH_MAX,
128			.result = ISC_R_SUCCESS,
129			.output = NAMED_PLUGINDIR "/foo.so",
130		},
131		{
132			NS_TEST_ID("no space at all in target buffer"),
133			.input = "/usr/lib/named/foo.so",
134			.output_size = 0,
135			.result = ISC_R_NOSPACE,
136		},
137		{
138			NS_TEST_ID("target buffer too small to fit input"),
139			.input = "/usr/lib/named/foo.so",
140			.output_size = 1,
141			.result = ISC_R_NOSPACE,
142		},
143		{
144			NS_TEST_ID("target buffer too small to fit NULL byte"),
145			.input = "/foo.so",
146			.output_size = 7,
147			.result = ISC_R_NOSPACE,
148		},
149		{
150			NS_TEST_ID("target buffer too small to fit full path"),
151			.input = "foo.so",
152			.output_size = 7,
153			.result = ISC_R_NOSPACE,
154		},
155	};
156
157	for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
158		run_full_path_test(&tests[i], state);
159	}
160}
161
162ISC_TEST_LIST_START
163
164ISC_TEST_ENTRY_CUSTOM(ns_plugin_expandpath, setup_managers, teardown_managers)
165
166ISC_TEST_LIST_END
167
168ISC_TEST_MAIN
169