@@ -403,9 +403,15 @@ def test_exemplars_with_hash_in_label_values(self):
403403 @unittest .skipIf (sys .version_info < (3 , 3 ), "Test requires Python 3.3+." )
404404 def test_fallback_to_state_machine_label_parsing (self ):
405405 from unittest .mock import patch
406- label_parsing_function = "prometheus_client.openmetrics.parser._parse_labels_with_state_machine"
407- return_values = [{"foo" : "foo # bar" }, len ('foo="foo # bar"}' )]
408- with patch (label_parsing_function , return_value = return_values ) as mock :
406+ from prometheus_client .openmetrics .parser import _parse_sample
407+
408+ parse_sample_function = "prometheus_client.openmetrics.parser._parse_sample"
409+ parse_labels_function = "prometheus_client.openmetrics.parser._parse_labels"
410+ parse_remaining_function = "prometheus_client.openmetrics.parser._parse_remaining_text"
411+ state_machine_function = "prometheus_client.openmetrics.parser._parse_labels_with_state_machine"
412+
413+ parse_sample_return_value = Sample ("a_total" , {"foo" : "foo # bar" }, 1 )
414+ with patch (parse_sample_function , return_value = parse_sample_return_value ) as mock :
409415 families = text_string_to_metric_families ("""# TYPE a counter
410416# HELP a help
411417a_total{foo="foo # bar"} 1
@@ -414,7 +420,46 @@ def test_fallback_to_state_machine_label_parsing(self):
414420 a = CounterMetricFamily ("a" , "help" , labels = ["foo" ])
415421 a .add_metric (["foo # bar" ], 1 )
416422 self .assertEqual ([a ], list (families ))
417- mock .assert_called_with ('foo="foo # bar"} 1' )
423+ mock .assert_called_once_with ('a_total{foo="foo # bar"} 1' )
424+
425+ # First fallback case
426+ state_machine_return_values = [{"foo" : "foo # bar" }, len ('foo="foo # bar"}' )]
427+ parse_remaining_values = [1 , None , None ]
428+ with patch (parse_labels_function ) as mock1 :
429+ with patch (state_machine_function , return_value = state_machine_return_values ) as mock2 :
430+ with patch (parse_remaining_function , return_value = parse_remaining_values ) as mock3 :
431+ sample = _parse_sample ('a_total{foo="foo # bar"} 1' )
432+ s = Sample ("a_total" , {"foo" : "foo # bar" }, 1 )
433+ self .assertEqual (s , sample )
434+ mock1 .assert_not_called ()
435+ mock2 .assert_called_once_with ('foo="foo # bar"} 1' )
436+ mock3 .assert_called_once_with ('1' )
437+
438+ # Second fallback case
439+ state_machine_return_values = [{"le" : "1.0" }, len ('le="1.0"}' )]
440+ parse_remaining_values = [0.0 , Timestamp (123 , 0 ), Exemplar ({"a" : "b" }, 0.5 )]
441+ with patch (parse_labels_function ) as mock1 :
442+ with patch (state_machine_function , return_value = state_machine_return_values ) as mock2 :
443+ with patch (parse_remaining_function , return_value = parse_remaining_values ) as mock3 :
444+ sample = _parse_sample ('a_bucket{le="1.0"} 0 123 # {a="b"} 0.5' )
445+ s = Sample ("a_bucket" , {"le" : "1.0" }, 0.0 , Timestamp (123 , 0 ), Exemplar ({"a" : "b" }, 0.5 ))
446+ self .assertEqual (s , sample )
447+ mock1 .assert_not_called ()
448+ mock2 .assert_called_once_with ('le="1.0"} 0 123 # {a="b"} 0.5' )
449+ mock3 .assert_called_once_with ('0 123 # {a="b"} 0.5' )
450+
451+ # No need to fallback case
452+ parse_labels_return_values = {"foo" : "foo#bar" }
453+ parse_remaining_values = [1 , None , None ]
454+ with patch (parse_labels_function , return_value = parse_labels_return_values ) as mock1 :
455+ with patch (state_machine_function ) as mock2 :
456+ with patch (parse_remaining_function , return_value = parse_remaining_values ) as mock3 :
457+ sample = _parse_sample ('a_total{foo="foo#bar"} 1' )
458+ s = Sample ("a_total" , {"foo" : "foo#bar" }, 1 )
459+ self .assertEqual (s , sample )
460+ mock1 .assert_called_once_with ('foo="foo#bar"' )
461+ mock2 .assert_not_called ()
462+ mock3 .assert_called_once_with ('1' )
418463
419464 @unittest .skipIf (sys .version_info < (2 , 7 ), "Test requires Python 2.7+." )
420465 def test_roundtrip (self ):
@@ -495,6 +540,12 @@ def test_invalid_input(self):
495540 ('a{a=1} 1\n # EOF\n ' ),
496541 ('a{a="1} 1\n # EOF\n ' ),
497542 ('a{a=\' 1\' } 1\n # EOF\n ' ),
543+ # Missing equal or label value.
544+ ('a{a} 1\n # EOF\n ' ),
545+ ('a{a"value"} 1\n # EOF\n ' ),
546+ ('a{a""} 1\n # EOF\n ' ),
547+ ('a{a=} 1\n # EOF\n ' ),
548+ ('a{a="} 1\n # EOF\n ' ),
498549 # Missing or extra commas.
499550 ('a{a="1"b="2"} 1\n # EOF\n ' ),
500551 ('a{a="1",,b="2"} 1\n # EOF\n ' ),
0 commit comments