18c1441f8SAlexey Samsonov// 2*2946cd70SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3*2946cd70SChandler Carruth// See https://llvm.org/LICENSE.txt for license information. 4*2946cd70SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 58c1441f8SAlexey Samsonov 68c1441f8SAlexey Samsonov// 78c1441f8SAlexey Samsonov// testfilerunner.m 88c1441f8SAlexey Samsonov// testObjects 98c1441f8SAlexey Samsonov// 108c1441f8SAlexey Samsonov// Created by Blaine Garst on 9/24/08. 118c1441f8SAlexey Samsonov// 128c1441f8SAlexey Samsonov 138c1441f8SAlexey Samsonov#import "testfilerunner.h" 148c1441f8SAlexey Samsonov#import <Foundation/Foundation.h> 158c1441f8SAlexey Samsonov#include <stdio.h> 168c1441f8SAlexey Samsonov#include <unistd.h> 178c1441f8SAlexey Samsonov#include <fcntl.h> 188c1441f8SAlexey Samsonov#include <string.h> 198c1441f8SAlexey Samsonov#include <stdlib.h> 208c1441f8SAlexey Samsonov#include <stdbool.h> 218c1441f8SAlexey Samsonov 228c1441f8SAlexey Samsonovbool Everything = false; // do it also with 3 levels of optimization 238c1441f8SAlexey Samsonovbool DoClang = false; 248c1441f8SAlexey Samsonov 258c1441f8SAlexey Samsonovstatic bool isDirectory(char *path); 268c1441f8SAlexey Samsonovstatic bool isExecutable(char *path); 278c1441f8SAlexey Samsonovstatic bool isYounger(char *source, char *binary); 288c1441f8SAlexey Samsonovstatic bool readErrorFile(char *buffer, const char *from); 298c1441f8SAlexey Samsonov 308c1441f8SAlexey Samsonov__strong char *gcstrcpy2(__strong const char *arg, char *endp) { 318c1441f8SAlexey Samsonov unsigned size = endp - arg + 1; 328c1441f8SAlexey Samsonov __strong char *result = NSAllocateCollectable(size, 0); 338c1441f8SAlexey Samsonov strncpy(result, arg, size); 348c1441f8SAlexey Samsonov result[size-1] = 0; 358c1441f8SAlexey Samsonov return result; 368c1441f8SAlexey Samsonov} 378c1441f8SAlexey Samsonov__strong char *gcstrcpy1(__strong char *arg) { 388c1441f8SAlexey Samsonov unsigned size = strlen(arg) + 1; 398c1441f8SAlexey Samsonov __strong char *result = NSAllocateCollectable(size, 0); 408c1441f8SAlexey Samsonov strncpy(result, arg, size); 418c1441f8SAlexey Samsonov result[size-1] = 0; 428c1441f8SAlexey Samsonov return result; 438c1441f8SAlexey Samsonov} 448c1441f8SAlexey Samsonov 458c1441f8SAlexey Samsonov@implementation TestFileExe 468c1441f8SAlexey Samsonov 478c1441f8SAlexey Samsonov@synthesize options, compileLine, shouldFail, binaryName, sourceName; 488c1441f8SAlexey Samsonov@synthesize generator; 498c1441f8SAlexey Samsonov@synthesize libraryPath, frameworkPath; 508c1441f8SAlexey Samsonov 518c1441f8SAlexey Samsonov- (NSString *)description { 528c1441f8SAlexey Samsonov NSMutableString *result = [NSMutableString new]; 538c1441f8SAlexey Samsonov if (shouldFail) [result appendString:@"fail"]; 548c1441f8SAlexey Samsonov for (id x in compileLine) { 558c1441f8SAlexey Samsonov [result appendString:[NSString stringWithFormat:@" %s", (char *)x]]; 568c1441f8SAlexey Samsonov } 578c1441f8SAlexey Samsonov return result; 588c1441f8SAlexey Samsonov} 598c1441f8SAlexey Samsonov 608c1441f8SAlexey Samsonov- (__strong char *)radar { 618c1441f8SAlexey Samsonov return generator.radar; 628c1441f8SAlexey Samsonov} 638c1441f8SAlexey Samsonov 648c1441f8SAlexey Samsonov- (bool) compileUnlessExists:(bool)skip { 658c1441f8SAlexey Samsonov if (shouldFail) { 668c1441f8SAlexey Samsonov printf("don't use this to compile anymore!\n"); 678c1441f8SAlexey Samsonov return false; 688c1441f8SAlexey Samsonov } 698c1441f8SAlexey Samsonov if (skip && isExecutable(binaryName) && !isYounger(sourceName, binaryName)) return true; 708c1441f8SAlexey Samsonov int argc = [compileLine count]; 718c1441f8SAlexey Samsonov char *argv[argc+1]; 728c1441f8SAlexey Samsonov for (int i = 0; i < argc; ++i) 738c1441f8SAlexey Samsonov argv[i] = (char *)[compileLine pointerAtIndex:i]; 748c1441f8SAlexey Samsonov argv[argc] = NULL; 758c1441f8SAlexey Samsonov pid_t child = fork(); 768c1441f8SAlexey Samsonov if (child == 0) { 778c1441f8SAlexey Samsonov execv(argv[0], argv); 788c1441f8SAlexey Samsonov exit(10); // shouldn't happen 798c1441f8SAlexey Samsonov } 808c1441f8SAlexey Samsonov if (child < 0) { 818c1441f8SAlexey Samsonov printf("fork failed\n"); 828c1441f8SAlexey Samsonov return false; 838c1441f8SAlexey Samsonov } 848c1441f8SAlexey Samsonov int status = 0; 858c1441f8SAlexey Samsonov pid_t deadchild = wait(&status); 868c1441f8SAlexey Samsonov if (deadchild != child) { 878c1441f8SAlexey Samsonov printf("wait got %d instead of %d\n", deadchild, child); 888c1441f8SAlexey Samsonov exit(1); 898c1441f8SAlexey Samsonov } 908c1441f8SAlexey Samsonov if (WEXITSTATUS(status) == 0) { 918c1441f8SAlexey Samsonov return true; 928c1441f8SAlexey Samsonov } 938c1441f8SAlexey Samsonov printf("run failed\n"); 948c1441f8SAlexey Samsonov return false; 958c1441f8SAlexey Samsonov} 968c1441f8SAlexey Samsonov 978c1441f8SAlexey Samsonovbool lookforIn(char *lookfor, const char *format, pid_t child) { 988c1441f8SAlexey Samsonov char buffer[512]; 998c1441f8SAlexey Samsonov char got[512]; 1008c1441f8SAlexey Samsonov sprintf(buffer, format, child); 1018c1441f8SAlexey Samsonov bool gotOutput = readErrorFile(got, buffer); 1028c1441f8SAlexey Samsonov if (!gotOutput) { 1038c1441f8SAlexey Samsonov printf("**** didn't get an output file %s to analyze!!??\n", buffer); 1048c1441f8SAlexey Samsonov return false; 1058c1441f8SAlexey Samsonov } 1068c1441f8SAlexey Samsonov char *where = strstr(got, lookfor); 1078c1441f8SAlexey Samsonov if (!where) { 1088c1441f8SAlexey Samsonov printf("didn't find '%s' in output file %s\n", lookfor, buffer); 1098c1441f8SAlexey Samsonov return false; 1108c1441f8SAlexey Samsonov } 1118c1441f8SAlexey Samsonov unlink(buffer); 1128c1441f8SAlexey Samsonov return true; 1138c1441f8SAlexey Samsonov} 1148c1441f8SAlexey Samsonov 1158c1441f8SAlexey Samsonov- (bool) compileWithExpectedFailure { 1168c1441f8SAlexey Samsonov if (!shouldFail) { 1178c1441f8SAlexey Samsonov printf("Why am I being called?\n"); 1188c1441f8SAlexey Samsonov return false; 1198c1441f8SAlexey Samsonov } 1208c1441f8SAlexey Samsonov int argc = [compileLine count]; 1218c1441f8SAlexey Samsonov char *argv[argc+1]; 1228c1441f8SAlexey Samsonov for (int i = 0; i < argc; ++i) 1238c1441f8SAlexey Samsonov argv[i] = (char *)[compileLine pointerAtIndex:i]; 1248c1441f8SAlexey Samsonov argv[argc] = NULL; 1258c1441f8SAlexey Samsonov pid_t child = fork(); 1268c1441f8SAlexey Samsonov char buffer[512]; 1278c1441f8SAlexey Samsonov if (child == 0) { 1288c1441f8SAlexey Samsonov // in child 1298c1441f8SAlexey Samsonov sprintf(buffer, "/tmp/errorfile_%d", getpid()); 1308c1441f8SAlexey Samsonov close(1); 1318c1441f8SAlexey Samsonov int fd = creat(buffer, 0777); 1328c1441f8SAlexey Samsonov if (fd != 1) { 1338c1441f8SAlexey Samsonov fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd); 1348c1441f8SAlexey Samsonov exit(1); 1358c1441f8SAlexey Samsonov } 1368c1441f8SAlexey Samsonov close(2); 1378c1441f8SAlexey Samsonov dup(1); 1388c1441f8SAlexey Samsonov int result = execv(argv[0], argv); 1398c1441f8SAlexey Samsonov exit(10); 1408c1441f8SAlexey Samsonov } 1418c1441f8SAlexey Samsonov if (child < 0) { 1428c1441f8SAlexey Samsonov printf("fork failed\n"); 1438c1441f8SAlexey Samsonov return false; 1448c1441f8SAlexey Samsonov } 1458c1441f8SAlexey Samsonov int status = 0; 1468c1441f8SAlexey Samsonov pid_t deadchild = wait(&status); 1478c1441f8SAlexey Samsonov if (deadchild != child) { 1488c1441f8SAlexey Samsonov printf("wait got %d instead of %d\n", deadchild, child); 1498c1441f8SAlexey Samsonov exit(11); 1508c1441f8SAlexey Samsonov } 1518c1441f8SAlexey Samsonov if (WIFEXITED(status)) { 1528c1441f8SAlexey Samsonov if (WEXITSTATUS(status) == 0) { 1538c1441f8SAlexey Samsonov return false; 1548c1441f8SAlexey Samsonov } 1558c1441f8SAlexey Samsonov } 1568c1441f8SAlexey Samsonov else { 1578c1441f8SAlexey Samsonov printf("***** compiler borked/ICEd/died unexpectedly (status %x)\n", status); 1588c1441f8SAlexey Samsonov return false; 1598c1441f8SAlexey Samsonov } 1608c1441f8SAlexey Samsonov char *error = generator.errorString; 1618c1441f8SAlexey Samsonov 1628c1441f8SAlexey Samsonov if (!error) return true; 1638c1441f8SAlexey Samsonov#if 0 1648c1441f8SAlexey Samsonov char got[512]; 1658c1441f8SAlexey Samsonov sprintf(buffer, "/tmp/errorfile_%d", child); 1668c1441f8SAlexey Samsonov bool gotOutput = readErrorFile(got, buffer); 1678c1441f8SAlexey Samsonov if (!gotOutput) { 1688c1441f8SAlexey Samsonov printf("**** didn't get an error file %s to analyze!!??\n", buffer); 1698c1441f8SAlexey Samsonov return false; 1708c1441f8SAlexey Samsonov } 1718c1441f8SAlexey Samsonov char *where = strstr(got, error); 1728c1441f8SAlexey Samsonov if (!where) { 1738c1441f8SAlexey Samsonov printf("didn't find '%s' in error file %s\n", error, buffer); 1748c1441f8SAlexey Samsonov return false; 1758c1441f8SAlexey Samsonov } 1768c1441f8SAlexey Samsonov unlink(buffer); 1778c1441f8SAlexey Samsonov#else 1788c1441f8SAlexey Samsonov if (!lookforIn(error, "/tmp/errorfile_%d", child)) return false; 1798c1441f8SAlexey Samsonov#endif 1808c1441f8SAlexey Samsonov return true; 1818c1441f8SAlexey Samsonov} 1828c1441f8SAlexey Samsonov 1838c1441f8SAlexey Samsonov- (bool) run { 1848c1441f8SAlexey Samsonov if (shouldFail) return true; 1858c1441f8SAlexey Samsonov if (sizeof(long) == 4 && options & Do64) { 1868c1441f8SAlexey Samsonov return true; // skip 64-bit tests 1878c1441f8SAlexey Samsonov } 1888c1441f8SAlexey Samsonov int argc = 1; 1898c1441f8SAlexey Samsonov char *argv[argc+1]; 1908c1441f8SAlexey Samsonov argv[0] = binaryName; 1918c1441f8SAlexey Samsonov argv[argc] = NULL; 1928c1441f8SAlexey Samsonov pid_t child = fork(); 1938c1441f8SAlexey Samsonov if (child == 0) { 1948c1441f8SAlexey Samsonov // set up environment 1958c1441f8SAlexey Samsonov char lpath[1024]; 1968c1441f8SAlexey Samsonov char fpath[1024]; 1978c1441f8SAlexey Samsonov char *myenv[3]; 1988c1441f8SAlexey Samsonov int counter = 0; 1998c1441f8SAlexey Samsonov if (libraryPath) { 2008c1441f8SAlexey Samsonov sprintf(lpath, "DYLD_LIBRARY_PATH=%s", libraryPath); 2018c1441f8SAlexey Samsonov myenv[counter++] = lpath; 2028c1441f8SAlexey Samsonov } 2038c1441f8SAlexey Samsonov if (frameworkPath) { 2048c1441f8SAlexey Samsonov sprintf(fpath, "DYLD_FRAMEWORK_PATH=%s", frameworkPath); 2058c1441f8SAlexey Samsonov myenv[counter++] = fpath; 2068c1441f8SAlexey Samsonov } 2078c1441f8SAlexey Samsonov myenv[counter] = NULL; 2088c1441f8SAlexey Samsonov if (generator.warningString) { 2098c1441f8SAlexey Samsonov // set up stdout/stderr 2108c1441f8SAlexey Samsonov char outfile[1024]; 2118c1441f8SAlexey Samsonov sprintf(outfile, "/tmp/stdout_%d", getpid()); 2128c1441f8SAlexey Samsonov close(2); 2138c1441f8SAlexey Samsonov close(1); 2148c1441f8SAlexey Samsonov creat(outfile, 0700); 2158c1441f8SAlexey Samsonov dup(1); 2168c1441f8SAlexey Samsonov } 2178c1441f8SAlexey Samsonov execve(argv[0], argv, myenv); 2188c1441f8SAlexey Samsonov exit(10); // shouldn't happen 2198c1441f8SAlexey Samsonov } 2208c1441f8SAlexey Samsonov if (child < 0) { 2218c1441f8SAlexey Samsonov printf("fork failed\n"); 2228c1441f8SAlexey Samsonov return false; 2238c1441f8SAlexey Samsonov } 2248c1441f8SAlexey Samsonov int status = 0; 2258c1441f8SAlexey Samsonov pid_t deadchild = wait(&status); 2268c1441f8SAlexey Samsonov if (deadchild != child) { 2278c1441f8SAlexey Samsonov printf("wait got %d instead of %d\n", deadchild, child); 2288c1441f8SAlexey Samsonov exit(1); 2298c1441f8SAlexey Samsonov } 2308c1441f8SAlexey Samsonov if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 2318c1441f8SAlexey Samsonov if (generator.warningString) { 2328c1441f8SAlexey Samsonov if (!lookforIn(generator.warningString, "/tmp/stdout_%d", child)) return false; 2338c1441f8SAlexey Samsonov } 2348c1441f8SAlexey Samsonov return true; 2358c1441f8SAlexey Samsonov } 2368c1441f8SAlexey Samsonov printf("**** run failed for %s\n", binaryName); 2378c1441f8SAlexey Samsonov return false; 2388c1441f8SAlexey Samsonov} 2398c1441f8SAlexey Samsonov 2408c1441f8SAlexey Samsonov@end 2418c1441f8SAlexey Samsonov 2428c1441f8SAlexey Samsonov@implementation TestFileExeGenerator 2438c1441f8SAlexey Samsonov@synthesize filename, compilerPath, errorString; 2448c1441f8SAlexey Samsonov@synthesize hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64; 2458c1441f8SAlexey Samsonov@synthesize radar; 2468c1441f8SAlexey Samsonov@synthesize warningString; 2478c1441f8SAlexey Samsonov 2488c1441f8SAlexey Samsonov- (void)setFilename:(__strong char *)name { 2498c1441f8SAlexey Samsonov filename = gcstrcpy1(name); 2508c1441f8SAlexey Samsonov} 2518c1441f8SAlexey Samsonov- (void)setCompilerPath:(__strong char *)name { 2528c1441f8SAlexey Samsonov compilerPath = gcstrcpy1(name); 2538c1441f8SAlexey Samsonov} 2548c1441f8SAlexey Samsonov 2558c1441f8SAlexey Samsonov- (void)forMostThings:(NSMutableArray *)lines options:(int)options { 2568c1441f8SAlexey Samsonov TestFileExe *item = nil; 2578c1441f8SAlexey Samsonov item = [self lineForOptions:options]; 2588c1441f8SAlexey Samsonov if (item) [lines addObject:item]; 2598c1441f8SAlexey Samsonov item = [self lineForOptions:options|Do64]; 2608c1441f8SAlexey Samsonov if (item) [lines addObject:item]; 2618c1441f8SAlexey Samsonov item = [self lineForOptions:options|DoCPP]; 2628c1441f8SAlexey Samsonov if (item) [lines addObject:item]; 2638c1441f8SAlexey Samsonov item = [self lineForOptions:options|Do64|DoCPP]; 2648c1441f8SAlexey Samsonov if (item) [lines addObject:item]; 2658c1441f8SAlexey Samsonov} 2668c1441f8SAlexey Samsonov 2678c1441f8SAlexey Samsonov/* 2688c1441f8SAlexey Samsonov DoDashG = (1 << 8), 2698c1441f8SAlexey Samsonov DoDashO = (1 << 9), 2708c1441f8SAlexey Samsonov DoDashOs = (1 << 10), 2718c1441f8SAlexey Samsonov DoDashO2 = (1 << 11), 2728c1441f8SAlexey Samsonov*/ 2738c1441f8SAlexey Samsonov 2748c1441f8SAlexey Samsonov- (void)forAllThings:(NSMutableArray *)lines options:(int)options { 2758c1441f8SAlexey Samsonov [self forMostThings:lines options:options]; 2768c1441f8SAlexey Samsonov if (!Everything) { 2778c1441f8SAlexey Samsonov return; 2788c1441f8SAlexey Samsonov } 2798c1441f8SAlexey Samsonov // now do it with three explicit optimization flags 2808c1441f8SAlexey Samsonov [self forMostThings:lines options:options | DoDashO]; 2818c1441f8SAlexey Samsonov [self forMostThings:lines options:options | DoDashOs]; 2828c1441f8SAlexey Samsonov [self forMostThings:lines options:options | DoDashO2]; 2838c1441f8SAlexey Samsonov} 2848c1441f8SAlexey Samsonov 2858c1441f8SAlexey Samsonov- (NSArray *)allLines { 2868c1441f8SAlexey Samsonov NSMutableArray *result = [NSMutableArray new]; 2878c1441f8SAlexey Samsonov TestFileExe *item = nil; 2888c1441f8SAlexey Samsonov 2898c1441f8SAlexey Samsonov int options = 0; 2908c1441f8SAlexey Samsonov [self forAllThings:result options:0]; 2918c1441f8SAlexey Samsonov [self forAllThings:result options:DoOBJC | DoRR]; 2928c1441f8SAlexey Samsonov [self forAllThings:result options:DoOBJC | DoGC]; 2938c1441f8SAlexey Samsonov [self forAllThings:result options:DoOBJC | DoGCRR]; 2948c1441f8SAlexey Samsonov //[self forAllThings:result options:DoOBJC | DoRRGC]; 2958c1441f8SAlexey Samsonov 2968c1441f8SAlexey Samsonov return result; 2978c1441f8SAlexey Samsonov} 2988c1441f8SAlexey Samsonov 2998c1441f8SAlexey Samsonov- (void)addLibrary:(const char *)dashLSomething { 3008c1441f8SAlexey Samsonov if (!extraLibraries) { 3018c1441f8SAlexey Samsonov extraLibraries = [NSPointerArray pointerArrayWithOptions: 3028c1441f8SAlexey Samsonov NSPointerFunctionsStrongMemory | 3038c1441f8SAlexey Samsonov NSPointerFunctionsCStringPersonality]; 3048c1441f8SAlexey Samsonov } 3058c1441f8SAlexey Samsonov [extraLibraries addPointer:(void *)dashLSomething]; 3068c1441f8SAlexey Samsonov} 3078c1441f8SAlexey Samsonov 3088c1441f8SAlexey Samsonov- (TestFileExe *)lineForOptions:(int)options { // nil if no can do 3098c1441f8SAlexey Samsonov if (hasObjC && !(options & DoOBJC)) return nil; 3108c1441f8SAlexey Samsonov if (hasCPlusPlus && !(options & DoCPP)) return nil; 3118c1441f8SAlexey Samsonov if (hasObjC) { 3128c1441f8SAlexey Samsonov if (!hasGC && (options & (DoGC|DoGCRR))) return nil; // not smart enough 3138c1441f8SAlexey Samsonov if (!hasRR && (options & (DoRR|DoRRGC))) return nil; 3148c1441f8SAlexey Samsonov } 3158c1441f8SAlexey Samsonov NSPointerArray *pa = [NSPointerArray pointerArrayWithOptions: 3168c1441f8SAlexey Samsonov NSPointerFunctionsStrongMemory | 3178c1441f8SAlexey Samsonov NSPointerFunctionsCStringPersonality]; 3188c1441f8SAlexey Samsonov // construct path 3198c1441f8SAlexey Samsonov char path[512]; 3208c1441f8SAlexey Samsonov path[0] = 0; 3218c1441f8SAlexey Samsonov if (!compilerPath) compilerPath = "/usr/bin"; 3228c1441f8SAlexey Samsonov if (compilerPath) { 3238c1441f8SAlexey Samsonov strcat(path, compilerPath); 3248c1441f8SAlexey Samsonov strcat(path, "/"); 3258c1441f8SAlexey Samsonov } 3268c1441f8SAlexey Samsonov if (options & DoCPP) { 3278c1441f8SAlexey Samsonov strcat(path, DoClang ? "clang++" : "g++-4.2"); 3288c1441f8SAlexey Samsonov } 3298c1441f8SAlexey Samsonov else { 3308c1441f8SAlexey Samsonov strcat(path, DoClang ? "clang" : "gcc-4.2"); 3318c1441f8SAlexey Samsonov } 3328c1441f8SAlexey Samsonov [pa addPointer:gcstrcpy1(path)]; 3338c1441f8SAlexey Samsonov if (options & DoOBJC) { 3348c1441f8SAlexey Samsonov if (options & DoCPP) { 3358c1441f8SAlexey Samsonov [pa addPointer:"-ObjC++"]; 3368c1441f8SAlexey Samsonov } 3378c1441f8SAlexey Samsonov else { 3388c1441f8SAlexey Samsonov [pa addPointer:"-ObjC"]; 3398c1441f8SAlexey Samsonov } 3408c1441f8SAlexey Samsonov } 3418c1441f8SAlexey Samsonov [pa addPointer:"-g"]; 3428c1441f8SAlexey Samsonov if (options & DoDashO) [pa addPointer:"-O"]; 3438c1441f8SAlexey Samsonov else if (options & DoDashO2) [pa addPointer:"-O2"]; 3448c1441f8SAlexey Samsonov else if (options & DoDashOs) [pa addPointer:"-Os"]; 3458c1441f8SAlexey Samsonov if (wantsC99 && (! (options & DoCPP))) { 3468c1441f8SAlexey Samsonov [pa addPointer:"-std=c99"]; 3478c1441f8SAlexey Samsonov [pa addPointer:"-fblocks"]; 3488c1441f8SAlexey Samsonov } 3498c1441f8SAlexey Samsonov [pa addPointer:"-arch"]; 3508c1441f8SAlexey Samsonov [pa addPointer: (options & Do64) ? "x86_64" : "i386"]; 3518c1441f8SAlexey Samsonov 3528c1441f8SAlexey Samsonov if (options & DoOBJC) { 3538c1441f8SAlexey Samsonov switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) { 3548c1441f8SAlexey Samsonov case DoRR: 3558c1441f8SAlexey Samsonov break; 3568c1441f8SAlexey Samsonov case DoGC: 3578c1441f8SAlexey Samsonov [pa addPointer:"-fobjc-gc-only"]; 3588c1441f8SAlexey Samsonov break; 3598c1441f8SAlexey Samsonov case DoGCRR: 3608c1441f8SAlexey Samsonov [pa addPointer:"-fobjc-gc"]; 3618c1441f8SAlexey Samsonov break; 3628c1441f8SAlexey Samsonov case DoRRGC: 3638c1441f8SAlexey Samsonov printf("DoRRGC unsupported right now\n"); 3648c1441f8SAlexey Samsonov [pa addPointer:"-c"]; 3658c1441f8SAlexey Samsonov return nil; 3668c1441f8SAlexey Samsonov } 3678c1441f8SAlexey Samsonov [pa addPointer:"-framework"]; 3688c1441f8SAlexey Samsonov [pa addPointer:"Foundation"]; 3698c1441f8SAlexey Samsonov } 3708c1441f8SAlexey Samsonov [pa addPointer:gcstrcpy1(filename)]; 3718c1441f8SAlexey Samsonov [pa addPointer:"-o"]; 3728c1441f8SAlexey Samsonov 3738c1441f8SAlexey Samsonov path[0] = 0; 3748c1441f8SAlexey Samsonov strcat(path, filename); 3758c1441f8SAlexey Samsonov strcat(path, "."); 3768c1441f8SAlexey Samsonov strcat(path, (options & Do64) ? "64" : "32"); 3778c1441f8SAlexey Samsonov if (options & DoOBJC) { 3788c1441f8SAlexey Samsonov switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) { 3798c1441f8SAlexey Samsonov case DoRR: strcat(path, "-rr"); break; 3808c1441f8SAlexey Samsonov case DoGC: strcat(path, "-gconly"); break; 3818c1441f8SAlexey Samsonov case DoGCRR: strcat(path, "-gcrr"); break; 3828c1441f8SAlexey Samsonov case DoRRGC: strcat(path, "-rrgc"); break; 3838c1441f8SAlexey Samsonov } 3848c1441f8SAlexey Samsonov } 3858c1441f8SAlexey Samsonov if (options & DoCPP) strcat(path, "++"); 3868c1441f8SAlexey Samsonov if (options & DoDashO) strcat(path, "-O"); 3878c1441f8SAlexey Samsonov else if (options & DoDashO2) strcat(path, "-O2"); 3888c1441f8SAlexey Samsonov else if (options & DoDashOs) strcat(path, "-Os"); 3898c1441f8SAlexey Samsonov if (wantsC99) strcat(path, "-C99"); 3908c1441f8SAlexey Samsonov strcat(path, DoClang ? "-clang" : "-gcc"); 3918c1441f8SAlexey Samsonov strcat(path, "-bin"); 3928c1441f8SAlexey Samsonov TestFileExe *result = [TestFileExe new]; 3938c1441f8SAlexey Samsonov result.binaryName = gcstrcpy1(path); // could snarf copy in pa 3948c1441f8SAlexey Samsonov [pa addPointer:result.binaryName]; 3958c1441f8SAlexey Samsonov for (id cString in extraLibraries) { 3968c1441f8SAlexey Samsonov [pa addPointer:cString]; 3978c1441f8SAlexey Samsonov } 3988c1441f8SAlexey Samsonov 3998c1441f8SAlexey Samsonov result.sourceName = gcstrcpy1(filename); // could snarf copy in pa 4008c1441f8SAlexey Samsonov result.compileLine = pa; 4018c1441f8SAlexey Samsonov result.options = options; 4028c1441f8SAlexey Samsonov result.shouldFail = supposedToNotCompile; 4038c1441f8SAlexey Samsonov result.generator = self; 4048c1441f8SAlexey Samsonov return result; 4058c1441f8SAlexey Samsonov} 4068c1441f8SAlexey Samsonov 4078c1441f8SAlexey Samsonov+ (NSArray *)generatorsFromPath:(NSString *)path { 4088c1441f8SAlexey Samsonov FILE *fp = fopen([path fileSystemRepresentation], "r"); 4098c1441f8SAlexey Samsonov if (fp == NULL) return nil; 4108c1441f8SAlexey Samsonov NSArray *result = [self generatorsFromFILE:fp]; 4118c1441f8SAlexey Samsonov fclose(fp); 4128c1441f8SAlexey Samsonov return result; 4138c1441f8SAlexey Samsonov} 4148c1441f8SAlexey Samsonov 4158c1441f8SAlexey Samsonov#define LOOKFOR "CON" "FIG" 4168c1441f8SAlexey Samsonov 4178c1441f8SAlexey Samsonovchar *__strong parseRadar(char *line) { 4188c1441f8SAlexey Samsonov line = strstr(line, "rdar:"); // returns beginning 4198c1441f8SAlexey Samsonov char *endp = line + strlen("rdar:"); 4208c1441f8SAlexey Samsonov while (*endp && *endp != ' ' && *endp != '\n') 4218c1441f8SAlexey Samsonov ++endp; 4228c1441f8SAlexey Samsonov return gcstrcpy2(line, endp); 4238c1441f8SAlexey Samsonov} 4248c1441f8SAlexey Samsonov 4258c1441f8SAlexey Samsonov- (void)parseLibraries:(const char *)line { 4268c1441f8SAlexey Samsonov start: 4278c1441f8SAlexey Samsonov line = strstr(line, "-l"); 4288c1441f8SAlexey Samsonov char *endp = (char *)line + 2; 4298c1441f8SAlexey Samsonov while (*endp && *endp != ' ' && *endp != '\n') 4308c1441f8SAlexey Samsonov ++endp; 4318c1441f8SAlexey Samsonov [self addLibrary:gcstrcpy2(line, endp)]; 4328c1441f8SAlexey Samsonov if (strstr(endp, "-l")) { 4338c1441f8SAlexey Samsonov line = endp; 4348c1441f8SAlexey Samsonov goto start; 4358c1441f8SAlexey Samsonov } 4368c1441f8SAlexey Samsonov} 4378c1441f8SAlexey Samsonov 4388c1441f8SAlexey Samsonov+ (TestFileExeGenerator *)generatorFromLine:(char *)line filename:(char *)filename { 4398c1441f8SAlexey Samsonov TestFileExeGenerator *item = [TestFileExeGenerator new]; 4408c1441f8SAlexey Samsonov item.filename = gcstrcpy1(filename); 4418c1441f8SAlexey Samsonov if (strstr(line, "GC")) item.hasGC = true; 4428c1441f8SAlexey Samsonov if (strstr(line, "RR")) item.hasRR = true; 4438c1441f8SAlexey Samsonov if (strstr(line, "C++")) item.hasCPlusPlus = true; 4448c1441f8SAlexey Samsonov if (strstr(line, "-C99")) { 4458c1441f8SAlexey Samsonov item.wantsC99 = true; 4468c1441f8SAlexey Samsonov } 4478c1441f8SAlexey Samsonov if (strstr(line, "64")) item.wants64 = true; 4488c1441f8SAlexey Samsonov if (strstr(line, "32")) item.wants32 = true; 4498c1441f8SAlexey Samsonov if (strstr(line, "-l")) [item parseLibraries:line]; 4508c1441f8SAlexey Samsonov if (strstr(line, "open")) item.open = true; 4518c1441f8SAlexey Samsonov if (strstr(line, "FAIL")) item.supposedToNotCompile = true; // old 4528c1441f8SAlexey Samsonov // compile time error 4538c1441f8SAlexey Samsonov if (strstr(line, "error:")) { 4548c1441f8SAlexey Samsonov item.supposedToNotCompile = true; 4558c1441f8SAlexey Samsonov // zap newline 4568c1441f8SAlexey Samsonov char *error = strstr(line, "error:") + strlen("error:"); 4578c1441f8SAlexey Samsonov // make sure we have something before the newline 4588c1441f8SAlexey Samsonov char *newline = strstr(error, "\n"); 4598c1441f8SAlexey Samsonov if (newline && ((newline-error) > 1)) { 4608c1441f8SAlexey Samsonov *newline = 0; 4618c1441f8SAlexey Samsonov item.errorString = gcstrcpy1(strstr(line, "error:") + strlen("error: ")); 4628c1441f8SAlexey Samsonov } 4638c1441f8SAlexey Samsonov } 4648c1441f8SAlexey Samsonov // run time warning 4658c1441f8SAlexey Samsonov if (strstr(line, "runtime:")) { 4668c1441f8SAlexey Samsonov // zap newline 4678c1441f8SAlexey Samsonov char *error = strstr(line, "runtime:") + strlen("runtime:"); 4688c1441f8SAlexey Samsonov // make sure we have something before the newline 4698c1441f8SAlexey Samsonov char *newline = strstr(error, "\n"); 4708c1441f8SAlexey Samsonov if (newline && ((newline-error) > 1)) { 4718c1441f8SAlexey Samsonov *newline = 0; 4728c1441f8SAlexey Samsonov item.warningString = gcstrcpy1(strstr(line, "runtime:") + strlen("runtime:")); 4738c1441f8SAlexey Samsonov } 4748c1441f8SAlexey Samsonov } 4758c1441f8SAlexey Samsonov if (strstr(line, "rdar:")) item.radar = parseRadar(line); 4768c1441f8SAlexey Samsonov if (item.hasGC || item.hasRR) item.hasObjC = true; 4778c1441f8SAlexey Samsonov if (!item.wants32 && !item.wants64) { // give them both if they ask for neither 4788c1441f8SAlexey Samsonov item.wants32 = item.wants64 = true; 4798c1441f8SAlexey Samsonov } 4808c1441f8SAlexey Samsonov return item; 4818c1441f8SAlexey Samsonov} 4828c1441f8SAlexey Samsonov 4838c1441f8SAlexey Samsonov+ (NSArray *)generatorsFromFILE:(FILE *)fp { 4848c1441f8SAlexey Samsonov NSMutableArray *result = [NSMutableArray new]; 4858c1441f8SAlexey Samsonov // pretend this is a grep LOOKFOR *.[cmCM][cmCM] input 4868c1441f8SAlexey Samsonov // look for 4878c1441f8SAlexey Samsonov // filename: ... LOOKFOR [GC] [RR] [C++] [FAIL ...] 4888c1441f8SAlexey Samsonov char buf[512]; 4898c1441f8SAlexey Samsonov while (fgets(buf, 512, fp)) { 4908c1441f8SAlexey Samsonov char *config = strstr(buf, LOOKFOR); 4918c1441f8SAlexey Samsonov if (!config) continue; 4928c1441f8SAlexey Samsonov char *filename = buf; 4938c1441f8SAlexey Samsonov char *end = strchr(buf, ':'); 4948c1441f8SAlexey Samsonov *end = 0; 4958c1441f8SAlexey Samsonov [result addObject:[self generatorFromLine:config filename:filename]]; 4968c1441f8SAlexey Samsonov } 4978c1441f8SAlexey Samsonov return result; 4988c1441f8SAlexey Samsonov} 4998c1441f8SAlexey Samsonov 5008c1441f8SAlexey Samsonov+ (TestFileExeGenerator *)generatorFromFilename:(char *)filename { 5018c1441f8SAlexey Samsonov FILE *fp = fopen(filename, "r"); 5028c1441f8SAlexey Samsonov if (!fp) { 5038c1441f8SAlexey Samsonov printf("didn't open %s!!\n", filename); 5048c1441f8SAlexey Samsonov return nil; 5058c1441f8SAlexey Samsonov } 5068c1441f8SAlexey Samsonov char buf[512]; 5078c1441f8SAlexey Samsonov while (fgets(buf, 512, fp)) { 5088c1441f8SAlexey Samsonov char *config = strstr(buf, LOOKFOR); 5098c1441f8SAlexey Samsonov if (!config) continue; 5108c1441f8SAlexey Samsonov fclose(fp); 5118c1441f8SAlexey Samsonov return [self generatorFromLine:config filename:filename]; 5128c1441f8SAlexey Samsonov } 5138c1441f8SAlexey Samsonov fclose(fp); 5148c1441f8SAlexey Samsonov // guess from filename 5158c1441f8SAlexey Samsonov char *ext = strrchr(filename, '.'); 5168c1441f8SAlexey Samsonov if (!ext) return nil; 5178c1441f8SAlexey Samsonov TestFileExeGenerator *result = [TestFileExeGenerator new]; 5188c1441f8SAlexey Samsonov result.filename = gcstrcpy1(filename); 5198c1441f8SAlexey Samsonov if (!strncmp(ext, ".m", 2)) { 5208c1441f8SAlexey Samsonov result.hasObjC = true; 5218c1441f8SAlexey Samsonov result.hasRR = true; 5228c1441f8SAlexey Samsonov result.hasGC = true; 5238c1441f8SAlexey Samsonov } 5248c1441f8SAlexey Samsonov else if (!strcmp(ext, ".c")) { 5258c1441f8SAlexey Samsonov ; 5268c1441f8SAlexey Samsonov } 5278c1441f8SAlexey Samsonov else if (!strcmp(ext, ".M") || !strcmp(ext, ".mm")) { 5288c1441f8SAlexey Samsonov result.hasObjC = true; 5298c1441f8SAlexey Samsonov result.hasRR = true; 5308c1441f8SAlexey Samsonov result.hasGC = true; 5318c1441f8SAlexey Samsonov result.hasCPlusPlus = true; 5328c1441f8SAlexey Samsonov } 5338c1441f8SAlexey Samsonov else if (!strcmp(ext, ".cc") 5348c1441f8SAlexey Samsonov || !strcmp(ext, ".cp") 5358c1441f8SAlexey Samsonov || !strcmp(ext, ".cxx") 5368c1441f8SAlexey Samsonov || !strcmp(ext, ".cpp") 5378c1441f8SAlexey Samsonov || !strcmp(ext, ".CPP") 5388c1441f8SAlexey Samsonov || !strcmp(ext, ".c++") 5398c1441f8SAlexey Samsonov || !strcmp(ext, ".C")) { 5408c1441f8SAlexey Samsonov result.hasCPlusPlus = true; 5418c1441f8SAlexey Samsonov } 5428c1441f8SAlexey Samsonov else { 5438c1441f8SAlexey Samsonov printf("unknown extension, file %s ignored\n", filename); 5448c1441f8SAlexey Samsonov result = nil; 5458c1441f8SAlexey Samsonov } 5468c1441f8SAlexey Samsonov return result; 5478c1441f8SAlexey Samsonov 5488c1441f8SAlexey Samsonov} 5498c1441f8SAlexey Samsonov 5508c1441f8SAlexey Samsonov- (NSString *)description { 5518c1441f8SAlexey Samsonov return [NSString stringWithFormat:@"%s: %s%s%s%s%s%s", 5528c1441f8SAlexey Samsonov filename, 5538c1441f8SAlexey Samsonov LOOKFOR, 5548c1441f8SAlexey Samsonov hasGC ? " GC" : "", 5558c1441f8SAlexey Samsonov hasRR ? " RR" : "", 5568c1441f8SAlexey Samsonov hasCPlusPlus ? " C++" : "", 5578c1441f8SAlexey Samsonov wantsC99 ? "C99" : "", 5588c1441f8SAlexey Samsonov supposedToNotCompile ? " FAIL" : ""]; 5598c1441f8SAlexey Samsonov} 5608c1441f8SAlexey Samsonov 5618c1441f8SAlexey Samsonov@end 5628c1441f8SAlexey Samsonov 5638c1441f8SAlexey Samsonovvoid printDetails(NSArray *failures, const char *whatAreThey) { 5648c1441f8SAlexey Samsonov if ([failures count]) { 5658c1441f8SAlexey Samsonov NSMutableString *output = [NSMutableString new]; 5668c1441f8SAlexey Samsonov printf("%s:\n", whatAreThey); 5678c1441f8SAlexey Samsonov for (TestFileExe *line in failures) { 5688c1441f8SAlexey Samsonov printf("%s", line.binaryName); 5698c1441f8SAlexey Samsonov char *radar = line.generator.radar; 5708c1441f8SAlexey Samsonov if (radar) 5718c1441f8SAlexey Samsonov printf(" (due to %s?),", radar); 5728c1441f8SAlexey Samsonov printf(" recompile via:\n%s\n\n", line.description.UTF8String); 5738c1441f8SAlexey Samsonov } 5748c1441f8SAlexey Samsonov printf("\n"); 5758c1441f8SAlexey Samsonov } 5768c1441f8SAlexey Samsonov} 5778c1441f8SAlexey Samsonov 5788c1441f8SAlexey Samsonovvoid help(const char *whoami) { 5798c1441f8SAlexey Samsonov printf("Usage: %s [-fast] [-e] [-dyld librarypath] [gcc4.2dir] [-- | source1 ...]\n", whoami); 5808c1441f8SAlexey Samsonov printf(" -fast don't recompile if binary younger than source\n"); 5818c1441f8SAlexey Samsonov printf(" -open only run tests that are thought to still be unresolved\n"); 5828c1441f8SAlexey Samsonov printf(" -clang use the clang and clang++ compilers\n"); 5838c1441f8SAlexey Samsonov printf(" -e compile all variations also with -Os, -O2, -O3\n"); 5848c1441f8SAlexey Samsonov printf(" -dyld p override DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to p when running tests\n"); 5858c1441f8SAlexey Samsonov printf(" <compilerpath> directory containing gcc-4.2 (or clang) that you wish to use to compile the tests\n"); 5868c1441f8SAlexey Samsonov printf(" -- assume stdin is a grep CON" "FIG across the test sources\n"); 5878c1441f8SAlexey Samsonov printf(" otherwise treat each remaining argument as a single test file source\n"); 5888c1441f8SAlexey Samsonov printf("%s will compile and run individual test files under a variety of compilers, c, obj-c, c++, and objc++\n", whoami); 5898c1441f8SAlexey Samsonov printf(" .c files are compiled with all four compilers\n"); 5908c1441f8SAlexey Samsonov printf(" .m files are compiled with objc and objc++ compilers\n"); 5918c1441f8SAlexey Samsonov printf(" .C files are compiled with c++ and objc++ compilers\n"); 5928c1441f8SAlexey Samsonov printf(" .M files are compiled only with the objc++ compiler\n"); 5938c1441f8SAlexey Samsonov printf("(actually all forms of extensions recognized by the compilers are honored, .cc, .c++ etc.)\n"); 5948c1441f8SAlexey Samsonov printf("\nTest files should run to completion with no output and exit (return) 0 on success.\n"); 5958c1441f8SAlexey Samsonov printf("Further they should be able to be compiled and run with GC on or off and by the C++ compilers\n"); 5968c1441f8SAlexey Samsonov printf("A line containing the string CON" "FIG within the source enables restrictions to the above assumptions\n"); 5978c1441f8SAlexey Samsonov printf("and other options.\n"); 5988c1441f8SAlexey Samsonov printf("Following CON" "FIG the string\n"); 5998c1441f8SAlexey Samsonov printf(" C++ restricts the test to only be run by c++ and objc++ compilers\n"); 6008c1441f8SAlexey Samsonov printf(" GC restricts the test to only be compiled and run with GC on\n"); 6018c1441f8SAlexey Samsonov printf(" RR (retain/release) restricts the test to only be compiled and run with GC off\n"); 6028c1441f8SAlexey Samsonov printf("Additionally,\n"); 6038c1441f8SAlexey Samsonov printf(" -C99 restricts the C versions of the test to -fstd=c99 -fblocks\n"); 6048c1441f8SAlexey Samsonov printf(" -O adds the -O optimization level\n"); 6058c1441f8SAlexey Samsonov printf(" -O2 adds the -O2 optimization level\n"); 6068c1441f8SAlexey Samsonov printf(" -Os adds the -Os optimization level\n"); 6078c1441f8SAlexey Samsonov printf("Files that are known to exhibit unresolved problems can provide the term \"open\" and this can"); 6088c1441f8SAlexey Samsonov printf("in turn allow highlighting of fixes that have regressed as well as identify that fixes are now available.\n"); 6098c1441f8SAlexey Samsonov printf("Files that exhibit known bugs may provide\n"); 6108c1441f8SAlexey Samsonov printf(" rdar://whatever such that if they fail the rdar will get cited\n"); 6118c1441f8SAlexey Samsonov printf("Files that are expected to fail to compile should provide, as their last token sequence,\n"); 6128c1441f8SAlexey Samsonov printf(" error:\n"); 6138c1441f8SAlexey Samsonov printf(" or error: substring to match.\n"); 6148c1441f8SAlexey Samsonov printf("Files that are expected to produce a runtime error message should provide, as their last token sequence,\n"); 6158c1441f8SAlexey Samsonov printf(" warning: string to match\n"); 6168c1441f8SAlexey Samsonov printf("\n%s will compile and run all configurations of the test files and report a summary at the end. Good luck.\n", whoami); 6178c1441f8SAlexey Samsonov printf(" Blaine Garst blaine@apple.com\n"); 6188c1441f8SAlexey Samsonov} 6198c1441f8SAlexey Samsonov 6208c1441f8SAlexey Samsonovint main(int argc, char *argv[]) { 6218c1441f8SAlexey Samsonov printf("running on %s-bit architecture\n", sizeof(long) == 4 ? "32" : "64"); 6228c1441f8SAlexey Samsonov char *compilerDir = "/usr/bin"; 6238c1441f8SAlexey Samsonov NSMutableArray *generators = [NSMutableArray new]; 6248c1441f8SAlexey Samsonov bool doFast = false; 6258c1441f8SAlexey Samsonov bool doStdin = false; 6268c1441f8SAlexey Samsonov bool onlyOpen = false; 6278c1441f8SAlexey Samsonov char *libraryPath = getenv("DYLD_LIBRARY_PATH"); 6288c1441f8SAlexey Samsonov char *frameworkPath = getenv("DYLD_FRAMEWORK_PATH"); 6298c1441f8SAlexey Samsonov // process options 6308c1441f8SAlexey Samsonov while (argc > 1) { 6318c1441f8SAlexey Samsonov if (!strcmp(argv[1], "-fast")) { 6328c1441f8SAlexey Samsonov doFast = true; 6338c1441f8SAlexey Samsonov --argc; 6348c1441f8SAlexey Samsonov ++argv; 6358c1441f8SAlexey Samsonov } 6368c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "-dyld")) { 6378c1441f8SAlexey Samsonov doFast = true; 6388c1441f8SAlexey Samsonov --argc; 6398c1441f8SAlexey Samsonov ++argv; 6408c1441f8SAlexey Samsonov frameworkPath = argv[1]; 6418c1441f8SAlexey Samsonov libraryPath = argv[1]; 6428c1441f8SAlexey Samsonov --argc; 6438c1441f8SAlexey Samsonov ++argv; 6448c1441f8SAlexey Samsonov } 6458c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "-open")) { 6468c1441f8SAlexey Samsonov onlyOpen = true; 6478c1441f8SAlexey Samsonov --argc; 6488c1441f8SAlexey Samsonov ++argv; 6498c1441f8SAlexey Samsonov } 6508c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "-clang")) { 6518c1441f8SAlexey Samsonov DoClang = true; 6528c1441f8SAlexey Samsonov --argc; 6538c1441f8SAlexey Samsonov ++argv; 6548c1441f8SAlexey Samsonov } 6558c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "-e")) { 6568c1441f8SAlexey Samsonov Everything = true; 6578c1441f8SAlexey Samsonov --argc; 6588c1441f8SAlexey Samsonov ++argv; 6598c1441f8SAlexey Samsonov } 6608c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "--")) { 6618c1441f8SAlexey Samsonov doStdin = true; 6628c1441f8SAlexey Samsonov --argc; 6638c1441f8SAlexey Samsonov ++argv; 6648c1441f8SAlexey Samsonov } 6658c1441f8SAlexey Samsonov else if (!strcmp(argv[1], "-")) { 6668c1441f8SAlexey Samsonov help(argv[0]); 6678c1441f8SAlexey Samsonov return 1; 6688c1441f8SAlexey Samsonov } 6698c1441f8SAlexey Samsonov else if (argc > 1 && isDirectory(argv[1])) { 6708c1441f8SAlexey Samsonov compilerDir = argv[1]; 6718c1441f8SAlexey Samsonov ++argv; 6728c1441f8SAlexey Samsonov --argc; 6738c1441f8SAlexey Samsonov } 6748c1441f8SAlexey Samsonov else 6758c1441f8SAlexey Samsonov break; 6768c1441f8SAlexey Samsonov } 6778c1441f8SAlexey Samsonov // process remaining arguments, or stdin 6788c1441f8SAlexey Samsonov if (argc == 1) { 6798c1441f8SAlexey Samsonov if (doStdin) 6808c1441f8SAlexey Samsonov generators = (NSMutableArray *)[TestFileExeGenerator generatorsFromFILE:stdin]; 6818c1441f8SAlexey Samsonov else { 6828c1441f8SAlexey Samsonov help(argv[0]); 6838c1441f8SAlexey Samsonov return 1; 6848c1441f8SAlexey Samsonov } 6858c1441f8SAlexey Samsonov } 6868c1441f8SAlexey Samsonov else while (argc > 1) { 6878c1441f8SAlexey Samsonov TestFileExeGenerator *generator = [TestFileExeGenerator generatorFromFilename:argv[1]]; 6888c1441f8SAlexey Samsonov if (generator) [generators addObject:generator]; 6898c1441f8SAlexey Samsonov ++argv; 6908c1441f8SAlexey Samsonov --argc; 6918c1441f8SAlexey Samsonov } 6928c1441f8SAlexey Samsonov // see if we can generate all possibilities 6938c1441f8SAlexey Samsonov NSMutableArray *failureToCompile = [NSMutableArray new]; 6948c1441f8SAlexey Samsonov NSMutableArray *failureToFailToCompile = [NSMutableArray new]; 6958c1441f8SAlexey Samsonov NSMutableArray *failureToRun = [NSMutableArray new]; 6968c1441f8SAlexey Samsonov NSMutableArray *successes = [NSMutableArray new]; 6978c1441f8SAlexey Samsonov for (TestFileExeGenerator *generator in generators) { 6988c1441f8SAlexey Samsonov //NSLog(@"got %@", generator); 6998c1441f8SAlexey Samsonov if (onlyOpen && !generator.open) { 7008c1441f8SAlexey Samsonov //printf("skipping resolved test %s\n", generator.filename); 7018c1441f8SAlexey Samsonov continue; // skip closed if onlyOpen 7028c1441f8SAlexey Samsonov } 7038c1441f8SAlexey Samsonov if (!onlyOpen && generator.open) { 7048c1441f8SAlexey Samsonov //printf("skipping open test %s\n", generator.filename); 7058c1441f8SAlexey Samsonov continue; // skip open if not asked for onlyOpen 7068c1441f8SAlexey Samsonov } 7078c1441f8SAlexey Samsonov generator.compilerPath = compilerDir; 7088c1441f8SAlexey Samsonov NSArray *tests = [generator allLines]; 7098c1441f8SAlexey Samsonov for (TestFileExe *line in tests) { 7108c1441f8SAlexey Samsonov line.frameworkPath = frameworkPath; // tell generators about it instead XXX 7118c1441f8SAlexey Samsonov line.libraryPath = libraryPath; // tell generators about it instead XXX 7128c1441f8SAlexey Samsonov if ([line shouldFail]) { 7138c1441f8SAlexey Samsonov if (doFast) continue; // don't recompile & don't count as success 7148c1441f8SAlexey Samsonov if ([line compileWithExpectedFailure]) { 7158c1441f8SAlexey Samsonov [successes addObject:line]; 7168c1441f8SAlexey Samsonov } 7178c1441f8SAlexey Samsonov else 7188c1441f8SAlexey Samsonov [failureToFailToCompile addObject:line]; 7198c1441f8SAlexey Samsonov } 7208c1441f8SAlexey Samsonov else if ([line compileUnlessExists:doFast]) { 7218c1441f8SAlexey Samsonov if ([line run]) { 7228c1441f8SAlexey Samsonov printf("%s ran successfully\n", line.binaryName); 7238c1441f8SAlexey Samsonov [successes addObject:line]; 7248c1441f8SAlexey Samsonov } 7258c1441f8SAlexey Samsonov else { 7268c1441f8SAlexey Samsonov [failureToRun addObject:line]; 7278c1441f8SAlexey Samsonov } 7288c1441f8SAlexey Samsonov } 7298c1441f8SAlexey Samsonov else { 7308c1441f8SAlexey Samsonov [failureToCompile addObject:line]; 7318c1441f8SAlexey Samsonov } 7328c1441f8SAlexey Samsonov } 7338c1441f8SAlexey Samsonov } 7348c1441f8SAlexey Samsonov printf("\n--- results ---\n\n%lu successes\n%lu unexpected compile failures\n%lu failure to fail to compile errors\n%lu run failures\n", 7358c1441f8SAlexey Samsonov [successes count], [failureToCompile count], [failureToFailToCompile count], [failureToRun count]); 7368c1441f8SAlexey Samsonov printDetails(failureToCompile, "unexpected compile failures"); 7378c1441f8SAlexey Samsonov printDetails(failureToFailToCompile, "should have failed to compile but didn't failures"); 7388c1441f8SAlexey Samsonov printDetails(failureToRun, "run failures"); 7398c1441f8SAlexey Samsonov 7408c1441f8SAlexey Samsonov if (onlyOpen && [successes count]) { 7418c1441f8SAlexey Samsonov NSMutableSet *radars = [NSMutableSet new]; 7428c1441f8SAlexey Samsonov printf("The following tests ran successfully suggesting that they are now resolved:\n"); 7438c1441f8SAlexey Samsonov for (TestFileExe *line in successes) { 7448c1441f8SAlexey Samsonov printf("%s\n", line.binaryName); 7458c1441f8SAlexey Samsonov if (line.radar) [radars addObject:line.generator]; 7468c1441f8SAlexey Samsonov } 7478c1441f8SAlexey Samsonov if ([radars count]) { 7488c1441f8SAlexey Samsonov printf("The following radars may be resolved:\n"); 7498c1441f8SAlexey Samsonov for (TestFileExeGenerator *line in radars) { 7508c1441f8SAlexey Samsonov printf("%s\n", line.radar); 7518c1441f8SAlexey Samsonov } 7528c1441f8SAlexey Samsonov } 7538c1441f8SAlexey Samsonov } 7548c1441f8SAlexey Samsonov 7558c1441f8SAlexey Samsonov return [failureToCompile count] + [failureToRun count]; 7568c1441f8SAlexey Samsonov} 7578c1441f8SAlexey Samsonov 7588c1441f8SAlexey Samsonov#include <sys/stat.h> 7598c1441f8SAlexey Samsonov 7608c1441f8SAlexey Samsonovstatic bool isDirectory(char *path) { 7618c1441f8SAlexey Samsonov struct stat statb; 7628c1441f8SAlexey Samsonov int retval = stat(path, &statb); 7638c1441f8SAlexey Samsonov if (retval != 0) return false; 7648c1441f8SAlexey Samsonov if (statb.st_mode & S_IFDIR) return true; 7658c1441f8SAlexey Samsonov return false; 7668c1441f8SAlexey Samsonov} 7678c1441f8SAlexey Samsonov 7688c1441f8SAlexey Samsonovstatic bool isExecutable(char *path) { 7698c1441f8SAlexey Samsonov struct stat statb; 7708c1441f8SAlexey Samsonov int retval = stat(path, &statb); 7718c1441f8SAlexey Samsonov if (retval != 0) return false; 7728c1441f8SAlexey Samsonov if (!(statb.st_mode & S_IFREG)) return false; 7738c1441f8SAlexey Samsonov if (statb.st_mode & S_IXUSR) return true; 7748c1441f8SAlexey Samsonov return false; 7758c1441f8SAlexey Samsonov} 7768c1441f8SAlexey Samsonov 7778c1441f8SAlexey Samsonovstatic bool isYounger(char *source, char *binary) { 7788c1441f8SAlexey Samsonov struct stat statb; 7798c1441f8SAlexey Samsonov int retval = stat(binary, &statb); 7808c1441f8SAlexey Samsonov if (retval != 0) return true; // if doesn't exit, lie 7818c1441f8SAlexey Samsonov 7828c1441f8SAlexey Samsonov struct stat stata; 7838c1441f8SAlexey Samsonov retval = stat(source, &stata); 7848c1441f8SAlexey Samsonov if (retval != 0) return true; // we're hosed 7858c1441f8SAlexey Samsonov // the greater the timeval the younger it is 7868c1441f8SAlexey Samsonov if (stata.st_mtimespec.tv_sec > statb.st_mtimespec.tv_sec) return true; 7878c1441f8SAlexey Samsonov if (stata.st_mtimespec.tv_nsec > statb.st_mtimespec.tv_nsec) return true; 7888c1441f8SAlexey Samsonov return false; 7898c1441f8SAlexey Samsonov} 7908c1441f8SAlexey Samsonov 7918c1441f8SAlexey Samsonovstatic bool readErrorFile(char *buffer, const char *from) { 7928c1441f8SAlexey Samsonov int fd = open(from, 0); 7938c1441f8SAlexey Samsonov if (fd < 0) { 7948c1441f8SAlexey Samsonov printf("didn't open %s, (might not have been created?)\n", buffer); 7958c1441f8SAlexey Samsonov return false; 7968c1441f8SAlexey Samsonov } 7978c1441f8SAlexey Samsonov int count = read(fd, buffer, 512); 7988c1441f8SAlexey Samsonov if (count < 1) { 7998c1441f8SAlexey Samsonov printf("read error on %s\n", buffer); 8008c1441f8SAlexey Samsonov return false; 8018c1441f8SAlexey Samsonov } 8028c1441f8SAlexey Samsonov buffer[count-1] = 0; // zap newline 8038c1441f8SAlexey Samsonov return true; 8048c1441f8SAlexey Samsonov} 805