xref: /aosp_15_r20/external/bazelbuild-rules_testing/tests/truth_tests.bzl (revision d605057434dcabba796c020773aab68d9790ff9f)
1*d6050574SRomain Jobredeaux# Copyright 2023 The Bazel Authors. All rights reserved.
2*d6050574SRomain Jobredeaux#
3*d6050574SRomain Jobredeaux# Licensed under the Apache License, Version 2.0 (the "License");
4*d6050574SRomain Jobredeaux# you may not use this file except in compliance with the License.
5*d6050574SRomain Jobredeaux# You may obtain a copy of the License at
6*d6050574SRomain Jobredeaux#
7*d6050574SRomain Jobredeaux#     http://www.apache.org/licenses/LICENSE-2.0
8*d6050574SRomain Jobredeaux#
9*d6050574SRomain Jobredeaux# Unless required by applicable law or agreed to in writing, software
10*d6050574SRomain Jobredeaux# distributed under the License is distributed on an "AS IS" BASIS,
11*d6050574SRomain Jobredeaux# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d6050574SRomain Jobredeaux# See the License for the specific language governing permissions and
13*d6050574SRomain Jobredeaux# limitations under the License.
14*d6050574SRomain Jobredeaux
15*d6050574SRomain Jobredeaux"""Tests for truth.bzl."""
16*d6050574SRomain Jobredeaux
17*d6050574SRomain Jobredeauxload("@bazel_skylib//lib:unittest.bzl", ut_asserts = "asserts")
18*d6050574SRomain Jobredeauxload("//lib:truth.bzl", "matching", "subjects", "truth")
19*d6050574SRomain Jobredeauxload("//lib:analysis_test.bzl", "analysis_test", "test_suite")
20*d6050574SRomain Jobredeaux
21*d6050574SRomain Jobredeaux# Bazel 5 has a bug where every access of testing.ExecutionInfo is a new
22*d6050574SRomain Jobredeaux# object that isn't equal to itself. This is fixed in Bazel 6.
23*d6050574SRomain Jobredeaux_IS_BAZEL_6_OR_HIGHER = (testing.ExecutionInfo == testing.ExecutionInfo)
24*d6050574SRomain Jobredeaux
25*d6050574SRomain Jobredeaux_suite = []
26*d6050574SRomain Jobredeaux
27*d6050574SRomain Jobredeauxdef _fake_env(env):
28*d6050574SRomain Jobredeaux    failures = []
29*d6050574SRomain Jobredeaux    env1 = struct(
30*d6050574SRomain Jobredeaux        ctx = env.ctx,
31*d6050574SRomain Jobredeaux        failures = failures,
32*d6050574SRomain Jobredeaux        fail = lambda msg: failures.append(msg),  # Silent fail
33*d6050574SRomain Jobredeaux    )
34*d6050574SRomain Jobredeaux    env2 = struct(
35*d6050574SRomain Jobredeaux        ctx = env.ctx,
36*d6050574SRomain Jobredeaux        failures = failures,
37*d6050574SRomain Jobredeaux        fail = lambda msg: failures.append(msg),  # Silent fail
38*d6050574SRomain Jobredeaux        expect = truth.expect(env1),
39*d6050574SRomain Jobredeaux        reset = lambda: failures.clear(),
40*d6050574SRomain Jobredeaux    )
41*d6050574SRomain Jobredeaux    return env2
42*d6050574SRomain Jobredeaux
43*d6050574SRomain Jobredeauxdef _end(env, fake_env):
44*d6050574SRomain Jobredeaux    _guard_against_stray_failures(env = env, fake_env = fake_env)
45*d6050574SRomain Jobredeaux
46*d6050574SRomain Jobredeauxdef _guard_against_stray_failures(*, env, fake_env):
47*d6050574SRomain Jobredeaux    ut_asserts.true(
48*d6050574SRomain Jobredeaux        env,
49*d6050574SRomain Jobredeaux        len(fake_env.failures) == 0,
50*d6050574SRomain Jobredeaux        "failures remain: clear after each expected failure\n{}".format(
51*d6050574SRomain Jobredeaux            "\n".join(fake_env.failures),
52*d6050574SRomain Jobredeaux        ),
53*d6050574SRomain Jobredeaux    )
54*d6050574SRomain Jobredeaux
55*d6050574SRomain Jobredeauxdef action_subject_test(name):
56*d6050574SRomain Jobredeaux    analysis_test(name, impl = _action_subject_test, target = "truth_tests_helper")
57*d6050574SRomain Jobredeaux
58*d6050574SRomain Jobredeauxdef _action_subject_test(env, target):
59*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
60*d6050574SRomain Jobredeaux    subject = fake_env.expect.that_target(
61*d6050574SRomain Jobredeaux        target,
62*d6050574SRomain Jobredeaux    ).action_named("Action1")
63*d6050574SRomain Jobredeaux
64*d6050574SRomain Jobredeaux    subject.contains_flag_values([
65*d6050574SRomain Jobredeaux        ("--arg1flag", "arg1value"),
66*d6050574SRomain Jobredeaux        ("--arg2flag", "arg2value"),
67*d6050574SRomain Jobredeaux    ])
68*d6050574SRomain Jobredeaux    _assert_no_failures(
69*d6050574SRomain Jobredeaux        fake_env,
70*d6050574SRomain Jobredeaux        env = env,
71*d6050574SRomain Jobredeaux        msg = "check contains_flag_values success",
72*d6050574SRomain Jobredeaux    )
73*d6050574SRomain Jobredeaux
74*d6050574SRomain Jobredeaux    subject.contains_flag_values([
75*d6050574SRomain Jobredeaux        ("--missingflag", "whatever"),
76*d6050574SRomain Jobredeaux        ("--arg1flag", "wrongvalue"),
77*d6050574SRomain Jobredeaux    ])
78*d6050574SRomain Jobredeaux    _assert_failure(
79*d6050574SRomain Jobredeaux        fake_env,
80*d6050574SRomain Jobredeaux        [
81*d6050574SRomain Jobredeaux            "2 expected flags with values missing from argv",
82*d6050574SRomain Jobredeaux            "0: '--arg1flag' with value 'wrongvalue'",
83*d6050574SRomain Jobredeaux            "1: '--missingflag' (not specified)",
84*d6050574SRomain Jobredeaux            "actual argv",
85*d6050574SRomain Jobredeaux            "1: arg1",
86*d6050574SRomain Jobredeaux            "2: --boolflag",
87*d6050574SRomain Jobredeaux            "3: --arg1flag",
88*d6050574SRomain Jobredeaux            "4: arg1value",
89*d6050574SRomain Jobredeaux            "5: --arg2flag=arg2value",
90*d6050574SRomain Jobredeaux        ],
91*d6050574SRomain Jobredeaux        env = env,
92*d6050574SRomain Jobredeaux        msg = "check contains_flag_values failure",
93*d6050574SRomain Jobredeaux    )
94*d6050574SRomain Jobredeaux
95*d6050574SRomain Jobredeaux    subject.contains_none_of_flag_values([
96*d6050574SRomain Jobredeaux        ("--doesnotexist", "whatever"),
97*d6050574SRomain Jobredeaux        ("--arg1flag", "differentvalue"),
98*d6050574SRomain Jobredeaux    ])
99*d6050574SRomain Jobredeaux    _assert_no_failures(
100*d6050574SRomain Jobredeaux        fake_env,
101*d6050574SRomain Jobredeaux        env = env,
102*d6050574SRomain Jobredeaux        msg = "check contains_none_of_flag_values success",
103*d6050574SRomain Jobredeaux    )
104*d6050574SRomain Jobredeaux
105*d6050574SRomain Jobredeaux    subject.contains_none_of_flag_values([
106*d6050574SRomain Jobredeaux        ("--arg1flag", "arg1value"),
107*d6050574SRomain Jobredeaux    ])
108*d6050574SRomain Jobredeaux    _assert_failure(
109*d6050574SRomain Jobredeaux        fake_env,
110*d6050574SRomain Jobredeaux        [
111*d6050574SRomain Jobredeaux            ("expected not to contain any of: \n" +  # note space after colon
112*d6050574SRomain Jobredeaux             "  0: '--arg1flag' with value 'arg1value'\n"),
113*d6050574SRomain Jobredeaux            ("but 1 found:\n" +
114*d6050574SRomain Jobredeaux             "  0: '--arg1flag' with value 'arg1value'\n"),
115*d6050574SRomain Jobredeaux            "actual values:\n",
116*d6050574SRomain Jobredeaux            # Element 0 of actual is omitted because it has build-config
117*d6050574SRomain Jobredeaux            # specific values within it.
118*d6050574SRomain Jobredeaux            ("  1: arg1\n" +
119*d6050574SRomain Jobredeaux             "  2: --boolflag\n" +
120*d6050574SRomain Jobredeaux             "  3: --arg1flag\n" +
121*d6050574SRomain Jobredeaux             "  4: arg1value\n" +
122*d6050574SRomain Jobredeaux             "  5: --arg2flag=arg2value\n"),
123*d6050574SRomain Jobredeaux        ],
124*d6050574SRomain Jobredeaux        env = env,
125*d6050574SRomain Jobredeaux        msg = "check contains_none_of_flag_values failure",
126*d6050574SRomain Jobredeaux    )
127*d6050574SRomain Jobredeaux    _end(env, fake_env)
128*d6050574SRomain Jobredeaux
129*d6050574SRomain Jobredeaux_suite.append(action_subject_test)
130*d6050574SRomain Jobredeaux
131*d6050574SRomain Jobredeauxdef bool_subject_test(name):
132*d6050574SRomain Jobredeaux    analysis_test(name, impl = _bool_subject_test, target = "truth_tests_helper")
133*d6050574SRomain Jobredeaux
134*d6050574SRomain Jobredeauxdef _bool_subject_test(env, _target):
135*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
136*d6050574SRomain Jobredeaux    fake_env.expect.that_bool(True).equals(True)
137*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
138*d6050574SRomain Jobredeaux    fake_env.expect.that_bool(False).equals(False)
139*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
140*d6050574SRomain Jobredeaux
141*d6050574SRomain Jobredeaux    fake_env.expect.that_bool(True).equals(False)
142*d6050574SRomain Jobredeaux    _assert_failure(fake_env, [
143*d6050574SRomain Jobredeaux        "expected: False",
144*d6050574SRomain Jobredeaux        "actual: True",
145*d6050574SRomain Jobredeaux    ], env = env)
146*d6050574SRomain Jobredeaux
147*d6050574SRomain Jobredeaux    fake_env.expect.that_bool(True, "MYEXPR").equals(False)
148*d6050574SRomain Jobredeaux    _assert_failure(fake_env, ["MYEXPR"], env = env)
149*d6050574SRomain Jobredeaux
150*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_bool(True)
151*d6050574SRomain Jobredeaux    subject.not_equals(True)
152*d6050574SRomain Jobredeaux    _assert_failure(
153*d6050574SRomain Jobredeaux        fake_env,
154*d6050574SRomain Jobredeaux        ["expected not to be: True", "actual: True"],
155*d6050574SRomain Jobredeaux        env = env,
156*d6050574SRomain Jobredeaux        msg = "check not_equals fails with same type",
157*d6050574SRomain Jobredeaux    )
158*d6050574SRomain Jobredeaux    subject.not_equals(None)
159*d6050574SRomain Jobredeaux    _assert_failure(
160*d6050574SRomain Jobredeaux        fake_env,
161*d6050574SRomain Jobredeaux        ["expected not to be: None (type: NoneType)", "actual: True (type: bool)"],
162*d6050574SRomain Jobredeaux        env = env,
163*d6050574SRomain Jobredeaux        msg = "check not_equals due to different type",
164*d6050574SRomain Jobredeaux    )
165*d6050574SRomain Jobredeaux    subject.not_equals(False)
166*d6050574SRomain Jobredeaux    _assert_no_failures(
167*d6050574SRomain Jobredeaux        fake_env,
168*d6050574SRomain Jobredeaux        env = env,
169*d6050574SRomain Jobredeaux        msg = "check BoolSubject.not_equals with unequal value of same type",
170*d6050574SRomain Jobredeaux    )
171*d6050574SRomain Jobredeaux
172*d6050574SRomain Jobredeaux    subject.is_in([True, False])
173*d6050574SRomain Jobredeaux    _assert_no_failures(
174*d6050574SRomain Jobredeaux        fake_env,
175*d6050574SRomain Jobredeaux        env = env,
176*d6050574SRomain Jobredeaux        msg = "check BoolSubject.is_in with matching values",
177*d6050574SRomain Jobredeaux    )
178*d6050574SRomain Jobredeaux    subject.is_in([None, 39])
179*d6050574SRomain Jobredeaux    _assert_failure(
180*d6050574SRomain Jobredeaux        fake_env,
181*d6050574SRomain Jobredeaux        ["expected any of:", "None", "39", "actual: True"],
182*d6050574SRomain Jobredeaux        env = env,
183*d6050574SRomain Jobredeaux        msg = "check is_in mismatched values",
184*d6050574SRomain Jobredeaux    )
185*d6050574SRomain Jobredeaux
186*d6050574SRomain Jobredeaux    _end(env, fake_env)
187*d6050574SRomain Jobredeaux
188*d6050574SRomain Jobredeaux_suite.append(bool_subject_test)
189*d6050574SRomain Jobredeaux
190*d6050574SRomain Jobredeauxdef collection_custom_expr_test(name):
191*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_custom_expr_test, target = "truth_tests_helper")
192*d6050574SRomain Jobredeaux
193*d6050574SRomain Jobredeauxdef _collection_custom_expr_test(env, _target):
194*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
195*d6050574SRomain Jobredeaux    subject = fake_env.expect.that_collection(["a"], "MYEXPR")
196*d6050574SRomain Jobredeaux    subject.contains_exactly([])
197*d6050574SRomain Jobredeaux    _assert_failure(fake_env, ["MYEXPR"], env = env)
198*d6050574SRomain Jobredeaux    _end(env, fake_env)
199*d6050574SRomain Jobredeaux
200*d6050574SRomain Jobredeaux_suite.append(collection_custom_expr_test)
201*d6050574SRomain Jobredeaux
202*d6050574SRomain Jobredeauxdef collection_has_size_test(name):
203*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_has_size_test, target = "truth_tests_helper")
204*d6050574SRomain Jobredeaux
205*d6050574SRomain Jobredeauxdef _collection_has_size_test(env, _target):
206*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
207*d6050574SRomain Jobredeaux    subject = fake_env.expect.that_collection(["a", "b", "c", "d"])
208*d6050574SRomain Jobredeaux
209*d6050574SRomain Jobredeaux    subject.has_size(4)
210*d6050574SRomain Jobredeaux    _assert_no_failures(
211*d6050574SRomain Jobredeaux        fake_env,
212*d6050574SRomain Jobredeaux        env = env,
213*d6050574SRomain Jobredeaux        msg = "check actual has expected size",
214*d6050574SRomain Jobredeaux    )
215*d6050574SRomain Jobredeaux
216*d6050574SRomain Jobredeaux    subject.has_size(0)
217*d6050574SRomain Jobredeaux    _assert_failure(
218*d6050574SRomain Jobredeaux        fake_env,
219*d6050574SRomain Jobredeaux        ["value of: collection.size()"],
220*d6050574SRomain Jobredeaux        env = env,
221*d6050574SRomain Jobredeaux        msg = "check actual does not have expected size",
222*d6050574SRomain Jobredeaux    )
223*d6050574SRomain Jobredeaux
224*d6050574SRomain Jobredeaux    _end(env, fake_env)
225*d6050574SRomain Jobredeaux
226*d6050574SRomain Jobredeaux_suite.append(collection_has_size_test)
227*d6050574SRomain Jobredeaux
228*d6050574SRomain Jobredeauxdef collection_contains_test(name):
229*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_test, target = "truth_tests_helper")
230*d6050574SRomain Jobredeaux
231*d6050574SRomain Jobredeauxdef _collection_contains_test(env, _target):
232*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
233*d6050574SRomain Jobredeaux    subject = fake_env.expect.that_collection(["a", "b", "c", "d"])
234*d6050574SRomain Jobredeaux
235*d6050574SRomain Jobredeaux    subject.contains("a")
236*d6050574SRomain Jobredeaux    _assert_no_failures(
237*d6050574SRomain Jobredeaux        fake_env,
238*d6050574SRomain Jobredeaux        env = env,
239*d6050574SRomain Jobredeaux        msg = "check actual does contain expected",
240*d6050574SRomain Jobredeaux    )
241*d6050574SRomain Jobredeaux
242*d6050574SRomain Jobredeaux    subject.contains("never")
243*d6050574SRomain Jobredeaux    _assert_failure(
244*d6050574SRomain Jobredeaux        fake_env,
245*d6050574SRomain Jobredeaux        ["expected to contain: never", "actual values", "0: a"],
246*d6050574SRomain Jobredeaux        env = env,
247*d6050574SRomain Jobredeaux        msg = "check actual is missing expected",
248*d6050574SRomain Jobredeaux    )
249*d6050574SRomain Jobredeaux
250*d6050574SRomain Jobredeaux    _end(env, fake_env)
251*d6050574SRomain Jobredeaux
252*d6050574SRomain Jobredeaux_suite.append(collection_contains_test)
253*d6050574SRomain Jobredeaux
254*d6050574SRomain Jobredeauxdef collection_contains_predicate_test(name):
255*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_predicate_test, target = "truth_tests_helper")
256*d6050574SRomain Jobredeaux
257*d6050574SRomain Jobredeauxdef _collection_contains_predicate_test(env, _target):
258*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
259*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c", "d"])
260*d6050574SRomain Jobredeaux
261*d6050574SRomain Jobredeaux    subject.contains_predicate(matching.contains("a"))
262*d6050574SRomain Jobredeaux    _assert_no_failures(
263*d6050574SRomain Jobredeaux        fake_env,
264*d6050574SRomain Jobredeaux        env = env,
265*d6050574SRomain Jobredeaux        msg = "check actual does contains expected",
266*d6050574SRomain Jobredeaux    )
267*d6050574SRomain Jobredeaux
268*d6050574SRomain Jobredeaux    subject.contains_predicate(matching.contains("never"))
269*d6050574SRomain Jobredeaux    _assert_failure(
270*d6050574SRomain Jobredeaux        fake_env,
271*d6050574SRomain Jobredeaux        ["expected to contain: <contains never>", "actual values", "0: a"],
272*d6050574SRomain Jobredeaux        env = env,
273*d6050574SRomain Jobredeaux        msg = "check actual is missing a value",
274*d6050574SRomain Jobredeaux    )
275*d6050574SRomain Jobredeaux    _end(env, fake_env)
276*d6050574SRomain Jobredeaux
277*d6050574SRomain Jobredeaux_suite.append(collection_contains_predicate_test)
278*d6050574SRomain Jobredeaux
279*d6050574SRomain Jobredeauxdef collection_contains_at_least_test(name):
280*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_at_least_test, target = "truth_tests_helper")
281*d6050574SRomain Jobredeaux
282*d6050574SRomain Jobredeauxdef _collection_contains_at_least_test(env, _target):
283*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
284*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c", "d"])
285*d6050574SRomain Jobredeaux
286*d6050574SRomain Jobredeaux    subject.contains_at_least(["a", "b", "c"]).in_order()
287*d6050574SRomain Jobredeaux    _assert_no_failures(
288*d6050574SRomain Jobredeaux        fake_env,
289*d6050574SRomain Jobredeaux        env = env,
290*d6050574SRomain Jobredeaux        msg = "check expected and actual with same elements in same order",
291*d6050574SRomain Jobredeaux    )
292*d6050574SRomain Jobredeaux
293*d6050574SRomain Jobredeaux    subject.contains_at_least(["never"])
294*d6050574SRomain Jobredeaux    _assert_failure(
295*d6050574SRomain Jobredeaux        fake_env,
296*d6050574SRomain Jobredeaux        ["expected elements missing", "never", "actual values", "0: a"],
297*d6050574SRomain Jobredeaux        env = env,
298*d6050574SRomain Jobredeaux        msg = "check actual is missing a value",
299*d6050574SRomain Jobredeaux    )
300*d6050574SRomain Jobredeaux
301*d6050574SRomain Jobredeaux    subject.contains_at_least([
302*d6050574SRomain Jobredeaux        "b",
303*d6050574SRomain Jobredeaux        "a",
304*d6050574SRomain Jobredeaux    ]).in_order()
305*d6050574SRomain Jobredeaux    _assert_failure(
306*d6050574SRomain Jobredeaux        fake_env,
307*d6050574SRomain Jobredeaux        [
308*d6050574SRomain Jobredeaux            "incorrect order",
309*d6050574SRomain Jobredeaux            "0: b found at offset 1",
310*d6050574SRomain Jobredeaux            "1: a found at offset 0",
311*d6050574SRomain Jobredeaux        ],
312*d6050574SRomain Jobredeaux        env = env,
313*d6050574SRomain Jobredeaux        msg = "check expected values present in wrong order",
314*d6050574SRomain Jobredeaux    )
315*d6050574SRomain Jobredeaux
316*d6050574SRomain Jobredeaux    _end(env, fake_env)
317*d6050574SRomain Jobredeaux
318*d6050574SRomain Jobredeaux_suite.append(collection_contains_at_least_test)
319*d6050574SRomain Jobredeaux
320*d6050574SRomain Jobredeauxdef collection_contains_at_least_predicates_test(name):
321*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_at_least_predicates_test, target = "truth_tests_helper")
322*d6050574SRomain Jobredeaux
323*d6050574SRomain Jobredeauxdef _collection_contains_at_least_predicates_test(env, _target):
324*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
325*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c", "d"])
326*d6050574SRomain Jobredeaux    subject.contains_at_least_predicates([
327*d6050574SRomain Jobredeaux        matching.contains("a"),
328*d6050574SRomain Jobredeaux        matching.contains("b"),
329*d6050574SRomain Jobredeaux        matching.contains("c"),
330*d6050574SRomain Jobredeaux    ]).in_order()
331*d6050574SRomain Jobredeaux
332*d6050574SRomain Jobredeaux    subject.contains_at_least_predicates([
333*d6050574SRomain Jobredeaux        matching.never("never"),
334*d6050574SRomain Jobredeaux    ])
335*d6050574SRomain Jobredeaux    _assert_failure(
336*d6050574SRomain Jobredeaux        fake_env,
337*d6050574SRomain Jobredeaux        ["expected elements missing", "never", "actual values", "0: a"],
338*d6050574SRomain Jobredeaux        env = env,
339*d6050574SRomain Jobredeaux    )
340*d6050574SRomain Jobredeaux
341*d6050574SRomain Jobredeaux    subject.contains_at_least_predicates([
342*d6050574SRomain Jobredeaux        matching.custom("<MATCHER-B>", lambda v: "b" in v),
343*d6050574SRomain Jobredeaux        matching.custom("<MATCHER-A>", lambda v: "a" in v),
344*d6050574SRomain Jobredeaux    ]).in_order()
345*d6050574SRomain Jobredeaux    _assert_failure(
346*d6050574SRomain Jobredeaux        fake_env,
347*d6050574SRomain Jobredeaux        [
348*d6050574SRomain Jobredeaux            "incorrect order",
349*d6050574SRomain Jobredeaux            "0: <MATCHER-B> matched at offset 1 (matched: b)",
350*d6050574SRomain Jobredeaux            "1: <MATCHER-A> matched at offset 0 (matched: a)",
351*d6050574SRomain Jobredeaux        ],
352*d6050574SRomain Jobredeaux        env = env,
353*d6050574SRomain Jobredeaux    )
354*d6050574SRomain Jobredeaux
355*d6050574SRomain Jobredeaux    _end(env, fake_env)
356*d6050574SRomain Jobredeaux
357*d6050574SRomain Jobredeaux_suite.append(collection_contains_at_least_predicates_test)
358*d6050574SRomain Jobredeaux
359*d6050574SRomain Jobredeauxdef collection_contains_exactly_test(name):
360*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_exactly_test, target = "truth_tests_helper")
361*d6050574SRomain Jobredeaux
362*d6050574SRomain Jobredeauxdef _collection_contains_exactly_test(env, _target):
363*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
364*d6050574SRomain Jobredeaux
365*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection([])
366*d6050574SRomain Jobredeaux    subject.contains_exactly(["a"])
367*d6050574SRomain Jobredeaux    _assert_failure(
368*d6050574SRomain Jobredeaux        fake_env,
369*d6050574SRomain Jobredeaux        [
370*d6050574SRomain Jobredeaux            "1 missing:\n  0: a",
371*d6050574SRomain Jobredeaux            "expected exactly:\n  0: a",
372*d6050574SRomain Jobredeaux            "actual values:\n  <empty>",
373*d6050574SRomain Jobredeaux        ],
374*d6050574SRomain Jobredeaux        env = env,
375*d6050574SRomain Jobredeaux        msg = "check empty actual vs non-empty expected",
376*d6050574SRomain Jobredeaux    )
377*d6050574SRomain Jobredeaux
378*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["b"])
379*d6050574SRomain Jobredeaux    subject.contains_exactly([])
380*d6050574SRomain Jobredeaux    _assert_failure(
381*d6050574SRomain Jobredeaux        fake_env,
382*d6050574SRomain Jobredeaux        [
383*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: b",
384*d6050574SRomain Jobredeaux            "expected exactly:\n  <empty>",
385*d6050574SRomain Jobredeaux            "actual values:\n  0: b",
386*d6050574SRomain Jobredeaux        ],
387*d6050574SRomain Jobredeaux        env = env,
388*d6050574SRomain Jobredeaux        msg = "check non-empty actual vs empty expected",
389*d6050574SRomain Jobredeaux    )
390*d6050574SRomain Jobredeaux
391*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["c"])
392*d6050574SRomain Jobredeaux    order = subject.contains_exactly(["c"])
393*d6050574SRomain Jobredeaux    _assert_no_failures(
394*d6050574SRomain Jobredeaux        fake_env,
395*d6050574SRomain Jobredeaux        env = env,
396*d6050574SRomain Jobredeaux        msg = "check expected and actual with same elements in same order",
397*d6050574SRomain Jobredeaux    )
398*d6050574SRomain Jobredeaux    order.in_order()
399*d6050574SRomain Jobredeaux    _assert_no_failures(
400*d6050574SRomain Jobredeaux        fake_env,
401*d6050574SRomain Jobredeaux        env = env,
402*d6050574SRomain Jobredeaux        msg = "check exact elements are in order",
403*d6050574SRomain Jobredeaux    )
404*d6050574SRomain Jobredeaux
405*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["d"])
406*d6050574SRomain Jobredeaux    subject.contains_exactly(["e"])
407*d6050574SRomain Jobredeaux    _assert_failure(
408*d6050574SRomain Jobredeaux        fake_env,
409*d6050574SRomain Jobredeaux        [
410*d6050574SRomain Jobredeaux            "1 missing:\n  0: e",
411*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: d",
412*d6050574SRomain Jobredeaux            "expected exactly:\n  0: e",
413*d6050574SRomain Jobredeaux            "actual values:\n  0: d",
414*d6050574SRomain Jobredeaux        ],
415*d6050574SRomain Jobredeaux        env = env,
416*d6050574SRomain Jobredeaux        msg = "check disjoint values; same length",
417*d6050574SRomain Jobredeaux    )
418*d6050574SRomain Jobredeaux
419*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["f", "g"])
420*d6050574SRomain Jobredeaux    order = subject.contains_exactly(["g", "f"])
421*d6050574SRomain Jobredeaux    _assert_no_failures(
422*d6050574SRomain Jobredeaux        fake_env,
423*d6050574SRomain Jobredeaux        env = env,
424*d6050574SRomain Jobredeaux        msg = "check same elements with expected in different order",
425*d6050574SRomain Jobredeaux    )
426*d6050574SRomain Jobredeaux    order.in_order()
427*d6050574SRomain Jobredeaux    _assert_failure(
428*d6050574SRomain Jobredeaux        fake_env,
429*d6050574SRomain Jobredeaux        [
430*d6050574SRomain Jobredeaux            "expected values all found, but with incorrect order",
431*d6050574SRomain Jobredeaux            "0: g found at offset 1",
432*d6050574SRomain Jobredeaux            "1: f found at offset 0",
433*d6050574SRomain Jobredeaux            "actual values:",
434*d6050574SRomain Jobredeaux            "0: f",
435*d6050574SRomain Jobredeaux            "1: g",
436*d6050574SRomain Jobredeaux        ],
437*d6050574SRomain Jobredeaux        env = env,
438*d6050574SRomain Jobredeaux        msg = "check same elements out of order",
439*d6050574SRomain Jobredeaux    )
440*d6050574SRomain Jobredeaux
441*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["x", "y"])
442*d6050574SRomain Jobredeaux    subject.contains_exactly(["y"])
443*d6050574SRomain Jobredeaux    _assert_failure(
444*d6050574SRomain Jobredeaux        fake_env,
445*d6050574SRomain Jobredeaux        [
446*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: x",
447*d6050574SRomain Jobredeaux            "expected exactly:\n  0: y",
448*d6050574SRomain Jobredeaux            "actual values:\n  0: x\n  1: y",
449*d6050574SRomain Jobredeaux        ],
450*d6050574SRomain Jobredeaux        env = env,
451*d6050574SRomain Jobredeaux        msg = "check expected subset of actual",
452*d6050574SRomain Jobredeaux    )
453*d6050574SRomain Jobredeaux
454*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c", "d"])
455*d6050574SRomain Jobredeaux    subject.contains_exactly(["a", "b", "c", "d"])
456*d6050574SRomain Jobredeaux    _assert_no_failures(
457*d6050574SRomain Jobredeaux        fake_env,
458*d6050574SRomain Jobredeaux        env = env,
459*d6050574SRomain Jobredeaux        msg = "check expected and actual with exact elements and order; 4 values",
460*d6050574SRomain Jobredeaux    )
461*d6050574SRomain Jobredeaux
462*d6050574SRomain Jobredeaux    subject.contains_exactly(["d", "b", "a", "c"])
463*d6050574SRomain Jobredeaux    _assert_no_failures(
464*d6050574SRomain Jobredeaux        fake_env,
465*d6050574SRomain Jobredeaux        env = env,
466*d6050574SRomain Jobredeaux        msg = "check expected and actual same elements and different order; 4 values",
467*d6050574SRomain Jobredeaux    )
468*d6050574SRomain Jobredeaux
469*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "a"])
470*d6050574SRomain Jobredeaux    subject.contains_exactly(["a", "b", "a"])
471*d6050574SRomain Jobredeaux    _assert_no_failures(
472*d6050574SRomain Jobredeaux        fake_env,
473*d6050574SRomain Jobredeaux        env = env,
474*d6050574SRomain Jobredeaux        msg = "check multiplicity, same expected/actual order",
475*d6050574SRomain Jobredeaux    )
476*d6050574SRomain Jobredeaux
477*d6050574SRomain Jobredeaux    subject.contains_exactly(["b", "a", "a"])
478*d6050574SRomain Jobredeaux    _assert_no_failures(
479*d6050574SRomain Jobredeaux        fake_env,
480*d6050574SRomain Jobredeaux        env = env,
481*d6050574SRomain Jobredeaux        msg = "check multiplicity; different expected/actual order",
482*d6050574SRomain Jobredeaux    )
483*d6050574SRomain Jobredeaux
484*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection([
485*d6050574SRomain Jobredeaux        "one",
486*d6050574SRomain Jobredeaux        "two",
487*d6050574SRomain Jobredeaux        "one",
488*d6050574SRomain Jobredeaux        "three",
489*d6050574SRomain Jobredeaux        "one",
490*d6050574SRomain Jobredeaux        "four",
491*d6050574SRomain Jobredeaux    ])
492*d6050574SRomain Jobredeaux
493*d6050574SRomain Jobredeaux    subject.contains_exactly(["one", "two", "three", "five"])
494*d6050574SRomain Jobredeaux    _assert_failure(
495*d6050574SRomain Jobredeaux        fake_env,
496*d6050574SRomain Jobredeaux        [
497*d6050574SRomain Jobredeaux            ("1 missing:\n" +
498*d6050574SRomain Jobredeaux             "  0: five"),
499*d6050574SRomain Jobredeaux            ("3 unexpected:\n" +
500*d6050574SRomain Jobredeaux             "  0: four\n" +
501*d6050574SRomain Jobredeaux             "  1: one\n" +
502*d6050574SRomain Jobredeaux             "  2: one\n"),
503*d6050574SRomain Jobredeaux            ("expected exactly:\n" +
504*d6050574SRomain Jobredeaux             "  0: one\n" +
505*d6050574SRomain Jobredeaux             "  1: two\n" +
506*d6050574SRomain Jobredeaux             "  2: three\n" +
507*d6050574SRomain Jobredeaux             "  3: five\n"),
508*d6050574SRomain Jobredeaux        ],
509*d6050574SRomain Jobredeaux        env = env,
510*d6050574SRomain Jobredeaux        msg = "check multiplicity; expected with multiple, expected with unique",
511*d6050574SRomain Jobredeaux    )
512*d6050574SRomain Jobredeaux
513*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["one", "four", "three", "two", "five"])
514*d6050574SRomain Jobredeaux    order = subject.contains_exactly(["one", "two", "three", "four", "five"])
515*d6050574SRomain Jobredeaux    _assert_no_failures(
516*d6050574SRomain Jobredeaux        fake_env,
517*d6050574SRomain Jobredeaux        env = env,
518*d6050574SRomain Jobredeaux        msg = "check same elements with expected in different order",
519*d6050574SRomain Jobredeaux    )
520*d6050574SRomain Jobredeaux    order.in_order()
521*d6050574SRomain Jobredeaux    _assert_failure(
522*d6050574SRomain Jobredeaux        fake_env,
523*d6050574SRomain Jobredeaux        [
524*d6050574SRomain Jobredeaux            "expected values all found, but with incorrect order:",
525*d6050574SRomain Jobredeaux            "0: one found at offset 0",
526*d6050574SRomain Jobredeaux            "1: two found at offset 3",
527*d6050574SRomain Jobredeaux            "2: three found at offset 2",
528*d6050574SRomain Jobredeaux            "3: four found at offset 1",
529*d6050574SRomain Jobredeaux            "4: five found at offset 4",
530*d6050574SRomain Jobredeaux            "actual values:",
531*d6050574SRomain Jobredeaux            "0: one",
532*d6050574SRomain Jobredeaux            "1: four",
533*d6050574SRomain Jobredeaux            "2: three",
534*d6050574SRomain Jobredeaux            "3: two",
535*d6050574SRomain Jobredeaux            "4: five",
536*d6050574SRomain Jobredeaux        ],
537*d6050574SRomain Jobredeaux        env = env,
538*d6050574SRomain Jobredeaux        msg = "check same elements out of order",
539*d6050574SRomain Jobredeaux    )
540*d6050574SRomain Jobredeaux
541*d6050574SRomain Jobredeaux    _end(env, fake_env)
542*d6050574SRomain Jobredeaux
543*d6050574SRomain Jobredeaux_suite.append(collection_contains_exactly_test)
544*d6050574SRomain Jobredeaux
545*d6050574SRomain Jobredeauxdef collection_contains_exactly_predicates_test(name):
546*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_exactly_predicates_test, target = "truth_tests_helper")
547*d6050574SRomain Jobredeaux
548*d6050574SRomain Jobredeauxdef _collection_contains_exactly_predicates_test(env, _target):
549*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
550*d6050574SRomain Jobredeaux
551*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection([])
552*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([matching.contains("a")])
553*d6050574SRomain Jobredeaux    _assert_failure(
554*d6050574SRomain Jobredeaux        fake_env,
555*d6050574SRomain Jobredeaux        [
556*d6050574SRomain Jobredeaux            "1 missing:\n  0: <contains a>",
557*d6050574SRomain Jobredeaux            "expected exactly:\n  0: <contains a>",
558*d6050574SRomain Jobredeaux            "actual values:\n  <empty>",
559*d6050574SRomain Jobredeaux        ],
560*d6050574SRomain Jobredeaux        env = env,
561*d6050574SRomain Jobredeaux        msg = "check empty actual vs non-empty expected",
562*d6050574SRomain Jobredeaux    )
563*d6050574SRomain Jobredeaux
564*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["b"])
565*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([])
566*d6050574SRomain Jobredeaux    _assert_failure(
567*d6050574SRomain Jobredeaux        fake_env,
568*d6050574SRomain Jobredeaux        [
569*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: b",
570*d6050574SRomain Jobredeaux            "expected exactly:\n  <empty>",
571*d6050574SRomain Jobredeaux            "actual values:\n  0: b",
572*d6050574SRomain Jobredeaux        ],
573*d6050574SRomain Jobredeaux        env = env,
574*d6050574SRomain Jobredeaux        msg = "check non-empty actual vs empty expected",
575*d6050574SRomain Jobredeaux    )
576*d6050574SRomain Jobredeaux
577*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["c"])
578*d6050574SRomain Jobredeaux    order = subject.contains_exactly_predicates([matching.contains("c")])
579*d6050574SRomain Jobredeaux    _assert_no_failures(
580*d6050574SRomain Jobredeaux        fake_env,
581*d6050574SRomain Jobredeaux        env = env,
582*d6050574SRomain Jobredeaux        msg = "check expected and actual with same elements in same order",
583*d6050574SRomain Jobredeaux    )
584*d6050574SRomain Jobredeaux    order.in_order()
585*d6050574SRomain Jobredeaux    _assert_no_failures(
586*d6050574SRomain Jobredeaux        fake_env,
587*d6050574SRomain Jobredeaux        env = env,
588*d6050574SRomain Jobredeaux        msg = "check exact elements are in order",
589*d6050574SRomain Jobredeaux    )
590*d6050574SRomain Jobredeaux
591*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["d"])
592*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([matching.contains("e")])
593*d6050574SRomain Jobredeaux    _assert_failure(
594*d6050574SRomain Jobredeaux        fake_env,
595*d6050574SRomain Jobredeaux        [
596*d6050574SRomain Jobredeaux            "1 missing:\n  0: <contains e>",
597*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: d",
598*d6050574SRomain Jobredeaux            "expected exactly:\n  0: <contains e>",
599*d6050574SRomain Jobredeaux            "actual values:\n  0: d",
600*d6050574SRomain Jobredeaux        ],
601*d6050574SRomain Jobredeaux        env = env,
602*d6050574SRomain Jobredeaux        msg = "check disjoint values; same length",
603*d6050574SRomain Jobredeaux    )
604*d6050574SRomain Jobredeaux
605*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["f", "g"])
606*d6050574SRomain Jobredeaux    order = subject.contains_exactly_predicates([
607*d6050574SRomain Jobredeaux        matching.contains("g"),
608*d6050574SRomain Jobredeaux        matching.contains("f"),
609*d6050574SRomain Jobredeaux    ])
610*d6050574SRomain Jobredeaux    _assert_no_failures(
611*d6050574SRomain Jobredeaux        fake_env,
612*d6050574SRomain Jobredeaux        env = env,
613*d6050574SRomain Jobredeaux        msg = "check same elements with expected in different order",
614*d6050574SRomain Jobredeaux    )
615*d6050574SRomain Jobredeaux    order.in_order()
616*d6050574SRomain Jobredeaux    _assert_failure(
617*d6050574SRomain Jobredeaux        fake_env,
618*d6050574SRomain Jobredeaux        [
619*d6050574SRomain Jobredeaux            "expected values all found, but with incorrect order",
620*d6050574SRomain Jobredeaux            "0: <contains g> matched at offset 1 (matched: g)",
621*d6050574SRomain Jobredeaux            "1: <contains f> matched at offset 0 (matched: f)",
622*d6050574SRomain Jobredeaux            "actual values:",
623*d6050574SRomain Jobredeaux            "0: f",
624*d6050574SRomain Jobredeaux            "1: g",
625*d6050574SRomain Jobredeaux        ],
626*d6050574SRomain Jobredeaux        env = env,
627*d6050574SRomain Jobredeaux        msg = "check same elements out of order",
628*d6050574SRomain Jobredeaux    )
629*d6050574SRomain Jobredeaux
630*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["x", "y"])
631*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([matching.contains("y")])
632*d6050574SRomain Jobredeaux    _assert_failure(
633*d6050574SRomain Jobredeaux        fake_env,
634*d6050574SRomain Jobredeaux        [
635*d6050574SRomain Jobredeaux            "1 unexpected:\n  0: x",
636*d6050574SRomain Jobredeaux            "expected exactly:\n  0: <contains y>",
637*d6050574SRomain Jobredeaux            "actual values:\n  0: x\n  1: y",
638*d6050574SRomain Jobredeaux        ],
639*d6050574SRomain Jobredeaux        env = env,
640*d6050574SRomain Jobredeaux        msg = "check expected subset of actual",
641*d6050574SRomain Jobredeaux    )
642*d6050574SRomain Jobredeaux
643*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c", "d"])
644*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([
645*d6050574SRomain Jobredeaux        matching.contains("a"),
646*d6050574SRomain Jobredeaux        matching.contains("b"),
647*d6050574SRomain Jobredeaux        matching.contains("c"),
648*d6050574SRomain Jobredeaux        matching.contains("d"),
649*d6050574SRomain Jobredeaux    ])
650*d6050574SRomain Jobredeaux    _assert_no_failures(
651*d6050574SRomain Jobredeaux        fake_env,
652*d6050574SRomain Jobredeaux        env = env,
653*d6050574SRomain Jobredeaux        msg = "check expected and actual with exact elements and order; 4 values",
654*d6050574SRomain Jobredeaux    )
655*d6050574SRomain Jobredeaux
656*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([
657*d6050574SRomain Jobredeaux        matching.contains("d"),
658*d6050574SRomain Jobredeaux        matching.contains("b"),
659*d6050574SRomain Jobredeaux        matching.contains("a"),
660*d6050574SRomain Jobredeaux        matching.contains("c"),
661*d6050574SRomain Jobredeaux    ])
662*d6050574SRomain Jobredeaux    _assert_no_failures(
663*d6050574SRomain Jobredeaux        fake_env,
664*d6050574SRomain Jobredeaux        env = env,
665*d6050574SRomain Jobredeaux        msg = "check expected and actual same elements and different order; 4 values",
666*d6050574SRomain Jobredeaux    )
667*d6050574SRomain Jobredeaux
668*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "a"])
669*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([
670*d6050574SRomain Jobredeaux        matching.contains("a"),
671*d6050574SRomain Jobredeaux        matching.contains("b"),
672*d6050574SRomain Jobredeaux        matching.contains("a"),
673*d6050574SRomain Jobredeaux    ])
674*d6050574SRomain Jobredeaux    _assert_no_failures(
675*d6050574SRomain Jobredeaux        fake_env,
676*d6050574SRomain Jobredeaux        env = env,
677*d6050574SRomain Jobredeaux        msg = "check multiplicity, same expected/actual order",
678*d6050574SRomain Jobredeaux    )
679*d6050574SRomain Jobredeaux
680*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([
681*d6050574SRomain Jobredeaux        matching.contains("b"),
682*d6050574SRomain Jobredeaux        matching.contains("a"),
683*d6050574SRomain Jobredeaux        matching.contains("a"),
684*d6050574SRomain Jobredeaux    ])
685*d6050574SRomain Jobredeaux    _assert_no_failures(
686*d6050574SRomain Jobredeaux        fake_env,
687*d6050574SRomain Jobredeaux        env = env,
688*d6050574SRomain Jobredeaux        msg = "check multiplicity; different expected/actual order",
689*d6050574SRomain Jobredeaux    )
690*d6050574SRomain Jobredeaux
691*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection([
692*d6050574SRomain Jobredeaux        "one",
693*d6050574SRomain Jobredeaux        "two",
694*d6050574SRomain Jobredeaux        "one",
695*d6050574SRomain Jobredeaux        "three",
696*d6050574SRomain Jobredeaux        "one",
697*d6050574SRomain Jobredeaux        "four",
698*d6050574SRomain Jobredeaux    ])
699*d6050574SRomain Jobredeaux
700*d6050574SRomain Jobredeaux    subject.contains_exactly_predicates([
701*d6050574SRomain Jobredeaux        matching.contains("one"),
702*d6050574SRomain Jobredeaux        matching.contains("two"),
703*d6050574SRomain Jobredeaux        matching.contains("three"),
704*d6050574SRomain Jobredeaux        matching.contains("five"),
705*d6050574SRomain Jobredeaux    ])
706*d6050574SRomain Jobredeaux    _assert_failure(
707*d6050574SRomain Jobredeaux        fake_env,
708*d6050574SRomain Jobredeaux        [
709*d6050574SRomain Jobredeaux            ("1 missing:\n" +
710*d6050574SRomain Jobredeaux             "  0: <contains five>"),
711*d6050574SRomain Jobredeaux            ("3 unexpected:\n" +
712*d6050574SRomain Jobredeaux             "  0: four\n" +
713*d6050574SRomain Jobredeaux             "  1: one\n" +
714*d6050574SRomain Jobredeaux             "  2: one\n"),
715*d6050574SRomain Jobredeaux            ("expected exactly:\n" +
716*d6050574SRomain Jobredeaux             "  0: <contains one>\n" +
717*d6050574SRomain Jobredeaux             "  1: <contains two>\n" +
718*d6050574SRomain Jobredeaux             "  2: <contains three>\n" +
719*d6050574SRomain Jobredeaux             "  3: <contains five>\n"),
720*d6050574SRomain Jobredeaux        ],
721*d6050574SRomain Jobredeaux        env = env,
722*d6050574SRomain Jobredeaux        msg = "check multiplicity; expected with multiple, expected with unique",
723*d6050574SRomain Jobredeaux    )
724*d6050574SRomain Jobredeaux    _end(env, fake_env)
725*d6050574SRomain Jobredeaux
726*d6050574SRomain Jobredeaux_suite.append(collection_contains_exactly_predicates_test)
727*d6050574SRomain Jobredeaux
728*d6050574SRomain Jobredeauxdef collection_contains_none_of_test(name):
729*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_contains_none_of_test, target = "truth_tests_helper")
730*d6050574SRomain Jobredeaux
731*d6050574SRomain Jobredeauxdef _collection_contains_none_of_test(env, _target):
732*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
733*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a"])
734*d6050574SRomain Jobredeaux
735*d6050574SRomain Jobredeaux    subject.contains_none_of(["b"])
736*d6050574SRomain Jobredeaux    _assert_no_failures(
737*d6050574SRomain Jobredeaux        fake_env,
738*d6050574SRomain Jobredeaux        env = env,
739*d6050574SRomain Jobredeaux        msg = "check actual contains none of",
740*d6050574SRomain Jobredeaux    )
741*d6050574SRomain Jobredeaux
742*d6050574SRomain Jobredeaux    subject.contains_none_of(["a"])
743*d6050574SRomain Jobredeaux    _assert_failure(
744*d6050574SRomain Jobredeaux        fake_env,
745*d6050574SRomain Jobredeaux        [
746*d6050574SRomain Jobredeaux            "expected not to contain any of:",
747*d6050574SRomain Jobredeaux            "  0: a",
748*d6050574SRomain Jobredeaux            "but 1 found",
749*d6050574SRomain Jobredeaux            "actual values:",
750*d6050574SRomain Jobredeaux        ],
751*d6050574SRomain Jobredeaux        env = env,
752*d6050574SRomain Jobredeaux        msg = "check actual contains an unexpected value",
753*d6050574SRomain Jobredeaux    )
754*d6050574SRomain Jobredeaux    _end(env, fake_env)
755*d6050574SRomain Jobredeaux
756*d6050574SRomain Jobredeaux_suite.append(collection_contains_none_of_test)
757*d6050574SRomain Jobredeaux
758*d6050574SRomain Jobredeauxdef collection_not_contains_test(name):
759*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_not_contains_test, target = "truth_tests_helper")
760*d6050574SRomain Jobredeaux
761*d6050574SRomain Jobredeauxdef _collection_not_contains_test(env, _target):
762*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
763*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a"])
764*d6050574SRomain Jobredeaux
765*d6050574SRomain Jobredeaux    subject.not_contains("b")
766*d6050574SRomain Jobredeaux    _assert_no_failures(
767*d6050574SRomain Jobredeaux        fake_env,
768*d6050574SRomain Jobredeaux        env = env,
769*d6050574SRomain Jobredeaux        msg = "check not_contains passes",
770*d6050574SRomain Jobredeaux    )
771*d6050574SRomain Jobredeaux    subject.not_contains("a")
772*d6050574SRomain Jobredeaux    _assert_failure(
773*d6050574SRomain Jobredeaux        fake_env,
774*d6050574SRomain Jobredeaux        [
775*d6050574SRomain Jobredeaux            "expected not to contain",
776*d6050574SRomain Jobredeaux            "0: a",
777*d6050574SRomain Jobredeaux        ],
778*d6050574SRomain Jobredeaux        env = env,
779*d6050574SRomain Jobredeaux        msg = "check not_contains fails",
780*d6050574SRomain Jobredeaux    )
781*d6050574SRomain Jobredeaux
782*d6050574SRomain Jobredeaux_suite.append(collection_not_contains_test)
783*d6050574SRomain Jobredeaux
784*d6050574SRomain Jobredeauxdef collection_not_contains_predicate_test(name):
785*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_not_contains_predicate_test, target = "truth_tests_helper")
786*d6050574SRomain Jobredeaux
787*d6050574SRomain Jobredeauxdef _collection_not_contains_predicate_test(env, _target):
788*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
789*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a"])
790*d6050574SRomain Jobredeaux
791*d6050574SRomain Jobredeaux    subject.not_contains_predicate(matching.contains("b"))
792*d6050574SRomain Jobredeaux    _assert_no_failures(
793*d6050574SRomain Jobredeaux        fake_env,
794*d6050574SRomain Jobredeaux        env = env,
795*d6050574SRomain Jobredeaux        msg = "check actual does not contain a value",
796*d6050574SRomain Jobredeaux    )
797*d6050574SRomain Jobredeaux
798*d6050574SRomain Jobredeaux    subject.not_contains_predicate(matching.contains("a"))
799*d6050574SRomain Jobredeaux    _assert_failure(
800*d6050574SRomain Jobredeaux        fake_env,
801*d6050574SRomain Jobredeaux        ["expected not to contain any of: <contains a>", "but 1 found:", "0: a"],
802*d6050574SRomain Jobredeaux        env = env,
803*d6050574SRomain Jobredeaux        msg = "check actual contains an unexpected value",
804*d6050574SRomain Jobredeaux    )
805*d6050574SRomain Jobredeaux    _end(env, fake_env)
806*d6050574SRomain Jobredeaux
807*d6050574SRomain Jobredeaux_suite.append(collection_not_contains_predicate_test)
808*d6050574SRomain Jobredeaux
809*d6050574SRomain Jobredeauxdef collection_offset_test(name):
810*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_offset_test, target = "truth_tests_helper")
811*d6050574SRomain Jobredeaux
812*d6050574SRomain Jobredeauxdef _collection_offset_test(env, _target):
813*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
814*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_collection(["a", "b", "c"])
815*d6050574SRomain Jobredeaux
816*d6050574SRomain Jobredeaux    offset_value = subject.offset(0, factory = lambda v, meta: v)
817*d6050574SRomain Jobredeaux    ut_asserts.true(env, offset_value == "a", "unexpected offset value at 0")
818*d6050574SRomain Jobredeaux
819*d6050574SRomain Jobredeaux    offset_value = subject.offset(-1, factory = lambda v, meta: v)
820*d6050574SRomain Jobredeaux    ut_asserts.true(env, offset_value == "c", "unexpected offset value at -1")
821*d6050574SRomain Jobredeaux
822*d6050574SRomain Jobredeaux    subject.offset(1, factory = subjects.str).equals("not-b")
823*d6050574SRomain Jobredeaux
824*d6050574SRomain Jobredeaux    _assert_failure(
825*d6050574SRomain Jobredeaux        fake_env,
826*d6050574SRomain Jobredeaux        [".offset(1)"],
827*d6050574SRomain Jobredeaux        env = env,
828*d6050574SRomain Jobredeaux        msg = "offset error message context not found",
829*d6050574SRomain Jobredeaux    )
830*d6050574SRomain Jobredeaux
831*d6050574SRomain Jobredeaux    _end(env, fake_env)
832*d6050574SRomain Jobredeaux
833*d6050574SRomain Jobredeaux_suite.append(collection_offset_test)
834*d6050574SRomain Jobredeaux
835*d6050574SRomain Jobredeauxdef _collection_transform_test(name):
836*d6050574SRomain Jobredeaux    analysis_test(name, impl = _collection_transform_test_impl, target = "truth_tests_helper")
837*d6050574SRomain Jobredeaux
838*d6050574SRomain Jobredeauxdef _collection_transform_test_impl(env, target):
839*d6050574SRomain Jobredeaux    _ = target  # @unused
840*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
841*d6050574SRomain Jobredeaux    starter = truth.expect(fake_env).that_collection(["alan", "bert", "cari"])
842*d6050574SRomain Jobredeaux
843*d6050574SRomain Jobredeaux    actual = starter.transform(
844*d6050574SRomain Jobredeaux        "values that contain a",
845*d6050574SRomain Jobredeaux        filter = lambda v: "a" in v,
846*d6050574SRomain Jobredeaux    )
847*d6050574SRomain Jobredeaux    actual.contains("not-present")
848*d6050574SRomain Jobredeaux    _assert_failure(
849*d6050574SRomain Jobredeaux        fake_env,
850*d6050574SRomain Jobredeaux        [
851*d6050574SRomain Jobredeaux            "transform()",
852*d6050574SRomain Jobredeaux            "0: alan",
853*d6050574SRomain Jobredeaux            "1: cari",
854*d6050574SRomain Jobredeaux            "transform: values that contain a",
855*d6050574SRomain Jobredeaux        ],
856*d6050574SRomain Jobredeaux        env = env,
857*d6050574SRomain Jobredeaux        msg = "transform with lambda filter",
858*d6050574SRomain Jobredeaux    )
859*d6050574SRomain Jobredeaux
860*d6050574SRomain Jobredeaux    actual = starter.transform(filter = matching.contains("b"))
861*d6050574SRomain Jobredeaux    actual.contains("not-present")
862*d6050574SRomain Jobredeaux    _assert_failure(
863*d6050574SRomain Jobredeaux        fake_env,
864*d6050574SRomain Jobredeaux        [
865*d6050574SRomain Jobredeaux            "0: bert",
866*d6050574SRomain Jobredeaux            "transform: filter=<contains b>",
867*d6050574SRomain Jobredeaux        ],
868*d6050574SRomain Jobredeaux        env = env,
869*d6050574SRomain Jobredeaux        msg = "transform with matcher filter",
870*d6050574SRomain Jobredeaux    )
871*d6050574SRomain Jobredeaux
872*d6050574SRomain Jobredeaux    def contains_c(v):
873*d6050574SRomain Jobredeaux        return "c" in v
874*d6050574SRomain Jobredeaux
875*d6050574SRomain Jobredeaux    actual = starter.transform(filter = contains_c)
876*d6050574SRomain Jobredeaux    actual.contains("not-present")
877*d6050574SRomain Jobredeaux    _assert_failure(
878*d6050574SRomain Jobredeaux        fake_env,
879*d6050574SRomain Jobredeaux        [
880*d6050574SRomain Jobredeaux            "0: cari",
881*d6050574SRomain Jobredeaux            "transform: filter=contains_c(...)",
882*d6050574SRomain Jobredeaux        ],
883*d6050574SRomain Jobredeaux        env = env,
884*d6050574SRomain Jobredeaux        msg = "transform with named function filter",
885*d6050574SRomain Jobredeaux    )
886*d6050574SRomain Jobredeaux
887*d6050574SRomain Jobredeaux    actual = starter.transform(
888*d6050574SRomain Jobredeaux        "v.upper(); match even offsets",
889*d6050574SRomain Jobredeaux        map_each = lambda v: "{}-{}".format(v[0], v[1].upper()),
890*d6050574SRomain Jobredeaux        loop = enumerate,
891*d6050574SRomain Jobredeaux    )
892*d6050574SRomain Jobredeaux    actual.contains("not-present")
893*d6050574SRomain Jobredeaux    _assert_failure(
894*d6050574SRomain Jobredeaux        fake_env,
895*d6050574SRomain Jobredeaux        [
896*d6050574SRomain Jobredeaux            "transform()",
897*d6050574SRomain Jobredeaux            "0: 0-ALAN",
898*d6050574SRomain Jobredeaux            "1: 1-BERT",
899*d6050574SRomain Jobredeaux            "2: 2-CARI",
900*d6050574SRomain Jobredeaux            "transform: v.upper(); match even offsets",
901*d6050574SRomain Jobredeaux        ],
902*d6050574SRomain Jobredeaux        env = env,
903*d6050574SRomain Jobredeaux        msg = "transform with all args",
904*d6050574SRomain Jobredeaux    )
905*d6050574SRomain Jobredeaux
906*d6050574SRomain Jobredeaux    _end(env, fake_env)
907*d6050574SRomain Jobredeaux
908*d6050574SRomain Jobredeaux_suite.append(_collection_transform_test)
909*d6050574SRomain Jobredeaux
910*d6050574SRomain Jobredeauxdef execution_info_test(name):
911*d6050574SRomain Jobredeaux    analysis_test(name, impl = _execution_info_test, target = "truth_tests_helper")
912*d6050574SRomain Jobredeaux
913*d6050574SRomain Jobredeauxdef _execution_info_test(env, target):
914*d6050574SRomain Jobredeaux    # TODO(rlevasseur): Remove this after cl/474597236 is released in Blaze
915*d6050574SRomain Jobredeaux    exec_info_is_ctor = str(testing.ExecutionInfo) == "<function ExecutionInfo>"
916*d6050574SRomain Jobredeaux    if not exec_info_is_ctor:
917*d6050574SRomain Jobredeaux        return
918*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
919*d6050574SRomain Jobredeaux
920*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target).provider(testing.ExecutionInfo)
921*d6050574SRomain Jobredeaux    subject.requirements().contains_exactly({"EIKEY1": "EIVALUE1"})
922*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
923*d6050574SRomain Jobredeaux    if _IS_BAZEL_6_OR_HIGHER:
924*d6050574SRomain Jobredeaux        subject.exec_group().equals("THE_EXEC_GROUP")
925*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
926*d6050574SRomain Jobredeaux    _end(env, fake_env)
927*d6050574SRomain Jobredeaux
928*d6050574SRomain Jobredeaux_suite.append(execution_info_test)
929*d6050574SRomain Jobredeaux
930*d6050574SRomain Jobredeauxdef depset_file_subject_test(name):
931*d6050574SRomain Jobredeaux    analysis_test(name, impl = _depset_file_subject_test, target = "truth_tests_data_files")
932*d6050574SRomain Jobredeaux
933*d6050574SRomain Jobredeauxdef _depset_file_subject_test(env, target):
934*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
935*d6050574SRomain Jobredeaux
936*d6050574SRomain Jobredeaux    # We go through a target so that the usual format_str kwargs are present.
937*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target).default_outputs()
938*d6050574SRomain Jobredeaux
939*d6050574SRomain Jobredeaux    # The CollectionSubject tests cover contains_at_least_predicates in
940*d6050574SRomain Jobredeaux    # more depth, so just do some basic tests here.
941*d6050574SRomain Jobredeaux    subject.contains_at_least_predicates([
942*d6050574SRomain Jobredeaux        matching.file_path_matches("txt"),
943*d6050574SRomain Jobredeaux    ])
944*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
945*d6050574SRomain Jobredeaux
946*d6050574SRomain Jobredeaux    subject.contains_at_least_predicates([
947*d6050574SRomain Jobredeaux        matching.file_path_matches("NOT THERE"),
948*d6050574SRomain Jobredeaux    ])
949*d6050574SRomain Jobredeaux    _assert_failure(
950*d6050574SRomain Jobredeaux        fake_env,
951*d6050574SRomain Jobredeaux        ["NOT THERE", "file1.txt"],
952*d6050574SRomain Jobredeaux        env = env,
953*d6050574SRomain Jobredeaux    )
954*d6050574SRomain Jobredeaux
955*d6050574SRomain Jobredeaux    subject.contains_predicate(matching.file_path_matches("txt"))
956*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
957*d6050574SRomain Jobredeaux    subject.contains_predicate(matching.file_path_matches("NOT THERE"))
958*d6050574SRomain Jobredeaux    _assert_failure(
959*d6050574SRomain Jobredeaux        fake_env,
960*d6050574SRomain Jobredeaux        ["NOT THERE", "file1.txt"],
961*d6050574SRomain Jobredeaux        env = env,
962*d6050574SRomain Jobredeaux    )
963*d6050574SRomain Jobredeaux
964*d6050574SRomain Jobredeaux    subject.contains_exactly(["{package}/testdata/file1.txt"])
965*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
966*d6050574SRomain Jobredeaux    subject.contains_exactly(["NOT THERE"])
967*d6050574SRomain Jobredeaux    _assert_failure(
968*d6050574SRomain Jobredeaux        fake_env,
969*d6050574SRomain Jobredeaux        ["NOT THERE", "file1.txt"],
970*d6050574SRomain Jobredeaux        env = env,
971*d6050574SRomain Jobredeaux    )
972*d6050574SRomain Jobredeaux
973*d6050574SRomain Jobredeaux    subject.not_contains("does-not-contain")
974*d6050574SRomain Jobredeaux    _assert_no_failures(
975*d6050574SRomain Jobredeaux        fake_env,
976*d6050574SRomain Jobredeaux        env = env,
977*d6050574SRomain Jobredeaux        msg = "DepsetFilesubject.not_contains success test",
978*d6050574SRomain Jobredeaux    )
979*d6050574SRomain Jobredeaux    subject.not_contains("{package}/testdata/file1.txt")
980*d6050574SRomain Jobredeaux    _assert_failure(
981*d6050574SRomain Jobredeaux        fake_env,
982*d6050574SRomain Jobredeaux        ["expected not to contain any of", "file1.txt"],
983*d6050574SRomain Jobredeaux        env = env,
984*d6050574SRomain Jobredeaux        msg = "DepsetFilesubject.not_contains failure test",
985*d6050574SRomain Jobredeaux    )
986*d6050574SRomain Jobredeaux
987*d6050574SRomain Jobredeaux    _end(env, fake_env)
988*d6050574SRomain Jobredeaux
989*d6050574SRomain Jobredeaux_suite.append(depset_file_subject_test)
990*d6050574SRomain Jobredeaux
991*d6050574SRomain Jobredeauxdef dict_subject_test(name):
992*d6050574SRomain Jobredeaux    analysis_test(name, impl = _dict_subject_test, target = "truth_tests_helper")
993*d6050574SRomain Jobredeaux
994*d6050574SRomain Jobredeauxdef _dict_subject_test(env, _target):
995*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
996*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_dict({"a": 1, "b": 2, "c": 3})
997*d6050574SRomain Jobredeaux
998*d6050574SRomain Jobredeaux    def factory(value, *, meta):
999*d6050574SRomain Jobredeaux        return struct(value = value, meta = meta)
1000*d6050574SRomain Jobredeaux
1001*d6050574SRomain Jobredeaux    actual = subject.get("a", factory = factory)
1002*d6050574SRomain Jobredeaux
1003*d6050574SRomain Jobredeaux    truth.expect(env).that_int(actual.value).equals(1)
1004*d6050574SRomain Jobredeaux    truth.expect(env).that_collection(actual.meta._exprs).contains("get(a)")
1005*d6050574SRomain Jobredeaux
1006*d6050574SRomain Jobredeaux    subject.contains_exactly({"a": 1, "b": 2, "c": 3})
1007*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1008*d6050574SRomain Jobredeaux
1009*d6050574SRomain Jobredeaux    subject.contains_exactly({"d": 4, "a": 99})
1010*d6050574SRomain Jobredeaux    _assert_failure(
1011*d6050574SRomain Jobredeaux        fake_env,
1012*d6050574SRomain Jobredeaux        [
1013*d6050574SRomain Jobredeaux            ("expected dict: {\n" +
1014*d6050574SRomain Jobredeaux             "  a: <int 99>\n" +
1015*d6050574SRomain Jobredeaux             "  d: <int 4>\n" +
1016*d6050574SRomain Jobredeaux             "}\n"),
1017*d6050574SRomain Jobredeaux            ("1 missing keys:\n" +
1018*d6050574SRomain Jobredeaux             "  0: d\n"),
1019*d6050574SRomain Jobredeaux            ("2 unexpected keys:\n" +
1020*d6050574SRomain Jobredeaux             "  0: b\n" +
1021*d6050574SRomain Jobredeaux             "  1: c\n"),
1022*d6050574SRomain Jobredeaux            ("1 incorrect entries:\n" +
1023*d6050574SRomain Jobredeaux             "key a:\n" +
1024*d6050574SRomain Jobredeaux             "  expected: 99\n" +
1025*d6050574SRomain Jobredeaux             "  but was : 1\n"),
1026*d6050574SRomain Jobredeaux            ("actual: {\n" +
1027*d6050574SRomain Jobredeaux             "  a: <int 1>\n" +
1028*d6050574SRomain Jobredeaux             "  b: <int 2>\n" +
1029*d6050574SRomain Jobredeaux             "  c: <int 3>\n" +
1030*d6050574SRomain Jobredeaux             "}\n"),
1031*d6050574SRomain Jobredeaux        ],
1032*d6050574SRomain Jobredeaux        env = env,
1033*d6050574SRomain Jobredeaux    )
1034*d6050574SRomain Jobredeaux
1035*d6050574SRomain Jobredeaux    subject.contains_at_least({"a": 1})
1036*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1037*d6050574SRomain Jobredeaux
1038*d6050574SRomain Jobredeaux    subject.contains_at_least({"d": 91, "a": 74})
1039*d6050574SRomain Jobredeaux    _assert_failure(
1040*d6050574SRomain Jobredeaux        fake_env,
1041*d6050574SRomain Jobredeaux        [
1042*d6050574SRomain Jobredeaux            ("expected dict: {\n" +
1043*d6050574SRomain Jobredeaux             "  a: <int 74>\n" +
1044*d6050574SRomain Jobredeaux             "  d: <int 91>\n" +
1045*d6050574SRomain Jobredeaux             "}\n"),
1046*d6050574SRomain Jobredeaux            ("1 missing keys:\n" +
1047*d6050574SRomain Jobredeaux             "  0: d\n"),
1048*d6050574SRomain Jobredeaux            ("1 incorrect entries:\n" +
1049*d6050574SRomain Jobredeaux             "key a:\n" +
1050*d6050574SRomain Jobredeaux             "  expected: 74\n" +
1051*d6050574SRomain Jobredeaux             "  but was : 1\n"),
1052*d6050574SRomain Jobredeaux            ("actual: {\n" +
1053*d6050574SRomain Jobredeaux             "  a: <int 1>\n" +
1054*d6050574SRomain Jobredeaux             "  b: <int 2>\n" +
1055*d6050574SRomain Jobredeaux             "  c: <int 3>\n" +
1056*d6050574SRomain Jobredeaux             "}\n"),
1057*d6050574SRomain Jobredeaux        ],
1058*d6050574SRomain Jobredeaux        env = env,
1059*d6050574SRomain Jobredeaux    )
1060*d6050574SRomain Jobredeaux
1061*d6050574SRomain Jobredeaux    # NOTE: we use the real env for this, since we're doing a real assert
1062*d6050574SRomain Jobredeaux    truth.expect(env).that_collection(
1063*d6050574SRomain Jobredeaux        subject.keys().actual,
1064*d6050574SRomain Jobredeaux    ).contains_exactly(["a", "b", "c"])
1065*d6050574SRomain Jobredeaux
1066*d6050574SRomain Jobredeaux    _end(env, fake_env)
1067*d6050574SRomain Jobredeaux
1068*d6050574SRomain Jobredeaux_suite.append(dict_subject_test)
1069*d6050574SRomain Jobredeaux
1070*d6050574SRomain Jobredeauxdef expect_test(name):
1071*d6050574SRomain Jobredeaux    analysis_test(name, impl = _expect_test, target = "truth_tests_helper")
1072*d6050574SRomain Jobredeaux
1073*d6050574SRomain Jobredeauxdef _expect_test(env, target):
1074*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1075*d6050574SRomain Jobredeaux    expect = truth.expect(fake_env)
1076*d6050574SRomain Jobredeaux
1077*d6050574SRomain Jobredeaux    ut_asserts.true(
1078*d6050574SRomain Jobredeaux        env,
1079*d6050574SRomain Jobredeaux        expect.that_target(target) != None,
1080*d6050574SRomain Jobredeaux        msg = "expect.that_target",
1081*d6050574SRomain Jobredeaux    )
1082*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1083*d6050574SRomain Jobredeaux
1084*d6050574SRomain Jobredeaux    expect.where(
1085*d6050574SRomain Jobredeaux        foo = "bar",
1086*d6050574SRomain Jobredeaux        baz = "qux",
1087*d6050574SRomain Jobredeaux    ).that_bool(True).equals(False)
1088*d6050574SRomain Jobredeaux    _assert_failure(
1089*d6050574SRomain Jobredeaux        fake_env,
1090*d6050574SRomain Jobredeaux        ["foo: bar", "baz: qux"],
1091*d6050574SRomain Jobredeaux        env = env,
1092*d6050574SRomain Jobredeaux    )
1093*d6050574SRomain Jobredeaux    _end(env, fake_env)
1094*d6050574SRomain Jobredeaux
1095*d6050574SRomain Jobredeaux_suite.append(expect_test)
1096*d6050574SRomain Jobredeaux
1097*d6050574SRomain Jobredeauxdef file_subject_test(name):
1098*d6050574SRomain Jobredeaux    analysis_test(name, impl = _file_subject_test, target = "truth_tests_data_files")
1099*d6050574SRomain Jobredeaux
1100*d6050574SRomain Jobredeauxdef _file_subject_test(env, target):
1101*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1102*d6050574SRomain Jobredeaux    package = target.label.package
1103*d6050574SRomain Jobredeaux    expect = truth.expect(fake_env)
1104*d6050574SRomain Jobredeaux    subject = expect.that_file(target.files.to_list()[0])
1105*d6050574SRomain Jobredeaux    subject.short_path_equals(package + "/testdata/file1.txt")
1106*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1107*d6050574SRomain Jobredeaux
1108*d6050574SRomain Jobredeaux    subject.short_path_equals("landon-and-hope-forever.txt")
1109*d6050574SRomain Jobredeaux    _assert_failure(
1110*d6050574SRomain Jobredeaux        fake_env,
1111*d6050574SRomain Jobredeaux        [
1112*d6050574SRomain Jobredeaux            "value of: file",
1113*d6050574SRomain Jobredeaux            "expected: landon-and-hope-forever.txt",
1114*d6050574SRomain Jobredeaux            "actual: {}/testdata/file1.txt".format(package),
1115*d6050574SRomain Jobredeaux        ],
1116*d6050574SRomain Jobredeaux        env = env,
1117*d6050574SRomain Jobredeaux    )
1118*d6050574SRomain Jobredeaux
1119*d6050574SRomain Jobredeaux    subject = expect.that_file(
1120*d6050574SRomain Jobredeaux        target.files.to_list()[0],
1121*d6050574SRomain Jobredeaux        meta = expect.meta.derive(
1122*d6050574SRomain Jobredeaux            format_str_kwargs = {"custom": "file1.txt"},
1123*d6050574SRomain Jobredeaux        ),
1124*d6050574SRomain Jobredeaux    )
1125*d6050574SRomain Jobredeaux
1126*d6050574SRomain Jobredeaux    # NOTE: We purposefully don't use `{package}` because we're just
1127*d6050574SRomain Jobredeaux    # testing the `{custom}` keyword
1128*d6050574SRomain Jobredeaux    subject.short_path_equals(package + "/testdata/{custom}")
1129*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1130*d6050574SRomain Jobredeaux
1131*d6050574SRomain Jobredeaux    _end(env, fake_env)
1132*d6050574SRomain Jobredeaux
1133*d6050574SRomain Jobredeaux_suite.append(file_subject_test)
1134*d6050574SRomain Jobredeaux
1135*d6050574SRomain Jobredeauxdef label_subject_test(name):
1136*d6050574SRomain Jobredeaux    analysis_test(name, impl = _label_subject_test, target = "truth_tests_helper")
1137*d6050574SRomain Jobredeaux
1138*d6050574SRomain Jobredeauxdef _label_subject_test(env, target):
1139*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1140*d6050574SRomain Jobredeaux
1141*d6050574SRomain Jobredeaux    expect = truth.expect(fake_env)
1142*d6050574SRomain Jobredeaux    subject = expect.that_target(target).label()
1143*d6050574SRomain Jobredeaux
1144*d6050574SRomain Jobredeaux    subject.equals("//tests:truth_tests_helper")
1145*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1146*d6050574SRomain Jobredeaux
1147*d6050574SRomain Jobredeaux    subject.equals(Label("//tests:truth_tests_helper"))
1148*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1149*d6050574SRomain Jobredeaux
1150*d6050574SRomain Jobredeaux    subject.equals("//nope")
1151*d6050574SRomain Jobredeaux    _assert_failure(
1152*d6050574SRomain Jobredeaux        fake_env,
1153*d6050574SRomain Jobredeaux        ["expected: " + str(Label("//nope")), "actual:", "_helper"],
1154*d6050574SRomain Jobredeaux        env = env,
1155*d6050574SRomain Jobredeaux    )
1156*d6050574SRomain Jobredeaux
1157*d6050574SRomain Jobredeaux    subject = subjects.label(Label("//some/pkg:label"), expect.meta)
1158*d6050574SRomain Jobredeaux    subject.is_in(["//foo:bar", "//some/pkg:label"])
1159*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, msg = "is_in with matched str values", env = env)
1160*d6050574SRomain Jobredeaux    subject.is_in([Label("//bar:baz"), Label("//some/pkg:label")])
1161*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, msg = "is_in with matched label values", env = env)
1162*d6050574SRomain Jobredeaux    subject.is_in(["//not:there", Label("//other:value")])
1163*d6050574SRomain Jobredeaux    _assert_failure(
1164*d6050574SRomain Jobredeaux        fake_env,
1165*d6050574SRomain Jobredeaux        [
1166*d6050574SRomain Jobredeaux            "expected any of:",
1167*d6050574SRomain Jobredeaux            "//not:there",
1168*d6050574SRomain Jobredeaux            "//other:value",
1169*d6050574SRomain Jobredeaux            "actual: " + str(Label("//some/pkg:label")),
1170*d6050574SRomain Jobredeaux        ],
1171*d6050574SRomain Jobredeaux        msg = "check is_in fails",
1172*d6050574SRomain Jobredeaux        env = env,
1173*d6050574SRomain Jobredeaux    )
1174*d6050574SRomain Jobredeaux
1175*d6050574SRomain Jobredeaux    _end(env, fake_env)
1176*d6050574SRomain Jobredeaux
1177*d6050574SRomain Jobredeaux_suite.append(label_subject_test)
1178*d6050574SRomain Jobredeaux
1179*d6050574SRomain Jobredeauxdef runfiles_subject_test(name):
1180*d6050574SRomain Jobredeaux    analysis_test(name, impl = _runfiles_subject_test, target = "truth_tests_helper")
1181*d6050574SRomain Jobredeaux
1182*d6050574SRomain Jobredeauxdef _runfiles_subject_test(env, target):
1183*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1184*d6050574SRomain Jobredeaux
1185*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target).runfiles()
1186*d6050574SRomain Jobredeaux    subject.contains("{workspace}/{package}/default_runfile1.txt")
1187*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1188*d6050574SRomain Jobredeaux
1189*d6050574SRomain Jobredeaux    subject.contains("does-not-exist")
1190*d6050574SRomain Jobredeaux    _assert_failure(
1191*d6050574SRomain Jobredeaux        fake_env,
1192*d6050574SRomain Jobredeaux        [
1193*d6050574SRomain Jobredeaux            "expected to contain: does-not-exist",
1194*d6050574SRomain Jobredeaux            "actual default runfiles:",
1195*d6050574SRomain Jobredeaux            "default_runfile1.txt",
1196*d6050574SRomain Jobredeaux            "target: ".format(target.label),
1197*d6050574SRomain Jobredeaux        ],
1198*d6050574SRomain Jobredeaux        env = env,
1199*d6050574SRomain Jobredeaux        msg = "check contains",
1200*d6050574SRomain Jobredeaux    )
1201*d6050574SRomain Jobredeaux
1202*d6050574SRomain Jobredeaux    subject.contains_none_of(["{workspace}/{package}/not-there.txt"])
1203*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1204*d6050574SRomain Jobredeaux
1205*d6050574SRomain Jobredeaux    subject.contains_none_of(["{workspace}/{package}/default_runfile1.txt"])
1206*d6050574SRomain Jobredeaux    _assert_failure(
1207*d6050574SRomain Jobredeaux        fake_env,
1208*d6050574SRomain Jobredeaux        [
1209*d6050574SRomain Jobredeaux            "expected not to contain any of",
1210*d6050574SRomain Jobredeaux            "default_runfile1.txt",
1211*d6050574SRomain Jobredeaux            env.ctx.workspace_name,
1212*d6050574SRomain Jobredeaux        ],
1213*d6050574SRomain Jobredeaux        env = env,
1214*d6050574SRomain Jobredeaux        msg = "check contains none of",
1215*d6050574SRomain Jobredeaux    )
1216*d6050574SRomain Jobredeaux
1217*d6050574SRomain Jobredeaux    subject.contains_exactly([
1218*d6050574SRomain Jobredeaux        "{workspace}/{package}/default_runfile1.txt",
1219*d6050574SRomain Jobredeaux        "{workspace}/{package}/truth_tests_helper.txt",
1220*d6050574SRomain Jobredeaux    ])
1221*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1222*d6050574SRomain Jobredeaux    subject.contains_exactly([
1223*d6050574SRomain Jobredeaux        "{workspace}/{package}/not-there.txt",
1224*d6050574SRomain Jobredeaux    ])
1225*d6050574SRomain Jobredeaux    _assert_failure(
1226*d6050574SRomain Jobredeaux        fake_env,
1227*d6050574SRomain Jobredeaux        [
1228*d6050574SRomain Jobredeaux            "1 missing",
1229*d6050574SRomain Jobredeaux            "not-there.txt",
1230*d6050574SRomain Jobredeaux            env.ctx.workspace_name,
1231*d6050574SRomain Jobredeaux        ],
1232*d6050574SRomain Jobredeaux        env = env,
1233*d6050574SRomain Jobredeaux        msg = "check contains_exactly fails",
1234*d6050574SRomain Jobredeaux    )
1235*d6050574SRomain Jobredeaux
1236*d6050574SRomain Jobredeaux    subject.contains_at_least([
1237*d6050574SRomain Jobredeaux        "{workspace}/{package}/default_runfile1.txt",
1238*d6050574SRomain Jobredeaux    ])
1239*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1240*d6050574SRomain Jobredeaux    subject.contains_at_least([
1241*d6050574SRomain Jobredeaux        "not-there.txt",
1242*d6050574SRomain Jobredeaux    ])
1243*d6050574SRomain Jobredeaux    _assert_failure(
1244*d6050574SRomain Jobredeaux        fake_env,
1245*d6050574SRomain Jobredeaux        [
1246*d6050574SRomain Jobredeaux            "1 expected paths missing",
1247*d6050574SRomain Jobredeaux            "not-there.txt",
1248*d6050574SRomain Jobredeaux            env.ctx.workspace_name,
1249*d6050574SRomain Jobredeaux        ],
1250*d6050574SRomain Jobredeaux        env = env,
1251*d6050574SRomain Jobredeaux        msg = "check contains_at_least fails",
1252*d6050574SRomain Jobredeaux    )
1253*d6050574SRomain Jobredeaux
1254*d6050574SRomain Jobredeaux    _end(env, fake_env)
1255*d6050574SRomain Jobredeaux
1256*d6050574SRomain Jobredeaux_suite.append(runfiles_subject_test)
1257*d6050574SRomain Jobredeaux
1258*d6050574SRomain Jobredeauxdef str_subject_test(name):
1259*d6050574SRomain Jobredeaux    analysis_test(name, impl = _str_subject_test, target = "truth_tests_helper")
1260*d6050574SRomain Jobredeaux
1261*d6050574SRomain Jobredeauxdef _str_subject_test(env, _target):
1262*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1263*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_str("foobar")
1264*d6050574SRomain Jobredeaux
1265*d6050574SRomain Jobredeaux    subject.contains("ob")
1266*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1267*d6050574SRomain Jobredeaux
1268*d6050574SRomain Jobredeaux    subject.contains("nope")
1269*d6050574SRomain Jobredeaux    _assert_failure(
1270*d6050574SRomain Jobredeaux        fake_env,
1271*d6050574SRomain Jobredeaux        ["expected to contain: nope", "actual: foobar"],
1272*d6050574SRomain Jobredeaux        env = env,
1273*d6050574SRomain Jobredeaux        msg = "check contains",
1274*d6050574SRomain Jobredeaux    )
1275*d6050574SRomain Jobredeaux
1276*d6050574SRomain Jobredeaux    subject.equals("foobar")
1277*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1278*d6050574SRomain Jobredeaux
1279*d6050574SRomain Jobredeaux    subject.equals("not foobar")
1280*d6050574SRomain Jobredeaux    _assert_failure(
1281*d6050574SRomain Jobredeaux        fake_env,
1282*d6050574SRomain Jobredeaux        ["expected: not foobar", "actual: foobar"],
1283*d6050574SRomain Jobredeaux        env = env,
1284*d6050574SRomain Jobredeaux        msg = "check equals",
1285*d6050574SRomain Jobredeaux    )
1286*d6050574SRomain Jobredeaux
1287*d6050574SRomain Jobredeaux    result = subject.split("b")
1288*d6050574SRomain Jobredeaux    ut_asserts.true(env, result.actual == ["foo", "ar"], "incorrectly split")
1289*d6050574SRomain Jobredeaux
1290*d6050574SRomain Jobredeaux    subject.not_equals("foobar")
1291*d6050574SRomain Jobredeaux    _assert_failure(
1292*d6050574SRomain Jobredeaux        fake_env,
1293*d6050574SRomain Jobredeaux        ["expected not to be: foobar", "actual: foobar"],
1294*d6050574SRomain Jobredeaux        env = env,
1295*d6050574SRomain Jobredeaux        msg = "check not_equals with equal value",
1296*d6050574SRomain Jobredeaux    )
1297*d6050574SRomain Jobredeaux    subject.not_equals(47)
1298*d6050574SRomain Jobredeaux    _assert_failure(
1299*d6050574SRomain Jobredeaux        fake_env,
1300*d6050574SRomain Jobredeaux        ["expected not to be: 47 (type: int)", "actual: foobar (type: string)"],
1301*d6050574SRomain Jobredeaux        env = env,
1302*d6050574SRomain Jobredeaux        msg = "check not_equals with different type",
1303*d6050574SRomain Jobredeaux    )
1304*d6050574SRomain Jobredeaux    subject.not_equals("not-foobar")
1305*d6050574SRomain Jobredeaux    _assert_no_failures(
1306*d6050574SRomain Jobredeaux        fake_env,
1307*d6050574SRomain Jobredeaux        env = env,
1308*d6050574SRomain Jobredeaux        msg = "check not_equals with unequal value of same type",
1309*d6050574SRomain Jobredeaux    )
1310*d6050574SRomain Jobredeaux
1311*d6050574SRomain Jobredeaux    subject.is_in(["xxx", "yyy", "zzz"])
1312*d6050574SRomain Jobredeaux    _assert_failure(
1313*d6050574SRomain Jobredeaux        fake_env,
1314*d6050574SRomain Jobredeaux        ["expected any of:", "xxx", "yyy", "zzz", "actual: foobar"],
1315*d6050574SRomain Jobredeaux        env = env,
1316*d6050574SRomain Jobredeaux        msg = "check is_in with non-matching values",
1317*d6050574SRomain Jobredeaux    )
1318*d6050574SRomain Jobredeaux    subject.is_in(["foobar", "y", "z"])
1319*d6050574SRomain Jobredeaux    _assert_no_failures(
1320*d6050574SRomain Jobredeaux        fake_env,
1321*d6050574SRomain Jobredeaux        env = env,
1322*d6050574SRomain Jobredeaux        msg = "check is_in with matching values",
1323*d6050574SRomain Jobredeaux    )
1324*d6050574SRomain Jobredeaux    _end(env, fake_env)
1325*d6050574SRomain Jobredeaux
1326*d6050574SRomain Jobredeaux_suite.append(str_subject_test)
1327*d6050574SRomain Jobredeaux
1328*d6050574SRomain Jobredeauxdef target_subject_test(name):
1329*d6050574SRomain Jobredeaux    analysis_test(name, impl = _target_subject_test, target = "truth_tests_helper")  #TODO also file target
1330*d6050574SRomain Jobredeaux
1331*d6050574SRomain Jobredeauxdef _target_subject_test(env, target):
1332*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1333*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target)
1334*d6050574SRomain Jobredeaux
1335*d6050574SRomain Jobredeaux    # First a static string, no formatting parameters
1336*d6050574SRomain Jobredeaux    result = subject.action_generating("{package}/default_runfile1.txt")
1337*d6050574SRomain Jobredeaux    ut_asserts.true(env, result != None, msg = "action_generating gave None")
1338*d6050574SRomain Jobredeaux
1339*d6050574SRomain Jobredeaux    # Now try it with formatting parameters
1340*d6050574SRomain Jobredeaux    result = subject.action_generating("{package}/{name}.txt")
1341*d6050574SRomain Jobredeaux    ut_asserts.true(env, result != None, msg = "action_generating gave None")
1342*d6050574SRomain Jobredeaux
1343*d6050574SRomain Jobredeaux    result = subject.label()
1344*d6050574SRomain Jobredeaux    ut_asserts.true(env, result != None, msg = "label gave None")
1345*d6050574SRomain Jobredeaux
1346*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target)
1347*d6050574SRomain Jobredeaux
1348*d6050574SRomain Jobredeaux    tags = subject.tags()
1349*d6050574SRomain Jobredeaux    ut_asserts.true(env, tags != None, msg = "tags gave None")
1350*d6050574SRomain Jobredeaux
1351*d6050574SRomain Jobredeaux    tags.contains_exactly(["tag1", "tag2"])
1352*d6050574SRomain Jobredeaux    _assert_no_failures(
1353*d6050574SRomain Jobredeaux        fake_env,
1354*d6050574SRomain Jobredeaux        env = env,
1355*d6050574SRomain Jobredeaux        msg = "check TargetSubject.tags()",
1356*d6050574SRomain Jobredeaux    )
1357*d6050574SRomain Jobredeaux
1358*d6050574SRomain Jobredeaux    attr_subject = subject.attr("testonly")
1359*d6050574SRomain Jobredeaux    ut_asserts.true(env, attr_subject != None, msg = "attr(testonly) gave None")
1360*d6050574SRomain Jobredeaux
1361*d6050574SRomain Jobredeaux    custom_subject = subject.attr(
1362*d6050574SRomain Jobredeaux        "testonly",
1363*d6050574SRomain Jobredeaux        factory = lambda v, meta: struct(custom = True),
1364*d6050574SRomain Jobredeaux    )
1365*d6050574SRomain Jobredeaux    ut_asserts.true(
1366*d6050574SRomain Jobredeaux        env,
1367*d6050574SRomain Jobredeaux        custom_subject.custom == True,
1368*d6050574SRomain Jobredeaux        msg = "attr() with custom factory gave wrong value",
1369*d6050574SRomain Jobredeaux    )
1370*d6050574SRomain Jobredeaux
1371*d6050574SRomain Jobredeaux    output_group_subject = subject.output_group("some_group")
1372*d6050574SRomain Jobredeaux    output_group_subject.contains("{package}/output_group_file.txt")
1373*d6050574SRomain Jobredeaux    _assert_no_failures(
1374*d6050574SRomain Jobredeaux        fake_env,
1375*d6050574SRomain Jobredeaux        env = env,
1376*d6050574SRomain Jobredeaux        msg = "check TargetSubject.output_group()",
1377*d6050574SRomain Jobredeaux    )
1378*d6050574SRomain Jobredeaux
1379*d6050574SRomain Jobredeaux    _end(env, fake_env)
1380*d6050574SRomain Jobredeaux
1381*d6050574SRomain Jobredeaux_suite.append(target_subject_test)
1382*d6050574SRomain Jobredeaux
1383*d6050574SRomain Jobredeauxdef run_environment_info_subject_test(name):
1384*d6050574SRomain Jobredeaux    analysis_test(name, impl = _run_environment_info_subject_test, target = "truth_tests_helper")
1385*d6050574SRomain Jobredeaux
1386*d6050574SRomain Jobredeauxdef _run_environment_info_subject_test(env, target):
1387*d6050574SRomain Jobredeaux    fake_env = _fake_env(env)
1388*d6050574SRomain Jobredeaux
1389*d6050574SRomain Jobredeaux    subject = truth.expect(fake_env).that_target(target).provider(
1390*d6050574SRomain Jobredeaux        RunEnvironmentInfo,
1391*d6050574SRomain Jobredeaux    )
1392*d6050574SRomain Jobredeaux
1393*d6050574SRomain Jobredeaux    subject.environment().contains_exactly({
1394*d6050574SRomain Jobredeaux        "EKEY1": "EVALUE1",
1395*d6050574SRomain Jobredeaux        "EKEY2": "EVALUE2",
1396*d6050574SRomain Jobredeaux    })
1397*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1398*d6050574SRomain Jobredeaux
1399*d6050574SRomain Jobredeaux    subject.inherited_environment().contains_exactly(["INHERIT1", "INHERIT2"])
1400*d6050574SRomain Jobredeaux    _assert_no_failures(fake_env, env = env)
1401*d6050574SRomain Jobredeaux
1402*d6050574SRomain Jobredeaux    _end(env, fake_env)
1403*d6050574SRomain Jobredeaux
1404*d6050574SRomain Jobredeaux_suite.append(run_environment_info_subject_test)
1405*d6050574SRomain Jobredeaux
1406*d6050574SRomain Jobredeauxdef _add_failure_works_test(name):
1407*d6050574SRomain Jobredeaux    analysis_test(
1408*d6050574SRomain Jobredeaux        name,
1409*d6050574SRomain Jobredeaux        impl = _add_failure_works_test_impl,
1410*d6050574SRomain Jobredeaux        target = "truth_tests_noop",
1411*d6050574SRomain Jobredeaux        expect_failure = True,
1412*d6050574SRomain Jobredeaux    )
1413*d6050574SRomain Jobredeaux
1414*d6050574SRomain Jobredeauxdef _add_failure_works_test_impl(env, target):
1415*d6050574SRomain Jobredeaux    """Test that the real add_failure() codepath works.
1416*d6050574SRomain Jobredeaux
1417*d6050574SRomain Jobredeaux    All the other tests mock out the fail() call, this is the one test that doesn't.
1418*d6050574SRomain Jobredeaux    """
1419*d6050574SRomain Jobredeaux    _ = target  # @unused
1420*d6050574SRomain Jobredeaux
1421*d6050574SRomain Jobredeaux    # NOTE: this prints a spurious message.
1422*d6050574SRomain Jobredeaux    env.expect.meta.add_failure("FAKE PROBLEM", "FAKE ACTUAL")
1423*d6050574SRomain Jobredeaux
1424*d6050574SRomain Jobredeaux    failures = list(env._failures)
1425*d6050574SRomain Jobredeaux    env._failures.clear()
1426*d6050574SRomain Jobredeaux
1427*d6050574SRomain Jobredeaux    if len(failures) != 1:
1428*d6050574SRomain Jobredeaux        env.fail("Expected len(failures) == 1, got " + str(len(failures)))
1429*d6050574SRomain Jobredeaux    else:
1430*d6050574SRomain Jobredeaux        failure = failures[0]
1431*d6050574SRomain Jobredeaux        if "FAKE PROBLEM" not in failure:
1432*d6050574SRomain Jobredeaux            env.fail("Expected string 'FAKE PROBLEM' not found in failure message")
1433*d6050574SRomain Jobredeaux        if "FAKE ACTUAL" not in failure:
1434*d6050574SRomain Jobredeaux            env.fail("Expected string 'FAKE ACTUAL' not found in failure message")
1435*d6050574SRomain Jobredeaux
1436*d6050574SRomain Jobredeaux_suite.append(_add_failure_works_test)
1437*d6050574SRomain Jobredeaux
1438*d6050574SRomain Jobredeauxdef _assert_no_failures(fake_env, *, env, msg = ""):
1439*d6050574SRomain Jobredeaux    fail_lines = [
1440*d6050574SRomain Jobredeaux        "expected no failures, but found failures",
1441*d6050574SRomain Jobredeaux        msg,
1442*d6050574SRomain Jobredeaux        "===== FAILURE MESSAGES =====",
1443*d6050574SRomain Jobredeaux    ]
1444*d6050574SRomain Jobredeaux    fail_lines.extend(fake_env.failures)
1445*d6050574SRomain Jobredeaux    fail_lines.append("===== END FAILURE MESSAGES ====")
1446*d6050574SRomain Jobredeaux    fail_msg = "\n".join(fail_lines)
1447*d6050574SRomain Jobredeaux    ut_asserts.true(env, len(fake_env.failures) == 0, msg = fail_msg)
1448*d6050574SRomain Jobredeaux    fake_env.reset()
1449*d6050574SRomain Jobredeaux
1450*d6050574SRomain Jobredeauxdef _assert_failure(fake_env, expected_strs, *, env, msg = ""):
1451*d6050574SRomain Jobredeaux    if len(fake_env.failures) != 1:
1452*d6050574SRomain Jobredeaux        env.fail("expected exactly 1 failure, but found {}".format(len(fake_env.failures)))
1453*d6050574SRomain Jobredeaux
1454*d6050574SRomain Jobredeaux    if len(fake_env.failures) > 0:
1455*d6050574SRomain Jobredeaux        failure = fake_env.failures[0]
1456*d6050574SRomain Jobredeaux        for expected in expected_strs:
1457*d6050574SRomain Jobredeaux            if expected not in failure:
1458*d6050574SRomain Jobredeaux                env.fail((
1459*d6050574SRomain Jobredeaux                    "\nFailure message incorrect:\n{}\n" +
1460*d6050574SRomain Jobredeaux                    "===== EXPECTED ERROR SUBSTRING =====\n{}\n" +
1461*d6050574SRomain Jobredeaux                    "===== END EXPECTED ERROR SUBSTRING =====\n" +
1462*d6050574SRomain Jobredeaux                    "===== ACTUAL FAILURE MESSAGE =====\n{}\n" +
1463*d6050574SRomain Jobredeaux                    "===== END ACTUAL FAILURE MESSAGE ====="
1464*d6050574SRomain Jobredeaux                ).format(
1465*d6050574SRomain Jobredeaux                    msg,
1466*d6050574SRomain Jobredeaux                    expected,
1467*d6050574SRomain Jobredeaux                    failure,
1468*d6050574SRomain Jobredeaux                ))
1469*d6050574SRomain Jobredeaux
1470*d6050574SRomain Jobredeaux    fake_env.reset()
1471*d6050574SRomain Jobredeaux
1472*d6050574SRomain Jobredeauxdef _test_helper_impl(ctx):
1473*d6050574SRomain Jobredeaux    action_output = ctx.actions.declare_file("action.txt")
1474*d6050574SRomain Jobredeaux    ctx.actions.run(
1475*d6050574SRomain Jobredeaux        outputs = [action_output],
1476*d6050574SRomain Jobredeaux        executable = ctx.executable.tool,
1477*d6050574SRomain Jobredeaux        arguments = [
1478*d6050574SRomain Jobredeaux            "arg1",
1479*d6050574SRomain Jobredeaux            "--boolflag",
1480*d6050574SRomain Jobredeaux            "--arg1flag",
1481*d6050574SRomain Jobredeaux            "arg1value",
1482*d6050574SRomain Jobredeaux            "--arg2flag=arg2value",
1483*d6050574SRomain Jobredeaux        ],
1484*d6050574SRomain Jobredeaux        mnemonic = "Action1",
1485*d6050574SRomain Jobredeaux    )
1486*d6050574SRomain Jobredeaux    if _IS_BAZEL_6_OR_HIGHER:
1487*d6050574SRomain Jobredeaux        exec_info_bazel_6_kwargs = {"exec_group": "THE_EXEC_GROUP"}
1488*d6050574SRomain Jobredeaux    else:
1489*d6050574SRomain Jobredeaux        exec_info_bazel_6_kwargs = {}
1490*d6050574SRomain Jobredeaux
1491*d6050574SRomain Jobredeaux    return [
1492*d6050574SRomain Jobredeaux        DefaultInfo(
1493*d6050574SRomain Jobredeaux            default_runfiles = ctx.runfiles(
1494*d6050574SRomain Jobredeaux                files = [
1495*d6050574SRomain Jobredeaux                    _empty_file(ctx, "default_runfile1.txt"),
1496*d6050574SRomain Jobredeaux                    _empty_file(ctx, ctx.label.name + ".txt"),
1497*d6050574SRomain Jobredeaux                ],
1498*d6050574SRomain Jobredeaux            ),
1499*d6050574SRomain Jobredeaux        ),
1500*d6050574SRomain Jobredeaux        testing.TestEnvironment(
1501*d6050574SRomain Jobredeaux            environment = {"EKEY1": "EVALUE1", "EKEY2": "EVALUE2"},
1502*d6050574SRomain Jobredeaux            inherited_environment = ["INHERIT1", "INHERIT2"],
1503*d6050574SRomain Jobredeaux        ),
1504*d6050574SRomain Jobredeaux        testing.ExecutionInfo({"EIKEY1": "EIVALUE1"}, **exec_info_bazel_6_kwargs),
1505*d6050574SRomain Jobredeaux        OutputGroupInfo(
1506*d6050574SRomain Jobredeaux            some_group = depset([_empty_file(ctx, "output_group_file.txt")]),
1507*d6050574SRomain Jobredeaux        ),
1508*d6050574SRomain Jobredeaux    ]
1509*d6050574SRomain Jobredeaux
1510*d6050574SRomain Jobredeauxtest_helper = rule(
1511*d6050574SRomain Jobredeaux    implementation = _test_helper_impl,
1512*d6050574SRomain Jobredeaux    attrs = {
1513*d6050574SRomain Jobredeaux        "tool": attr.label(
1514*d6050574SRomain Jobredeaux            default = ":truth_tests_noop",
1515*d6050574SRomain Jobredeaux            executable = True,
1516*d6050574SRomain Jobredeaux            cfg = "exec",
1517*d6050574SRomain Jobredeaux        ),
1518*d6050574SRomain Jobredeaux    },
1519*d6050574SRomain Jobredeaux)
1520*d6050574SRomain Jobredeaux
1521*d6050574SRomain Jobredeauxdef _empty_file(ctx, name):
1522*d6050574SRomain Jobredeaux    file = ctx.actions.declare_file(name)
1523*d6050574SRomain Jobredeaux    ctx.actions.write(file, content = "")
1524*d6050574SRomain Jobredeaux    return file
1525*d6050574SRomain Jobredeaux
1526*d6050574SRomain Jobredeauxdef _noop_binary_impl(ctx):
1527*d6050574SRomain Jobredeaux    return DefaultInfo(executable = _empty_file(ctx, ctx.label.name))
1528*d6050574SRomain Jobredeaux
1529*d6050574SRomain Jobredeauxnoop_binary = rule(
1530*d6050574SRomain Jobredeaux    implementation = _noop_binary_impl,
1531*d6050574SRomain Jobredeaux    executable = True,
1532*d6050574SRomain Jobredeaux)
1533*d6050574SRomain Jobredeaux
1534*d6050574SRomain Jobredeauxdef truth_test_suite(name):
1535*d6050574SRomain Jobredeaux    # Unit tests can't directly create File objects, so we have a generic
1536*d6050574SRomain Jobredeaux    # collection of files they can put in custom attributes to use.
1537*d6050574SRomain Jobredeaux    native.filegroup(
1538*d6050574SRomain Jobredeaux        name = "truth_tests_data_files",
1539*d6050574SRomain Jobredeaux        srcs = native.glob(["testdata/**"]),
1540*d6050574SRomain Jobredeaux    )
1541*d6050574SRomain Jobredeaux    test_helper(
1542*d6050574SRomain Jobredeaux        name = "truth_tests_helper",
1543*d6050574SRomain Jobredeaux        tags = ["tag1", "tag2"],
1544*d6050574SRomain Jobredeaux    )
1545*d6050574SRomain Jobredeaux    noop_binary(name = "truth_tests_noop")
1546*d6050574SRomain Jobredeaux
1547*d6050574SRomain Jobredeaux    test_suite(
1548*d6050574SRomain Jobredeaux        name = name,
1549*d6050574SRomain Jobredeaux        tests = _suite,
1550*d6050574SRomain Jobredeaux    )
1551