@@ -71,6 +71,57 @@ def validate_with_exit_code(self, exit_code: int):
7171 self ._finish_callback (self )
7272 return self
7373
74+ def validate_with_text (self , text : str ):
75+ """
76+ Validate command output matches expected text exactly.
77+
78+ Example:
79+ traffic_ctl.config().get("proxy.config.product_name").validate_with_text("Apache Traffic Server")
80+ """
81+ self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (text , self ._dir , self ._tn )
82+ self ._finish_callback (self )
83+ return self
84+
85+ def validate_result_with_text (self , text : str ):
86+ """
87+ Validate RPC result matches expected JSON exactly. Wraps text in JSON-RPC envelope.
88+
89+ Example:
90+ traffic_ctl.rpc().invoke(handler="get_connection_tracker_info").validate_result_with_text(
91+ '{"outbound": {"count": "0", "list": []}}'
92+ )
93+ """
94+ full_text = f'{{\" jsonrpc\" : \" 2.0\" , \" result\" : { text } , \" id\" : { "``" } }}'
95+ self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (full_text , self ._dir , self ._tn )
96+ self ._finish_callback (self )
97+ return self
98+
99+ def validate_json_contains (self , ** field_checks ):
100+ """
101+ Validate JSON output contains specific field:value pairs. Only checks specified fields.
102+ Prints detailed error on failure: "FAIL: field_name = actual_value (expected expected_value)"
103+ stream.all.txt will contain the actual output with the failed fields.
104+
105+ Example:
106+ traffic_ctl.server().status().validate_json_contains(
107+ initialized_done='true', is_draining='false'
108+ )
109+ """
110+ import json
111+ checks_str = ', ' .join (f"'{ k } ': '{ v } '" for k , v in field_checks .items ())
112+ self ._cmd = (
113+ f'{ self ._cmd } | python3 -c "'
114+ f"import sys, json; "
115+ f"d = json.load(sys.stdin); "
116+ f"c = {{{ checks_str } }}; "
117+ f"failed = [(k, v, str(d.get(k))) for k, v in c.items() if str(d.get(k)) != v]; "
118+ f"[print(f'FAIL: {{k}} = {{actual}} (expected {{expected}})', file=sys.stderr) "
119+ f"for k, expected, actual in failed]; "
120+ f"exit(0 if not failed else 1)"
121+ f'"' )
122+ self ._finish_callback (self )
123+ return self
124+
74125
75126class Config (Common ):
76127 """
@@ -119,10 +170,6 @@ def validate_with_goldfile(self, file: str):
119170 self ._tr .Processes .Default .Streams .stdout = os .path .join ("gold" , file )
120171 self .__finish ()
121172
122- def validate_with_text (self , text : str ):
123- self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (text , self ._dir , self ._tn )
124- self .__finish ()
125-
126173
127174class Server (Common ):
128175 """
@@ -165,10 +212,6 @@ def __finish(self):
165212 """
166213 self ._tr .Processes .Default .Command = self ._cmd
167214
168- def validate_with_text (self , text : str ):
169- self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (text , self ._dir , self ._tn )
170- self .__finish ()
171-
172215
173216class RPC (Common ):
174217 """
@@ -197,15 +240,6 @@ def __finish(self):
197240 """
198241 self ._tr .Processes .Default .Command = self ._cmd
199242
200- def validate_with_text (self , text : str ):
201- self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (text , self ._dir , self ._tn )
202- self .__finish ()
203-
204- def validate_result_with_text (self , text : str ):
205- full_text = f'{{\" jsonrpc\" : \" 2.0\" , \" result\" : { text } , \" id\" : { "``" } }}'
206- self ._tr .Processes .Default .Streams .stdout = MakeGoldFileWithText (full_text , self ._dir , self ._tn )
207- self .__finish ()
208-
209243
210244'''
211245
0 commit comments