# Copyright 2018 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Defines a test rule that asserts the number of output files in another rule.

This rule operates in Bazel's analysis phase, not in its execution phase, and so
it's faster than a conventional test rule would be.

Furthermore this rule's action does not depend on any of the inputs (because the
assertion is done in the analysis phase) so Bazel won't even build the input
files to run the test. The test has constant execution time.

=== Use ===

Use this rule to assert the size of a filegroup or any other rule and catch
sudden, unexpected changes in the size.

The `margin` attribute allows specifying a tolerance value (percentage), to
allow for organic, expected growth or shrinkage of the target rule.

=== Example ===

The "resources_size_test" test fails if the number of files in
"resources" changes from 123 by more than 3 percent:

    filegroup(
        name = "resources",
        srcs = glob(["**"]) + [
            "//foo/bar:resources"
            "//baz:resources",
        ],
    )

    rule_size_test(
        name = "resources_size_test",
        src = ":resources",

        # Expect 123 files in ":resources", with an error margin of 3% to allow
        # for slight changes.
        expect = 123,
        margin = 3,
    )
"""

def _impl(ctx):
    if ctx.attr.expect < 0:
        fail("ERROR: rule_size_test.expect must be positive")

    if ctx.attr.margin < 0 or ctx.attr.margin > 100:
        # Do not allow more than 100% change in size.
        fail("ERROR: rule_size_test.margin must be in range [0..100]")

    if ctx.attr.expect == 0 and ctx.attr.margin != 0:
        # Allow no margin when expecting 0 files, to avoid division by zero.
        fail("ERROR: rule_size_test.margin must be 0 when " +
             "rule_size_test.expect is 0")

    amount = len(ctx.attr.src[DefaultInfo].files)

    if ctx.attr.margin > 0:
        if amount >= ctx.attr.expect:
            diff = amount - ctx.attr.expect
        else:
            diff = ctx.attr.expect - amount

        if ((diff * 100) // ctx.attr.expect) > ctx.attr.margin:
            fail(("ERROR: rule_size_test: expected %d file(s) within %d%% " +
                  "error margin, got %d file(s) (%d%% difference)") % (
                ctx.attr.expect,
                ctx.attr.margin,
                amount,
                (diff * 100) // ctx.attr.expect,
            ))
    elif amount != ctx.attr.expect:
        fail(("ERROR: rule_size_test: expected exactly %d file(s), got %d " +
              "file(s)") % (ctx.attr.expect, amount))

    if ctx.attr.is_windows:
        test_bin = ctx.actions.declare_file(ctx.label.name + ".bat")
        ctx.actions.write(output = test_bin, content = "", is_executable = True)
    else:
        test_bin = ctx.actions.declare_file(ctx.label.name + ".sh")
        ctx.actions.write(
            output = test_bin,
            content = "#!/bin/sh",
            is_executable = True,
        )

    return [DefaultInfo(executable = test_bin)]

_rule_size_test = rule(
    implementation = _impl,
    attrs = {
        # The target whose number of output files this rule asserts. The number
        # of output files is the size of the target's DefaultInfo.files field.
        "src": attr.label(allow_files = True),
        # A non-negative integer, the expected number of files that the target
        # in `src` outputs. If 0, then `margin` must also be 0.
        "expect": attr.int(mandatory = True),
        # A percentage value, in the range of [0..100]. Allows for tolerance in
        # the difference between expected and actual number of files in `src`.
        # If 0, then the target in `src` must output exactly `expect` many
        # files.
        "margin": attr.int(mandatory = True),
        # True if running on Windows, False otherwise.
        "is_windows": attr.bool(mandatory = True),
    },
    test = True,
)

def rule_size_test(name, **kwargs):
    _rule_size_test(
        name = name,
        is_windows = select({
            "@bazel_tools//src/conditions:windows": True,
            "//conditions:default": False,
        }),
        **kwargs
    )
