Repository: incubator-hawq Updated Branches: refs/heads/HAWQ-400 7c6a9171f -> 167da1a08 (forced update)
HAWQ-400. Support expected exit codes for regression tests. Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/167da1a0 Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/167da1a0 Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/167da1a0 Branch: refs/heads/HAWQ-400 Commit: 167da1a08adca0309838f9586e065833255b6b68 Parents: 37a5043 Author: Oleksandr Diachenko <odiache...@pivotal.io> Authored: Fri Feb 12 21:07:33 2016 -0800 Committer: Oleksandr Diachenko <odiache...@pivotal.io> Committed: Tue Feb 16 15:49:10 2016 -0800 ---------------------------------------------------------------------- src/test/regress/GNUmakefile | 2 +- src/test/regress/expected_statuses | 1 + src/test/regress/pg_regress.c | 279 +++++++++++++++++++++----------- 3 files changed, 190 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/167da1a0/src/test/regress/GNUmakefile ---------------------------------------------------------------------- diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile index 7b3f51d..841d163 100644 --- a/src/test/regress/GNUmakefile +++ b/src/test/regress/GNUmakefile @@ -143,7 +143,7 @@ installcheck-parallel: all upg2-setup ugpart-setup $(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=$(srcdir)/parallel_schedule --srcdir=$(abs_srcdir) installcheck-good: all ./current_good_schedule upg2-setup ugpart-setup - $(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=./current_good_schedule --srcdir=$(abs_srcdir) + $(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=./current_good_schedule --srcdir=$(abs_srcdir) --expected-statuses-file=expected_statuses installcheck-goh: all ./goh_schedule upg2-setup ugpart-setup $(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=./goh_schedule --srcdir=$(abs_srcdir) --tablespace=hdfs_ts http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/167da1a0/src/test/regress/expected_statuses ---------------------------------------------------------------------- diff --git a/src/test/regress/expected_statuses b/src/test/regress/expected_statuses new file mode 100644 index 0000000..16c50d1 --- /dev/null +++ b/src/test/regress/expected_statuses @@ -0,0 +1 @@ +hcatalog_lookup:2 \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/167da1a0/src/test/regress/pg_regress.c ---------------------------------------------------------------------- diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index b222a0b..2a7bb26 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -41,6 +41,14 @@ typedef struct _resultmap struct _resultmap *next; } _resultmap; +/*linked list of statuses for tests*/ +typedef struct _statuslist +{ + char *test; + int status; + struct _statuslist *next; +} _statuslist; + /* * Values obtained from pg_config_paths.h and Makefile. * In non-temp_install mode, the only thing we need is the location of psql, @@ -84,15 +92,15 @@ static char *user = NULL; static char *srcdir = NULL; static _stringlist *extraroles = NULL; static char *initfile = "./init_file"; -static char *tablespace = ""; +static char *expected_statuses_file = "expected_statuses"; /* internal variables */ static const char *progname; static char *logfilename; static FILE *logfile; static char *difffilename; - static _resultmap *resultmap = NULL; +static _statuslist *expected_statuses = NULL; static int success_count = 0; static int fail_count = 0; @@ -122,6 +130,11 @@ psql_command(const char *database, const char *query,...) /* This extension allows gcc to check the format string for consistency with the supplied arguments. */ __attribute__((format(printf, 2, 3))); +static void +log_child_exit(int exitstatus, int expected_status); + +static bool +is_status_expected(int exit_status, int expected_status); #ifdef WIN32 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE); @@ -529,6 +542,78 @@ convert_sourcefiles(void) } /* + * Load expected statuses from given file name. + * Line format is + * test_name:expected_return_code + */ +static void +load_expected_statuses(char *filename) +{ + char buf[MAXPGPATH]; + FILE *f; + int i; + int status; + int sep_index; + char *sep_ptr; + bool line_valid; + + f = fopen(filename, "r"); + if (!f) + { + fprintf(stderr, _("could not open file with expected statuses for reading: \n")); + exit_nicely(2); + } + + while (fgets(buf, sizeof(buf), f)) + { + + i = strlen(buf); + while (i > 0 && isspace((unsigned char) buf[i - 1])) + buf[--i] = '\0'; + + sep_ptr = strchr(buf, ':'); + + if (sep_ptr == NULL) + { + fprintf(stderr, _("incorrect expected statuses entry: %s\n"), buf); + exit_nicely(2); + } + + sep_index = sep_ptr - buf; + + char test[sep_index+1]; + memset(test, 0, sizeof(test)); + + strncpy(test, buf, sep_index); + test[sep_index+1] = '\0'; + + + char status_str[strlen(buf)-sep_index]; + memset(status_str, 0, sizeof(status_str)); + strncpy(status_str, buf + sep_index +1, strlen(buf)); + status_str[sep_index+1] = '\0'; + + line_valid = (sscanf(status_str, "%d", (int *) (&status)) == 1); + + if (!line_valid) + { + fprintf(stderr, _("incorrect expected statuses entry: %s\n"), buf); + exit_nicely(2); + } + + _statuslist *entry = malloc(sizeof(_statuslist)); + + entry->test = strdup(test); + entry->status = status; + entry->next = expected_statuses; + expected_statuses = entry; + + } + + fclose(f); +} + +/* * Scan resultmap file to find which platform-specific expected files to use. * * The format of each line of the file is @@ -620,6 +705,27 @@ load_resultmap(void) } /* + * Get expected status for given test + */ +static +const int +get_expected_status(const char *test) +{ + _statuslist *es; + + for (es = expected_statuses; es != NULL; es = es->next) + { + if (strcmp(test, es->test) == 0) + { + return es->status; + } + } + + return 0; //default value +} + + +/* * Check in resultmap if we should be looking at a different file */ static @@ -770,6 +876,7 @@ initialize_environment(void) convert_sourcefiles(); load_resultmap(); + load_expected_statuses(expected_statuses_file); } /* @@ -1333,32 +1440,70 @@ wait_for_tests(PID_TYPE * pids, int *statuses, char **names, int num_tests) } /* - * report nonzero exit code from a test process + * Print test status depending on differences, actual, expected statuses */ static void -log_child_failure(int exitstatus) +print_test_status(bool differ, int actual_status, int expected_status, double diff_secs) { - if (WIFEXITED(exitstatus)) - status(_(" (test process exited with exit code %d)"), - WEXITSTATUS(exitstatus)); - else if (WIFSIGNALED(exitstatus)) - { -#if defined(WIN32) - status(_(" (test process was terminated by exception 0x%X)"), - WTERMSIG(exitstatus)); -#elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST - status(_(" (test process was terminated by signal %d: %s)"), - WTERMSIG(exitstatus), - WTERMSIG(exitstatus) < NSIG ? - sys_siglist[WTERMSIG(exitstatus)] : "(unknown))"); -#else - status(_(" (test process was terminated by signal %d)"), - WTERMSIG(exitstatus)); -#endif + + if (!differ && is_status_expected(actual_status, expected_status)) + { + status(_("ok")); + if (diff_secs > 0) + status(_(" (%.2f sec)"), diff_secs); + success_count++; + } else + { + status(_("FAILED")); + if (diff_secs > 0) + status(_(" (%.2f sec)"), diff_secs); + fail_count++; + log_child_exit(actual_status, expected_status); + } + + status_end(); +} + +/* + * Returns true if actual exit code was expected + */ +static bool +is_status_expected(int exit_status, int expected_status) +{ + return (WEXITSTATUS(exit_status) == expected_status); +} + + +/* + * Report unexpected exit code or termination by signal for test process + */ +static void +log_child_exit(int exitstatus, int expected_status) +{ + if (!is_status_expected(exitstatus, expected_status)) + { + if (WIFEXITED(exitstatus)) + status(_(" (test process exited with unexpected exit code %d, but was expected exit code %d)"), + WEXITSTATUS(exitstatus), expected_status); + else if (WIFSIGNALED(exitstatus)) + { + #if defined(WIN32) + status(_(" (test process was terminated by exception 0x%X)"), + WTERMSIG(exitstatus)); + #elif defined(HAVE_DECL_SYS_SIGLIST) && HAVE_DECL_SYS_SIGLIST + status(_(" (test process was terminated by signal %d: %s)"), + WTERMSIG(exitstatus), + WTERMSIG(exitstatus) < NSIG ? + sys_siglist[WTERMSIG(exitstatus)] : "(unknown))"); + #else + status(_(" (test process was terminated by signal %d)"), + WTERMSIG(exitstatus)); + #endif + } + else + status(_(" (test process exited with unrecognized status %d)"), + exitstatus); } - else - status(_(" (test process exited with unrecognized status %d)"), - exitstatus); } /* @@ -1374,7 +1519,6 @@ run_schedule(const char *schedule, test_function tfunc) _stringlist *tags[MAX_PARALLEL_TESTS]; PID_TYPE pids[MAX_PARALLEL_TESTS]; int statuses[MAX_PARALLEL_TESTS]; - _stringlist *ignorelist = NULL; char scbuf[1024]; FILE *scf; int line_num = 0; @@ -1401,6 +1545,8 @@ run_schedule(const char *schedule, test_function tfunc) struct timeval start_time, end_time; double diff_secs; + + line_num++; for (i = 0; i < MAX_PARALLEL_TESTS; i++) @@ -1425,6 +1571,7 @@ run_schedule(const char *schedule, test_function tfunc) test = scbuf + 6; + /* MPP-9643: allow ability to disable tests per platform */ snprintf(cmd, sizeof(cmd), SYSTEMQUOTE "gpexclude.pl --test %s --exclude %s.EXCLUDE --quiet " SYSTEMQUOTE, test, schedule); @@ -1434,8 +1581,6 @@ run_schedule(const char *schedule, test_function tfunc) c = test; while (*c && isspace((unsigned char) *c)) c++; - add_stringlist_item(&ignorelist, c); - /* * Note: ignore: lines do not run the test, they just * say that failure of this test when run later on is @@ -1451,7 +1596,6 @@ run_schedule(const char *schedule, test_function tfunc) c = scbuf + 8; while (*c && isspace((unsigned char) *c)) c++; - add_stringlist_item(&ignorelist, c); /* * Note: ignore: lines do not run the test, they just say that @@ -1471,6 +1615,8 @@ run_schedule(const char *schedule, test_function tfunc) inword = false; for (c = test; *c; c++) { + + if (isspace((unsigned char) *c)) { *c = '\0'; @@ -1585,42 +1731,9 @@ run_schedule(const char *schedule, test_function tfunc) differ |= newdiff; } - if (differ) - { - bool ignore = false; - _stringlist *sl; - - for (sl = ignorelist; sl != NULL; sl = sl->next) - { - if (strcmp(tests[i], sl->str) == 0) - { - ignore = true; - break; - } - } - if (ignore) - { - status(_("failed (ignored)")); - fail_ignore_count++; - } - else - { - status(_("FAILED")); - status(_(" (%.2f sec)"), diff_secs); - fail_count++; - } - } - else - { - status(_("ok")); - status(_(" (%.2f sec)"), diff_secs); - success_count++; - } - - if (statuses[i] != 0) - log_child_failure(statuses[i]); + int expected_status = get_expected_status(test); - status_end(); + print_test_status(differ, statuses[i], expected_status, -1); } } @@ -1672,19 +1785,9 @@ run_single_test(const char *test, test_function tfunc) differ |= newdiff; } - if (differ) - { - status(_("FAILED")); - fail_count++; - } - else - { - status(_("ok")); - success_count++; - } + int expected_status = get_expected_status(test); - if (exit_status != 0) - log_child_failure(exit_status); + print_test_status(differ, exit_status, expected_status, -1); status_end(); } @@ -1890,6 +1993,7 @@ help(void) printf(_(" (can be used multiple times to concatenate)\n")); printf(_(" --srcdir=DIR absolute path to source directory (for VPATH builds)\n")); printf(_(" --init-file=GPD_INIT_FILE init file to be used for gpdiff\n")); + printf(_(" --expected-statuses-file=EXPECTED_STATUSES_FILE file to read expected return codes for each test\n")); printf(_("\n")); printf(_("Options for using an existing installation:\n")); printf(_(" --host=HOST use postmaster running on HOST\n")); @@ -1931,8 +2035,8 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc {"psqldir", required_argument, NULL, 16}, {"srcdir", required_argument, NULL, 17}, {"create-role", required_argument, NULL, 18}, - {"init-file", required_argument, NULL, 19}, - {"tablespace", required_argument, NULL, 19}, + {"init-file", required_argument, NULL, 19}, + {"expected-statuses-file", required_argument, NULL, 20}, {NULL, 0, NULL, 0} }; @@ -2025,20 +2129,13 @@ regression_main(int argc, char *argv[], init_function ifunc, test_function tfunc case 18: split_to_stringlist(strdup(optarg), ", ", &extraroles); break; - case 19: - initfile = strdup(optarg); - break; - case 20: - tablespace = malloc(11 + strlen(optarg) + 1); - if (!tablespace) - { - fprintf(stderr, _("out of memory.\n")); - exit_nicely(2); - } - snprintf(tablespace, 11 + strlen(optarg) + 1, - "TABLESPACE %s", optarg); - break; - default: + case 19: + initfile = strdup(optarg); + break; + case 20: + expected_statuses_file = strdup(optarg); + break; + default: /* getopt_long already emitted a complaint */ fprintf(stderr, _("\nTry \"%s -h\" for more information.\n"), progname);