blob: 43d2468c4f4a1cabc45dd614636737e0068aefd8 [file] [log] [blame]
nstrazd4658eb2000-10-09 20:25:12 +00001/*
2 This is an example quickhitter test based on tests/link03.c. The comments
3 have been changed to explain how the quickhit package can be used
4*/
nstrazd4658eb2000-10-09 20:25:12 +00005/*
6 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of version 2 of the GNU General Public License as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it would be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * Further, this software is distributed without any warranty that it is
17 * free of the rightful claim of any third person regarding infringement
18 * or the like. Any license provided herein, whether implied or
19 * otherwise, applies only to this software file. Patent licenses, if
20 * any, provided herein do not apply to combinations of this program with
21 * other software, or any other product whatsoever.
22 *
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write the Free Software Foundation, Inc., 59
25 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
26 *
27 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
28 * Mountain View, CA 94043, or:
29 *
30 * http://www.sgi.com
31 *
32 * For further information regarding this notice, see:
33 *
34 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
35 *
36 */
nstraz562c7372000-10-10 21:57:51 +000037/* $Id: quickhit.c,v 1.2 2000/10/10 21:57:51 nstraz Exp $ */
nstrazd4658eb2000-10-09 20:25:12 +000038/**********************************************************
39 *
40 * OS Test - Silicon Graphics, Inc.
41 *
42 * TEST IDENTIFIER : link03
43 *
44 * EXECUTED BY : anyone
45 *
46 * TEST TITLE : multi links tests
47 *
48 * PARENT DOCUMENT : usctpl01
49 *
50 * TEST CASE TOTAL : 2
51 *
52 * WALL CLOCK TIME : 1
53 *
54 * CPU TYPES : ALL
55 *
56 * AUTHOR : Richard Logan
57 *
58 * CO-PILOT : William Roske
59 *
60 * DATE STARTED : 03/31/94
61 *
62 * INITIAL RELEASE : UNICOS 7.0
63 *
64 * TEST CASES
65 *
66 * 1.) link(2) returns...(See Description)
67 *
68 * INPUT SPECIFICATIONS
69 * The standard options for system call tests are accepted.
70 * (See the parse_opts(3) man page).
71 * -N #links : Use #links links every iteration
72 *
73 * OUTPUT SPECIFICATIONS
74 *
75 * DURATION
76 * Terminates - with frequency and infinite modes.
77 *
78 * SIGNALS
79 * Uses SIGUSR1 to pause before test if option set.
80 * (See the parse_opts(3) man page).
81 *
82 * RESOURCES
83 * None
84 *
85 * ENVIRONMENTAL NEEDS
86 * No run-time environmental needs.
87 *
88 * SPECIAL PROCEDURAL REQUIREMENTS
89 * None
90 *
91 * INTERCASE DEPENDENCIES
92 * None
93 *
94 * DETAILED DESCRIPTION
95 * This is a Phase I test for the link(2) system call. It is intended
96 * to provide a limited exposure of the system call, for now. It
97 * should/will be extended when full functional tests are written for
98 * link(2).
99 *
100 * Setup:
101 * Setup signal handling.
102 * Pause for SIGUSR1 if option specified.
103 *
104 * Test:
105 * Loop if the proper options are given.
106 * Execute system call
107 * Check return code, if system call failed (return=-1)
108 * Log the errno and Issue a FAIL message.
109 * Otherwise, Issue a PASS message.
110 *
111 * Cleanup:
112 * Print errno log and/or timing stats if options given
113 *
114 *
115 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
116
117#include <sys/types.h>
118#include <sys/fcntl.h>
119#include <sys/stat.h>
120#include <errno.h>
121#include <string.h>
122#include <signal.h>
123 /* test.h and usctest.h are the two header files that are required by the
124 * quickhit package. They contain function and macro declarations which you
125 * can use in your test programs
126 */
127#include "test.h"
128#include "usctest.h"
129
130 /* The setup and cleanup functions are basic parts of a test case. These
131 * steps are usually put in separate functions for clarity. The help function
132 * is only needed when you are adding new command line options.
133 */
134void setup();
135void help();
136void cleanup();
137
138char *TCID="link03"; /* Test program identifier. */
139int TST_TOTAL=2; /* Total number of test cases. */
140extern int Tst_count; /* Test Case counter for tst_* routines */
141extern int Tst_nobuf;
142
143int exp_enos[]={0, 0};
144
145#define BASENAME "lkfile"
146
147char Basename[255];
148char Fname[255];
149int Nlinks=0;
150
151/* To add command line options you need to declare a structure to pass to
152 * parse_opts(). options is the structure used in this example. The format is
153 * the string that should be added to optstring in getopt(3), an integer that
154 * will be used as a flag if the option is given, and a pointer to a string that
155 * should receive the optarg parameter from getopt(3). Here we add a -N
156 * option. Long options are not supported at this time.
157 */
158char *Nlinkarg;
159int Nflag=0;
160
161/* for test specific parse_opts options */
162option_t options[] = {
163 { "N:", &Nflag, &Nlinkarg }, /* -N #links */
164 { NULL, NULL, NULL }
165};
166
167/***********************************************************************
168 * Main
169 ***********************************************************************/
170int
171main(int ac, char **av)
172{
173 int lc; /* loop counter */
174 char *msg; /* message returned from parse_opts */
175 struct stat fbuf, lbuf;
176 int cnt;
177 int nlinks;
178 char lname[255];
179
180 Tst_nobuf=1;
181
182 /***************************************************************
183 * parse standard options
184 ***************************************************************/
185 /* start off by parsing the command line options. We provide a function
186 * that understands many common options to control looping. If you are not
187 * adding any new options, pass NULL in place of options and &help.
188 */
189 if ( (msg=parse_opts(ac, av, options, &help)) != (char *) NULL ) {
190 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
191 tst_exit();
192 }
193
194 if ( Nflag ) {
195 if (sscanf(Nlinkarg, "%i", &Nlinks) != 1 ) {
196 tst_brkm(TBROK, NULL, "--N option arg is not a number");
197 tst_exit();
198 }
199 if ( Nlinks > 1000 ) {
200 tst_resm(TWARN, "--N option arg > 1000 - may get errno:%d (EMLINK)",
201 EMLINK);
202 }
203 }
204
205 /***************************************************************
206 * perform global setup for test
207 ***************************************************************/
208 /* Next you should run a setup routine to make sure your environment is
209 * sane.
210 */
211 setup();
212
213 /* set the expected errnos... */
214 TEST_EXP_ENOS(exp_enos);
215
216 /***************************************************************
217 * check looping state
218 ***************************************************************/
219 /* TEST_LOOPING() is a macro that will make sure the test continues
220 * looping according to the standard command line args.
221 */
222 for (lc=0; TEST_LOOPING(lc); lc++) {
223
224 /* reset Tst_count in case we are looping. */
225 Tst_count=0;
226
227 if ( Nlinks )
228 nlinks = Nlinks;
229 else
230 /* min of 10 links and max of a 100 links */
231 nlinks = (lc%90)+10;
232
233 for(cnt=1; cnt < nlinks; cnt++) {
234
235 sprintf(lname, "%s%d", Basename, cnt);
236 /*
237 * Call link(2)
238 */
nstraz562c7372000-10-10 21:57:51 +0000239 /* Use the TEST() macro to wrap your syscalls. It saves the return
240 * to TEST_RETURN and the errno to TEST_ERRNO
241 */
nstrazd4658eb2000-10-09 20:25:12 +0000242 TEST(link(Fname, lname));
243
244 /* check return code */
245 if ( TEST_RETURN == -1 ) {
nstraz562c7372000-10-10 21:57:51 +0000246 /* To gather stats on errnos returned, log the errno */
nstrazd4658eb2000-10-09 20:25:12 +0000247 TEST_ERROR_LOG(TEST_ERRNO);
nstraz562c7372000-10-10 21:57:51 +0000248 /* If you determine that testing shouldn't continue, report your
249 * results using tst_brkm(). The remaining test cases will be
250 * marked broken. TFAIL is the result type for a test failure,
251 * cleanup is the cleanup routine to call, and the rest is your
252 * message in printf form.
253 */
nstrazd4658eb2000-10-09 20:25:12 +0000254 tst_brkm(TFAIL, cleanup, "link(%s, %s) Failed, errno=%d : %s",
255 Fname, lname, TEST_ERRNO, strerror(TEST_ERRNO));
256 }
257 }
258
259 /***************************************************************
260 * only perform functional verification if flag set (-f not given)
261 ***************************************************************/
262 if ( STD_FUNCTIONAL_TEST ) {
263 stat(Fname, &fbuf);
264
265 for(cnt=1; cnt < nlinks; cnt++) {
266 sprintf(lname, "%s%d", Basename, cnt);
267
268 stat(lname, &lbuf);
269 if ( fbuf.st_nlink <= 1 || lbuf.st_nlink <= 1 ||
270 (fbuf.st_nlink != lbuf.st_nlink) ) {
271
nstraz562c7372000-10-10 21:57:51 +0000272 /* When you have results to report, and testing can
273 * continue, use tst_resm() to record those results. Use
274 * TFAIL if the test case failed and your message in printf
275 * style.
276 */
nstrazd4658eb2000-10-09 20:25:12 +0000277 tst_resm(TFAIL,
278 "link(%s, %s[1-%d]) ret %d for %d files, stat values do not match %d %d",
279 Fname, Basename, nlinks, TEST_RETURN, nlinks,
280 fbuf.st_nlink, lbuf.st_nlink);
281 break;
282 }
283 }
284 if ( cnt >= nlinks ) {
nstraz562c7372000-10-10 21:57:51 +0000285 /* Here the test case passed so we use TPASS */
nstrazd4658eb2000-10-09 20:25:12 +0000286 tst_resm(TPASS,
287 "link(%s, %s[1-%d]) ret %d for %d files, stat linkcounts match %d",
288 Fname, Basename, nlinks, TEST_RETURN, nlinks,
289 fbuf.st_nlink);
290 }
291 }
292 else
293 Tst_count++;
294
nstraz562c7372000-10-10 21:57:51 +0000295 /* Here we clean up after the test case so we can do another iteration.
296 */
nstrazd4658eb2000-10-09 20:25:12 +0000297 for(cnt=1; cnt < nlinks; cnt++) {
298
299 sprintf(lname, "%s%d", Basename, cnt);
300
301 if (unlink(lname) == -1) {
302 tst_res(TWARN, "unlink(%s) Failed, errno=%d : %s",
303 Fname, errno, strerror(errno));
304 }
305 }
306
307 } /* End for TEST_LOOPING */
308
309 /***************************************************************
310 * cleanup and exit
311 ***************************************************************/
312 cleanup();
313
314 return 0;
315} /* End main */
316
317/***************************************************************
318 * help
319 ***************************************************************/
320/* The custom help() function is really simple. Just write your help message to
321 * standard out. Your help function will be called after the standard options
322 * have been printed
323 */
324void
325help()
326{
327 printf(" -N #links : create #links hard links every iteration\n");
328}
329
330/***************************************************************
331 * setup() - performs all ONE TIME setup for this test.
332 ***************************************************************/
333void
334setup()
335{
336 int fd;
337
338 /* You will want to enable some signal handling so you can capture
339 * unexpected signals like SIGSEGV.
340 */
341 tst_sig(NOFORK, DEF_HANDLER, cleanup);
342
343 /* Pause if that option was specified */
344 /* One cavet that hasn't been fixed yet. TEST_PAUSE contains the code to
345 * fork the test with the -c option. You want to make sure you do this
346 * before you create your temporary directory.
347 */
348 TEST_PAUSE;
349
350 /* If you are doing any file work, you should use a temporary directory. We
351 * provide tst_tmpdir() which will create a uniquely named temporary
352 * directory and cd into it. You can now create files in the current
353 * directory without worrying.
354 */
355 tst_tmpdir();
356
357 sprintf(Fname,"%s_%d", BASENAME, getpid());
358 if ((fd = open(Fname,O_RDWR|O_CREAT,0700)) == -1) {
359 tst_brkm(TBROK, cleanup,
360 "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s",
361 Fname, errno, strerror(errno));
362 } else if (close(fd) == -1) {
363 tst_res(TWARN, "close(%s) Failed, errno=%d : %s",
364 Fname, errno, strerror(errno));
365 }
366 sprintf(Basename, "%s_%d.", BASENAME, getpid());
367}
368
369/***************************************************************
370 * cleanup() - performs all ONE TIME cleanup for this test at
371 * completion or premature exit.
372 ***************************************************************/
373void
374cleanup()
375{
376 /*
377 * print timing stats if that option was specified.
378 * print errno log if that option was specified.
379 */
380 TEST_CLEANUP;
381
382 /* If you use a temporary directory, you need to be sure you remove it. Use
383 * tst_rmdir() to do it automatically.
384 */
385 tst_rmdir();
386
387 /* exit with return code appropriate for results */
388 tst_exit();
389}