aboutsummaryrefslogtreecommitdiff
path: root/tests/shell_tests.bzl
blob: 5b83f9f22ab7c15b6394662d50bb5caf774699da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Copyright 2017 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.

"""Unit tests for shell.bzl."""

load("//lib:shell.bzl", "shell")
load("//lib:unittest.bzl", "asserts", "unittest")

def _shell_array_literal_test(ctx):
    """Unit tests for shell.array_literal."""
    env = unittest.begin(ctx)

    asserts.equals(env, "()", shell.array_literal([]))
    asserts.equals(env, "('1')", shell.array_literal([1]))
    asserts.equals(env, "('1' '2' '3')", shell.array_literal([1, 2, 3]))
    asserts.equals(env, "('$foo')", shell.array_literal(["$foo"]))
    asserts.equals(env, "('qu\"o\"te')", shell.array_literal(['qu"o"te']))

    return unittest.end(env)

shell_array_literal_test = unittest.make(_shell_array_literal_test)

def _shell_quote_test(ctx):
    """Unit tests for shell.quote."""
    env = unittest.begin(ctx)

    asserts.equals(env, "'foo'", shell.quote("foo"))
    asserts.equals(env, "'foo bar'", shell.quote("foo bar"))
    asserts.equals(env, "'three   spaces'", shell.quote("three   spaces"))
    asserts.equals(env, "'  leading'", shell.quote("  leading"))
    asserts.equals(env, "'trailing  '", shell.quote("trailing  "))
    asserts.equals(env, "'new\nline'", shell.quote("new\nline"))
    asserts.equals(env, "'tab\tcharacter'", shell.quote("tab\tcharacter"))
    asserts.equals(env, "'$foo'", shell.quote("$foo"))
    asserts.equals(env, "'qu\"o\"te'", shell.quote('qu"o"te'))
    asserts.equals(env, "'it'\\''s'", shell.quote("it's"))
    asserts.equals(env, "'foo\\bar'", shell.quote("foo\\bar"))
    asserts.equals(env, "'back`echo q`uote'", shell.quote("back`echo q`uote"))

    return unittest.end(env)

shell_quote_test = unittest.make(_shell_quote_test)

def _shell_args_test_gen_impl(ctx):
    """Test argument escaping: this rule writes a script for a sh_test."""
    args = [
        "foo",
        "foo bar",
        "three   spaces",
        "  leading",
        "trailing  ",
        "new\nline",
        "tab\tcharacter",
        "$foo",
        'qu"o"te',
        "it's",
        "foo\\bar",
        "back`echo q`uote",
    ]
    script_content = "\n".join([
        "#!/usr/bin/env bash",
        "myarray=" + shell.array_literal(args),
        'output=$(echo "${myarray[@]}")',
        # For logging:
        'echo "DEBUG: output=[${output}]" >&2',
        # The following is a shell representation of what the echo of the quoted
        # array will look like.  It looks a bit confusing considering it's shell
        # quoted into Python.  Shell using single quotes to minimize shell
        # escaping, so only the single quote needs to be escaped as '\'', all
        # others are essentially kept literally.
        "expected='foo foo bar three   spaces   leading trailing   new",
        "line tab\tcharacter $foo qu\"o\"te it'\\''s foo\\bar back`echo q`uote'",
        '[[ "${output}" == "${expected}" ]]',
    ])
    out = ctx.actions.declare_file(ctx.label.name + ".sh")
    ctx.actions.write(
        output = out,
        content = script_content,
        is_executable = True,
    )
    return [DefaultInfo(files = depset([out]))]

shell_args_test_gen = rule(
    implementation = _shell_args_test_gen_impl,
)

def shell_test_suite():
    """Creates the test targets and test suite for shell.bzl tests."""
    unittest.suite(
        "shell_tests",
        shell_array_literal_test,
        shell_quote_test,
    )