1 /* Copyright 2020-2021 IGEL Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
25 #include "dlmclient.h"
26 #include "test-helpers.h"
27 #include "test-socket-server.h"
29 #define SOCKETDIR "/tmp"
31 #define TEST_LEASE_NAME "test-lease"
33 /************** Test fixutre functions *************/
34 struct test_config default_test_config;
36 static void test_setup(void)
38 dlm_enable_debug_log(true);
39 setenv("DLM_RUNTIME_PATH", SOCKETDIR, 1);
41 default_test_config = (struct test_config){
42 .lease_name = TEST_LEASE_NAME,
47 static void test_shutdown(void)
49 test_config_cleanup(&default_test_config);
52 /************** Lease manager error tests *************/
54 /* These tests verify that the client library gracefully handles
55 * failures when trying to receive data from the lease manager.
56 * Failures or errors in the lease manager should cause meaningful
57 * errors to be reported by the client. Lease manager errors should
58 * not cause crashes or invalid state in the client */
60 /* manager_connection_err
62 * Test details: Simulate socket connection failure.
63 * Expected results: dlm_get_lease() fails.
65 START_TEST(manager_connection_err)
67 struct server_state *sstate = test_server_start(&default_test_config);
69 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME "-bad");
71 ck_assert_ptr_eq(lease, NULL);
73 test_server_stop(sstate);
77 /* no_data_from_manager
79 * Test details: Close the remote (lease manager) without sending any data.
80 * Currently this means that the lease request has been rejected
83 * TODO: Update this when the client-server protocol is updated to
84 * include the reason for the lease rejection.
86 * Expected results: dlm_get_lease() fails, errno set to EACCESS.
88 START_TEST(no_data_from_manager)
91 struct test_config config = {
92 .lease_name = TEST_LEASE_NAME,
96 struct server_state *sstate = test_server_start(&config);
98 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
100 ck_assert_ptr_eq(lease, NULL);
101 ck_assert_int_eq(errno, EACCES);
103 test_server_stop(sstate);
107 /* no_lease_fd_from_manager
109 * Test details: Simulate receiving response from lease manager with
110 * no fd attached. (i.e. a protocol error)
112 * Expected results: dlm_get_lease() fails, errno set to EPROTO.
114 START_TEST(no_lease_fd_from_manager)
116 /* Receive message from the lease manager with missing lease fd */
117 struct test_config config = {
118 .lease_name = TEST_LEASE_NAME,
119 .send_data_without_fd = true,
122 struct server_state *sstate = test_server_start(&config);
124 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
126 ck_assert_ptr_eq(lease, NULL);
127 ck_assert_int_eq(errno, EPROTO);
129 test_server_stop(sstate);
133 static void add_lease_manager_error_tests(Suite *s)
135 TCase *tc = tcase_create("Lease manager error handling");
137 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
139 tcase_add_test(tc, manager_connection_err);
140 tcase_add_test(tc, no_data_from_manager);
141 tcase_add_test(tc, no_lease_fd_from_manager);
143 suite_add_tcase(s, tc);
146 /************** Lease handling tests *****************/
148 /* These tests verify that the client library handles the received
149 * lease data properly. Receiving the lease fds without leaks,
150 * properly passing the fds to the client application and cleaning
151 * them up on release.
154 static int count_open_fds(void)
157 DIR *dirp = opendir("/proc/self/fd");
158 while ((readdir(dirp) != NULL))
164 /* receive_fd_from_manager
166 * Test details: Successfully receive a file descriptor.
167 * Expected results: dlm_get_lease() succeeds.
168 * dlm_lease_fd() returns the correct fd value.
170 START_TEST(receive_fd_from_manager)
172 struct server_state *sstate = test_server_start(&default_test_config);
174 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
175 ck_assert_ptr_ne(lease, NULL);
177 int received_fd = dlm_lease_fd(lease);
179 int sent_fd = default_test_config.fds[0];
181 check_fd_equality(received_fd, sent_fd);
183 dlm_release_lease(lease);
185 test_server_stop(sstate);
190 /* lease_fd_is_closed_on_release
192 * Test details: Verify that dlm_release_lease() closes the lease fd.
193 * Expected results: lease fd is closed.
195 START_TEST(lease_fd_is_closed_on_release)
197 struct server_state *sstate = test_server_start(&default_test_config);
199 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
200 ck_assert_ptr_ne(lease, NULL);
202 int received_fd = dlm_lease_fd(lease);
204 check_fd_is_open(received_fd);
205 dlm_release_lease(lease);
206 check_fd_is_closed(received_fd);
208 test_server_stop(sstate);
212 /* dlm_lease_fd_always_returns_same_lease
214 * Test details: Verify that dlm_lease_fd() always returns the same value
216 * Expected results: same value is returned when called multiple times.
218 START_TEST(dlm_lease_fd_always_returns_same_lease)
220 struct server_state *sstate = test_server_start(&default_test_config);
222 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
223 ck_assert_ptr_ne(lease, NULL);
225 int received_fd = dlm_lease_fd(lease);
227 ck_assert_int_eq(received_fd, dlm_lease_fd(lease));
228 ck_assert_int_eq(received_fd, dlm_lease_fd(lease));
230 dlm_release_lease(lease);
232 test_server_stop(sstate);
236 START_TEST(verify_that_unused_fds_are_not_leaked)
238 int nopen_fds = count_open_fds();
240 struct test_config config = {
241 .lease_name = TEST_LEASE_NAME,
245 struct server_state *sstate = test_server_start(&config);
247 struct dlm_lease *lease = dlm_get_lease(TEST_LEASE_NAME);
249 ck_assert_ptr_eq(lease, NULL);
250 ck_assert_int_eq(errno, EPROTO);
252 dlm_release_lease(lease);
254 test_server_stop(sstate);
256 test_config_cleanup(&config);
257 ck_assert_int_eq(nopen_fds, count_open_fds());
261 static void add_lease_handling_tests(Suite *s)
263 TCase *tc = tcase_create("Lease processing tests");
265 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
267 tcase_add_test(tc, receive_fd_from_manager);
268 tcase_add_test(tc, lease_fd_is_closed_on_release);
269 tcase_add_test(tc, dlm_lease_fd_always_returns_same_lease);
270 tcase_add_test(tc, verify_that_unused_fds_are_not_leaked);
271 suite_add_tcase(s, tc);
280 s = suite_create("DLM client library tests");
282 add_lease_manager_error_tests(s);
283 add_lease_handling_tests(s);
285 sr = srunner_create(s);
287 srunner_run_all(sr, CK_NORMAL);
288 number_failed = srunner_ntests_failed(sr);
290 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;