This is an automated email from the ASF dual-hosted git repository.

mlibbey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 9c2c816c6a hrw4u: add validation for some boolean values (#12553)
9c2c816c6a is described below

commit 9c2c816c6a7d3f9c8babcdbc5915a2478fce836f
Author: mlibbey <[email protected]>
AuthorDate: Thu Oct 9 14:29:53 2025 -0700

    hrw4u: add validation for some boolean values (#12553)
    
    When the expected value is a boolean, we should make sure it actually is 
one of the accepted inputs. Its also generally confusing if they should be 
quoted or not, so try to give the user some indication that quotes are bad for 
these values.
---
 tools/hrw4u/src/symbols.py                            |  4 ++++
 tools/hrw4u/src/types.py                              | 18 +++++++++++++++---
 .../data/ops/http_cntl_invalid_bool.fail.error.txt    |  1 +
 .../data/ops/http_cntl_invalid_bool.fail.input.txt    |  3 +++
 .../data/ops/http_cntl_quoted_bool.fail.error.txt     |  1 +
 .../data/ops/http_cntl_quoted_bool.fail.input.txt     |  3 +++
 .../tests/data/ops/http_cntl_valid_bools.ast.txt      |  1 +
 .../tests/data/ops/http_cntl_valid_bools.input.txt    | 19 +++++++++++++++++++
 .../tests/data/ops/http_cntl_valid_bools.output.txt   | 18 ++++++++++++++++++
 .../data/ops/skip_remap_quoted_bool.fail.error.txt    |  1 +
 .../data/ops/skip_remap_quoted_bool.fail.input.txt    |  3 +++
 tools/hrw4u/tests/test_ops.py                         |  7 +++++++
 12 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/tools/hrw4u/src/symbols.py b/tools/hrw4u/src/symbols.py
index 7f13d0f88f..1d88305da8 100644
--- a/tools/hrw4u/src/symbols.py
+++ b/tools/hrw4u/src/symbols.py
@@ -73,6 +73,10 @@ class SymbolResolver(SymbolResolverBase):
                         if validator:
                             validator(qualifier)
 
+                        # Add boolean value validation for http.cntl 
assignments.
+                        if op_key == "http.cntl.":
+                            types.SuffixGroup.BOOL_FIELDS.validate(value)
+
                         if isinstance(commands, (list, tuple)):
                             if value == '""':
                                 return f"{commands[0]} {qualifier}"
diff --git a/tools/hrw4u/src/types.py b/tools/hrw4u/src/types.py
index 5ba2839003..213e084a59 100644
--- a/tools/hrw4u/src/types.py
+++ b/tools/hrw4u/src/types.py
@@ -99,9 +99,21 @@ class SuffixGroup(Enum):
     def validate(self, suffix: str) -> None:
         allowed_upper = {val.upper() for val in self.value}
         if suffix.upper() not in allowed_upper:
-            raise ValueError(
-                f"Invalid suffix '{suffix}' for group '{self.name}'. "
-                f"Must be one of: {', '.join(sorted(self.value))}")
+            # Special handling for BOOL_FIELDS to detect quoted boolean values
+            if self == SuffixGroup.BOOL_FIELDS:
+                bool_msg = f"Invalid boolean value '{suffix}'. Must be one of: 
{', '.join(sorted(self.value))}"
+
+                # Check if this is a quoted boolean value
+                is_double_quoted = (suffix.startswith('"') and 
suffix.endswith('"'))
+                is_single_quoted = (suffix.startswith("'") and 
suffix.endswith("'"))
+                if ((is_double_quoted or is_single_quoted) and len(suffix) > 2 
and suffix[1:-1].upper() in allowed_upper):
+                    raise ValueError(f"{bool_msg} and must not be quoted")
+                else:
+                    raise ValueError(bool_msg)
+            else:
+                raise ValueError(
+                    f"Invalid suffix '{suffix}' for group '{self.name}'. "
+                    f"Must be one of: {', '.join(sorted(self.value))}")
 
 
 class VarType(Enum):
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.error.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.error.txt
new file mode 100644
index 0000000000..c05550731a
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.error.txt
@@ -0,0 +1 @@
+Invalid boolean value 'invalid_value'. Must be one of: 0, 1, FALSE, NO, OFF, 
ON, TRUE, YES
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.input.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.input.txt
new file mode 100644
index 0000000000..66567beeb0
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_invalid_bool.fail.input.txt
@@ -0,0 +1,3 @@
+SEND_RESPONSE {
+    http.cntl.LOGGING = invalid_value;
+}
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.error.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.error.txt
new file mode 100644
index 0000000000..4a4000facc
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.error.txt
@@ -0,0 +1 @@
+Invalid boolean value '"true"'. Must be one of: 0, 1, FALSE, NO, OFF, ON, 
TRUE, YES and must not be quoted
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.input.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.input.txt
new file mode 100644
index 0000000000..ba1f988008
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_quoted_bool.fail.input.txt
@@ -0,0 +1,3 @@
+SEND_RESPONSE {
+    http.cntl.LOGGING = "true";
+}
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.ast.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.ast.txt
new file mode 100644
index 0000000000..6029280f56
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.ast.txt
@@ -0,0 +1 @@
+(program (section SEND_RESPONSE { (sectionBody (statement http.cntl.LOGGING = 
(value TRUE) ;)) (sectionBody (statement http.cntl.TXN_DEBUG = (value FALSE) 
;)) (sectionBody (statement http.cntl.REQ_CACHEABLE = (value YES) ;)) 
(sectionBody (statement http.cntl.RESP_CACHEABLE = (value NO) ;)) (sectionBody 
(statement http.cntl.SERVER_NO_STORE = (value ON) ;)) (sectionBody (statement 
http.cntl.SKIP_REMAP = (value OFF) ;)) (sectionBody (statement 
http.cntl.INTERCEPT_RETRY = (value 1) ;)) (sect [...]
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.input.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.input.txt
new file mode 100644
index 0000000000..508b328231
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.input.txt
@@ -0,0 +1,19 @@
+SEND_RESPONSE {
+    http.cntl.LOGGING = TRUE;
+    http.cntl.TXN_DEBUG = FALSE;
+    http.cntl.REQ_CACHEABLE = YES;
+    http.cntl.RESP_CACHEABLE = NO;
+    http.cntl.SERVER_NO_STORE = ON;
+    http.cntl.SKIP_REMAP = OFF;
+    http.cntl.INTERCEPT_RETRY = 1;
+    http.cntl.LOGGING = 0;
+    http.cntl.TXN_DEBUG = true;
+    http.cntl.REQ_CACHEABLE = false;
+    http.cntl.RESP_CACHEABLE = yes;
+    http.cntl.SERVER_NO_STORE = no;
+    http.cntl.SKIP_REMAP = on;
+    http.cntl.INTERCEPT_RETRY = off;
+    http.cntl.LOGGING = True;
+    http.cntl.TXN_DEBUG = False;
+    http.cntl.LOGGING = TRue;
+}
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.output.txt 
b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.output.txt
new file mode 100644
index 0000000000..d90fac00d6
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/http_cntl_valid_bools.output.txt
@@ -0,0 +1,18 @@
+cond %{SEND_RESPONSE_HDR_HOOK} [AND]
+    set-http-cntl LOGGING TRUE
+    set-http-cntl TXN_DEBUG FALSE
+    set-http-cntl REQ_CACHEABLE YES
+    set-http-cntl RESP_CACHEABLE NO
+    set-http-cntl SERVER_NO_STORE ON
+    set-http-cntl SKIP_REMAP OFF
+    set-http-cntl INTERCEPT_RETRY 1
+    set-http-cntl LOGGING 0
+    set-http-cntl TXN_DEBUG true
+    set-http-cntl REQ_CACHEABLE false
+    set-http-cntl RESP_CACHEABLE yes
+    set-http-cntl SERVER_NO_STORE no
+    set-http-cntl SKIP_REMAP on
+    set-http-cntl INTERCEPT_RETRY off
+    set-http-cntl LOGGING True
+    set-http-cntl TXN_DEBUG False
+    set-http-cntl LOGGING TRue
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.error.txt 
b/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.error.txt
new file mode 100644
index 0000000000..4a4000facc
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.error.txt
@@ -0,0 +1 @@
+Invalid boolean value '"true"'. Must be one of: 0, 1, FALSE, NO, OFF, ON, 
TRUE, YES and must not be quoted
\ No newline at end of file
diff --git a/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.input.txt 
b/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.input.txt
new file mode 100644
index 0000000000..a894cbb5c8
--- /dev/null
+++ b/tools/hrw4u/tests/data/ops/skip_remap_quoted_bool.fail.input.txt
@@ -0,0 +1,3 @@
+SEND_REQUEST {
+    skip-remap("true");
+}
\ No newline at end of file
diff --git a/tools/hrw4u/tests/test_ops.py b/tools/hrw4u/tests/test_ops.py
index e38b4706a0..c8d06115f2 100644
--- a/tools/hrw4u/tests/test_ops.py
+++ b/tools/hrw4u/tests/test_ops.py
@@ -35,3 +35,10 @@ def test_output_matches(input_file: Path, output_file: Path) 
-> None:
 def test_ast_matches(input_file: Path, ast_file: Path) -> None:
     """Test that AST structure matches expected AST for ops test cases."""
     utils.run_ast_test(input_file, ast_file)
+
+
[email protected]
[email protected]
[email protected]("input_file", utils.collect_failing_inputs("ops"))
+def test_invalid_inputs_fail(input_file):
+    utils.run_failing_test(input_file)

Reply via email to