* Win32 (NT, Win2k, XP). replace() doesn't work on Win95/98/Me.
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.46 2007/01/05 22:20:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.47 2007/01/19 16:42:24 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
/*
- * fnames
+ * pgfnames
*
- * return a list of the names of objects in the argument directory
+ * return a list of the names of objects in the argument directory. Caller
+ * must call pgfnames_cleanup later to free the memory allocated by this
+ * function.
*/
-static char **
-fnames(char *path)
+char **
+pgfnames(char *path)
{
DIR *dir;
struct dirent *file;
/*
- * fnames_cleanup
+ * pgfnames_cleanup
*
* deallocate memory used for filenames
*/
-static void
-fnames_cleanup(char **filenames)
+void
+pgfnames_cleanup(char **filenames)
{
char **fn;
* we copy all the names out of the directory before we start modifying
* it.
*/
- filenames = fnames(path);
+ filenames = pgfnames(path);
if (filenames == NULL)
return false;
if (!rmtree(filepath, true))
{
/* we already reported the error */
- fnames_cleanup(filenames);
+ pgfnames_cleanup(filenames);
return false;
}
}
goto report_and_fail;
}
- fnames_cleanup(filenames);
+ pgfnames_cleanup(filenames);
return true;
report_and_fail:
fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
filepath, strerror(errno));
#endif
- fnames_cleanup(filenames);
+ pgfnames_cleanup(filenames);
return false;
}
# Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
-# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.63 2007/01/05 22:20:03 momjian Exp $
+# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.64 2007/01/19 16:42:24 alvherre Exp $
#
#-------------------------------------------------------------------------
# stuff to pass into build of pg_regress
EXTRADEFS = '-DHOST_TUPLE="$(host_tuple)"' \
'-DMAKEPROG="$(MAKE)"' \
- '-DSHELLPROG="$(SHELL)"'
+ '-DSHELLPROG="$(SHELL)"' \
+ '-DDLSUFFIX="$(DLSUFFIX)"'
##
## Prepare for tests
rm -f $(NAME)$(DLSUFFIX)
$(LN_S) $(shlib) $(NAME)$(DLSUFFIX)
-# Build test input and expected files
-
-file_list := copy create_function_1 create_function_2 misc constraints tablespace
+# Test input and expected files. These are created by pg_regress itself, so we
+# don't have a rule to create them. We do need rules to clean them however.
+file_list := $(subst .source,, $(notdir $(wildcard $(top_srcdir)/$(subdir)/input/*.source)))
input_files := $(foreach file, $(file_list), sql/$(file).sql)
output_files := $(foreach file, $(file_list), expected/$(file).out)
-all: $(input_files) $(output_files)
-
ifneq ($(PORTNAME),win32)
abs_srcdir := $(shell cd $(srcdir) && pwd)
abs_builddir := $(shell pwd)
abs_builddir := $(shell pwd -W)
endif
-testtablespace := $(abs_builddir)/testtablespace
-
-
-define sed-command
-sed -e 's,@abs_srcdir@,$(abs_srcdir),g' \
- -e 's,@abs_builddir@,$(abs_builddir),g' \
- -e 's,@testtablespace@,$(testtablespace),g' \
- -e 's/@DLSUFFIX@/$(DLSUFFIX)/g' $< >$@
-endef
-
-$(input_files): sql/%.sql: input/%.source
- $(sed-command)
-
-$(output_files): expected/%.out: output/%.source
- $(sed-command)
-
# When doing a VPATH build, copy over the remaining .sql and .out
# files so that the driver script can find them. We have to use an
# absolute path for the targets, because otherwise make will try to
check: all
-rm -rf ./testtablespace
mkdir ./testtablespace
- ./pg_regress --temp-install=./tmp_check --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --schedule=$(srcdir)/parallel_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE)
+ ./pg_regress --temp-install=./tmp_check --top-builddir=$(top_builddir) --srcdir=$(abs_srcdir) --temp-port=$(TEMP_PORT) --schedule=$(srcdir)/parallel_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE)
installcheck: all
-rm -rf ./testtablespace
mkdir ./testtablespace
- ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE)
+ ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule --srcdir=$(abs_srcdir) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE)
installcheck-parallel: all
-rm -rf ./testtablespace
mkdir ./testtablespace
- ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/parallel_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE)
+ ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/parallel_schedule --srcdir=$(abs_srcdir) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE)
# old interfaces follow...
runtest-parallel: installcheck-parallel
bigtest:
- ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) numeric_big
+ ./pg_regress --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule --srcdir=$(abs_srcdir) --multibyte=$(MULTIBYTE) --load-language=plpgsql $(NOLOCALE) numeric_big
bigcheck:
- ./pg_regress --temp-install=./tmp_check --top-builddir=$(top_builddir) --temp-port=$(TEMP_PORT) --schedule=$(srcdir)/parallel_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE) numeric_big
+ ./pg_regress --temp-install=./tmp_check --top-builddir=$(top_builddir) --srcdir=$(abs_srcdir) --temp-port=$(TEMP_PORT) --schedule=$(srcdir)/parallel_schedule --multibyte=$(MULTIBYTE) --load-language=plpgsql $(MAXCONNOPT) $(NOLOCALE) numeric_big
##
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.25 2007/01/05 22:20:03 momjian Exp $
+ * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.26 2007/01/19 16:42:24 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
static char *hostname = NULL;
static int port = -1;
static char *user = NULL;
+static char *srcdir = NULL;
/* internal variables */
static const char *progname;
static int fail_count = 0;
static int fail_ignore_count = 0;
+static bool
+directory_exists(const char *dir);
+static void
+make_directory(const char *dir);
+
static void
header(const char *fmt,...)
/* This extension allows gcc to check the format string for consistency with
return false;
}
+/*
+ * Replace all occurances of a string in a string with a different string.
+ * NOTE: Assumes there is enough room in the target buffer!
+ */
+static void
+replace_string(char *string, char *replace, char *replacement)
+{
+ char *ptr;
+
+ while ((ptr = strstr(string, replace)) != NULL)
+ {
+ char *dup = strdup(string);
+
+ strncpy(string, dup, ptr - string);
+ string[ptr - string] = 0;
+ strcat(string, replacement);
+ strcat(string, dup + (ptr - string) + strlen(replace));
+ free(dup);
+ }
+}
+
+/*
+ * Convert *.source found in the "source" directory, replacing certain tokens
+ * in the file contents with their intended values, and put the resulting files
+ * in the "dest" directory, replacing the ".source" prefix in their names with
+ * the given suffix.
+ */
+static void
+convert_sourcefiles_in(char *source, char *dest, char *suffix)
+{
+ char abs_srcdir[MAXPGPATH];
+ char abs_builddir[MAXPGPATH];
+ char testtablespace[MAXPGPATH];
+ char indir[MAXPGPATH];
+ char **name;
+ char **names;
+ int count = 0;
+#ifdef WIN32
+ char *c;
+#endif
+
+ if (!getcwd(abs_builddir, sizeof(abs_builddir)))
+ {
+ fprintf(stderr, _("%s: could not get current directory: %s\n"),
+ progname, strerror(errno));
+ exit_nicely(2);
+ }
+
+ /*
+ * in a VPATH build, use the provided source directory; otherwise, use
+ * the current directory.
+ */
+ if (srcdir)
+ strcpy(abs_srcdir, srcdir);
+ else
+ strcpy(abs_srcdir, abs_builddir);
+
+ snprintf(indir, MAXPGPATH, "%s/%s", abs_srcdir, source);
+ names = pgfnames(indir);
+ if (!names)
+ /* Error logged in pgfnames */
+ exit_nicely(2);
+
+#ifdef WIN32
+ /* in Win32, replace backslashes with forward slashes */
+ for (c = abs_builddir; *c; c++)
+ if (*c == '\\')
+ *c = '/';
+ for (c = abs_srcdir; *c; c++)
+ if (*c == '\\')
+ *c = '/';
+#endif
+
+ /* try to create the test tablespace dir if it doesn't exist */
+ snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", abs_builddir);
+ if (directory_exists(testtablespace))
+ rmtree(testtablespace, true);
+ make_directory(testtablespace);
+
+ /* finally loop on each file and do the replacement */
+ for (name = names; *name; name++)
+ {
+ char srcfile[MAXPGPATH];
+ char destfile[MAXPGPATH];
+ char prefix[MAXPGPATH];
+ FILE *infile,
+ *outfile;
+ char line[1024];
+
+ /* reject filenames not finishing in ".source" */
+ if (strlen(*name) < 8)
+ continue;
+ if (strcmp(*name + strlen(*name) - 7, ".source") != 0)
+ continue;
+
+ count++;
+
+ /* build the full actual paths to open */
+ snprintf(prefix, strlen(*name) - 6, "%s", *name);
+ snprintf(srcfile, MAXPGPATH, "%s/%s", indir, *name);
+ snprintf(destfile, MAXPGPATH, "%s/%s.%s", dest, prefix, suffix);
+
+ infile = fopen(srcfile, "r");
+ if (!infile)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+ progname, srcfile, strerror(errno));
+ exit_nicely(2);
+ }
+ outfile = fopen(destfile, "w");
+ if (!outfile)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+ progname, destfile, strerror(errno));
+ exit_nicely(2);
+ }
+ while (fgets(line, sizeof(line), infile))
+ {
+ replace_string(line, "@abs_srcdir@", abs_srcdir);
+ replace_string(line, "@abs_builddir@", abs_builddir);
+ replace_string(line, "@testtablespace@", testtablespace);
+ replace_string(line, "@DLSUFFIX@", DLSUFFIX);
+ fputs(line, outfile);
+ }
+ fclose(infile);
+ fclose(outfile);
+ }
+
+ /*
+ * If we didn't process any files, complain because it probably means
+ * somebody neglected to pass the needed --srcdir argument.
+ */
+ if (count <= 0)
+ {
+ fprintf(stderr, _("%s: no *.source files found in %s\n"),
+ progname, indir);
+ exit_nicely(2);
+ }
+
+ pgfnames_cleanup(names);
+}
+
+static void
+convert_sourcefiles(void)
+{
+ convert_sourcefiles_in("input", "sql", "sql");
+ convert_sourcefiles_in("output", "expected", "out");
+}
+
/*
* Scan resultmap file to find which platform-specific expected files to use.
*
printf(_("(using postmaster on Unix socket, default port)\n"));
}
+ convert_sourcefiles();
load_resultmap();
}
printf(_(" --outputdir=DIR place output files in DIR (default \".\")\n"));
printf(_(" --schedule=FILE use test ordering schedule from FILE\n"));
printf(_(" (may be used multiple times to concatenate)\n"));
+ printf(_(" --srcdir=DIR absolute path to source directory (for VPATH builds)\n"));
printf(_(" --temp-install=DIR create a temporary installation in DIR\n"));
printf(_(" --no-locale use C locale\n"));
printf(_("\n"));
{"port", required_argument, NULL, 14},
{"user", required_argument, NULL, 15},
{"psqldir", required_argument, NULL, 16},
+ {"srcdir", required_argument, NULL, 17},
{NULL, 0, NULL, 0}
};
if (strlen(optarg))
psqldir = strdup(optarg);
break;
+ case 17:
+ srcdir = strdup(optarg);
+ break;
default:
/* getopt_long already emitted a complaint */
fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"),