1#include "KCAPI_Keychain.h" 2#include "KCAPI_Manager.h" 3#include "testKeychainAPI.h" 4#include "Radar.h" 5#include <unistd.h> 6 7#if TARGET_RT_MAC_MACHO 8 #include <OSServices/KeychainCore.h> 9 #include <OSServices/KeychainCorePriv.h> 10 #include <SecurityHI/KeychainHI.h> 11#else 12 #include <Keychain.h> 13 #include <iostream> 14 #include <SIOUX.h> 15 static void GetArg(int &outArgc, char** &outArgv); 16#endif 17 18static char* gResourcePath = NULL; 19static char* GetResourcePath(char**argv); 20static int gSleep=0; 21 22#ifndef TEST_SCRIPT_PATH 23 #define TEST_SCRIPT_PATH (getenv("TESTKEYCHAINAPI_TEST_SCRIPT_PATH") ? getenv("TESTKEYCHAINAPI_TEST_SCRIPT_PATH") : gResourcePath) 24#endif 25 26 27int main(int argc, char** argv) 28{ 29 30#if defined(__MWERKS__) 31 // Set SIOUX window position to top left corner 32 // so that Security Dialogs will not cover the 33 // window 34 SIOUXSettings.toppixel = 40; 35 SIOUXSettings.leftpixel = 5; 36 37 // emulate argc, argv 38 GetArg(argc, argv); 39#endif 40 41 gResourcePath = GetResourcePath(argv); 42 43 try{ 44 CTestApp aTestApp(argc, argv); 45 aTestApp.Run(); 46 } 47 catch(const char *inErrorMsg){ 48 fprintf(stderr, "ERROR : %s\n", inErrorMsg); 49 } 50 51 if(gSleep) 52 { 53 fprintf(stderr, "\n-----> sleeping...\n"); 54 sleep(60000); 55 } 56 57} 58 59CTestApp::CTestApp( 60 int inArgc, 61 char ** inArgv) 62 :mArgc(inArgc), mArgv(inArgv), 63 mVerbose(false), mRelaxErrorChecking(false) 64{ 65} 66 67void 68CTestApp::Run() 69{ 70 int ch; 71 bool didWork = false; 72 const char *options = "hH?vlew:f:r:R:n:s:S"; 73 74#if TARGET_RT_MAC_MACHO 75 extern char * optarg; 76 while ((ch = getopt(mArgc, mArgv, options)) != -1){ 77#else 78 char * optarg = NULL; 79 for(int i=1; i<mArgc; i++){ 80 if(mArgv[i][0] == '-'){ 81 char *p; 82 ch = mArgv[i][1]; 83 if(p = strchr(options, ch)) 84 if(p[1] == ':') optarg = mArgv[++i]; 85 } 86#endif 87 switch(ch){ 88 case 'v':{ 89 mVerbose = true; 90 break; 91 } 92 93 case 'e':{ 94 mRelaxErrorChecking = true; 95 break; 96 } 97 98 case 's':{ 99 DoRunSubTestScript(optarg); 100 didWork = true; 101 break; 102 } 103 104 case 'w':{ 105 DoDumpScript(optarg); 106 didWork = true; 107 break; 108 } 109 110 case 'f':{ 111 UInt32 aPass, aFail; 112 DoRunScript(optarg, aPass, aFail); 113 didWork = true; 114 break; 115 } 116 117 case 'n':{ 118 DoRunTestScript(optarg); 119 didWork = true; 120 break; 121 } 122 123 case 'R': 124 case 'r':{ 125 DoRadar(optarg); 126 didWork = true; 127 break; 128 } 129 130 case 'l':{ 131 DoRadar(NULL); 132 didWork = true; 133 break; 134 } 135 136 case 'h': 137 case 'H': 138 case '?': 139 break; 140 141 case 'S': 142 gSleep=1; 143 break; 144 } 145 } 146 if(!didWork) goto showUsage; 147 return; 148showUsage: 149 { 150 char * aProgname = strrchr(mArgv[0], '/'); 151 aProgname = (aProgname) ? aProgname+1 : mArgv[0]; 152 153 fprintf(stderr, "Usage : %s [-v][-e][-r {all} {ID}][-l][-n scriptNo][-s scriptNo][-f filename][-w {all} {ID}][-S] \n", aProgname); 154 fprintf(stderr, " -v verbose\n"); 155 fprintf(stderr, " -e relax return code checking\n"); 156 fprintf(stderr, " -s run sub-test cases\n"); 157 fprintf(stderr, " -r run a Radar bug\n"); 158 fprintf(stderr, " -l list all Radar bugs\n"); 159 fprintf(stderr, " -n run a test script\n"); 160 fprintf(stderr, " -f run your script\n"); 161 fprintf(stderr, " -w dump a script template\n"); 162 fprintf(stderr, " -S sleep before exiting (for use with MallocDebug)\n"); 163 fprintf(stderr, "\n default args -venall\n"); 164 165 166 } 167} 168 169 170// ��������������������������������������������������������������������������� 171// � DoRunTestScript 172// ��������������������������������������������������������������������������� 173void 174CTestApp::DoRunTestScript( 175 const char *inScriptNo) 176{ 177 FILE *aInput; 178 char aFullPath[256]; 179 UInt32 aPassCount = 0; 180 UInt32 aFailCount = 0; 181 182 if(!strcmp(inScriptNo, "all")){ 183 for(UInt32 i=0; i<50 /* 9999 */; i++){ 184#if TARGET_RT_MAC_MACHO 185 sprintf(aFullPath, "%s/script%04ld", TEST_SCRIPT_PATH, i); 186#else 187 sprintf(aFullPath, "%s:script%04ld", TEST_SCRIPT_PATH, i); 188#endif 189 if((aInput = fopen(aFullPath, "r")) != NULL){ 190 UInt32 aPass=0, aFail=0; 191 if(mVerbose) printf("\n\n-> -> -> Running script%04ld ...\n", i); 192 DoRunScript(aInput, aPass, aFail); 193 aPassCount += aPass; 194 aFailCount += aFail; 195 fclose(aInput); 196 } 197 } 198 } 199 else{ 200 201#if TARGET_RT_MAC_MACHO 202 sprintf(aFullPath, "%s//script%04d", TEST_SCRIPT_PATH, atoi(inScriptNo)); 203#else 204 sprintf(aFullPath, "%s:script%04d", TEST_SCRIPT_PATH, atoi(inScriptNo)); 205#endif 206 207 if((aInput = fopen(aFullPath, "r")) != NULL){ 208 DoRunScript(aInput, aPassCount, aFailCount); 209 fclose(aInput); 210 } 211 else{ 212 fprintf(stderr, "No script file for [%s]\n", inScriptNo); 213 return; 214 } 215 } 216 217 printf("Total number of test cases executed %ld : (passed = %ld, failed = %ld)\n", aPassCount+aFailCount, aPassCount, aFailCount); 218} 219 220// ��������������������������������������������������������������������������� 221// � DoRunSubTestScript 222// ��������������������������������������������������������������������������� 223void 224CTestApp::DoRunSubTestScript( 225 const char * inScriptNo) 226{ 227 FILE *aInput; 228 char aFullPath[256]; 229 UInt32 aPassCount = 0; 230 UInt32 aFailCount = 0; 231 UInt32 aStartScript = 0; 232 UInt32 aEndScript = 50; /* 9999 */ 233 234 // not "all" - run the specified test case's sub-test cases 235 if(strcmp(inScriptNo, "all")){ 236 aStartScript = aEndScript = atoi(inScriptNo); 237 } 238 239 for(UInt32 j=aStartScript; j<=aEndScript; j++){ 240 for(UInt32 i=0; i<5 /*999*/; i++){ 241#if TARGET_RT_MAC_MACHO 242 sprintf(aFullPath, "%s//script%04ld.%03ld", TEST_SCRIPT_PATH, j, i); 243#else 244 sprintf(aFullPath, "%s:script%04ld.%03ld", TEST_SCRIPT_PATH, j, i); 245#endif 246 247 if((aInput = fopen(aFullPath, "r")) != NULL){ 248 UInt32 aPass, aFail; 249 if(mVerbose) printf("\n\n-> -> -> Running script%04ld.%03ld ...\n", j, i); 250 DoRunScript(aInput, aPass, aFail); 251 aPassCount += aPass; 252 aFailCount += aFail; 253 fclose(aInput); 254 } 255 } 256 } 257 258 printf("Total number of test cases executed %ld : (passed = %ld, failed = %ld)\n", aPassCount+aFailCount, aPassCount, aFailCount); 259} 260 261// ��������������������������������������������������������������������������� 262// � DoRunScript 263// ��������������������������������������������������������������������������� 264void 265CTestApp::DoRunScript( 266 const char *inPath, 267 UInt32 &outPass, 268 UInt32 &outFail) 269{ 270 Cleanup(); 271 272 FILE *aInput = fopen(inPath, "r"); 273 if(aInput == NULL){ 274 fprintf(stderr, "ERROR Cannot open the file %s\n", inPath); 275 return; 276 } 277 DoRunScript(aInput, outPass, outFail); 278 fclose(aInput); 279} 280 281// ��������������������������������������������������������������������������� 282// � DoRunScript 283// ��������������������������������������������������������������������������� 284void 285CTestApp::DoRunScript( 286 FILE *inFile, 287 UInt32 &outPass, 288 UInt32 &outFail) 289{ 290 Cleanup(); 291 292 eKCOperationID aID; 293 UInt32 aPassCount = 0; 294 UInt32 aFailCount = 0; 295 296 try{ 297 while(KCOperation::ReadScript(inFile, aID) != EOF){ 298 KCOperation *aOperation = (KCOperation*)COpRegister::CreateOperation(aID, this); 299 if(aOperation == NULL){ 300 fprintf(stderr, "ERROR COpRegister::CreateOperation(%d) failed\n", aID); 301 break; 302 } 303 304 bool aResult = aOperation->RunScript(inFile); 305 aPassCount += (aResult) ? 1 : 0; 306 aFailCount += (!aResult) ? 1 : 0; 307 if(mVerbose){ 308 printf("TestCase No.%04ld (%s): %s\n", aPassCount+aFailCount, COpRegister::GetOperationName(aID), (aResult) ? "PASSED" : "FAILED"); 309 if(!aResult){ 310 fprintf(stdout, "%d %s\n", aID, COpRegister::GetOperationName(aID)); 311 aOperation->WriteResults(stdout); 312 } 313 } 314 delete aOperation; 315 } 316 } 317 catch(const char *inErrorMsg){ 318 fprintf(stderr, "ERROR : %s\n", inErrorMsg); 319 fprintf(stderr, " Terminating this script\n"); 320 } 321 322 outPass = aPassCount; 323 outFail = aFailCount; 324 325} 326 327// ��������������������������������������������������������������������������� 328// � DoDumpScript 329// ��������������������������������������������������������������������������� 330void 331CTestApp::DoDumpScript( 332 const char *inOperationNo) 333{ 334 FILE *aOutput = stdout; 335 bool aDoAll = (strcmp(inOperationNo, "all") == 0); 336 337 for(long i=0; i<OpID_NumOperations; i++){ 338 if(aDoAll || (atoi(inOperationNo) == i)){ 339 KCOperation *aOperation = (KCOperation*)COpRegister::CreateOperation((eKCOperationID)i, this); 340 if(aOperation == NULL){ 341 fprintf(stderr, "ERROR COpRegister::CreateOperation(%ld) failed\n", i); 342 continue; 343 } 344// aOperation->Operate(); 345 aOperation->WriteScript(aOutput); 346 delete aOperation; 347 } 348 } 349} 350 351 352 353// ��������������������������������������������������������������������������� 354// � DoRadar 355// ��������������������������������������������������������������������������� 356void 357CTestApp::DoRadar( 358 const char *inArg) 359{ 360 UInt32 i=0; 361 362 // -l (list all Radar bug descriptions) 363 if(inArg == NULL){ 364 while(gRadarBugs[i].testCaseFunc){ 365 printf("%s %s\n", gRadarBugs[i].ID, gRadarBugs[i].desc); 366 i++; 367 } 368 } 369 // -r all (run all Radar bugs) 370 else if(!strcmp(inArg, "all")){ 371 while(gRadarBugs[i].testCaseFunc){ 372 printf(">>>>>>>>>> Radar %s >>>>>>>>>>\n", gRadarBugs[i].ID); 373 printf("%s\n", gRadarBugs[i].desc); 374 (gRadarBugs[i].testCaseFunc)(this); 375 printf("<<<<<<<<<< Radar %s done <<<<<<<<<<\n\n", gRadarBugs[i].ID); 376 377 i++; 378 } 379 } 380 // -r nnnnn (run a specific Radar bug) 381 else{ 382 while(gRadarBugs[i].testCaseFunc){ 383 if(!strcmp(inArg, gRadarBugs[i].ID)){ 384 (gRadarBugs[i].testCaseFunc)(this); 385 return; 386 } 387 i++; 388 } 389 fprintf(stderr, "No such Radar ID\n"); 390 DoRadar(NULL); 391 } 392} 393 394void 395CTestApp::Cleanup() 396{ 397 KCOperation::Cleanup(); 398 KCItemOperation::Cleanup(); 399 KCSearchOperation::Cleanup(); 400} 401 402#if TARGET_RT_MAC_MACHO 403char* 404GetResourcePath(char **inArgv) 405{ 406 // Can I do better than this ? 407 const char *aResourcesDir = "../Resources/"; 408 const char *progname; 409 char *aResourcePath = NULL; 410 int len; 411 412 progname = strrchr(inArgv[0], '/'); 413 len = (progname) ? (strlen(inArgv[0]) - strlen(progname)+1) : 0; 414 aResourcePath = new char[len + strlen(aResourcesDir)+1]; 415 if(len) memcpy(aResourcePath, inArgv[0], len); 416 memcpy(aResourcePath+len, aResourcesDir, strlen(aResourcesDir)); 417 aResourcePath[len+strlen(aResourcesDir)] = '\0'; 418 return(aResourcePath); 419} 420#else 421char* 422GetResourcePath(char **inArgv) 423{ 424 // ��� temp solution 425 return("Work:CVS Project:Security:Tests:testKeychainAPI:testKeychainAPI:scripts"); 426} 427 428void GetArg( 429 int &outArgc, 430 char** &outArgv) 431{ 432 // emulate the command line arg 433 const char *kProgname = "testKeychainAPI"; 434 char *aBuffer = new char[1024]; 435 436 memset(aBuffer, 0, 1024); 437 strcpy(aBuffer, kProgname); 438 int i = strlen(kProgname)+1; 439 440 cout << kProgname << " "; 441 cin.getline(aBuffer+i, 1024-i); 442 for(; i<1028; i++) if(aBuffer[i] == ' ') aBuffer[i] = '\0'; 443 444 int j = 0; 445 char *p = aBuffer; 446 char **argv = new char*[128]; 447 do{ 448 if(strlen(p) > 0) argv[j++] = p; 449 p += strlen(p)+1; 450 } while(p < aBuffer+1024); 451 452 outArgc = j; 453 outArgv = argv; 454} 455 456char* 457UNIX_fgets( 458 char *inBuffer, 459 int inSize, 460 FILE *inFile) 461{ 462 // Scripts are in UNIX format 463 // so fgets() does not work on ClassicMac 464 // as is 465 for(int i=0; i<inSize; i++){ 466 inBuffer[i] = fgetc(inFile); 467 if(inBuffer[i] != '\r' && inBuffer[i] != '\n' && inBuffer[i] != EOF) continue; 468 if(inBuffer[i] == EOF && i==0) return NULL; 469 inBuffer[i] = '\n'; 470 inBuffer[i+1] = '\0'; 471 break; 472 } 473 return inBuffer; 474} 475 476#endif 477