ali@0: #include ali@0: #include ali@0: #include ali@0: #include ali@0: #include ali@0: #ifdef WIN32 ali@0: #include ali@0: #include ali@0: #endif ali@0: #include ali@0: #include "testcase.h" ali@0: ali@0: #if !HAVE_MKSTEMP ali@0: /* ali@0: * An insecure implementation of mkstemp(), for those platforms that ali@0: * don't support it. ali@0: */ ali@0: int mkstemp(char *template) ali@0: { ali@0: int fd; ali@0: char *s; ali@0: for(;;) ali@0: { ali@0: s=str_dup(template); ali@0: mktemp(s); ali@0: if (!*s) ali@0: { ali@0: errno=EEXIST; ali@0: mem_free(s); ali@0: return -1; ali@0: } ali@0: fd=open(s,O_RDWR|O_CREAT|O_EXCL,0600); ali@0: if (fd>0) ali@0: { ali@0: strcpy(template,s); ali@0: mem_free(s); ali@0: return fd; ali@0: } ali@0: else ali@0: mem_free(s); ali@0: } ali@0: } ali@0: #endif /* !HAVE_MKSTEMP */ ali@0: ali@0: /* ali@0: * As write(), but always convert NL to CR NL. ali@0: */ ali@0: static size_t write_text(int fd,const char *buf,size_t count) ali@0: { ali@0: size_t i; ali@0: FILE *fp; ali@0: fd=dup(fd); ali@0: if (fd<0) ali@0: return -1; ali@0: #ifdef WIN32 ali@0: if (_setmode(fd,_O_BINARY)<0) ali@0: { ali@0: close(fd); ali@0: return -1; ali@0: } ali@0: #endif ali@0: fp=fdopen(fd,"wb"); ali@0: if (!fp) ali@0: { ali@0: close(fd); ali@0: return -1; ali@0: } ali@0: for(i=0;iinput) ali@0: n=strlen(testcase->input); ali@0: else ali@0: n=0; ali@0: if (n && write_text(fd,testcase->input,n)!=n) ali@0: { ali@0: perror(input); ali@0: close(fd); ali@0: (void)remove(input); ali@0: return FALSE; ali@0: } ali@0: close(fd); ali@0: command[0]=getenv("GUTCHECK"); ali@0: if (!command[0]) ali@0: command[0]="." GC_DIR_SEPARATOR_S "gutcheck"; ali@0: command[1]=input; ali@0: command[2]=NULL; ali@0: if (testcase->expected) ali@0: r=spawn_sync(command,&output,&exit_status); ali@0: else ali@0: { ali@0: r=spawn_sync(command,NULL,&exit_status); ali@0: output=NULL; ali@0: } ali@0: (void)remove(input); ali@0: if (!r) ali@0: return FALSE; ali@0: if (testcase->expected) ali@0: { ali@0: expected=string_new("\n\nFile: "); ali@0: string_append(expected,input); ali@0: string_append(expected,"\n\n\n"); ali@0: header_len=expected->len; ali@0: string_append(expected,testcase->expected); ali@0: } ali@0: else ali@0: { ali@0: expected=NULL; ali@0: header_len=0; ali@0: } ali@0: if (expected && strcmp(output,expected->str)) ali@0: { ali@0: fprintf(stderr,"%s: FAIL\n",testcase->basename); ali@0: offset=common_prefix_length(output,expected->str); ali@0: if (offset==header_len && !output[offset]) ali@0: fprintf(stderr,"Unexpected zero warnings from gutcheck.\n"); ali@0: else ali@0: { ali@0: endp=strchr(output+offset,'\n'); ali@0: if (!endp) ali@0: endp=output+strlen(output); ali@0: report=string_new(NULL); ali@0: string_append_len(report,output,endp-output); ali@0: bol=strrchr(report->str,'\n'); ali@0: if (bol) ali@0: bol++; ali@0: else ali@0: bol=report->str; ali@0: col=offset-(bol-report->str); ali@0: fprintf(stderr,"Unexpected output from gutcheck:\n"); ali@0: if (report->len>=header_len) ali@0: fprintf(stderr,"%s\n%*s^\n",report->str+header_len,col,""); ali@0: else ali@0: fprintf(stderr,"%s\n%*s^\n",report->str,col,""); ali@0: string_free(report,TRUE); ali@0: } ali@0: string_free(expected,TRUE); ali@0: mem_free(output); ali@0: return FALSE; ali@0: } ali@0: string_free(expected,TRUE); ali@0: mem_free(output); ali@0: if (exit_status) ali@0: fprintf(stderr,"gutcheck exited with code %d\n",r); ali@0: if (!exit_status) ali@0: fprintf(stderr,"%s: PASS\n",testcase->basename); ali@0: return !exit_status; ali@0: } ali@0: ali@0: /* ali@0: * Free a testcase. ali@0: */ ali@0: void testcase_free(Testcase *testcase) ali@0: { ali@0: mem_free(testcase->basename); ali@0: mem_free(testcase->input); ali@0: mem_free(testcase->expected); ali@0: mem_free(testcase); ali@0: }