@@ -325,3 +325,133 @@ def test_monitor_input_mixed_commands(env):
325325 found = True
326326 break
327327 env .assertTrue (found )
328+
329+
330+ def test_monitor_input_malformed_placeholder_rejected (env ):
331+ """
332+ Test that malformed monitor placeholders are rejected with an error.
333+
334+ This test verifies that placeholders like:
335+ - __monitor_c1 (missing trailing __)
336+ - __monitor_c1_ (only one trailing underscore)
337+ - __monitor_c1__garbage (trailing characters)
338+ - __monitor_c1abc__ (non-numeric characters before __)
339+ are properly rejected when --monitor-input is provided.
340+ """
341+ # Create monitor input file
342+ test_dir = tempfile .mkdtemp ()
343+ monitor_file = os .path .join (test_dir , "monitor.txt" )
344+ with open (monitor_file , "w" ) as f :
345+ f .write (
346+ '[ proxy49 ] 1764031576.604009 [0 172.16.10.147:51682] "SET" "key1" "value1"\n '
347+ )
348+
349+ malformed_placeholders = [
350+ "__monitor_c1" , # missing trailing __
351+ "__monitor_c1_" , # only one trailing underscore
352+ "__monitor_c1__garbage" , # trailing characters after valid placeholder
353+ "__monitor_c1abc__" , # non-numeric characters before __
354+ "__monitor_c__" , # missing index number
355+ ]
356+
357+ config = get_default_memtier_config (threads = 1 , clients = 1 , requests = 10 )
358+ master_nodes_list = env .getMasterNodesList ()
359+
360+ for placeholder in malformed_placeholders :
361+ benchmark_specs = {
362+ "name" : env .testName ,
363+ "args" : [
364+ "--monitor-input={}" .format (monitor_file ),
365+ "--command={}" .format (placeholder ),
366+ ],
367+ }
368+ addTLSArgs (benchmark_specs , env )
369+
370+ add_required_env_arguments (benchmark_specs , config , env , master_nodes_list )
371+
372+ run_config = RunConfig (test_dir , env .testName , config , {})
373+ ensure_clean_benchmark_folder (run_config .results_dir )
374+
375+ benchmark = Benchmark .from_json (run_config , benchmark_specs )
376+
377+ # Run memtier_benchmark - should fail
378+ memtier_ok = benchmark .run ()
379+
380+ # Verify failure
381+ if memtier_ok :
382+ env .debugPrint (
383+ "Expected failure for malformed placeholder '{}' but it succeeded" .format (
384+ placeholder
385+ ),
386+ True ,
387+ )
388+ env .assertFalse (memtier_ok )
389+
390+ # Check stderr for error message
391+ stderr_file = "{0}/mb.stderr" .format (run_config .results_dir )
392+ if os .path .isfile (stderr_file ):
393+ with open (stderr_file ) as stderr :
394+ stderr_content = stderr .read ()
395+ # The placeholder should either be rejected as invalid monitor placeholder
396+ # or treated as unknown command by Redis
397+ has_error = (
398+ "invalid monitor placeholder" in stderr_content
399+ or "error" in stderr_content .lower ()
400+ )
401+ if not has_error :
402+ env .debugPrint (
403+ "Expected error message for '{}', got: {}" .format (
404+ placeholder , stderr_content
405+ ),
406+ True ,
407+ )
408+ env .assertTrue (has_error )
409+
410+
411+ def test_monitor_placeholder_literal_without_monitor_input (env ):
412+ """
413+ Test that __monitor_c1__ is treated as a literal command when --monitor-input is not provided.
414+
415+ When monitor input is not configured, placeholder-like strings should be sent
416+ to Redis as-is (which will result in an unknown command error from Redis).
417+ This verifies that the placeholder validation only applies when monitor is in use.
418+ """
419+ test_dir = tempfile .mkdtemp ()
420+
421+ # Configure memtier WITHOUT --monitor-input but WITH a monitor-like placeholder
422+ benchmark_specs = {
423+ "name" : env .testName ,
424+ "args" : [
425+ "--command=__monitor_c1__" , # This should be sent literally to Redis
426+ ],
427+ }
428+ addTLSArgs (benchmark_specs , env )
429+
430+ config = get_default_memtier_config (threads = 1 , clients = 1 , requests = 10 )
431+ master_nodes_list = env .getMasterNodesList ()
432+
433+ add_required_env_arguments (benchmark_specs , config , env , master_nodes_list )
434+
435+ config = RunConfig (test_dir , env .testName , config , {})
436+ ensure_clean_benchmark_folder (config .results_dir )
437+
438+ benchmark = Benchmark .from_json (config , benchmark_specs )
439+
440+ # Run memtier_benchmark
441+ # This should NOT fail with "invalid monitor placeholder" error
442+ # It will likely fail because Redis doesn't recognize __monitor_c1__ as a command,
443+ # but that's a Redis error, not a memtier validation error
444+ benchmark .run () # Result doesn't matter - we only care about the error type
445+
446+ # Check stderr - should NOT contain "invalid monitor placeholder"
447+ stderr_file = "{0}/mb.stderr" .format (config .results_dir )
448+ if os .path .isfile (stderr_file ):
449+ with open (stderr_file ) as stderr :
450+ stderr_content = stderr .read ()
451+ has_monitor_error = "invalid monitor placeholder" in stderr_content
452+ if has_monitor_error :
453+ env .debugPrint (
454+ "Placeholder validation should not apply without --monitor-input" ,
455+ True ,
456+ )
457+ env .assertFalse (has_monitor_error )
0 commit comments