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 ):
@@ -516,6 +522,19 @@ def print_err(lineno, context, err, message=None):
516522 stderr ("\t {}" .format (context ))
517523
518524
525+ def get_nb_matching_elements (cache , c , regexp , stop_at_first ):
526+ tree = cache .get_tree (c .args [0 ])
527+ pat , sep , attr = c .args [1 ].partition ('/@' )
528+ if sep : # attribute
529+ tree = cache .get_tree (c .args [0 ])
530+ return check_tree_attr (tree , pat , attr , c .args [2 ], False )
531+ else : # normalized text
532+ pat = c .args [1 ]
533+ if pat .endswith ('/text()' ):
534+ pat = pat [:- 7 ]
535+ return check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp , stop_at_first )
536+
537+
519538ERR_COUNT = 0
520539
521540
@@ -536,16 +555,7 @@ def check_command(c, cache):
536555 ret = check_string (cache .get_file (c .args [0 ]), c .args [1 ], regexp )
537556 elif len (c .args ) == 3 : # @has/matches <path> <pat> <match> = XML tree test
538557 cerr = "`XPATH PATTERN` did not match"
539- tree = cache .get_tree (c .args [0 ])
540- pat , sep , attr = c .args [1 ].partition ('/@' )
541- if sep : # attribute
542- tree = cache .get_tree (c .args [0 ])
543- ret = check_tree_attr (tree , pat , attr , c .args [2 ], regexp )
544- else : # normalized text
545- pat = c .args [1 ]
546- if pat .endswith ('/text()' ):
547- pat = pat [:- 7 ]
548- ret = check_tree_text (cache .get_tree (c .args [0 ]), pat , c .args [2 ], regexp )
558+ ret = get_nb_matching_elements (cache , c , regexp , True ) != 0
549559 else :
550560 raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
551561
@@ -555,6 +565,11 @@ def check_command(c, cache):
555565 found = get_tree_count (cache .get_tree (c .args [0 ]), c .args [1 ])
556566 cerr = "Expected {} occurrences but found {}" .format (expected , found )
557567 ret = expected == found
568+ elif len (c .args ) == 4 : # @count <path> <pat> <text> <count> = count test
569+ expected = int (c .args [3 ])
570+ found = get_nb_matching_elements (cache , c , False , False )
571+ cerr = "Expected {} occurrences but found {}" .format (expected , found )
572+ ret = found == expected
558573 else :
559574 raise InvalidCheck ('Invalid number of @{} arguments' .format (c .cmd ))
560575
0 commit comments