| 1 | #!/bin/bash |
| 2 | # |
| 3 | # SPDX-License-Identifier: GPL-2.0-only |
| 4 | # |
| 5 | # Copyright (C) 2020 Geneviève Bastien <gbastien@versatic.net> |
| 6 | # |
| 7 | # This file tests pretty printing in details some event classes that are |
| 8 | # not all covered by the main babeltrace tests with traces. |
| 9 | SH_TAP=1 |
| 10 | |
| 11 | if [ -n "${BT_TESTS_SRCDIR:-}" ]; then |
| 12 | UTILSSH="$BT_TESTS_SRCDIR/utils/utils.sh" |
| 13 | else |
| 14 | UTILSSH="$(dirname "$0")/../../utils/utils.sh" |
| 15 | fi |
| 16 | |
| 17 | # shellcheck source=../../utils/utils.sh |
| 18 | source "$UTILSSH" |
| 19 | |
| 20 | data_dir="$BT_TESTS_DATADIR/plugins/sink.text.pretty" |
| 21 | temp_stdout_expected_file=$(mktemp -t test-pretty-expected-stdout.XXXXXX) |
| 22 | |
| 23 | plan_tests 31 |
| 24 | |
| 25 | function compare_enum_sorted |
| 26 | { |
| 27 | local expected_file="$1" |
| 28 | local actual_file="$2" |
| 29 | |
| 30 | # The order in which enum labels are printed by a `sink.text.pretty` |
| 31 | # component directly depends on the order in which mappings were added |
| 32 | # to the enum field class in the source component. This order should |
| 33 | # not be relied on when testing. Relying on it caused problems with |
| 34 | # Python component classes because different versions of Python sort |
| 35 | # data structures differently (e.g. dictionaries are insertion sorted |
| 36 | # since Python 3.7). |
| 37 | |
| 38 | bt_run_in_py_env "${BT_TESTS_PYTHON_BIN}" "${BT_TESTS_SRCDIR}/utils/python/split_sort_compare.py" \ |
| 39 | "$(cat "$expected_file")" "$(cat "$actual_file")" |
| 40 | } |
| 41 | |
| 42 | function run_test |
| 43 | { |
| 44 | local test_name=$1 |
| 45 | local expected_to_fail="$2" |
| 46 | local value="$3" |
| 47 | local expected_stdout_file="$4" |
| 48 | local actual_stdout_file |
| 49 | local actual_stderr_file |
| 50 | local ret=0 |
| 51 | local local_args=( |
| 52 | "--plugin-path" "$data_dir" |
| 53 | "-c" "src.test-pretty.TheSourceOfProblems" |
| 54 | "-p" "enum-values=\"$enum_values\"" |
| 55 | "-p" "value=$value" |
| 56 | "-p" "enum-signed=$enum_signed" |
| 57 | "-c" "sink.text.pretty" |
| 58 | "-p" "print-enum-flags=true" |
| 59 | ) |
| 60 | |
| 61 | actual_stdout_file="$(mktemp -t actual-pretty-stdout.XXXXXX)" |
| 62 | actual_stderr_file="$(mktemp -t actual-pretty-stderr.XXXXXX)" |
| 63 | |
| 64 | bt_cli "$actual_stdout_file" "$actual_stderr_file" "${local_args[@]}" |
| 65 | |
| 66 | compare_enum_sorted "$expected_stdout_file" "$actual_stdout_file" |
| 67 | ret_stdout=$? |
| 68 | |
| 69 | bt_diff /dev/null "$actual_stderr_file" |
| 70 | ret_stderr=$? |
| 71 | |
| 72 | if ((ret_stdout != 0 || ret_stderr != 0)); then |
| 73 | ret=1 |
| 74 | fi |
| 75 | |
| 76 | rm -f "$actual_stdout_file" "$actual_stderr_file" |
| 77 | |
| 78 | if [ "$expected_to_fail" = "1" ]; then |
| 79 | isnt $ret 0 "$test_name signed=$enum_signed with value=$value doesn't match as expected" |
| 80 | else |
| 81 | ok $ret "$test_name signed=$enum_signed with value=$value matches" |
| 82 | fi |
| 83 | |
| 84 | } |
| 85 | |
| 86 | function test_normal_enum { |
| 87 | test_name="Normal enum" |
| 88 | enum_signed="$1" |
| 89 | enum_values="single,1,1 single2,2,2 single3,4,4 range,4,8 range2,15,20" |
| 90 | |
| 91 | # Hit a single value |
| 92 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 93 | with_enum: { enum_field = ( "single" : container = 1 ) } |
| 94 | END |
| 95 | run_test "$test_name" 0 1 "$temp_stdout_expected_file" |
| 96 | |
| 97 | # Hit a single range |
| 98 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 99 | with_enum: { enum_field = ( "range" : container = 7 ) } |
| 100 | END |
| 101 | run_test "$test_name" 0 7 "$temp_stdout_expected_file" |
| 102 | |
| 103 | # Hit a range and a value |
| 104 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 105 | with_enum: { enum_field = ( { "single3", "range" } : container = 4 ) } |
| 106 | END |
| 107 | run_test "$test_name" 0 4 "$temp_stdout_expected_file" |
| 108 | |
| 109 | # Hit a range and a value |
| 110 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 111 | with_enum: { enum_field = ( { "NOT_A_LABEL", "DOESNT_EXIST" } : container = 4 ) } |
| 112 | END |
| 113 | run_test "$test_name" 1 4 "$temp_stdout_expected_file" |
| 114 | |
| 115 | # Unknown |
| 116 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 117 | with_enum: { enum_field = ( <unknown> : container = 21 ) } |
| 118 | END |
| 119 | run_test "$test_name" 0 21 "$temp_stdout_expected_file" |
| 120 | |
| 121 | # Unknown but with bits with a value, but range larger than 1 element |
| 122 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 123 | with_enum: { enum_field = ( <unknown> : container = 12 ) } |
| 124 | END |
| 125 | run_test "$test_name" 0 12 "$temp_stdout_expected_file" |
| 126 | |
| 127 | # Unknown value of 0 |
| 128 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 129 | with_enum: { enum_field = ( <unknown> : container = 0 ) } |
| 130 | END |
| 131 | run_test "$test_name" 0 0 "$temp_stdout_expected_file" |
| 132 | } |
| 133 | |
| 134 | function test_normal_enum_negative { |
| 135 | test_name="Normal enum with negative value" |
| 136 | enum_signed="true" |
| 137 | enum_values="zero,0,0 single,1,1 single2,2,2 single3,4,4 range,4,8 negative,-1,-1 rangeNegative,-6,-2" |
| 138 | |
| 139 | # Hit a single negative value |
| 140 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 141 | with_enum: { enum_field = ( "negative" : container = -1 ) } |
| 142 | END |
| 143 | run_test "$test_name" 0 -1 "$temp_stdout_expected_file" |
| 144 | |
| 145 | # Hit a single negative range |
| 146 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 147 | with_enum: { enum_field = ( "rangeNegative" : container = -6 ) } |
| 148 | END |
| 149 | run_test "$test_name" 0 -6 "$temp_stdout_expected_file" |
| 150 | |
| 151 | # Unknown |
| 152 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 153 | with_enum: { enum_field = ( <unknown> : container = -7 ) } |
| 154 | END |
| 155 | run_test "$test_name" 0 -7 "$temp_stdout_expected_file" |
| 156 | |
| 157 | # value of 0 |
| 158 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 159 | with_enum: { enum_field = ( "zero" : container = 0 ) } |
| 160 | END |
| 161 | run_test "$test_name" 0 0 "$temp_stdout_expected_file" |
| 162 | } |
| 163 | |
| 164 | function test_bit_flag_enum { |
| 165 | test_name="Bit flag enum" |
| 166 | enum_signed="false" |
| 167 | enum_values="bit0,1,1 bit0bis,1,1 bit1,2,2 bit3,4,4 bit4,8,8 bit5,16,16 bit5,32,32" |
| 168 | |
| 169 | # Single value hit |
| 170 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 171 | with_enum: { enum_field = ( "bit1" : container = 2 ) } |
| 172 | END |
| 173 | run_test "$test_name" 0 2 "$temp_stdout_expected_file" |
| 174 | |
| 175 | # Multiple flags set |
| 176 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 177 | with_enum: { enum_field = ( "bit3" | "bit4" : container = 12 ) } |
| 178 | END |
| 179 | run_test "$test_name" 0 12 "$temp_stdout_expected_file" |
| 180 | |
| 181 | # Some unknown bit |
| 182 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 183 | with_enum: { enum_field = ( <unknown> : container = 68 ) } |
| 184 | END |
| 185 | run_test "$test_name" 0 68 "$temp_stdout_expected_file" |
| 186 | |
| 187 | # Multiple labels for bit 0 |
| 188 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 189 | with_enum: { enum_field = ( { "bit0", "bit0bis" } : container = 1 ) } |
| 190 | END |
| 191 | run_test "$test_name" 0 1 "$temp_stdout_expected_file" |
| 192 | |
| 193 | # Two labels for bit 0 and one label for bit 1 |
| 194 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 195 | with_enum: { enum_field = ( { "bit0", "bit0bis" } | "bit1" : container = 3 ) } |
| 196 | END |
| 197 | run_test "$test_name" 0 3 "$temp_stdout_expected_file" |
| 198 | |
| 199 | # Single label for bit 0 |
| 200 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 201 | with_enum: { enum_field = ( "bit5" | "bit5" : container = 48 ) } |
| 202 | END |
| 203 | run_test "$test_name" 0 48 "$temp_stdout_expected_file" |
| 204 | |
| 205 | # negative value |
| 206 | enum_signed="true" |
| 207 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 208 | with_enum: { enum_field = ( <unknown> : container = -1 ) } |
| 209 | END |
| 210 | run_test "$test_name" 0 -1 "$temp_stdout_expected_file" |
| 211 | } |
| 212 | |
| 213 | function test_mixed_enum { |
| 214 | test_name="Mixed enum bits at beginning" |
| 215 | enum_signed="false" |
| 216 | enum_values="bit0,1,1 bit1,2,2 bit2,4,4 bit3,8,8 bit4,16,16 range,32,44 singleValue,45,45" |
| 217 | |
| 218 | # Value with bit fields |
| 219 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 220 | with_enum: { enum_field = ( "bit0" | "bit1" | "bit2" | "bit3" | "bit4" : container = 31 ) } |
| 221 | END |
| 222 | run_test "$test_name" 0 31 "$temp_stdout_expected_file" |
| 223 | |
| 224 | # A value with some bit flags set, but within another range |
| 225 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 226 | with_enum: { enum_field = ( "range" : container = 36 ) } |
| 227 | END |
| 228 | run_test "$test_name" 0 36 "$temp_stdout_expected_file" |
| 229 | |
| 230 | # A value with some bit flags set, but corresponding to another value |
| 231 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 232 | with_enum: { enum_field = ( "singleValue" : container = 45 ) } |
| 233 | END |
| 234 | run_test "$test_name" 0 45 "$temp_stdout_expected_file" |
| 235 | |
| 236 | # Value above the ranges |
| 237 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 238 | with_enum: { enum_field = ( <unknown> : container = 46 ) } |
| 239 | END |
| 240 | run_test "$test_name" 0 46 "$temp_stdout_expected_file" |
| 241 | |
| 242 | # Since low values are often powers of 2, they may be considered bit flags too |
| 243 | test_name="Mixed enum bits at end" |
| 244 | enum_signed="false" |
| 245 | enum_values="val1,1,1 val2,2,2 val3,3,3 val4,4,4 val5,5,5 bit3,8,8 bit4,16,16 bit5,32,32" |
| 246 | |
| 247 | # Value with bit fields |
| 248 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 249 | with_enum: { enum_field = ( "bit4" : container = 16 ) } |
| 250 | END |
| 251 | run_test "$test_name" 0 16 "$temp_stdout_expected_file" |
| 252 | |
| 253 | # Value with a bit field set both at beginning and end |
| 254 | cat <<- 'END' > "$temp_stdout_expected_file" |
| 255 | with_enum: { enum_field = ( "val1" | "bit4" : container = 17 ) } |
| 256 | END |
| 257 | run_test "$test_name" 0 17 "$temp_stdout_expected_file" |
| 258 | } |
| 259 | |
| 260 | # Enumerations tests |
| 261 | test_normal_enum "false" |
| 262 | test_normal_enum "true" |
| 263 | test_normal_enum_negative |
| 264 | test_bit_flag_enum |
| 265 | test_mixed_enum |
| 266 | |
| 267 | rm -f "$temp_stdout_expected_file" |