diff --git a/.github/workflows/build-cloudberry-rocky8.yml b/.github/workflows/build-cloudberry-rocky8.yml index 2abf88060e3..e0936c725c8 100644 --- a/.github/workflows/build-cloudberry-rocky8.yml +++ b/.github/workflows/build-cloudberry-rocky8.yml @@ -339,6 +339,10 @@ jobs: }, {"test":"ic-cbdb-parallel", "make_configs":["src/test/regress:installcheck-cbdb-parallel"] + }, + {"test":"ic-recovery", + "make_configs":["src/test/recovery:installcheck"], + "enable_core_check":false } ] }' diff --git a/devops/build/automation/cloudberry/scripts/parse-results.pl b/devops/build/automation/cloudberry/scripts/parse-results.pl index d09085d5fb9..2c754bcae9d 100755 --- a/devops/build/automation/cloudberry/scripts/parse-results.pl +++ b/devops/build/automation/cloudberry/scripts/parse-results.pl @@ -110,7 +110,7 @@ my @ignored_test_list = (); while (<$fh>) { - # Match the summary lines + # Match the summary lines (pg_regress format) if (/All (\d+) tests passed\./) { $status = 'passed'; $total_tests = $1; @@ -132,8 +132,22 @@ $status = 'failed'; $failed_tests = $1 - $3; $ignored_tests = $3; - $total_tests = $2; - $passed_tests = $2 - $1; + + # TAP/prove summary format: "Files=N, Tests=N, ..." + } elsif (/^Files=\d+, Tests=(\d+),/) { + $total_tests = $1; + + # TAP/prove result: "Result: PASS" or "Result: FAIL" + } elsif (/^Result: PASS/) { + $status = 'passed'; + $passed_tests = $total_tests; + $failed_tests = 0; + } elsif (/^Result: FAIL/) { + $status = 'failed'; + + # TAP individual test failure: " t/xxx.pl (Wstat: ...)" + } elsif (/^\s+(t\/\S+\.pl)\s+\(Wstat:/) { + push @failed_test_list, $1; } # Capture failed tests @@ -150,8 +164,15 @@ # Close the log file close $fh; -# Validate failed test count matches found test names -if ($status eq 'failed' && scalar(@failed_test_list) != $failed_tests) { +# For TAP format, derive failed/passed counts from collected test names +if ($status eq 'failed' && $failed_tests == 0 && scalar(@failed_test_list) > 0) { + $failed_tests = scalar(@failed_test_list); + $passed_tests = $total_tests - $failed_tests if $total_tests > 0; +} + +# Validate failed test count matches found test names (pg_regress format only) +if ($status eq 'failed' && $failed_tests > 0 && scalar(@failed_test_list) > 0 + && scalar(@failed_test_list) != $failed_tests) { print "Error: Found $failed_tests failed tests in summary but found " . scalar(@failed_test_list) . " failed test names\n"; print "Failed test names found:\n"; foreach my $test (@failed_test_list) { diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index ed655baf989..f8bfa78b28e 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -3036,13 +3036,15 @@ CommitTransaction(void) DoPendingDbDeletes(true); /* - * Only QD holds the session level lock this long for a movedb operation. - * This is to prevent another transaction from moving database objects into - * the source database oid directory while it is being deleted. We don't - * worry about aborts as we release session level locks automatically during - * an abort as opposed to a commit. - */ - if(Gp_role == GP_ROLE_DISPATCH || IS_SINGLENODE()) + * Release the session level lock held for a movedb operation. This is to + * prevent another transaction from moving database objects into the source + * database oid directory while it is being deleted. We don't worry about + * aborts as we release session level locks automatically during an abort + * as opposed to a commit. We must also release in utility mode (e.g. + * standalone backends used in TAP tests). + */ + if (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_UTILITY || + IS_SINGLENODE()) MoveDbSessionLockRelease(); /* diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c index 2416522d016..e6822521694 100644 --- a/src/backend/commands/tablespace.c +++ b/src/backend/commands/tablespace.c @@ -328,7 +328,7 @@ CreateTableSpace(CreateTableSpaceStmt *stmt) } if (!location) - location = pstrdup(stmt->location); + location = pstrdup(stmt->location ? stmt->location : ""); if (stmt->filehandler) fileHandler = pstrdup(stmt->filehandler); @@ -1230,14 +1230,19 @@ destroy_tablespace_directories(Oid tablespaceoid, bool redo) linkloc = pstrdup(linkloc_with_version_dir); get_parent_directory(linkloc); - /* Remove the symlink target directory if it exists or is valid. */ + /* + * Remove the symlink target directory if it exists or is valid. + * If linkloc is a directory (e.g. in-place tablespace), readlink() + * will fail with EINVAL, which we can safely skip. + */ rllen = readlink(linkloc, link_target_dir, sizeof(link_target_dir)); if(rllen < 0) { - ereport(redo ? LOG : ERROR, - (errcode_for_file_access(), - errmsg("could not read symbolic link \"%s\": %m", - linkloc))); + if (errno != EINVAL) + ereport(redo ? LOG : ERROR, + (errcode_for_file_access(), + errmsg("could not read symbolic link \"%s\": %m", + linkloc))); } else if(rllen >= sizeof(link_target_dir)) { diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index 241ed8d49e8..e3010870f35 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -632,7 +632,7 @@ sub adjust_conf my $conffile = $self->data_dir . '/' . $filename; - my $contents = PostgreSQL::Test::Utils::slurp_file($conffile); + my $contents = TestLib::slurp_file($conffile); my @lines = split(/\n/, $contents); my @result; my $eq = $skip_equals ? '' : '= '; @@ -1220,7 +1220,7 @@ sub enable_archiving my $copy_command = $TestLib::windows_os ? qq{copy "%p" "$path\\\\%f"} - : qq{cp "%p" "$path/%f"}; + : qq{install -m 644 "%p" "$path/%f"}; # Enable archive_mode and archive_command on node $self->append_conf(