query_module01.c revision 4bb656a129f7507823e9e6d6b98b1a02fd80ef89
1/* 2 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * You should have received a copy of the GNU General Public License along 13 * with this program; if not, write the Free Software Foundation, Inc., 59 14 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 15 * 16 */ 17/********************************************************** 18 * 19 * TEST IDENTIFIER : query_module01 20 * 21 * EXECUTED BY : root / superuser 22 * 23 * TEST TITLE : Checking functionality of query_module(2) 24 * 25 * TEST CASE TOTAL : 6 26 * 27 * AUTHOR : Madhu T L <madhu.tarikere@wipro.com> 28 * 29 * SIGNALS 30 * Uses SIGUSR1 to pause before test if option set. 31 * (See the parse_opts(3) man page). 32 * 33 * DESCRIPTION 34 * Verify that, 35 * 1. query_module(2) is successful for NULL module name, which argument 36 * set to 0. 37 * 2. query_module(2) is successful for NULL module name, which argument 38 * set to QM_MODULES. 39 * 3. query_module(2) is successful for valid module name, which argument 40 * set to QM_DEPS. 41 * 4. query_module(2) is successful for valid module name, which argument 42 * set to QM_REFS. 43 * 5. query_module(2) is successful for valid module name, which argument 44 * set to QM_INFO. 45 * 6. query_module(2) is successful for valid module name, which argument 46 * set to QM_SYMBOLS. 47 * 48 * Setup: 49 * Setup signal handling. 50 * Test caller is superuser 51 * Initialize long module name 52 * Pause for SIGUSR1 if option specified. 53 * 54 * Test: 55 * Loop if the proper options are given. 56 * Execute system call 57 * Check return value and functionality, if success, 58 * Issue PASS message 59 * Otherwise, 60 * Issue FAIL message 61 * 62 * Cleanup: 63 * Print errno log and/or timing stats if options given 64 * 65 * USAGE: <for command-line> 66 * query_module01 [-c n] [-e] [-f] [-h] [-i n] [-I x] [-p] [-P x] [-t] 67 * where, -c n : Run n copies concurrently. 68 * -e : Turn on errno logging. 69 * -f : Turn off functional testing 70 * -h : Show help screen 71 * -i n : Execute test n times. 72 * -I x : Execute test for x seconds. 73 * -p : Pause for SIGUSR1 before starting 74 * -P x : Pause for x seconds between iterations. 75 * -t : Turn on syscall timing. 76 * 77 * RESTRICTIONS 78 * -c option has no effect for this testcase, even if used allows only 79 * one instance to run at a time. 80 * 81 * CHANGES 82 * 83 * 12/03/02 Added "force" to insmod to ignore kernel version. 84 * -Robbie Williamson <robbiew@us.ibm.com> 85 * 86 ****************************************************************/ 87 88#include <errno.h> 89#include <pwd.h> 90#include <sys/types.h> 91#include <unistd.h> 92#include <limits.h> 93#include <asm/atomic.h> 94#include <linux/module.h> 95#include "test.h" 96#include "usctest.h" 97 98#ifndef PAGE_SIZE 99#define PAGE_SIZE sysconf(_SC_PAGE_SIZE) 100#endif 101 102#define LONGMODNAMECHAR 'm' /* Arbitrarily selected */ 103#define MODNAMEMAX (PAGE_SIZE + 1) 104#define EXP_RET_VAL 0 105#define DUMMY_MOD "dummy_query_mod" 106#define DUMMY_MOD_DEP "dummy_query_mod_dep" 107#define QM_INVALID (QM_INFO + 100) 108 109/* Name of exported function in DUMMY_MOD */ 110#define EXP_FUNC_NAME "dummy_func_test" 111 112extern int Tst_count; 113 114struct test_case_t { /* test case structure */ 115 char *modname; 116 int which; 117 char *desc; 118 int (*setup)(void); /* Individual setup routine */ 119 void (*cleanup)(void); /* Individual cleanup routine */ 120}; 121 122char *TCID = "query_module01"; 123static char longmodname[MODNAMEMAX]; 124static int testno; 125static char out_buf[PAGE_SIZE]; 126static size_t ret; 127 128static int test_functionality(int, char *, size_t, size_t); 129static void setup(void); 130static void cleanup(void); 131static int setup1(void); 132static void cleanup1(void); 133static int setup2(void); 134static void cleanup2(void); 135 136static struct test_case_t tdat[] = { 137 { NULL, 0, "module name: NULL, which: 0", NULL, NULL}, 138 139 { NULL, QM_MODULES, "NULL module name, which: QM_MODULES", 140 setup1, cleanup1}, 141 142 { DUMMY_MOD_DEP, QM_DEPS, "valid module name, which: QM_DEPS", 143 setup2, cleanup2}, 144 145 { DUMMY_MOD, QM_REFS, "valid module name, which: QM_REFS", 146 setup2, cleanup2}, 147 148 { DUMMY_MOD, QM_INFO, "valid module name, which: QM_INFO", 149 setup1, cleanup1}, 150 151 { DUMMY_MOD, QM_SYMBOLS, "valid module name, which: QM_SYMBOLS", 152 setup1, cleanup1}, 153}; 154 155int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 156 157int 158main(int argc, char **argv) 159{ 160 int lc; /* loop counter */ 161 char *msg; /* message returned from parse_opts */ 162 size_t buflen = sizeof(out_buf); 163 164 /* parse standard options */ 165 if ((msg = parse_opts(argc, argv, (option_t *)NULL, NULL)) != 166 (char *)NULL) { 167 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); 168 } 169 170 if(STD_COPIES != 1) { 171 tst_resm(TINFO, "-c option has no effect for these testcases - " 172 "doesn't allow running more than one instance " 173 "at a time"); 174 STD_COPIES = 1; 175 } 176 177 tst_tmpdir(); 178 setup(); 179 180 /* check looping state if -i option is given */ 181 for (lc = 0; TEST_LOOPING(lc); lc++) { 182 /* reset Tst_count in case we are looping */ 183 Tst_count = 0; 184 185 for (testno = 0; testno < TST_TOTAL; ++testno) { 186 if( (tdat[testno].setup) && (tdat[testno].setup()) ) { 187 /* setup() failed, skip this test */ 188 continue; 189 } 190 191 TEST(query_module(tdat[testno].modname, 192 tdat[testno].which, (void *)out_buf, buflen, 193 &ret)); 194 195 if ( (TEST_RETURN == EXP_RET_VAL) && 196 !test_functionality(tdat[testno].which, 197 out_buf, buflen, ret) ) { 198 tst_resm(TPASS, "query_module() successful " 199 "for %s", tdat[testno].desc); 200 } else { 201 tst_resm(TFAIL, "query_module() failed for " 202 "%s ; returned" 203 " %d (expected %d), errno %d (expected" 204 " 0)", tdat[testno].desc, 205 TEST_RETURN, EXP_RET_VAL, TEST_ERRNO); 206 } 207 if(tdat[testno].cleanup) { 208 tdat[testno].cleanup(); 209 } 210 } 211 } 212 cleanup(); 213 214 /*NOTREACHED*/ 215 return 0; 216} 217 218int 219test_functionality(int which, char *buf, size_t bufsize, size_t ret) 220{ 221 int i = 0; 222 char *modname; 223 unsigned long *vals; 224 225 /* 226 * Don't perform functional verification, if STD_FUNCTIONAL_TEST is 227 * turned off 228 */ 229 if(STD_FUNCTIONAL_TEST == 0) { 230 return 0; 231 } 232 233 switch(which) { 234 case 0: 235 /* Always return SUCCESS */ 236 return 0; 237 238 case QM_MODULES: 239 case QM_DEPS: 240 /* Return SUCCESS if found DUMMY_MOD entry */ 241 modname = DUMMY_MOD; 242 break; 243 244 case QM_REFS: 245 /* Return SUCCESS if found DUMMY_MOD_DEP entry */ 246 modname = DUMMY_MOD_DEP; 247 break; 248 249 case QM_INFO: 250 /* 251 * Since module is already loaded, flags should show 252 * MOD_RUNNING 253 */ 254 if(((struct module_info *) buf) -> flags & 255 MOD_RUNNING) { 256 return 0; 257 } 258 return 1; 259 260 case QM_SYMBOLS: 261 vals = (unsigned long *)buf; 262 263 /* 264 * Find entry for atleast one symbol, checking for 265 * EXP_FUNC_NAME symbol, if found return SUCCESS. 266 */ 267 for( i = 0; i < ret; i++, vals +=2) { 268 269 /* buf + vals[1] - address of symbol name */ 270 if(!strcmp(buf + vals[1], EXP_FUNC_NAME)) { 271 return 0; 272 } 273 } 274 return 1; 275 276 default: 277 /* Unknown which type */ 278 return 1; 279 } 280 281 /* Return SUCCESS if found entry */ 282 for(i = 0; i != ret; i++) { 283 if(strcmp(buf, modname)) { 284 buf += strlen(buf) + 1; 285 } else{ 286 return 0; 287 } 288 } 289 return 1; 290 291} 292 293/* Insert a module of name mod */ 294int 295insert_mod(char *mod) 296{ 297 char cmd[80]; 298 299 if( sprintf(cmd, "cp `which %s.o` ./", mod) == -1) { 300 tst_resm(TBROK, "sprintf failed"); 301 return 1; 302 } 303 if(system(cmd) != 0 ) { 304 tst_resm(TBROK, "Failed to copy %s module", mod); 305 return 1; 306 } 307 308 /* Should use force to ignore kernel version & insure loading */ 309 /* -RW */ 310 /* if( sprintf(cmd, "insmod %s.o", mod) == -1) { */ 311 if( sprintf(cmd, "insmod --force -q %s.o >/dev/null 2>&1", mod) == -1) { 312 tst_resm(TBROK, "sprintf failed"); 313 return 1; 314 } 315 if(system(cmd) != 0 ) { 316 tst_resm(TBROK, "Failed to load %s module", mod); 317 return 1; 318 } 319 return 0; 320} 321 322int 323setup1(void) 324{ 325 if(insert_mod(DUMMY_MOD)) { 326 /* Failed */ 327 return 1; 328 } else { 329 return 0; 330 } 331} 332 333 334int 335setup2(void) 336{ 337 if(insert_mod(DUMMY_MOD)) { 338 /* Failed */ 339 return 1; 340 } 341 if(insert_mod(DUMMY_MOD_DEP)) { 342 /* Falied to load DUMMY_MOD_DEP, unload DUMMY_MOD */ 343 cleanup1(); 344 return 1; 345 } 346 return 0; 347} 348 349void 350cleanup1(void) 351{ 352 /* Remove the loadable module - DUMMY_MOD */ 353 if(system("rmmod "DUMMY_MOD) != 0) { 354 tst_brkm(TBROK, cleanup, "Failed to unload module %s", 355 DUMMY_MOD); 356 } 357} 358 359void 360cleanup2(void) 361{ 362 /* Remove the loadable module - DUMMY_MOD_DEP */ 363 if(system("rmmod "DUMMY_MOD_DEP) != 0) { 364 tst_brkm(TBROK, cleanup, "Failed to unload module %s", 365 DUMMY_MOD_DEP); 366 } 367 /* Remove the loadable module - DUMMY_MOD */ 368 cleanup1(); 369} 370 371 372/* 373 * setup() 374 * performs all ONE TIME setup for this test 375 */ 376void 377setup(void) 378{ 379 /* capture signals */ 380 tst_sig(FORK, DEF_HANDLER, cleanup); 381 382 /* Check whether we are root */ 383 if (geteuid() != 0) { 384 tst_brkm(TBROK, tst_exit, "Must be root for this test!"); 385 /*NOTREACHED*/ 386 } 387 388 if (tst_kvercmp(2,5,48) >= 0) 389 tst_brkm(TCONF, tst_exit, "This test will not work on " 390 "kernels after 2.5.48"); 391 392 /* Initialize longmodname to LONGMODNAMECHAR character */ 393 memset(longmodname, LONGMODNAMECHAR, MODNAMEMAX - 1); 394 395 /* Pause if that option was specified 396 * TEST_PAUSE contains the code to fork the test with the -c option. 397 */ 398 TEST_PAUSE; 399} 400 401/* 402 * cleanup() 403 * performs all ONE TIME cleanup for this test at 404 * completion or premature exit 405 */ 406void 407cleanup(void) 408{ 409 /* 410 * print timing stats if that option was specified. 411 * print errno log if that option was specified. 412 */ 413 414 TEST_CLEANUP; 415 tst_rmdir(); 416 /* exit with return code appropriate for results */ 417 tst_exit(); 418 /*NOTREACHED*/ 419} 420