1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
12 * the GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 *
18 */
19
20 /*
21 * File: ltpapicmd.c
22 *
23 * Description: This program impliments a command line version of some of the
24 * LTP harness API's. This will enable tests written in shell and
25 * other scripts to report problems and log results in the LTP
26 * harness format. The intent is to have a common format in which
27 * the C tests and tests written in scripts report results in
28 * a common format.
29 *
30 * The following LTP API's are available currently in command line
31 * form:
32 * tst_brk - Print result message and break remaining test cases
33 * tst_brkm - Print result message, including file contents, and
34 * break remaining test cases
35 * tst_res - Print result message, including file contents
36 * tst_resm - Print result message
37 * tst_exit - Exit test with a meaningful exit value
38 *
39 * These are the minimum set of functions or commands required to
40 * report results.
41 *
42 * Exit: All commands exit with
43 * 0 - on success
44 * -1 - on failure
45 *
46 * History
47 * Dec 10 2002 - Created - Manoj Iyer manjo@mail.utexas.edu
48 * Dec 12 2002 - Modified - Code that checked if the environment variables
49 * TCID and TST_TOTAL were set did not print usage message.
50 * Modified code to print usage message in each case.
51 * Dec 16 2002 - Modified - Code to get the test number, gets environment
52 * variable TST_COUNT and initializes tst_count.
53 * Dec 16 2002 - Documentation and comment changes.
54 * Feb 11 2003 - tst_count was set to -1 during init or setup in the script.
55 * this was causing tst_resm to issue a warning message.
56 * This bug is now fixed.
57 *
58 */
59
60 #include <sys/socket.h>
61 #include <stdio.h>
62 #include <string.h>
63 #include <stdlib.h>
64 #include <stdint.h>
65 #include "test.h"
66 #include "usctest.h"
67 #include "safe_macros.h"
68
69 char *TCID; /* Name of the testcase */
70 int TST_TOTAL; /* Total number of testcases */
71
72 static char cmd_name[1024]; /* name by which this program is invoked tst_brk etc */
73 static char *tst_total; /* total number of tests in the file. */
74 static char *tst_cntstr; /* sets the value of tst_count with this value */
75
76
77 /*
78 * Function: ident_ttype - Return test result type.
79 *
80 * Description: This function will return the test result type, it actually
81 * the string that is entered by the user to an integer value that
82 * is understood by the API's.
83 *
84 * Return: test type TPASS, TFAIL, TBROK, TCONF, TWARN, or TINFO
85 * on success
86 * -1 on failure
87 */
ident_ttype(char * tstype)88 int ident_ttype(char *tstype)
89 {
90 /* test result type one of TPASS, TFAIL, etc */
91 if (strcmp(tstype, "TBROK") == 0)
92 return TBROK;
93 else if (strcmp(tstype, "TFAIL") == 0)
94 return TFAIL;
95 else if (strcmp(tstype, "TPASS") == 0)
96 return TPASS;
97 else if (strcmp(tstype, "TCONF") == 0)
98 return TCONF;
99 else if (strcmp(tstype, "TWARN") == 0)
100 return TWARN;
101 else if (strcmp(tstype, "TINFO") == 0)
102 return TINFO;
103 else
104 return -1;
105 }
106
tst_cat_file(const char * filename)107 void tst_cat_file(const char *filename)
108 {
109 const char *cmd[] = {"cat", filename, NULL};
110
111 tst_cmd(NULL, cmd, NULL, NULL, 0);
112 }
113
apicmd_brk(int argc,char * argv[])114 void apicmd_brk(int argc, char *argv[])
115 {
116 int trestype;
117 char *file_name;
118
119 if (argc < 5) {
120 fprintf(stderr, "Usage: %s TTYPE FNAME FUNC STRING\n"
121 "\tTTYPE - Test Result Type; one of TFAIL, TBROK "
122 "and TCONF.\n"
123 "\tFNAME - Print contents of this file after the message\n"
124 "\tFUNC - Cleanup function (ignored), but MUST be provided\n"
125 "\tSTRING - Message explaining the test result\n",
126 cmd_name);
127 exit(1);
128 }
129 trestype = ident_ttype((argv++)[0]);
130 file_name = (argv++)[0];
131 tst_cat_file(file_name);
132 argv++;
133 tst_brkm(trestype, NULL, "%s", *argv);
134
135 }
136
apicmd_res(int argc,char * argv[])137 void apicmd_res(int argc, char *argv[])
138 {
139 int trestype;
140 char *file_name;
141
142 if (argc < 4) {
143 fprintf(stderr, "Usage: %s TTYPE FNAME STRING\n"
144 "\tTTYPE - Test Result Type; one of TFAIL, TBROK "
145 "and TCONF.\n"
146 "\tFNAME - Print contents of this file after the message\n"
147 "\tSTRING - Message explaining the test result\n",
148 cmd_name);
149 exit(1);
150 }
151 trestype = ident_ttype((argv++)[0]);
152 file_name = (argv++)[0];
153 tst_cat_file(file_name);
154 tst_resm(trestype, "%s", *argv);
155 }
156
apicmd_brkm(int argc,char * argv[])157 void apicmd_brkm(int argc, char *argv[])
158 {
159 int trestype;
160
161 if (argc < 4) {
162 fprintf(stderr, "Usage: %s TTYPE FUNC STRING\n"
163 "\tTTYPE - Test Result Type; one of TFAIL, TBROK "
164 "and TCONF.\n"
165 "\tFUNC - Cleanup function (ignored), but MUST be provided\n"
166 "\tSTRING - Message explaining the test result\n",
167 cmd_name);
168 exit(1);
169 }
170 trestype = ident_ttype((argv++)[0]);
171 argv++;
172 tst_brkm(trestype, NULL, "%s", *argv);
173 }
174
apicmd_resm(int argc,char * argv[])175 void apicmd_resm(int argc, char *argv[])
176 {
177 int trestype;
178
179 if (argc < 3) {
180 fprintf(stderr, "Usage: %s TTYPE STRING\n"
181 "\tTTYPE - Test Result Type; one of TFAIL, TBROK"
182 "and TCONF.\n"
183 "\tSTRING - Message explaining the test result\n",
184 cmd_name);
185 exit(1);
186 }
187 trestype = ident_ttype((argv++)[0]);
188 tst_resm(trestype, "%s", *argv);
189 }
190
191 struct param_pair {
192 char *cmd;
193 int value;
194 };
195
apicmd_fs_has_free(int argc,char * argv[])196 int apicmd_fs_has_free(int argc, char *argv[])
197 {
198 if (argc != 3) {
199 fprintf(stderr, "Usage: tst_fs_has_free path required_bytes\n"
200 "path: the pathname of the mounted filesystem\n"
201 "required_bytes: the required free space"
202 " (supports kB, MB and GB suffixes)\n");
203 exit(2);
204 }
205
206 char *endptr;
207 unsigned int required_kib = strtoull(argv[1], &endptr, 0);
208 unsigned int mul = TST_BYTES;
209
210 if (*argv[1] == '\0')
211 goto fs_has_free_err;
212
213 if (*endptr != '\0') {
214 if (!strcasecmp(endptr, "kB")) {
215 mul = TST_KB;
216 } else if (!strcasecmp(endptr, "MB")) {
217 mul = TST_MB;
218 } else if (!strcasecmp(endptr, "GB")) {
219 mul = TST_GB;
220 } else {
221 goto fs_has_free_err;
222 }
223 }
224
225 exit(!tst_fs_has_free(NULL, argv[0], required_kib, mul));
226
227 fs_has_free_err:
228 fprintf(stderr, "%s is not a valid size\n", argv[1]);
229 exit(2);
230 }
231
232 /*
233 * Function: main - entry point of this program
234 *
235 * Description: Parses the arguments to each command. Most commands have in
236 * common atlest 2 arguments, type of test result, which is one of
237 * TPASS, TFAIL, TBROK, TCONF, etc, and a message that describes
238 * the result. Other arguments are a file, the contents of which
239 * are printed after the type of test result and associated message
240 * is printed, also a cleanup function that will be executed.
241 * Currently this function name is ignored but MUST be provided
242 * for compatability reasons.
243 *
244 * The different commands are actually a hard link to this program
245 * the program invokes the appropriate function based on the
246 * command name with which it was invoked.
247 *
248 * Set the values for TCID to the name of the test case.
249 * set the value for TST_TOTAL for total number of tests this is
250 * required in case one test breaks and all following tests also
251 * should be reported as broken.
252 * Set tst_count before every individual test.
253 *
254 * Exit: 0 on success
255 * -1 on failure
256 */
main(int argc,char * argv[])257 int main(int argc, char *argv[])
258 {
259 strcpy(cmd_name, SAFE_BASENAME(NULL, (argv++)[0]));
260
261 TCID = getenv("TCID");
262 tst_total = getenv("TST_TOTAL");
263 tst_cntstr = getenv("TST_COUNT");
264 if (TCID == NULL || tst_total == NULL || tst_cntstr == NULL) {
265 if(!strcmp(cmd_name, "tst_fs_has_free")) {
266 fprintf(stderr,
267 "\nSet variables TCID, TST_TOTAL, and TST_COUNT before each test:\n"
268 "export TCID=<test name>\n"
269 "export TST_TOTAL=<Total Number of Tests >\n"
270 "export TST_COUNT=<Test case number>\n\n");
271 /* Make sure the user knows there's an error. */
272 abort();
273 }
274 } else {
275 TST_TOTAL = atoi(tst_total);
276 tst_count = atoi(tst_cntstr);
277 if (tst_count > 0)
278 tst_count--;
279
280 if (strcmp(TCID, " ") == 0) {
281 fprintf(stderr,
282 "Variable TCID not set, use: TCID=<test name>\n");
283 exit(1);
284 }
285 if (TST_TOTAL <= 0) {
286 fprintf(stderr,
287 "Variable TST_TOTAL is set to 0, must be "
288 "greater than zero\n");
289 exit(1);
290 }
291 }
292
293 if (strcmp(cmd_name, "tst_brk") == 0) {
294 apicmd_brk(argc, argv);
295 } else if (strcmp(cmd_name, "tst_res") == 0) {
296 apicmd_res(argc, argv);
297 } else if (strcmp(cmd_name, "tst_brkm") == 0) {
298 apicmd_brkm(argc, argv);
299 } else if (strcmp(cmd_name, "tst_resm") == 0) {
300 apicmd_resm(argc, argv);
301 } else if (strcmp(cmd_name, "tst_exit") == 0) {
302 tst_exit();
303 } else if (strcmp(cmd_name, "tst_ncpus") == 0) {
304 printf("%li\n", tst_ncpus());
305 } else if (strcmp(cmd_name, "tst_ncpus_conf") == 0) {
306 printf("%li\n", tst_ncpus_conf());
307 } else if (strcmp(cmd_name, "tst_ncpus_max") == 0) {
308 printf("%li\n", tst_ncpus_max());
309 } else if (strcmp(cmd_name, "tst_fs_has_free") == 0) {
310 apicmd_fs_has_free(argc, argv);
311 }
312
313 exit(0);
314 }
315