@@ -62,11 +62,14 @@ def _runfiles_subject_new(runfiles, meta, kind = None):
6262 actual = runfiles ,
6363 contains = lambda * a , ** k : _runfiles_subject_contains (self , * a , ** k ),
6464 contains_at_least = lambda * a , ** k : _runfiles_subject_contains_at_least (self , * a , ** k ),
65+ contains_at_least_predicates = lambda * a , ** k : _runfiles_subject_contains_at_least_predicates (self , * a , ** k ),
6566 contains_exactly = lambda * a , ** k : _runfiles_subject_contains_exactly (self , * a , ** k ),
67+ contains_exactly_predicates = lambda * a , ** k : _runfiles_subject_contains_exactly_predicates (self , * a , ** k ),
6668 contains_none_of = lambda * a , ** k : _runfiles_subject_contains_none_of (self , * a , ** k ),
6769 contains_predicate = lambda * a , ** k : _runfiles_subject_contains_predicate (self , * a , ** k ),
6870 not_contains = lambda * a , ** k : _runfiles_subject_not_contains (self , * a , ** k ),
6971 not_contains_predicate = lambda * a , ** k : _runfiles_subject_not_contains_predicate (self , * a , ** k ),
72+ paths = lambda * a , ** k : _runfiles_subject_paths (self , * a , ** k ),
7073 # keep sorted end
7174 )
7275 return public
@@ -117,6 +120,26 @@ def _runfiles_subject_contains_at_least(self, paths):
117120 container_name = "{}runfiles" .format (self .kind + " " if self .kind else "" ),
118121 ).contains_at_least (paths )
119122
123+ def _runfiles_subject_contains_at_least_predicates (self , matchers ):
124+ """Assert that the runfiles contains at least all of the provided matchers.
125+
126+ The runfile paths must match all the matchers. It can contain extra elements.
127+ The multiplicity of matchers is respected. Checking that the relative order
128+ of matches is the same as the passed-in matchers order can done by calling
129+ `in_order()`.
130+
131+ Args:
132+ self: implicitly added.
133+ matchers: ([`list`] of [`Matcher`]) (see `matchers` struct). They are
134+ passed string paths.
135+ """
136+ return CollectionSubject .new (
137+ self .actual_paths ,
138+ meta = self .meta ,
139+ element_plural_name = "paths" ,
140+ container_name = "{}runfiles" .format (self .kind + " " if self .kind else "" ),
141+ ).contains_at_least_predicates (matchers )
142+
120143def _runfiles_subject_contains_predicate (self , matcher ):
121144 """Asserts that `matcher` matches at least one value.
122145
@@ -173,6 +196,27 @@ def _runfiles_subject_contains_exactly(self, paths):
173196 meta = self .meta ,
174197 )
175198
199+ def _runfiles_subject_contains_exactly_predicates (self , expected ):
200+ """Asserts the runfiles contains exactly the given matchers.
201+
202+ See `CollectionSubject.contains_exactly_predicates` for details on
203+ behavior.
204+
205+ Args:
206+ self: implicitly added.
207+ expected: ([`list`] of [`Matcher`]) that must match. They are passed
208+ string paths.
209+
210+ Returns:
211+ [`Ordered`] (see `_ordered_incorrectly_new`).
212+ """
213+ return CollectionSubject .new (
214+ self .actual_paths ,
215+ meta = self .meta ,
216+ element_plural_name = "paths" ,
217+ container_name = "{}runfiles" .format (self .kind + " " if self .kind else "" ),
218+ ).contains_exactly_predicates (expected )
219+
176220def _runfiles_subject_contains_none_of (self , paths , require_workspace_prefix = True ):
177221 """Asserts the runfiles contain none of `paths`.
178222
@@ -244,6 +288,22 @@ def _runfiles_subject_not_contains_predicate(self, matcher):
244288 """
245289 check_not_contains_predicate (self .actual_paths , matcher , meta = self .meta )
246290
291+ def _runfiles_subject_paths (self ):
292+ """Returns a `CollectionSubject` of the computed runfile path strings.
293+
294+ Args:
295+ self: implicitly added
296+
297+ Returns:
298+ [`CollectionSubject`] of the runfile path strings.
299+ """
300+ return CollectionSubject .new (
301+ self .actual_paths ,
302+ meta = self .meta .derive ("paths()" ),
303+ element_plural_name = "paths" ,
304+ container_name = "{}runfiles" .format (self .kind + " " if self .kind else "" ),
305+ )
306+
247307def _runfiles_subject_check_workspace_prefix (self , path ):
248308 if not path .startswith (self .meta .ctx .workspace_name + "/" ):
249309 fail ("Rejecting path lacking workspace prefix: this often indicates " +
@@ -257,8 +317,10 @@ RunfilesSubject = struct(
257317 new = _runfiles_subject_new ,
258318 contains = _runfiles_subject_contains ,
259319 contains_at_least = _runfiles_subject_contains_at_least ,
320+ contains_at_least_predicates = _runfiles_subject_contains_at_least_predicates ,
260321 contains_predicate = _runfiles_subject_contains_predicate ,
261322 contains_exactly = _runfiles_subject_contains_exactly ,
323+ contains_exactly_predicates = _runfiles_subject_contains_exactly_predicates ,
262324 contains_none_of = _runfiles_subject_contains_none_of ,
263325 not_contains = _runfiles_subject_not_contains ,
264326 not_contains_predicate = _runfiles_subject_not_contains_predicate ,
0 commit comments