1 /*
2  * libdpkg - Debian packaging suite library routines
3  * t-command.c - test command implementation
4  *
5  * Copyright © 2010-2012 Guillem Jover <guillem@debian.org>
6  *
7  * This is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 #include <compat.h>
23 
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 
30 #include <dpkg/test.h>
31 #include <dpkg/subproc.h>
32 #include <dpkg/command.h>
33 #include <dpkg/dpkg.h>
34 
35 static void
test_command_init(void)36 test_command_init(void)
37 {
38 	struct command cmd;
39 
40 	command_init(&cmd, "/absolute/path/to/progname", NULL);
41 	test_str(cmd.filename, ==, "/absolute/path/to/progname");
42 	test_str(cmd.name, ==, "progname");
43 	test_pass(cmd.argc == 0);
44 	test_pass(cmd.argv[0] == NULL);
45 
46 	command_destroy(&cmd);
47 	test_pass(cmd.filename == NULL);
48 	test_pass(cmd.name == NULL);
49 	test_pass(cmd.argc == 0);
50 	test_pass(cmd.argv == NULL);
51 
52 	command_init(&cmd, "progname", NULL);
53 	test_str(cmd.filename, ==, "progname");
54 	test_str(cmd.name, ==, "progname");
55 	test_pass(cmd.argc == 0);
56 	test_pass(cmd.argv[0] == NULL);
57 
58 	command_destroy(&cmd);
59 
60 	command_init(&cmd, "progname", "description");
61 	test_str(cmd.filename, ==, "progname");
62 	test_str(cmd.name, ==, "description");
63 	test_pass(cmd.argc == 0);
64 	test_pass(cmd.argv[0] == NULL);
65 
66 	command_destroy(&cmd);
67 }
68 
69 static void
test_command_grow_argv(void)70 test_command_grow_argv(void)
71 {
72 	struct command cmd;
73 	int argv_size, i;
74 
75 	command_init(&cmd, "test", NULL);
76 
77 	argv_size = cmd.argv_size + 4;
78 	for (i = 0; i < argv_size; i++)
79 		command_add_arg(&cmd, "arg");
80 
81 	test_pass(cmd.argc == argv_size);
82 	test_pass(cmd.argv_size >= argv_size);
83 	test_str(cmd.argv[0], ==, "arg");
84 	test_str(cmd.argv[argv_size - 1], ==, "arg");
85 	test_pass(cmd.argv[argv_size] == NULL);
86 
87 	command_destroy(&cmd);
88 }
89 
90 static void
test_command_add_arg(void)91 test_command_add_arg(void)
92 {
93 	struct command cmd;
94 
95 	command_init(&cmd, "test", NULL);
96 
97 	command_add_arg(&cmd, "arg 0");
98 	test_pass(cmd.argc == 1);
99 	test_str(cmd.argv[0], ==, "arg 0");
100 	test_pass(cmd.argv[1] == NULL);
101 
102 	command_add_arg(&cmd, "arg 1");
103 	test_pass(cmd.argc == 2);
104 	test_str(cmd.argv[0], ==, "arg 0");
105 	test_str(cmd.argv[1], ==, "arg 1");
106 	test_pass(cmd.argv[2] == NULL);
107 
108 	command_add_arg(&cmd, "arg 2");
109 	test_pass(cmd.argc == 3);
110 	test_str(cmd.argv[0], ==, "arg 0");
111 	test_str(cmd.argv[1], ==, "arg 1");
112 	test_str(cmd.argv[2], ==, "arg 2");
113 	test_pass(cmd.argv[3] == NULL);
114 
115 	command_destroy(&cmd);
116 }
117 
118 static void
test_command_add_argl(void)119 test_command_add_argl(void)
120 {
121 	struct command cmd;
122 	const char *args[] = {
123 		"arg 1",
124 		"arg 2",
125 		"arg 3",
126 		NULL,
127 	};
128 
129 	command_init(&cmd, "test", NULL);
130 
131 	command_add_arg(&cmd, "arg 0");
132 
133 	command_add_argl(&cmd, args);
134 	test_pass(cmd.argc == 4);
135 	test_str(cmd.argv[0], ==, "arg 0");
136 	test_str(cmd.argv[1], ==, "arg 1");
137 	test_str(cmd.argv[2], ==, "arg 2");
138 	test_str(cmd.argv[3], ==, "arg 3");
139 	test_pass(cmd.argv[4] == NULL);
140 
141 	command_destroy(&cmd);
142 }
143 
144 static void
test_command_add_args(void)145 test_command_add_args(void)
146 {
147 	struct command cmd;
148 
149 	command_init(&cmd, "test", NULL);
150 
151 	command_add_arg(&cmd, "arg 0");
152 
153 	command_add_args(&cmd, "arg 1", "arg 2", "arg 3", NULL);
154 	test_pass(cmd.argc == 4);
155 	test_str(cmd.argv[0], ==, "arg 0");
156 	test_str(cmd.argv[1], ==, "arg 1");
157 	test_str(cmd.argv[2], ==, "arg 2");
158 	test_str(cmd.argv[3], ==, "arg 3");
159 	test_pass(cmd.argv[4] == NULL);
160 
161 	command_destroy(&cmd);
162 }
163 
164 static void
test_command_exec(void)165 test_command_exec(void)
166 {
167 	struct command cmd;
168 	pid_t pid;
169 	int ret;
170 
171 	command_init(&cmd, "true", "exec test");
172 
173 	command_add_arg(&cmd, "arg 0");
174 	command_add_arg(&cmd, "arg 1");
175 
176 	pid = subproc_fork();
177 
178 	if (pid == 0)
179 		command_exec(&cmd);
180 
181 	ret = subproc_reap(pid, "command exec test", 0);
182 	test_pass(ret == 0);
183 }
184 
185 static void
test_command_shell(void)186 test_command_shell(void)
187 {
188 	pid_t pid;
189 	int ret;
190 
191 	pid = subproc_fork();
192 	if (pid == 0)
193 		command_shell("true", "command shell pass test");
194 	ret = subproc_reap(pid, "command shell pass test", 0);
195 	test_pass(ret == 0);
196 
197 	pid = subproc_fork();
198 	if (pid == 0)
199 		command_shell("false", "command shell fail test");
200 	ret = subproc_reap(pid, "command shell fail test", SUBPROC_RETERROR);
201 	test_fail(ret == 0);
202 
203 	unsetenv("SHELL");
204 	pid = subproc_fork();
205 	if (pid == 0)
206 		command_shell("true", "command default shell test");
207 	ret = subproc_reap(pid, "command default shell test", 0);
208 	test_pass(ret == 0);
209 }
210 
TEST_ENTRY(test)211 TEST_ENTRY(test)
212 {
213 	test_plan(49);
214 
215 	test_command_init();
216 	test_command_grow_argv();
217 	test_command_add_arg();
218 	test_command_add_argl();
219 	test_command_add_args();
220 	test_command_exec();
221 	test_command_shell();
222 }
223