From 28d10da69f52af1b01fbc12fd503621713641500 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Fri, 14 Feb 2014 09:47:31 +0000 Subject: Move tests for BlocksRuntime and builtins to corresponding directories under test/ git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@201396 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/BlocksRuntime/testfilerunner.m | 805 ++++++++++++++++++++++++++++++++++++ 1 file changed, 805 insertions(+) create mode 100644 test/BlocksRuntime/testfilerunner.m (limited to 'test/BlocksRuntime/testfilerunner.m') diff --git a/test/BlocksRuntime/testfilerunner.m b/test/BlocksRuntime/testfilerunner.m new file mode 100644 index 000000000..459adf889 --- /dev/null +++ b/test/BlocksRuntime/testfilerunner.m @@ -0,0 +1,805 @@ +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. + +// +// testfilerunner.m +// testObjects +// +// Created by Blaine Garst on 9/24/08. +// + +#import "testfilerunner.h" +#import +#include +#include +#include +#include +#include +#include + +bool Everything = false; // do it also with 3 levels of optimization +bool DoClang = false; + +static bool isDirectory(char *path); +static bool isExecutable(char *path); +static bool isYounger(char *source, char *binary); +static bool readErrorFile(char *buffer, const char *from); + +__strong char *gcstrcpy2(__strong const char *arg, char *endp) { + unsigned size = endp - arg + 1; + __strong char *result = NSAllocateCollectable(size, 0); + strncpy(result, arg, size); + result[size-1] = 0; + return result; +} +__strong char *gcstrcpy1(__strong char *arg) { + unsigned size = strlen(arg) + 1; + __strong char *result = NSAllocateCollectable(size, 0); + strncpy(result, arg, size); + result[size-1] = 0; + return result; +} + +@implementation TestFileExe + +@synthesize options, compileLine, shouldFail, binaryName, sourceName; +@synthesize generator; +@synthesize libraryPath, frameworkPath; + +- (NSString *)description { + NSMutableString *result = [NSMutableString new]; + if (shouldFail) [result appendString:@"fail"]; + for (id x in compileLine) { + [result appendString:[NSString stringWithFormat:@" %s", (char *)x]]; + } + return result; +} + +- (__strong char *)radar { + return generator.radar; +} + +- (bool) compileUnlessExists:(bool)skip { + if (shouldFail) { + printf("don't use this to compile anymore!\n"); + return false; + } + if (skip && isExecutable(binaryName) && !isYounger(sourceName, binaryName)) return true; + int argc = [compileLine count]; + char *argv[argc+1]; + for (int i = 0; i < argc; ++i) + argv[i] = (char *)[compileLine pointerAtIndex:i]; + argv[argc] = NULL; + pid_t child = fork(); + if (child == 0) { + execv(argv[0], argv); + exit(10); // shouldn't happen + } + if (child < 0) { + printf("fork failed\n"); + return false; + } + int status = 0; + pid_t deadchild = wait(&status); + if (deadchild != child) { + printf("wait got %d instead of %d\n", deadchild, child); + exit(1); + } + if (WEXITSTATUS(status) == 0) { + return true; + } + printf("run failed\n"); + return false; +} + +bool lookforIn(char *lookfor, const char *format, pid_t child) { + char buffer[512]; + char got[512]; + sprintf(buffer, format, child); + bool gotOutput = readErrorFile(got, buffer); + if (!gotOutput) { + printf("**** didn't get an output file %s to analyze!!??\n", buffer); + return false; + } + char *where = strstr(got, lookfor); + if (!where) { + printf("didn't find '%s' in output file %s\n", lookfor, buffer); + return false; + } + unlink(buffer); + return true; +} + +- (bool) compileWithExpectedFailure { + if (!shouldFail) { + printf("Why am I being called?\n"); + return false; + } + int argc = [compileLine count]; + char *argv[argc+1]; + for (int i = 0; i < argc; ++i) + argv[i] = (char *)[compileLine pointerAtIndex:i]; + argv[argc] = NULL; + pid_t child = fork(); + char buffer[512]; + if (child == 0) { + // in child + sprintf(buffer, "/tmp/errorfile_%d", getpid()); + close(1); + int fd = creat(buffer, 0777); + if (fd != 1) { + fprintf(stderr, "didn't open custom error file %s as 1, got %d\n", buffer, fd); + exit(1); + } + close(2); + dup(1); + int result = execv(argv[0], argv); + exit(10); + } + if (child < 0) { + printf("fork failed\n"); + return false; + } + int status = 0; + pid_t deadchild = wait(&status); + if (deadchild != child) { + printf("wait got %d instead of %d\n", deadchild, child); + exit(11); + } + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) == 0) { + return false; + } + } + else { + printf("***** compiler borked/ICEd/died unexpectedly (status %x)\n", status); + return false; + } + char *error = generator.errorString; + + if (!error) return true; +#if 0 + char got[512]; + sprintf(buffer, "/tmp/errorfile_%d", child); + bool gotOutput = readErrorFile(got, buffer); + if (!gotOutput) { + printf("**** didn't get an error file %s to analyze!!??\n", buffer); + return false; + } + char *where = strstr(got, error); + if (!where) { + printf("didn't find '%s' in error file %s\n", error, buffer); + return false; + } + unlink(buffer); +#else + if (!lookforIn(error, "/tmp/errorfile_%d", child)) return false; +#endif + return true; +} + +- (bool) run { + if (shouldFail) return true; + if (sizeof(long) == 4 && options & Do64) { + return true; // skip 64-bit tests + } + int argc = 1; + char *argv[argc+1]; + argv[0] = binaryName; + argv[argc] = NULL; + pid_t child = fork(); + if (child == 0) { + // set up environment + char lpath[1024]; + char fpath[1024]; + char *myenv[3]; + int counter = 0; + if (libraryPath) { + sprintf(lpath, "DYLD_LIBRARY_PATH=%s", libraryPath); + myenv[counter++] = lpath; + } + if (frameworkPath) { + sprintf(fpath, "DYLD_FRAMEWORK_PATH=%s", frameworkPath); + myenv[counter++] = fpath; + } + myenv[counter] = NULL; + if (generator.warningString) { + // set up stdout/stderr + char outfile[1024]; + sprintf(outfile, "/tmp/stdout_%d", getpid()); + close(2); + close(1); + creat(outfile, 0700); + dup(1); + } + execve(argv[0], argv, myenv); + exit(10); // shouldn't happen + } + if (child < 0) { + printf("fork failed\n"); + return false; + } + int status = 0; + pid_t deadchild = wait(&status); + if (deadchild != child) { + printf("wait got %d instead of %d\n", deadchild, child); + exit(1); + } + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + if (generator.warningString) { + if (!lookforIn(generator.warningString, "/tmp/stdout_%d", child)) return false; + } + return true; + } + printf("**** run failed for %s\n", binaryName); + return false; +} + +@end + +@implementation TestFileExeGenerator +@synthesize filename, compilerPath, errorString; +@synthesize hasObjC, hasRR, hasGC, hasCPlusPlus, wantsC99, supposedToNotCompile, open, wants32, wants64; +@synthesize radar; +@synthesize warningString; + +- (void)setFilename:(__strong char *)name { + filename = gcstrcpy1(name); +} +- (void)setCompilerPath:(__strong char *)name { + compilerPath = gcstrcpy1(name); +} + +- (void)forMostThings:(NSMutableArray *)lines options:(int)options { + TestFileExe *item = nil; + item = [self lineForOptions:options]; + if (item) [lines addObject:item]; + item = [self lineForOptions:options|Do64]; + if (item) [lines addObject:item]; + item = [self lineForOptions:options|DoCPP]; + if (item) [lines addObject:item]; + item = [self lineForOptions:options|Do64|DoCPP]; + if (item) [lines addObject:item]; +} + +/* + DoDashG = (1 << 8), + DoDashO = (1 << 9), + DoDashOs = (1 << 10), + DoDashO2 = (1 << 11), +*/ + +- (void)forAllThings:(NSMutableArray *)lines options:(int)options { + [self forMostThings:lines options:options]; + if (!Everything) { + return; + } + // now do it with three explicit optimization flags + [self forMostThings:lines options:options | DoDashO]; + [self forMostThings:lines options:options | DoDashOs]; + [self forMostThings:lines options:options | DoDashO2]; +} + +- (NSArray *)allLines { + NSMutableArray *result = [NSMutableArray new]; + TestFileExe *item = nil; + + int options = 0; + [self forAllThings:result options:0]; + [self forAllThings:result options:DoOBJC | DoRR]; + [self forAllThings:result options:DoOBJC | DoGC]; + [self forAllThings:result options:DoOBJC | DoGCRR]; + //[self forAllThings:result options:DoOBJC | DoRRGC]; + + return result; +} + +- (void)addLibrary:(const char *)dashLSomething { + if (!extraLibraries) { + extraLibraries = [NSPointerArray pointerArrayWithOptions: + NSPointerFunctionsStrongMemory | + NSPointerFunctionsCStringPersonality]; + } + [extraLibraries addPointer:(void *)dashLSomething]; +} + +- (TestFileExe *)lineForOptions:(int)options { // nil if no can do + if (hasObjC && !(options & DoOBJC)) return nil; + if (hasCPlusPlus && !(options & DoCPP)) return nil; + if (hasObjC) { + if (!hasGC && (options & (DoGC|DoGCRR))) return nil; // not smart enough + if (!hasRR && (options & (DoRR|DoRRGC))) return nil; + } + NSPointerArray *pa = [NSPointerArray pointerArrayWithOptions: + NSPointerFunctionsStrongMemory | + NSPointerFunctionsCStringPersonality]; + // construct path + char path[512]; + path[0] = 0; + if (!compilerPath) compilerPath = "/usr/bin"; + if (compilerPath) { + strcat(path, compilerPath); + strcat(path, "/"); + } + if (options & DoCPP) { + strcat(path, DoClang ? "clang++" : "g++-4.2"); + } + else { + strcat(path, DoClang ? "clang" : "gcc-4.2"); + } + [pa addPointer:gcstrcpy1(path)]; + if (options & DoOBJC) { + if (options & DoCPP) { + [pa addPointer:"-ObjC++"]; + } + else { + [pa addPointer:"-ObjC"]; + } + } + [pa addPointer:"-g"]; + if (options & DoDashO) [pa addPointer:"-O"]; + else if (options & DoDashO2) [pa addPointer:"-O2"]; + else if (options & DoDashOs) [pa addPointer:"-Os"]; + if (wantsC99 && (! (options & DoCPP))) { + [pa addPointer:"-std=c99"]; + [pa addPointer:"-fblocks"]; + } + [pa addPointer:"-arch"]; + [pa addPointer: (options & Do64) ? "x86_64" : "i386"]; + + if (options & DoOBJC) { + switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) { + case DoRR: + break; + case DoGC: + [pa addPointer:"-fobjc-gc-only"]; + break; + case DoGCRR: + [pa addPointer:"-fobjc-gc"]; + break; + case DoRRGC: + printf("DoRRGC unsupported right now\n"); + [pa addPointer:"-c"]; + return nil; + } + [pa addPointer:"-framework"]; + [pa addPointer:"Foundation"]; + } + [pa addPointer:gcstrcpy1(filename)]; + [pa addPointer:"-o"]; + + path[0] = 0; + strcat(path, filename); + strcat(path, "."); + strcat(path, (options & Do64) ? "64" : "32"); + if (options & DoOBJC) { + switch (options & (DoRR|DoGC|DoGCRR|DoRRGC)) { + case DoRR: strcat(path, "-rr"); break; + case DoGC: strcat(path, "-gconly"); break; + case DoGCRR: strcat(path, "-gcrr"); break; + case DoRRGC: strcat(path, "-rrgc"); break; + } + } + if (options & DoCPP) strcat(path, "++"); + if (options & DoDashO) strcat(path, "-O"); + else if (options & DoDashO2) strcat(path, "-O2"); + else if (options & DoDashOs) strcat(path, "-Os"); + if (wantsC99) strcat(path, "-C99"); + strcat(path, DoClang ? "-clang" : "-gcc"); + strcat(path, "-bin"); + TestFileExe *result = [TestFileExe new]; + result.binaryName = gcstrcpy1(path); // could snarf copy in pa + [pa addPointer:result.binaryName]; + for (id cString in extraLibraries) { + [pa addPointer:cString]; + } + + result.sourceName = gcstrcpy1(filename); // could snarf copy in pa + result.compileLine = pa; + result.options = options; + result.shouldFail = supposedToNotCompile; + result.generator = self; + return result; +} + ++ (NSArray *)generatorsFromPath:(NSString *)path { + FILE *fp = fopen([path fileSystemRepresentation], "r"); + if (fp == NULL) return nil; + NSArray *result = [self generatorsFromFILE:fp]; + fclose(fp); + return result; +} + +#define LOOKFOR "CON" "FIG" + +char *__strong parseRadar(char *line) { + line = strstr(line, "rdar:"); // returns beginning + char *endp = line + strlen("rdar:"); + while (*endp && *endp != ' ' && *endp != '\n') + ++endp; + return gcstrcpy2(line, endp); +} + +- (void)parseLibraries:(const char *)line { + start: + line = strstr(line, "-l"); + char *endp = (char *)line + 2; + while (*endp && *endp != ' ' && *endp != '\n') + ++endp; + [self addLibrary:gcstrcpy2(line, endp)]; + if (strstr(endp, "-l")) { + line = endp; + goto start; + } +} + ++ (TestFileExeGenerator *)generatorFromLine:(char *)line filename:(char *)filename { + TestFileExeGenerator *item = [TestFileExeGenerator new]; + item.filename = gcstrcpy1(filename); + if (strstr(line, "GC")) item.hasGC = true; + if (strstr(line, "RR")) item.hasRR = true; + if (strstr(line, "C++")) item.hasCPlusPlus = true; + if (strstr(line, "-C99")) { + item.wantsC99 = true; + } + if (strstr(line, "64")) item.wants64 = true; + if (strstr(line, "32")) item.wants32 = true; + if (strstr(line, "-l")) [item parseLibraries:line]; + if (strstr(line, "open")) item.open = true; + if (strstr(line, "FAIL")) item.supposedToNotCompile = true; // old + // compile time error + if (strstr(line, "error:")) { + item.supposedToNotCompile = true; + // zap newline + char *error = strstr(line, "error:") + strlen("error:"); + // make sure we have something before the newline + char *newline = strstr(error, "\n"); + if (newline && ((newline-error) > 1)) { + *newline = 0; + item.errorString = gcstrcpy1(strstr(line, "error:") + strlen("error: ")); + } + } + // run time warning + if (strstr(line, "runtime:")) { + // zap newline + char *error = strstr(line, "runtime:") + strlen("runtime:"); + // make sure we have something before the newline + char *newline = strstr(error, "\n"); + if (newline && ((newline-error) > 1)) { + *newline = 0; + item.warningString = gcstrcpy1(strstr(line, "runtime:") + strlen("runtime:")); + } + } + if (strstr(line, "rdar:")) item.radar = parseRadar(line); + if (item.hasGC || item.hasRR) item.hasObjC = true; + if (!item.wants32 && !item.wants64) { // give them both if they ask for neither + item.wants32 = item.wants64 = true; + } + return item; +} + ++ (NSArray *)generatorsFromFILE:(FILE *)fp { + NSMutableArray *result = [NSMutableArray new]; + // pretend this is a grep LOOKFOR *.[cmCM][cmCM] input + // look for + // filename: ... LOOKFOR [GC] [RR] [C++] [FAIL ...] + char buf[512]; + while (fgets(buf, 512, fp)) { + char *config = strstr(buf, LOOKFOR); + if (!config) continue; + char *filename = buf; + char *end = strchr(buf, ':'); + *end = 0; + [result addObject:[self generatorFromLine:config filename:filename]]; + } + return result; +} + ++ (TestFileExeGenerator *)generatorFromFilename:(char *)filename { + FILE *fp = fopen(filename, "r"); + if (!fp) { + printf("didn't open %s!!\n", filename); + return nil; + } + char buf[512]; + while (fgets(buf, 512, fp)) { + char *config = strstr(buf, LOOKFOR); + if (!config) continue; + fclose(fp); + return [self generatorFromLine:config filename:filename]; + } + fclose(fp); + // guess from filename + char *ext = strrchr(filename, '.'); + if (!ext) return nil; + TestFileExeGenerator *result = [TestFileExeGenerator new]; + result.filename = gcstrcpy1(filename); + if (!strncmp(ext, ".m", 2)) { + result.hasObjC = true; + result.hasRR = true; + result.hasGC = true; + } + else if (!strcmp(ext, ".c")) { + ; + } + else if (!strcmp(ext, ".M") || !strcmp(ext, ".mm")) { + result.hasObjC = true; + result.hasRR = true; + result.hasGC = true; + result.hasCPlusPlus = true; + } + else if (!strcmp(ext, ".cc") + || !strcmp(ext, ".cp") + || !strcmp(ext, ".cxx") + || !strcmp(ext, ".cpp") + || !strcmp(ext, ".CPP") + || !strcmp(ext, ".c++") + || !strcmp(ext, ".C")) { + result.hasCPlusPlus = true; + } + else { + printf("unknown extension, file %s ignored\n", filename); + result = nil; + } + return result; + +} + +- (NSString *)description { + return [NSString stringWithFormat:@"%s: %s%s%s%s%s%s", + filename, + LOOKFOR, + hasGC ? " GC" : "", + hasRR ? " RR" : "", + hasCPlusPlus ? " C++" : "", + wantsC99 ? "C99" : "", + supposedToNotCompile ? " FAIL" : ""]; +} + +@end + +void printDetails(NSArray *failures, const char *whatAreThey) { + if ([failures count]) { + NSMutableString *output = [NSMutableString new]; + printf("%s:\n", whatAreThey); + for (TestFileExe *line in failures) { + printf("%s", line.binaryName); + char *radar = line.generator.radar; + if (radar) + printf(" (due to %s?),", radar); + printf(" recompile via:\n%s\n\n", line.description.UTF8String); + } + printf("\n"); + } +} + +void help(const char *whoami) { + printf("Usage: %s [-fast] [-e] [-dyld librarypath] [gcc4.2dir] [-- | source1 ...]\n", whoami); + printf(" -fast don't recompile if binary younger than source\n"); + printf(" -open only run tests that are thought to still be unresolved\n"); + printf(" -clang use the clang and clang++ compilers\n"); + printf(" -e compile all variations also with -Os, -O2, -O3\n"); + printf(" -dyld p override DYLD_LIBRARY_PATH and DYLD_FRAMEWORK_PATH to p when running tests\n"); + printf(" directory containing gcc-4.2 (or clang) that you wish to use to compile the tests\n"); + printf(" -- assume stdin is a grep CON" "FIG across the test sources\n"); + printf(" otherwise treat each remaining argument as a single test file source\n"); + printf("%s will compile and run individual test files under a variety of compilers, c, obj-c, c++, and objc++\n", whoami); + printf(" .c files are compiled with all four compilers\n"); + printf(" .m files are compiled with objc and objc++ compilers\n"); + printf(" .C files are compiled with c++ and objc++ compilers\n"); + printf(" .M files are compiled only with the objc++ compiler\n"); + printf("(actually all forms of extensions recognized by the compilers are honored, .cc, .c++ etc.)\n"); + printf("\nTest files should run to completion with no output and exit (return) 0 on success.\n"); + printf("Further they should be able to be compiled and run with GC on or off and by the C++ compilers\n"); + printf("A line containing the string CON" "FIG within the source enables restrictions to the above assumptions\n"); + printf("and other options.\n"); + printf("Following CON" "FIG the string\n"); + printf(" C++ restricts the test to only be run by c++ and objc++ compilers\n"); + printf(" GC restricts the test to only be compiled and run with GC on\n"); + printf(" RR (retain/release) restricts the test to only be compiled and run with GC off\n"); + printf("Additionally,\n"); + printf(" -C99 restricts the C versions of the test to -fstd=c99 -fblocks\n"); + printf(" -O adds the -O optimization level\n"); + printf(" -O2 adds the -O2 optimization level\n"); + printf(" -Os adds the -Os optimization level\n"); + printf("Files that are known to exhibit unresolved problems can provide the term \"open\" and this can"); + printf("in turn allow highlighting of fixes that have regressed as well as identify that fixes are now available.\n"); + printf("Files that exhibit known bugs may provide\n"); + printf(" rdar://whatever such that if they fail the rdar will get cited\n"); + printf("Files that are expected to fail to compile should provide, as their last token sequence,\n"); + printf(" error:\n"); + printf(" or error: substring to match.\n"); + printf("Files that are expected to produce a runtime error message should provide, as their last token sequence,\n"); + printf(" warning: string to match\n"); + printf("\n%s will compile and run all configurations of the test files and report a summary at the end. Good luck.\n", whoami); + printf(" Blaine Garst blaine@apple.com\n"); +} + +int main(int argc, char *argv[]) { + printf("running on %s-bit architecture\n", sizeof(long) == 4 ? "32" : "64"); + char *compilerDir = "/usr/bin"; + NSMutableArray *generators = [NSMutableArray new]; + bool doFast = false; + bool doStdin = false; + bool onlyOpen = false; + char *libraryPath = getenv("DYLD_LIBRARY_PATH"); + char *frameworkPath = getenv("DYLD_FRAMEWORK_PATH"); + // process options + while (argc > 1) { + if (!strcmp(argv[1], "-fast")) { + doFast = true; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "-dyld")) { + doFast = true; + --argc; + ++argv; + frameworkPath = argv[1]; + libraryPath = argv[1]; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "-open")) { + onlyOpen = true; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "-clang")) { + DoClang = true; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "-e")) { + Everything = true; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "--")) { + doStdin = true; + --argc; + ++argv; + } + else if (!strcmp(argv[1], "-")) { + help(argv[0]); + return 1; + } + else if (argc > 1 && isDirectory(argv[1])) { + compilerDir = argv[1]; + ++argv; + --argc; + } + else + break; + } + // process remaining arguments, or stdin + if (argc == 1) { + if (doStdin) + generators = (NSMutableArray *)[TestFileExeGenerator generatorsFromFILE:stdin]; + else { + help(argv[0]); + return 1; + } + } + else while (argc > 1) { + TestFileExeGenerator *generator = [TestFileExeGenerator generatorFromFilename:argv[1]]; + if (generator) [generators addObject:generator]; + ++argv; + --argc; + } + // see if we can generate all possibilities + NSMutableArray *failureToCompile = [NSMutableArray new]; + NSMutableArray *failureToFailToCompile = [NSMutableArray new]; + NSMutableArray *failureToRun = [NSMutableArray new]; + NSMutableArray *successes = [NSMutableArray new]; + for (TestFileExeGenerator *generator in generators) { + //NSLog(@"got %@", generator); + if (onlyOpen && !generator.open) { + //printf("skipping resolved test %s\n", generator.filename); + continue; // skip closed if onlyOpen + } + if (!onlyOpen && generator.open) { + //printf("skipping open test %s\n", generator.filename); + continue; // skip open if not asked for onlyOpen + } + generator.compilerPath = compilerDir; + NSArray *tests = [generator allLines]; + for (TestFileExe *line in tests) { + line.frameworkPath = frameworkPath; // tell generators about it instead XXX + line.libraryPath = libraryPath; // tell generators about it instead XXX + if ([line shouldFail]) { + if (doFast) continue; // don't recompile & don't count as success + if ([line compileWithExpectedFailure]) { + [successes addObject:line]; + } + else + [failureToFailToCompile addObject:line]; + } + else if ([line compileUnlessExists:doFast]) { + if ([line run]) { + printf("%s ran successfully\n", line.binaryName); + [successes addObject:line]; + } + else { + [failureToRun addObject:line]; + } + } + else { + [failureToCompile addObject:line]; + } + } + } + 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", + [successes count], [failureToCompile count], [failureToFailToCompile count], [failureToRun count]); + printDetails(failureToCompile, "unexpected compile failures"); + printDetails(failureToFailToCompile, "should have failed to compile but didn't failures"); + printDetails(failureToRun, "run failures"); + + if (onlyOpen && [successes count]) { + NSMutableSet *radars = [NSMutableSet new]; + printf("The following tests ran successfully suggesting that they are now resolved:\n"); + for (TestFileExe *line in successes) { + printf("%s\n", line.binaryName); + if (line.radar) [radars addObject:line.generator]; + } + if ([radars count]) { + printf("The following radars may be resolved:\n"); + for (TestFileExeGenerator *line in radars) { + printf("%s\n", line.radar); + } + } + } + + return [failureToCompile count] + [failureToRun count]; +} + +#include + +static bool isDirectory(char *path) { + struct stat statb; + int retval = stat(path, &statb); + if (retval != 0) return false; + if (statb.st_mode & S_IFDIR) return true; + return false; +} + +static bool isExecutable(char *path) { + struct stat statb; + int retval = stat(path, &statb); + if (retval != 0) return false; + if (!(statb.st_mode & S_IFREG)) return false; + if (statb.st_mode & S_IXUSR) return true; + return false; +} + +static bool isYounger(char *source, char *binary) { + struct stat statb; + int retval = stat(binary, &statb); + if (retval != 0) return true; // if doesn't exit, lie + + struct stat stata; + retval = stat(source, &stata); + if (retval != 0) return true; // we're hosed + // the greater the timeval the younger it is + if (stata.st_mtimespec.tv_sec > statb.st_mtimespec.tv_sec) return true; + if (stata.st_mtimespec.tv_nsec > statb.st_mtimespec.tv_nsec) return true; + return false; +} + +static bool readErrorFile(char *buffer, const char *from) { + int fd = open(from, 0); + if (fd < 0) { + printf("didn't open %s, (might not have been created?)\n", buffer); + return false; + } + int count = read(fd, buffer, 512); + if (count < 1) { + printf("read error on %s\n", buffer); + return false; + } + buffer[count-1] = 0; // zap newline + return true; +} -- cgit v1.2.3