From e5d8f8af448ac47ad63b3a9c893a578801d12963 Mon Sep 17 00:00:00 2001 From: Alexandre Felipe Date: Thu, 17 Sep 2026 08:43:52 +0100 Subject: [PATCH] pg_regress: multi-line test groups This support multi-line test groups instead of requiring test: all test in a single line it also support test: tests in different lines this will make it more readable, and showing line numbers having one test per line makes it much easier to see how many tests are in a group. --- src/test/regress/parallel_schedule | 272 ++++++++++++++++++++++++++--- src/test/regress/pg_regress.c | 31 +++- 2 files changed, 278 insertions(+), 25 deletions(-) diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 1c84e3011b1..547766e6152 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -14,21 +14,80 @@ test: test_setup # ---------- # The first group of parallel tests # ---------- -test: boolean char name varchar text int2 int4 int8 oid float4 float8 bit numeric txid uuid enum money rangetypes pg_lsn regproc +test: + boolean + char + name + varchar + text + int2 + int4 + int8 + oid + float4 + float8 + bit + numeric + txid + uuid + enum + money + rangetypes + pg_lsn + regproc # ---------- # The second group of parallel tests # multirangetypes depends on rangetypes # multirangetypes shouldn't run concurrently with type_sanity # ---------- -test: strings md5 numerology point lseg line box path polygon circle date time timetz timestamp timestamptz interval inet macaddr macaddr8 multirangetypes +test: + strings + md5 + numerology + point + lseg + line + box + path + polygon + circle + date + time + timetz + timestamp + timestamptz + interval + inet + macaddr + macaddr8 + multirangetypes # ---------- # Another group of parallel tests # geometry depends on point, lseg, line, box, path, polygon, circle # horology depends on date, time, timetz, timestamp, timestamptz, interval # ---------- -test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comments expressions unicode xid mvcc database stats_import pg_ndistinct pg_dependencies oid8 encoding euc_kr +test: + geometry + horology + tstypes + regex + type_sanity + opr_sanity + misc_sanity + comments + expressions + unicode + xid + mvcc + database + stats_import + pg_ndistinct + pg_dependencies + oid8 + encoding + euc_kr # ---------- # Load huge amounts of data @@ -36,20 +95,57 @@ test: geometry horology tstypes regex type_sanity opr_sanity misc_sanity comment # execute two copy tests in parallel, to check that copy itself # is concurrent safe. # ---------- -test: copy copyselect copydml copyencoding insert insert_conflict +test: + copy + copyselect + copydml + copyencoding + insert + insert_conflict # ---------- # More groups of parallel tests # Note: many of the tests in later groups depend on create_index # ---------- -test: create_function_c create_misc create_operator create_procedure create_table create_type create_schema -test: create_index create_index_spgist create_view index_including index_including_gist +test: + create_function_c + create_misc + create_operator + create_procedure + create_table + create_type + create_schema + +test: + create_index + create_index_spgist + create_view + index_including + index_including_gist # ---------- # Another group of parallel tests # (19 tests) # ---------- -test: create_aggregate create_function_sql create_cast constraints triggers select inherit typed_table vacuum drop_if_exists updatable_views roleattributes create_am hash_func errors infinite_recurse slope_catalog slope +test: + create_aggregate + create_function_sql + create_cast + constraints + triggers + select + inherit + typed_table + vacuum + drop_if_exists + updatable_views + roleattributes + create_am + hash_func + errors + infinite_recurse + slope_catalog + slope # ---------- # sanity_check does a vacuum, affecting the sort order of SELECT * @@ -63,29 +159,91 @@ test: sanity_check # join depends on create_misc # (20 tests) # ---------- -test: select_into select_distinct select_distinct_on select_implicit select_having subselect union case join aggregates transactions random portals arrays btree_index hash_index update delete namespace prepared_xacts +test: + select_into + select_distinct + select_distinct_on + select_implicit + select_having + subselect + union + case + join + aggregates + transactions + random + portals + arrays + btree_index + hash_index + update + delete + namespace + prepared_xacts # ---------- # Another group of parallel tests # (20 tests) # ---------- -test: brin gin gist spgist privileges init_privs security_label collate matview lock replica_identity rowsecurity object_address tablesample groupingsets drop_operator password identity generated_stored join_hash +test: + brin + gin + gist + spgist + privileges + init_privs + security_label + collate + matview + lock + replica_identity + rowsecurity + object_address + tablesample + groupingsets + drop_operator + password + identity + generated_stored + join_hash # ---------- # Additional BRIN tests # ---------- -test: brin_bloom brin_multi +test: + brin_bloom + brin_multi # ---------- # Another group of parallel tests # (20 tests) # ---------- -test: create_table_like alter_generic alter_operator misc async dbsize merge misc_functions nls sysviews tsrf tid tidscan tidrangescan collate.utf8 collate.icu.utf8 incremental_sort create_role without_overlaps generated_virtual +test: + alter_generic alter_operator + create_table_like + create_role + misc misc_functions + async + dbsize + merge + nls + sysviews + tsrf + tid tidscan tidrangescan + collate.utf8 collate.icu.utf8 + incremental_sort + without_overlaps + generated_virtual # collate.linux.utf8 and collate.icu.utf8 tests cannot be run in parallel with each other # psql depends on create_am # amutils depends on geometry, create_index_spgist, hash_index, brin -test: rules psql psql_crosstab psql_pipeline amutils stats_ext collate.linux.utf8 collate.windows.win1252 +test: + amutils + psql psql_crosstab psql_pipeline + collate.linux.utf8 collate.windows.win1252 + rules + stats_ext # ---------- # Run these alone so they don't run out of parallel workers @@ -100,18 +258,46 @@ test: vacuum_parallel test: maintain_every # no relation related tests can be put in this group -test: publication subscription +test: + publication + subscription # ---------- # Another group of parallel tests # select_views depends on create_view # ---------- -test: select_views portals_p2 foreign_key dependency guc bitmapops combocid tsearch tsdicts foreign_data window xmlmap functional_deps advisory_lock indirect_toast equivclass stats_rewrite +test: + select_views + portals_p2 + foreign_key + dependency + guc + bitmapops + combocid + tsearch + tsdicts + foreign_data + window + xmlmap + functional_deps + advisory_lock + indirect_toast + equivclass + stats_rewrite # ---------- # Another group of parallel tests (JSON related) # ---------- -test: json jsonb json_encoding jsonpath jsonpath_encoding jsonb_jsonpath sqljson sqljson_queryfuncs sqljson_jsontable +test: + json + jsonb + json_encoding + jsonpath + jsonpath_encoding + jsonb_jsonpath + sqljson + sqljson_queryfuncs + sqljson_jsontable # ---------- # Another group of parallel tests @@ -119,7 +305,25 @@ test: json jsonb json_encoding jsonpath jsonpath_encoding jsonb_jsonpath sqljson # NB: temp.sql does reconnects which transiently uses 2 connections, # so keep this parallel group to at most 19 tests # ---------- -test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml +test: + plancache + limit + plpgsql + copy2 + temp + domain + rangefuncs + prepare + conversion + truncate + alter_table + sequence + polymorphism + rowtypes + returning + largeobject + with + xml # ---------- # Another group of parallel tests @@ -127,26 +331,50 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion tr # The stats test resets stats, so nothing else needing stats access can be in # this group. # ---------- -test: partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain memoize stats predicate numa eager_aggregate planner_est +test: + partition_join + partition_prune + reloptions + hash_part + indexing + partition_aggregate + partition_info + tuplesort + explain + memoize + stats + predicate + numa + eager_aggregate + planner_est # ---------- # Another group of parallel tests (compression) # ---------- -test: compression compression_lz4 compression_pglz cluster +test: + compression + compression_lz4 + compression_pglz + cluster # event_trigger depends on create_am and cannot run concurrently with # any test that runs DDL # oidjoins is read-only, though, and should run late for best coverage -test: oidjoins event_trigger +test: + oidjoins + event_trigger # event_trigger_login cannot run concurrently with any other tests because # on-login event handling could catch connection of a concurrent test. -test: event_trigger_login +test: + event_trigger_login # this test also uses event triggers, so likewise run it by itself -test: fast_default +test: + fast_default # run tablespace test at the end because it drops the tablespace created during # setup that other tests may use. -test: tablespace +test: + tablespace diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index 13944701bc7..1ff4885d76a 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -1744,6 +1744,7 @@ run_schedule(const char *schedule, test_start_function startfunc, char *c; int num_tests; bool inword; + bool multiline_test; int i; line_num++; @@ -1755,7 +1756,7 @@ run_schedule(const char *schedule, test_start_function startfunc, if (scbuf[0] == '\0' || scbuf[0] == '#') continue; - if (strncmp(scbuf, "test: ", 6) == 0) + if (strncmp(scbuf, "test:", 5) == 0) test = scbuf + 6; else { @@ -1764,9 +1765,12 @@ run_schedule(const char *schedule, test_start_function startfunc, } num_tests = 0; + +test_line: /* avoid move this piece of code for now to keep v1 patch small */ inword = false; for (c = test;; c++) { + if(*c == '#') break; if (*c == '\0' || isspace((unsigned char) *c)) { if (inword) @@ -1797,10 +1801,31 @@ run_schedule(const char *schedule, test_start_function startfunc, } } + /* + * Found `test: # no tests` treat it as a multiline test group + */ if (num_tests == 0) { - bail("syntax error in schedule file \"%s\" line %d: %s", - schedule, line_num, scbuf); + multiline_test = true; + } + + if(multiline_test) + { + /* Scan one more line */ + if(fgets(scbuf, sizeof(scbuf), scf)) + line_num++; + else + scbuf[0] = 0; + /* if indented parse the test cases*/ + if(scbuf[0] == ' ' || scbuf[0] == '\t') + { + test = scbuf + 1; + goto test_line; + } else if(strncmp(scbuf, "test:", 5) == 0) { + bail("%s line %d, expected a new line after a multiline test group", schedule, line_num++); + } + /* end of indented block, run! */ + multiline_test = false; } if (num_tests == 1) -- 2.53.0