/*------------------------------------------------------------------------- * * pg_regress_ecpg --- regression test driver for ecpg * * This is a C implementation of the previous shell script for running * the regression tests, and should be mostly compatible with it. * Initial author of C translation: Magnus Hagander * * This code is released under the terms of the PostgreSQL License. * * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $PostgreSQL$ * *------------------------------------------------------------------------- */ #include "pg_regress.h" static int ecpg_compile(const char *inputdir, const char *pgcfile, const char *cfile, const char *binary, const char *ecpg_binary, const char* ecpg_flags, int isrelease) { char cwd[MAXPGPATH]; const char *ecpgcmdfmt = SYSTEMQUOTE "\"%s\\ecpg\" --regression %s -o \"%s\" \"%s\"" SYSTEMQUOTE; const char *clcmdfmt = "cl.exe %s /TC /MD%s /I. /I..\\..\\include /I..\\..\\..\\libpq /I..\\..\\..\\..\\include /link /defaultlib:..\\..\\..\\..\\..\\%s\\libecpg\\libecpg.lib /defaultlib:..\\..\\..\\..\\..\\%s\\libecpg_compat\\libecpg_compat.lib /defaultlib:..\\..\\..\\..\\..\\%s\\libpgtypes\\libpgtypes.lib /out:\"%s\""; int size = strlen(clcmdfmt) + 1024; char *s = malloc(size); char *p; /* XXX - check for ERANGE */ getcwd(cwd, MAXPGPATH); chdir(inputdir); snprintf(s, size, ecpgcmdfmt, ecpg_binary, ecpg_flags, cfile, pgcfile); printf("executing %s\n", s); system(s); snprintf(s, size, clcmdfmt, cfile, isrelease ? "" : "d", isrelease ? "Release" : "debug", isrelease ? "Release" : "debug", isrelease ? "Release" : "debug", binary); printf("executing %s\n", s); system(s); strcpy(s, binary); strcat(s, ".manifest"); printf("deleting %s\n", s); //unlink(s); strcpy(s, binary); p = strstr(s, ".exe"); *p = '\0'; strcat(s, ".obj"); printf("deleting %s\n", s); //unlink(s); strcpy(s, binary); p = strstr(s, ".exe"); *p = '\0'; strcat(s, ".suo"); printf("deleting %s\n", s); unlink(s); chdir(cwd); return 1; } #define LINEBUFSIZE 300 static void ecpg_filter(const char *sourcefile, const char *outfile) { /* * Create a filtered copy of sourcefile, replacing * #line x "./../bla/foo.h" * with * #line x "foo.h" */ FILE *s, *t; char linebuf[LINEBUFSIZE]; s = fopen(sourcefile, "r"); if (!s) { fprintf(stderr, "Could not open file %s for reading\n", sourcefile); exit_nicely(2); } t = fopen(outfile, "w"); if (!t) { fprintf(stderr, "Could not open file %s for writing\n", outfile); exit_nicely(2); } while (fgets(linebuf, LINEBUFSIZE, s)) { /* check for "#line " in the beginning */ if (strstr(linebuf, "#line ") == linebuf) { char *p = strchr(linebuf, '"'); char *n; int plen = 1; while (*p && (*(p + plen) == '.' || strchr(p + plen, '/') != NULL)) { plen++; } /* plen is one more than the number of . and / characters */ if (plen > 1) { n = (char *) malloc(plen); strncpy(n, p+1, plen - 1); n[plen-1] = '\0'; replace_string(linebuf, n, ""); } } fputs(linebuf, t); } fclose(s); fclose(t); } /* * start an ecpg test process for specified file (including redirection), * and return process ID */ static PID_TYPE ecpg_start_test(const char *testname, _stringlist **resultfiles, _stringlist **expectfiles, _stringlist **tags) { PID_TYPE pid; char inprg[MAXPGPATH]; char insource[MAXPGPATH]; char *outfile_stdout, expectfile_stdout[MAXPGPATH]; char *outfile_stderr, expectfile_stderr[MAXPGPATH]; char *outfile_source, expectfile_source[MAXPGPATH]; char cmd[MAXPGPATH * 3]; char *testname_dash; snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname); testname_dash = strdup(testname); replace_string(testname_dash, "/", "-"); snprintf(expectfile_stdout, sizeof(expectfile_stdout), "%s/expected/%s.stdout", outputdir, testname_dash); snprintf(expectfile_stderr, sizeof(expectfile_stderr), "%s/expected/%s.stderr", outputdir, testname_dash); snprintf(expectfile_source, sizeof(expectfile_source), "%s/expected/%s.c", outputdir, testname_dash); /* * We can use replace_string() here because the replacement string does * not occupy more space than the replaced one. */ outfile_stdout = strdup(expectfile_stdout); replace_string(outfile_stdout, "/expected/", "/results/"); outfile_stderr = strdup(expectfile_stderr); replace_string(outfile_stderr, "/expected/", "/results/"); outfile_source = strdup(expectfile_source); replace_string(outfile_source, "/expected/", "/results/"); add_stringlist_item(resultfiles, outfile_stdout); add_stringlist_item(expectfiles, expectfile_stdout); add_stringlist_item(tags, "stdout"); add_stringlist_item(resultfiles, outfile_stderr); add_stringlist_item(expectfiles, expectfile_stderr); add_stringlist_item(tags, "stderr"); add_stringlist_item(resultfiles, outfile_source); add_stringlist_item(expectfiles, expectfile_source); add_stringlist_item(tags, "source"); /* XXX - move to tmp dir */ snprintf(insource, sizeof(insource), "%s.c", testname); if (strstr(host_platform, "-win32vc")) { char pgcfile[MAXPGPATH]; char cfile[MAXPGPATH]; char exefile[MAXPGPATH]; char testdir[MAXPGPATH]; char *p; char *ecpg_flags = ""; /* testname is like foo/bar, replace '/' with \0 */ strcpy(testdir, testname); p = strchr(testdir, '/'); if (!p) { /* XXX */ } *p = '\0'; strcpy(pgcfile, p+1); strcat(pgcfile, ".pgc"); strcpy(exefile, p+1); strcat(exefile, ".exe"); strcpy(cfile, p+1); strcat(cfile, ".c"); if (strstr(testname, "compat_informix")) { if (strstr(testname, "rnull")) ecpg_flags = "-C INFORMIX -r no_indicator"; else ecpg_flags = "-C INFORMIX"; } else ecpg_flags = ""; /* XXX: detect release build */ ecpg_compile(testdir, pgcfile, cfile, exefile, ecpgdir, ecpg_flags, 0); } ecpg_filter(insource, outfile_source); snprintf(inprg, sizeof(inprg), "%s/%s", inputdir, testname); snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "\"%s\" >\"%s\" 2>\"%s\"" SYSTEMQUOTE, inprg, outfile_stdout, outfile_stderr); pid = spawn_process(cmd); if (pid == INVALID_PID) { fprintf(stderr, _("could not start process for test %s\n"), testname); exit_nicely(2); } free(outfile_stdout); free(outfile_stderr); free(outfile_source); return pid; } static void ecpg_init(void) { /* no reason to set -w for ecpg checks, except for when on windows */ if (strstr(host_platform, "-win32")) basic_diff_opts = "-w"; else basic_diff_opts = ""; if (strstr(host_platform, "-win32")) pretty_diff_opts = "-C3 -w"; else pretty_diff_opts = "-C3"; } int main(int argc, char *argv[]) { return regression_main(argc, argv, ecpg_init, ecpg_start_test); }