Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SSSD tests: Server instantiation
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include <sys/types.h>
24 : #include <sys/stat.h>
25 : #include <fcntl.h>
26 :
27 : #include <popt.h>
28 : #include "util/util.h"
29 : #include "util/strtonum.h"
30 : #include "tests/cmocka/common_mock.h"
31 :
32 2 : static void wait_for_fg_server(pid_t pid)
33 : {
34 : pid_t wpid;
35 : int status;
36 :
37 2 : assert_int_not_equal(pid, -1);
38 :
39 2 : wpid = waitpid(pid, &status, 0);
40 2 : assert_int_equal(wpid, pid);
41 2 : assert_true(WIFEXITED(status));
42 2 : assert_int_equal(WEXITSTATUS(status), 0);
43 2 : }
44 :
45 1 : static void wait_for_bg_server(const char *pidfile)
46 : {
47 : int fd;
48 : uint32_t tmp;
49 : char buf[16];
50 : pid_t pid;
51 : int ret;
52 : int count;
53 :
54 1 : count = 0;
55 : do {
56 : struct stat sb;
57 :
58 2 : count++;
59 2 : if (count > 200) {
60 0 : fail();
61 0 : break;
62 : }
63 :
64 2 : ret = stat(pidfile, &sb);
65 2 : usleep(50000);
66 2 : } while (ret != 0);
67 :
68 : /* read the pidfile */
69 1 : fd = open(pidfile, O_RDONLY);
70 1 : assert_false(fd < 0);
71 :
72 1 : ret = read(fd, buf, sizeof(buf));
73 1 : close(fd);
74 1 : assert_false(ret <= 0);
75 :
76 1 : buf[sizeof(buf) - 1] = '\0';
77 :
78 1 : errno = 0;
79 1 : tmp = strtouint32(buf, NULL, 10);
80 1 : assert_int_not_equal(tmp, 0);
81 1 : assert_int_equal(errno, 0);
82 :
83 1 : pid = (pid_t) (tmp);
84 :
85 : /* Make sure the daemon goes away! */
86 1 : ret = kill(pid, SIGTERM);
87 1 : fprintf(stderr, "killing %u\n", pid);
88 1 : assert_true(ret == 0);
89 :
90 1 : unlink(pidfile);
91 1 : }
92 :
93 1 : void test_run_as_root_fg(void **state)
94 : {
95 : int ret;
96 : struct main_context *main_ctx;
97 : pid_t pid;
98 :
99 : /* Must root as root, real or fake */
100 1 : assert_int_equal(geteuid(), 0);
101 :
102 1 : pid = fork();
103 2 : if (pid == 0) {
104 1 : ret = server_setup(__FUNCTION__, 0, 0, 0,
105 : __FUNCTION__, &main_ctx);
106 1 : assert_int_equal(ret, 0);
107 1 : exit(0);
108 : }
109 1 : wait_for_fg_server(pid);
110 1 : }
111 :
112 1 : void test_run_as_sssd_fg(void **state)
113 : {
114 : int ret;
115 : struct main_context *main_ctx;
116 : struct passwd *sssd;
117 : pid_t pid;
118 :
119 : /* Must root as root, real or fake */
120 1 : assert_int_equal(geteuid(), 0);
121 :
122 1 : sssd = getpwnam("sssd");
123 1 : assert_non_null(sssd);
124 :
125 1 : pid = fork();
126 2 : if (pid == 0) {
127 1 : ret = server_setup(__FUNCTION__, 0, sssd->pw_uid, sssd->pw_gid,
128 : __FUNCTION__, &main_ctx);
129 1 : assert_int_equal(ret, 0);
130 1 : exit(0);
131 : }
132 1 : wait_for_fg_server(pid);
133 1 : }
134 :
135 1 : void test_run_as_root_daemon(void **state)
136 : {
137 : int ret;
138 : struct main_context *main_ctx;
139 : pid_t pid;
140 : char *pidfile;
141 :
142 : /* Must root as root, real or fake */
143 1 : assert_int_equal(geteuid(), 0);
144 :
145 1 : pidfile = talloc_asprintf(NULL, "%s/%s.pid", TEST_PID_PATH, __FUNCTION__);
146 :
147 : /* Make sure there are no leftovers */
148 1 : unlink(pidfile);
149 :
150 1 : pid = fork();
151 2 : if (pid == 0) {
152 1 : ret = server_setup(__FUNCTION__, FLAGS_PID_FILE,
153 : 0, 0, __FUNCTION__, &main_ctx);
154 1 : assert_int_equal(ret, 0);
155 :
156 1 : server_loop(main_ctx);
157 0 : exit(0);
158 : }
159 :
160 1 : wait_for_bg_server(pidfile);
161 1 : talloc_free(pidfile);
162 1 : }
163 :
164 1 : int main(int argc, const char *argv[])
165 : {
166 : poptContext pc;
167 : int opt;
168 : int rv;
169 6 : struct poptOption long_options[] = {
170 : POPT_AUTOHELP
171 5 : SSSD_DEBUG_OPTS
172 : POPT_TABLEEND
173 : };
174 :
175 1 : const struct CMUnitTest tests[] = {
176 : cmocka_unit_test(test_run_as_root_fg),
177 : cmocka_unit_test(test_run_as_sssd_fg),
178 : cmocka_unit_test(test_run_as_root_daemon),
179 : };
180 :
181 : /* Set debug level to invalid value so we can deside if -d 0 was used. */
182 1 : debug_level = SSSDBG_INVALID;
183 :
184 1 : pc = poptGetContext(argv[0], argc, argv, long_options, 0);
185 1 : while((opt = poptGetNextOpt(pc)) != -1) {
186 : switch(opt) {
187 : default:
188 0 : fprintf(stderr, "\nInvalid option %s: %s\n\n",
189 : poptBadOption(pc, 0), poptStrerror(opt));
190 0 : poptPrintUsage(pc, stderr, 0);
191 0 : return 1;
192 : }
193 : }
194 1 : poptFreeContext(pc);
195 :
196 1 : DEBUG_CLI_INIT(debug_level);
197 :
198 : /* Even though normally the tests should clean up after themselves
199 : * they might not after a failed run. Remove the old db to be sure */
200 1 : tests_set_cwd();
201 1 : test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
202 1 : test_dom_suite_setup(TEST_DB_PATH);
203 :
204 1 : rv = cmocka_run_group_tests(tests, NULL, NULL);
205 1 : if (rv != 0) {
206 0 : test_dom_suite_cleanup(TEST_DB_PATH, CONFDB_FILE, NULL);
207 : }
208 :
209 1 : return rv;
210 : }
|