From a1cb5da7c6c7746285f4c52fff89edcd945e1997 Mon Sep 17 00:00:00 2001 From: kzangeli Date: Sat, 5 Sep 2026 00:31:27 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20REQUIRE=5FFEATURE=20/=20SKIP=5FFEATURE?= =?UTF-8?q?=20=E2=80=94=20applicability=20against=20the=20BINARY?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A test can already say which run CONFIGURATION it applies to (REQUIRE_). It could not say which BUILD it applies to, and that is a different question: a broker with an endpoint compiled out is indistinguishable from a full one until asked, and the tests for that endpoint are not candidates for the run. # REQUIRE_FEATURE: A B applies only if the build has ALL of them # SKIP_FEATURE: A B applies only if the build has NONE of them A separate mechanism from REQUIRE_ rather than another entry in the value-matching arrays, because the matching is not the same. REQUIRE_ holds ONE current value and asks whether it is among the alternatives, so "REQUIRE_DB: corDB mongoc" means either. A feature list is a SET, and a test that needs two features needs both — feeding it through the same arrays would have made "REQUIRE_FEATURE: A B" mean "A or B", the opposite reading. SKIP_FEATURE is the direction a reduced build needs: a test asserting the 501 for an endpoint that is not in the build can only run where it is not in the build. Both drop the test from the run list rather than reporting it skipped, the same as any REQUIRE_. The set comes from COR_TEST_FEATURES, which the repo's corTestParams.sh sets — normally by asking the binary what it was built with. UNSET means the repo does not report features and both markers go inert: every test runs. That is the loud failure rather than the quiet one, since a suite that silently skipped everything on a broken detection would look green. Also documents a REGEX() trap the above walked into: the pattern is spliced into the line unbracketed, so a top-level | alternates the WHOLE line. REGEX(true|false) accepts "true" and rejects "false" while looking correct. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01TGatXwrHx1CreL49sCuS37 --- README.md | 27 ++++++++++++++++++++ corTest | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/README.md b/README.md index 4e38b5f..26d0e53 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,27 @@ decided to pass on those five; they simply do not apply to the chosen database. `SKIP_` is the other thing: a test that does apply and is being passed over, which is worth reporting as such. +A third pair asks about the BINARY rather than the run: + +``` +# REQUIRE_FEATURE: A B the test applies only if the build has ALL of them +# SKIP_FEATURE: A B the test applies only if the build has NONE of them +``` + +Separate from `REQUIRE_` because it is a different question with different +matching. `REQUIRE_` holds ONE current value and asks whether it is among +the listed alternatives, so `REQUIRE_DB: corDB mongoc` means "either". A feature +list is a SET, and `REQUIRE_FEATURE: A B` means a test that needs both — the +opposite reading. `SKIP_FEATURE` is the direction a reduced build needs: a test +asserting the 501 for an endpoint compiled out can only run where it is out. +Both drop the test from the run list rather than reporting it skipped. + +The set comes from `COR_TEST_FEATURES`, space-separated, which the repo's +`corTestParams.sh` sets — normally by asking the binary what it was built with. +UNSET means the repo does not report features, and then both markers are inert +and every test runs: a broken detection fails loudly instead of silently +skipping the suite. + `--INIT--`, `--RUN--` and `--TEARDOWN--` are executed with `bash`, so they can use shell freely — and any helper functions the repo exposes (see below). @@ -97,6 +118,12 @@ Content-Length: REGEX(\d+) "id": "REGEX(urn:ngsi-ld:.+)" ``` +⚠️ The pattern is spliced into the line's pattern UNBRACKETED, so a top-level +`|` alternates the whole line, not the parenthesised part: `x: REGEX(true|false)` +becomes `x:\ true|false`, which matches `x: true` and then demands that `false` +start at column 1. It accepts one branch and rejects the other while looking +correct. Write a pattern without top-level alternation (`REGEX([a-z]+)`). + **`#SORT_START` / `#SORT_END`** — the lines between the markers are compared order-independently, for output whose ordering isn't guaranteed: diff --git a/corTest b/corTest index 5f0d806..a97e4eb 100755 --- a/corTest +++ b/corTest @@ -416,6 +416,78 @@ function reportSkip() } +# ----------------------------------------------------------------------------- +# +# featureOn - is compiled into the binary under test? +# +function featureOn() +{ + case " $COR_TEST_FEATURES " in + *" $1 "*) return 0 ;; + esac + return 1 +} + + +# ----------------------------------------------------------------------------- +# +# featureApplies - does this test case apply to the BUILD under test? +# +# # REQUIRE_FEATURE: A B ... (the test applies only if the build has ALL of them) +# # SKIP_FEATURE: A B ... (the test applies only if the build has NONE of them) +# +# A separate question from REQUIRE_ above, and so a separate mechanism. +# REQUIRE_ asks "is the run configured this way", and matches ONE current +# value against a list of alternatives. This asks "does the binary contain that +# code at all", and matches against a SET - every name in the list has to be in +# it. Feeding features through the value-matching arrays would have made +# "REQUIRE_FEATURE: A B" mean "A or B", which is the opposite of what a test +# needing both features means. +# +# SKIP_FEATURE is the direction a compiled-out build needs: a test that asserts +# the 501 for an endpoint that is not in the build can only run where the +# endpoint is not in the build. +# +# COR_TEST_FEATURES holds the ON features, space separated - the repo's +# corTestParams.sh sets it, normally by asking the binary. UNSET means the repo +# does not report a feature set, and then both markers are inert: every test +# runs. That is the loud failure rather than the quiet one - a suite that +# silently skipped everything on a broken detection would look green. +# +# Returns 0 if the test applies, 1 if it does not (sets NA_REASON). +# +function featureApplies() +{ + local testFile="$1" + local line + local f + + if [ -z "${COR_TEST_FEATURES+set}" ]; then return 0; fi + + line=$(grep "^# *REQUIRE_FEATURE:" "$testFile" 2>/dev/null | head -1) + if [ -n "$line" ]; then + for f in ${line#*:}; do + if ! featureOn "$f"; then + NA_REASON="build has no $f" + return 1 + fi + done + fi + + line=$(grep "^# *SKIP_FEATURE:" "$testFile" 2>/dev/null | head -1) + if [ -n "$line" ]; then + for f in ${line#*:}; do + if featureOn "$f"; then + NA_REASON="build has $f" + return 1 + fi + done + fi + + return 0 +} + + # ----------------------------------------------------------------------------- # # testApplies - does this test case apply to the configuration being run? @@ -436,6 +508,8 @@ function testApplies() local testFile="$1" NA_REASON="" + if ! featureApplies "$testFile"; then return 1; fi + for ix in "${!COR_CLI_PARAM_TAGS[@]}"; do local tag="${COR_CLI_PARAM_TAGS[$ix]}" if [ -z "$tag" ]; then continue; fi