9494 in the specified file. The number of occurrences must match the given
9595 count.
9696
97+ * `@count PATH XPATH TEXT COUNT` checks for the occurrence of the given XPath
98+ with the given text in the specified file. The number of occurrences must
99+ match the given count.
100+
97101* `@snapshot NAME PATH XPATH` creates a snapshot test named NAME.
98102 A snapshot test captures a subtree of the DOM, at the location
99103 determined by the XPath, and compares it to a pre-recorded value
@@ -382,23 +386,25 @@ def check_tree_attr(tree, path, attr, pat, regexp):
382386 return ret
383387
384388
385- def check_tree_text (tree , path , pat , regexp ):
389+ # Returns the number of occurences matching the regex (`regexp`) and the text (`pat`).
390+ def check_tree_text (tree , path , pat , regexp , stop_at_first ):
386391 path = normalize_xpath (path )
387- ret = False
392+ match_count = 0
388393 try :
389394 for e in tree .findall (path ):
390395 try :
391396 value = flatten (e )
392397 except KeyError :
393398 continue
394399 else :
395- ret = check_string (value , pat , regexp )
396- if ret :
397- break
400+ if check_string (value , pat , regexp ):
401+ match_count += 1
402+ if stop_at_first :
403+ break
398404 except Exception :
399405 print ('Failed to get path "{}"' .format (path ))
400406 raise
401- return ret
407+ return match_count
402408
403409
404410def get_tree_count (tree , path ):
@@ -518,6 +524,19 @@ def print_err(lineno, context, err, message=None):
518524 stderr ("\t {}" .format (context ))
519525
520526
527+ def get_nb_matching_elements (cache , c , regexp , stop_at_first ):
528+ tree = cache .get_tree (c .args [0 ])
529+ pat , sep , attr = c .args [1 ].partition ('/@' )
530+ if sep : # attribute
531+ tree = cache .get_tree (c .args [0 ])
532+ return check_tree_attr (tree , pat , attr , c .args [2 ], False )
533+ else : # normalized text
534+ pat = c .args [1 ]
535+ if pat .endswith ('/text()' ):
536+ pat = pat [:- 7 ]
537+ return check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp , stop_at_first )
538+
539+
521540ERR_COUNT = 0
522541
523542
@@ -538,16 +557,7 @@ def check_command(c, cache):
538557 ret = check_string (cache .get_file (c .args [0 ]), c .args [1 ], regexp )
539558 elif len (c .args ) == 3 : # @has/matches <path> <pat> <match> = XML tree test
540559 cerr = "`XPATH PATTERN` did not match"
541- tree = cache .get_tree (c .args [0 ])
542- pat , sep , attr = c .args [1 ].partition ('/@' )
543- if sep : # attribute
544- tree = cache .get_tree (c .args [0 ])
545- ret = check_tree_attr (tree , pat , attr , c .args [2 ], regexp )
546- else : # normalized text
547- pat = c .args [1 ]
548- if pat .endswith ('/text()' ):
549- pat = pat [:- 7 ]
550- ret = check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp )
560+ ret = get_nb_matching_elements (cache , c , regexp , True ) != 0
551561 else :
552562 raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
553563
@@ -557,6 +567,11 @@ def check_command(c, cache):
557567 found = get_tree_count (cache .get_tree (c .args [0 ]), c .args [1 ])
558568 cerr = "Expected {} occurrences but found {}" .format (expected , found )
559569 ret = expected == found
570+ elif len (c .args ) == 4 : # @count <path> <pat> <text> <count> = count test
571+ expected = int (c .args [3 ])
572+ found = get_nb_matching_elements (cache , c , False , False )
573+ cerr = "Expected {} occurrences but found {}" .format (expected , found )
574+ ret = found == expected
560575 else :
561576 raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
562577
0 commit comments