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"""Utilities for testing rules_testing code.""" 16*d6050574SRomain Jobredeaux 17*d6050574SRomain Jobredeaux# buildifier: disable=bzl-visibility 18*d6050574SRomain Jobredeauxload("//lib/private:expect_meta.bzl", "ExpectMeta") 19*d6050574SRomain Jobredeauxload("//lib:truth.bzl", "matching") 20*d6050574SRomain Jobredeaux 21*d6050574SRomain Jobredeauxdef _fake_meta(real_env): 22*d6050574SRomain Jobredeaux """Create a fake ExpectMeta object for testing. 23*d6050574SRomain Jobredeaux 24*d6050574SRomain Jobredeaux The fake ExpectMeta object copies a real ExpectMeta object, except: 25*d6050574SRomain Jobredeaux * Failures are only recorded and don't cause a failure in `real_env`. 26*d6050574SRomain Jobredeaux * `failures` attribute is added; this is a list of failures seen. 27*d6050574SRomain Jobredeaux * `reset` attribute is added; this clears the failures list. 28*d6050574SRomain Jobredeaux 29*d6050574SRomain Jobredeaux Args: 30*d6050574SRomain Jobredeaux real_env: A real env object from the rules_testing framework. 31*d6050574SRomain Jobredeaux 32*d6050574SRomain Jobredeaux Returns: 33*d6050574SRomain Jobredeaux struct, a fake ExpectMeta object. 34*d6050574SRomain Jobredeaux """ 35*d6050574SRomain Jobredeaux failures = [] 36*d6050574SRomain Jobredeaux fake_env = struct( 37*d6050574SRomain Jobredeaux ctx = real_env.ctx, 38*d6050574SRomain Jobredeaux fail = lambda msg: failures.append(msg), 39*d6050574SRomain Jobredeaux failures = failures, 40*d6050574SRomain Jobredeaux ) 41*d6050574SRomain Jobredeaux meta_impl = ExpectMeta.new(fake_env) 42*d6050574SRomain Jobredeaux meta_impl_kwargs = { 43*d6050574SRomain Jobredeaux attr: getattr(meta_impl, attr) 44*d6050574SRomain Jobredeaux for attr in dir(meta_impl) 45*d6050574SRomain Jobredeaux if attr not in ("to_json", "to_proto") 46*d6050574SRomain Jobredeaux } 47*d6050574SRomain Jobredeaux fake_meta = struct( 48*d6050574SRomain Jobredeaux failures = failures, 49*d6050574SRomain Jobredeaux reset = lambda: failures.clear(), 50*d6050574SRomain Jobredeaux **meta_impl_kwargs 51*d6050574SRomain Jobredeaux ) 52*d6050574SRomain Jobredeaux return fake_meta 53*d6050574SRomain Jobredeaux 54*d6050574SRomain Jobredeauxdef _expect_no_failures(env, fake_meta, case): 55*d6050574SRomain Jobredeaux """Check that a fake meta object had no failures. 56*d6050574SRomain Jobredeaux 57*d6050574SRomain Jobredeaux NOTE: This clears the list of failures after checking. This is done 58*d6050574SRomain Jobredeaux so that an earlier failure is only reported once. 59*d6050574SRomain Jobredeaux 60*d6050574SRomain Jobredeaux Args: 61*d6050574SRomain Jobredeaux env: Real `Expect` object to perform asserts. 62*d6050574SRomain Jobredeaux fake_meta: A fake meta object that had failures recorded. 63*d6050574SRomain Jobredeaux case: str, a description of the case that was tested. 64*d6050574SRomain Jobredeaux """ 65*d6050574SRomain Jobredeaux env.expect.that_collection( 66*d6050574SRomain Jobredeaux fake_meta.failures, 67*d6050574SRomain Jobredeaux expr = case, 68*d6050574SRomain Jobredeaux ).contains_exactly([]) 69*d6050574SRomain Jobredeaux fake_meta.reset() 70*d6050574SRomain Jobredeaux 71*d6050574SRomain Jobredeauxdef _expect_failures(env, fake_meta, case, *errors): 72*d6050574SRomain Jobredeaux """Check that a fake meta object has matching error strings. 73*d6050574SRomain Jobredeaux 74*d6050574SRomain Jobredeaux NOTE: This clears the list of failures after checking. This is done 75*d6050574SRomain Jobredeaux so that an earlier failure is only reported once. 76*d6050574SRomain Jobredeaux 77*d6050574SRomain Jobredeaux Args: 78*d6050574SRomain Jobredeaux env: Real `Expect` object to perform asserts. 79*d6050574SRomain Jobredeaux fake_meta: A fake meta object that had failures recorded. 80*d6050574SRomain Jobredeaux case: str, a description of the case that was tested. 81*d6050574SRomain Jobredeaux *errors: list of strings. These are patterns to match, as supported 82*d6050574SRomain Jobredeaux by `matching.str_matches` (e.g. `*`-style patterns) 83*d6050574SRomain Jobredeaux """ 84*d6050574SRomain Jobredeaux env.expect.that_collection( 85*d6050574SRomain Jobredeaux fake_meta.failures, 86*d6050574SRomain Jobredeaux expr = case, 87*d6050574SRomain Jobredeaux ).contains_at_least_predicates( 88*d6050574SRomain Jobredeaux [matching.str_matches(e) for e in errors], 89*d6050574SRomain Jobredeaux ) 90*d6050574SRomain Jobredeaux fake_meta.reset() 91*d6050574SRomain Jobredeaux 92*d6050574SRomain Jobredeauxtest_util = struct( 93*d6050574SRomain Jobredeaux fake_meta = _fake_meta, 94*d6050574SRomain Jobredeaux expect_no_failures = _expect_no_failures, 95*d6050574SRomain Jobredeaux expect_failures = _expect_failures, 96*d6050574SRomain Jobredeaux) 97