summaryrefslogtreecommitdiff
path: root/test/suites/color_diagnostics.bash
blob: 8295eb1c47138dcc65969945ec569b5eb90962de (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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
if $COMPILER_TYPE_GCC; then
    color_diagnostics_enable='-fdiagnostics-color'
    color_diagnostics_disable='-fno-diagnostics-color'
elif $COMPILER_TYPE_CLANG; then
    color_diagnostics_enable='-fcolor-diagnostics'
    color_diagnostics_disable='-fno-color-diagnostics'
fi

SUITE_color_diagnostics_PROBE() {
    if ! script --return --quiet --command true /dev/null </dev/null >/dev/null 2>&1; then
        echo "the script tool is not installed or does not support required options"
        return
    fi

    if ! $RUN_WIN_XFAIL; then
        echo "color_diagnostics tests are broken on Windows."
        return
    fi

    # Probe that real compiler actually supports colored diagnostics.
    if [[ ! $color_diagnostics_enable || ! $color_diagnostics_disable ]]; then
        echo "compiler $COMPILER does not support colored diagnostics"
    elif ! $COMPILER $color_diagnostics_enable -E - </dev/null >/dev/null 2>&1; then
        echo "compiler $COMPILER (version: $compiler_version) does not support $color_diagnostics_enable"
    elif ! $COMPILER $color_diagnostics_disable -E - </dev/null >/dev/null 2>&1; then
        echo "compiler $COMPILER (version: $compiler_version) does not support $color_diagnostics_disable"
    fi
}

SUITE_color_diagnostics_SETUP() {
    if $run_second_cpp; then
        export CCACHE_CPP2=1
    else
        export CCACHE_NOCPP2=1
    fi

    unset GCC_COLORS
    export TERM=vt100
}

color_diagnostics_expect_color() {
    expect_contains "${1:?}" $'\033['
    expect_contains <(fgrep 'Wreturn-type' "$1") $'\033['
    expect_contains <(fgrep 'from preprocessor' "$1") $'\033['
}

color_diagnostics_expect_no_color() {
    expect_not_contains "${1:?}" $'\033['
}

color_diagnostics_generate_code() {
    cat <<'EOF' >"$1"
int stderr(void) { /* Warn about no return statement. */ }
#warning "Warning from preprocessor"
EOF
}

# Heap's permutation algorithm
color_diagnostics_generate_permutations() {
    local -i i
    local -i k="${1:?}-1"
    if ((k)); then
        color_diagnostics_generate_permutations "$k"
        for ((i = 0; i < k; ++i)); do
            if ((k & 1)); then
                local tmp=${A[$i]}
                A[$i]=${A[$k]}
                A[$k]=$tmp
            else
                local tmp=${A[0]}
                A[0]=${A[$k]}
                A[$k]=$tmp
            fi
            color_diagnostics_generate_permutations "$k"
        done
    else
        echo "${A[@]}"
    fi
}

color_diagnostics_run_on_pty() {
    script --return --quiet --command "unset GCC_COLORS; CCACHE_DIR='$CCACHE_DIR' ${2:?}" /dev/null </dev/null >"${1:?}"

    # script returns early on some platforms (leaving a child process living for
    # a short while) and the output may therefore still be pending. Work around
    # this by sleeping until the output file has content.
    retries=0
    while [ ! -s "$1" -a "$retries" -lt 100 ]; do
        sleep 0.1
        retries=$((retries + 1))
    done
}

color_diagnostics_test() {
    # -------------------------------------------------------------------------
    TEST "Colored diagnostics automatically disabled when stderr is not a TTY (run_second_cpp=$run_second_cpp)"

    color_diagnostics_generate_code test1.c
    $CCACHE_COMPILE -Wreturn-type -c -o test1.o test1.c 2>test1.stderr
    color_diagnostics_expect_no_color test1.stderr

    # Check that subsequently running on a TTY generates a cache hit.
    color_diagnostics_run_on_pty test1.output "$CCACHE_COMPILE -Wreturn-type -c -o test1.o test1.c"
    color_diagnostics_expect_color test1.output
    expect_stat cache_miss 1
    expect_stat preprocessed_cache_hit 1

    # -------------------------------------------------------------------------
    TEST "Colored diagnostics automatically enabled when stderr is a TTY (run_second_cpp=$run_second_cpp)"

    color_diagnostics_generate_code test1.c
    color_diagnostics_run_on_pty test1.output "$CCACHE_COMPILE -Wreturn-type -c -o test1.o test1.c"
    color_diagnostics_expect_color test1.output

    # Check that subsequently running without a TTY generates a cache hit.
    $CCACHE_COMPILE -Wreturn-type -c -o test1.o test1.c 2>test1.stderr
    color_diagnostics_expect_no_color test1.stderr
    expect_stat cache_miss 1
    expect_stat preprocessed_cache_hit 1

    if $COMPILER_TYPE_GCC; then
        # ---------------------------------------------------------------------
        TEST "-fcolor-diagnostics not accepted for GCC"

        generate_code 1 test.c

        if $CCACHE_COMPILE -fcolor-diagnostics -c test.c >&/dev/null; then
            test_failed "-fcolor-diagnostics unexpectedly accepted by GCC"
        fi
        expect_stat preprocessor_error 1

        # ---------------------------------------------------------------------
        TEST "-fcolor-diagnostics not accepted for GCC for cached result"

        generate_code 1 test.c

        if ! $CCACHE_COMPILE -c test.c >&/dev/null; then
            test_failed "unknown error compiling"
        fi
        if $CCACHE_COMPILE -fcolor-diagnostics -c test.c >&/dev/null; then
            test_failed "-fcolor-diagnostics unexpectedly accepted by GCC"
        fi
        expect_stat preprocessor_error 1

        # ---------------------------------------------------------------------
        TEST "-fcolor-diagnostics passed to underlying compiler for unknown compiler type"

        generate_code 1 test.c

        CCACHE_COMPILERTYPE=other $CCACHE_COMPILE -c test.c
        expect_stat cache_miss 1

        if CCACHE_COMPILERTYPE=other $CCACHE_COMPILE -fcolor-diagnostics -c test.c >&/dev/null; then
            test_failed "-fcolor-diagnostics unexpectedly accepted by GCC"
        fi
        expect_stat preprocessor_error 1
    fi

    if $COMPILER_TYPE_CLANG; then
        # ---------------------------------------------------------------------
        TEST "-fcolor-diagnostics works when passed to cc1 with -Xclang"

        color_diagnostics_generate_code test1.c
        $CCACHE_COMPILE -Xclang -fcolor-diagnostics -Wreturn-type -c -o test1.o test1.c 2>test1.stderr
        color_diagnostics_expect_color test1.stderr
    fi

    while read -r case; do
        # ---------------------------------------------------------------------
        TEST "Cache object shared across ${case} (run_second_cpp=$run_second_cpp)"

        color_diagnostics_generate_code test1.c
        local each
        for each in ${case}; do
            case $each in
                color,*)
                    local color_flag=$color_diagnostics_enable
                    local color_expect=color
                    ;;
                nocolor,*)
                    local color_flag=$color_diagnostics_disable
                    local color_expect=no_color
                    ;;
            esac
            case $each in
                *,tty)
                    color_diagnostics_run_on_pty test1.output "$CCACHE_COMPILE $color_flag -Wreturn-type -c -o test1.o test1.c"
                    color_diagnostics_expect_$color_expect test1.output
                    ;;
                *,notty)
                    $CCACHE_COMPILE $color_flag -Wreturn-type -c -o test1.o test1.c 2>test1.stderr
                    color_diagnostics_expect_$color_expect test1.stderr
                    ;;
            esac
        done
        expect_stat cache_miss 1
        expect_stat preprocessed_cache_hit 3
    done < <(
        A=({color,nocolor},{tty,notty})
        color_diagnostics_generate_permutations "${#A[@]}"
    )
}

SUITE_color_diagnostics() {
    run_second_cpp=true color_diagnostics_test
    run_second_cpp=false color_diagnostics_test
}