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.
24 #include "lease-server.h"
26 #include "test-helpers.h"
27 #include "test-socket-client.h"
29 #define SOCKETDIR "/tmp"
31 #define ARRAY_LENGTH(x) sizeof(x) / sizeof(x[0])
33 /************** Test fixutre functions *************************/
34 struct test_config default_test_config;
36 #define TEST_LEASE_NAME "test-lease"
38 static struct lease_handle test_lease = {
39 .name = TEST_LEASE_NAME,
42 static void test_setup(void)
44 dlm_log_enable_debug(true);
45 setenv("DLM_RUNTIME_PATH", SOCKETDIR, 1);
47 default_test_config = (struct test_config){
52 static void test_shutdown(void)
54 test_config_cleanup(&default_test_config);
57 static struct ls *create_default_server(void)
59 struct lease_handle *leases[] = {
62 struct ls *ls = ls_create(leases, 1);
63 ck_assert_ptr_ne(ls, NULL);
67 /************** Lease server error handling tests *************/
69 /* duplicate_server_failure
71 * Test details: Try to intialize the same server twice
72 * Expected results: ls_create() fails.
74 START_TEST(duplicate_server_failure)
76 struct lease_handle *leases[] = {&test_lease, &test_lease};
77 struct ls *ls = ls_create(leases, 2);
78 ck_assert_ptr_eq(ls, NULL);
82 START_TEST(long_lease_name_failure)
84 char long_lease_name[200];
86 size_t len = sizeof(long_lease_name) - 1;
87 memset(long_lease_name, 'a', len);
88 long_lease_name[len] = '\0';
90 struct lease_handle long_name_lease = {.name = long_lease_name};
92 struct lease_handle *leases[] = {&long_name_lease};
93 struct ls *ls = ls_create(leases, 1);
94 ck_assert_ptr_eq(ls, NULL);
98 static void add_error_tests(Suite *s)
100 TCase *tc = tcase_create("Lease server errors");
102 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
104 tcase_add_test(tc, duplicate_server_failure);
105 tcase_add_test(tc, long_lease_name_failure);
106 suite_add_tcase(s, tc);
109 /************** Client request handling tests ************/
111 /* Test the handling of client requests. Make sure that the
112 * proper struct ls_req are generated for each client request.
115 static void check_request(struct ls_req *req,
116 struct lease_handle *expected_lease,
117 enum ls_req_type expected_type)
119 ck_assert_ptr_eq(req->lease_handle, expected_lease);
120 ck_assert_int_eq(req->type, expected_type);
123 static void get_and_check_request(struct ls *ls,
124 struct lease_handle *expected_lease,
125 enum ls_req_type expected_type)
128 bool req_valid = ls_get_request(ls, &req);
129 ck_assert_int_eq(req_valid, true);
130 check_request(&req, expected_lease, expected_type);
133 /* issue_lease_request_and_release
135 * Test details: Generate a lease request and lease release command from
137 * Expected results: One get lease and one release lease request are returned
138 * from ls_get_request().
140 START_TEST(issue_lease_request_and_release)
142 struct ls *ls = create_default_server();
144 struct client_state *cstate = test_client_start(&default_test_config);
146 get_and_check_request(ls, &test_lease, LS_REQ_GET_LEASE);
147 test_client_stop(cstate);
148 get_and_check_request(ls, &test_lease, LS_REQ_RELEASE_LEASE);
153 /* issue_lease_request_and_early_release
155 * Test details: Close client connection immediately after connecting (before
156 * lease request is processed)
157 * Expected results: Should be the same result as
158 * issue_lease_request_and_release.
160 START_TEST(issue_lease_request_and_early_release)
162 struct ls *ls = create_default_server();
164 struct client_state *cstate = test_client_start(&default_test_config);
166 test_client_stop(cstate);
167 get_and_check_request(ls, &test_lease, LS_REQ_GET_LEASE);
168 get_and_check_request(ls, &test_lease, LS_REQ_RELEASE_LEASE);
173 /* issue_multiple_lease_requests
175 * Test details: Generate multiple lease requests to the same lease server from
176 * multiple clients at the same time
177 * Expected results: One lease request per client is returned from
179 * (Test will process each connection in series and either
180 * keep the current connection or switch a new one.)
181 * Only one client remains connected at the end of the test,
182 * and it returns a validlease release request.
184 START_TEST(issue_multiple_lease_requests)
186 /* List of which client connections to accept.
187 * If the nth element is `false` that client request will be
188 * rejected, and should be reflected in the final configuration
190 bool keep_current_client[] = {false, true, true, false, true};
192 struct lease_handle *leases[] = {
195 struct ls *ls = ls_create(leases, 1);
197 const int clients = ARRAY_LENGTH(keep_current_client);
198 struct test_config configs[clients];
199 struct client_state *cstates[clients];
202 struct ls_client *current_client = NULL;
204 /* Start all clients and accept / reject connections */
205 for (int i = 0; i < clients; i++) {
206 configs[i] = default_test_config;
207 cstates[i] = test_client_start(&configs[i]);
208 ck_assert_int_eq(ls_get_request(ls, &req), true);
209 check_request(&req, &test_lease, LS_REQ_GET_LEASE);
210 if (current_client && keep_current_client[i]) {
211 ls_disconnect_client(ls, req.client);
214 ls_disconnect_client(ls, current_client);
215 current_client = req.client;
219 /* Shut down all clients */
220 for (int i = 0; i < clients; i++)
221 test_client_stop(cstates[i]);
223 /* Check that a valid release is received from the last accepted client
225 ck_assert_int_eq(ls_get_request(ls, &req), true);
226 check_request(&req, &test_lease, LS_REQ_RELEASE_LEASE);
227 ck_assert_ptr_eq(current_client, req.client);
229 /* Check that no other client connections have completed */
230 int connections_completed = 0;
231 for (int i = 0; i < clients; i++) {
232 if (configs[i].connection_completed) {
233 connections_completed++;
234 ck_assert_int_eq(connections_completed, 1);
241 static void add_client_request_tests(Suite *s)
243 TCase *tc = tcase_create("Client request testing");
245 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
247 tcase_add_test(tc, issue_lease_request_and_release);
248 tcase_add_test(tc, issue_lease_request_and_early_release);
249 tcase_add_test(tc, issue_multiple_lease_requests);
250 suite_add_tcase(s, tc);
253 /************** File descriptor sending tests ************/
255 /* Test the sending (and failure to send) of file descriptors
261 * Test details: Send a valid fd to a given client.
262 * Expected results: The correct fd is successfully sent.
264 START_TEST(send_fd_to_client)
266 struct ls *ls = create_default_server();
268 struct client_state *cstate = test_client_start(&default_test_config);
271 bool req_valid = ls_get_request(ls, &req);
272 ck_assert_int_eq(req_valid, true);
273 check_request(&req, &test_lease, LS_REQ_GET_LEASE);
275 /* send an fd to the client*/
276 int test_fd = get_dummy_fd();
277 ck_assert_int_eq(ls_send_fd(ls, req.client, test_fd), true);
279 test_client_stop(cstate);
280 get_and_check_request(ls, &test_lease, LS_REQ_RELEASE_LEASE);
282 ck_assert_int_eq(default_test_config.connection_completed, true);
283 ck_assert_int_eq(default_test_config.has_data, true);
284 check_fd_equality(test_fd, default_test_config.received_fd);
289 /* ls_send_fd_is_noop_when_fd_is_invalid
291 * Test details: Call ls_send_fd() with an invalid fd.
292 * Expected results: No fd is sent to client. The connection to the
295 START_TEST(ls_send_fd_is_noop_when_fd_is_invalid)
297 struct ls *ls = create_default_server();
299 struct client_state *cstate = test_client_start(&default_test_config);
302 bool req_valid = ls_get_request(ls, &req);
303 ck_assert_int_eq(req_valid, true);
304 check_request(&req, &test_lease, LS_REQ_GET_LEASE);
306 int invalid_fd = get_dummy_fd();
309 ck_assert_int_eq(ls_send_fd(ls, req.client, invalid_fd), false);
311 test_client_stop(cstate);
312 get_and_check_request(ls, &test_lease, LS_REQ_RELEASE_LEASE);
313 ck_assert_int_eq(default_test_config.connection_completed, true);
314 ck_assert_int_eq(default_test_config.has_data, false);
319 static void add_fd_send_tests(Suite *s)
321 TCase *tc = tcase_create("File descriptor sending tests");
323 tcase_add_checked_fixture(tc, test_setup, test_shutdown);
325 tcase_add_test(tc, send_fd_to_client);
326 tcase_add_test(tc, ls_send_fd_is_noop_when_fd_is_invalid);
327 suite_add_tcase(s, tc);
336 s = suite_create("DLM lease server tests");
339 add_client_request_tests(s);
340 add_fd_send_tests(s);
342 sr = srunner_create(s);
344 srunner_run_all(sr, CK_NORMAL);
345 number_failed = srunner_ntests_failed(sr);
347 return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;