| 1 | #!/bin/bash |
| 2 | # |
| 3 | # Copyright (C) - 2020 EfficiOS, inc |
| 4 | # |
| 5 | # This library is free software; you can redistribute it and/or modify it under |
| 6 | # the terms of the GNU Lesser General Public License as published by the Free |
| 7 | # Software Foundation; version 2.1 of the License. |
| 8 | # |
| 9 | # This library is distributed in the hope that it will be useful, but WITHOUT |
| 10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 11 | # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more |
| 12 | # details. |
| 13 | # |
| 14 | # You should have received a copy of the GNU Lesser General Public License |
| 15 | # along with this library; if not, write to the Free Software Foundation, Inc., |
| 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 17 | |
| 18 | # Test the `lttng add-trigger` command line interface. |
| 19 | |
| 20 | CURDIR="$(dirname "$0")" |
| 21 | TESTDIR="$CURDIR/../../.." |
| 22 | |
| 23 | # shellcheck source=../../../utils/utils.sh |
| 24 | source "$TESTDIR/utils/utils.sh" |
| 25 | |
| 26 | plan_tests 174 |
| 27 | |
| 28 | FULL_LTTNG_BIN="${TESTDIR}/../src/bin/lttng/${LTTNG_BIN}" |
| 29 | |
| 30 | # shellcheck disable=SC2119 |
| 31 | start_lttng_sessiond_notap |
| 32 | |
| 33 | tmp_stdout=$(mktemp -t test_parse_cli_trigger_stdout.XXXXXX) |
| 34 | tmp_stderr=$(mktemp -t test_parse_cli_trigger_stderr.XXXXXX) |
| 35 | uprobe_elf_binary="${TESTDIR}/utils/testapp/userspace-probe-elf-binary/.libs/userspace-probe-elf-binary" |
| 36 | |
| 37 | if [ "$(id -u)" == "0" ]; then |
| 38 | ist_root=1 |
| 39 | else |
| 40 | ist_root=0 |
| 41 | fi |
| 42 | |
| 43 | function test_success () |
| 44 | { |
| 45 | local test_name="$1" |
| 46 | shift |
| 47 | |
| 48 | diag "${FULL_LTTNG_BIN} add-trigger $*" |
| 49 | "${FULL_LTTNG_BIN}" add-trigger "$@" > "${tmp_stdout}" 2> "${tmp_stderr}" |
| 50 | ok $? "${test_name}: exit code is 0" |
| 51 | |
| 52 | diff -u "${tmp_stdout}" <(echo "Trigger registered successfully.") |
| 53 | ok $? "${test_name}: expected stdout" |
| 54 | |
| 55 | diff -u "${tmp_stderr}" /dev/null |
| 56 | ok $? "${test_name}: expected stderr" |
| 57 | } |
| 58 | |
| 59 | function test_failure () |
| 60 | { |
| 61 | local test_name="$1" |
| 62 | local error_msg="$2" |
| 63 | |
| 64 | shift 2 |
| 65 | |
| 66 | diag "${FULL_LTTNG_BIN} add-trigger $*" |
| 67 | "${FULL_LTTNG_BIN}" add-trigger "$@" > "${tmp_stdout}" 2> "${tmp_stderr}" |
| 68 | isnt $? 0 "${test_name}: exit code is not 0" |
| 69 | |
| 70 | diff -u "${tmp_stdout}" /dev/null |
| 71 | ok $? "${test_name}: expected stdout" |
| 72 | |
| 73 | diff -u "${tmp_stderr}" <(echo "${error_msg}") |
| 74 | ok $? "${test_name}: expected stderr" |
| 75 | } |
| 76 | |
| 77 | # top-level options |
| 78 | test_success "explicit id" \ |
| 79 | --id hohoho \ |
| 80 | --condition on-event some-event-id -u \ |
| 81 | --action notify |
| 82 | |
| 83 | # `--condition on-event` successes |
| 84 | test_success "--condition on-event some-event -u" \ |
| 85 | --condition on-event some-event -u \ |
| 86 | --action notify |
| 87 | |
| 88 | test_success "--condition on-event -a -u" \ |
| 89 | --condition on-event -a -u \ |
| 90 | --action notify |
| 91 | |
| 92 | test_success "--fire-once-after" \ |
| 93 | --condition on-event -u test-fire-once-after \ |
| 94 | --action notify \ |
| 95 | --fire-once-after=55 |
| 96 | |
| 97 | test_success "--fire-every" \ |
| 98 | --condition on-event -u test-fire-every \ |
| 99 | --action notify \ |
| 100 | --fire-every=55 |
| 101 | |
| 102 | skip $ist_root "non-root user: skipping kprobe tests" 9 || { |
| 103 | test_success "--condition on-event probe by symbol" \ |
| 104 | --condition on-event -k --probe=lttng_channel_enable my_channel_enable \ |
| 105 | --action notify |
| 106 | |
| 107 | channel_enable_addr=$(grep ' t lttng_channel_enable\s\[lttng_tracer\]$' /proc/kallsyms | cut -f 1 -d ' ') |
| 108 | channel_disable_addr=$(grep ' t lttng_channel_disable\s\[lttng_tracer\]$' /proc/kallsyms | cut -f 1 -d ' ') |
| 109 | |
| 110 | # We need to find a valid offset. |
| 111 | base_symbol="" |
| 112 | offset=0 |
| 113 | if [[ 0x$channel_enable_addr -lt 0x$channel_disable_addr ]]; then |
| 114 | base_symbol="lttng_channel_enable" |
| 115 | offset=$(( 0x$channel_disable_addr - 0x$channel_enable_addr )) |
| 116 | else |
| 117 | base_symbol="lttng_channel_disable" |
| 118 | offset=$(( 0x$channel_enable_addr - 0x$channel_disable_addr )) |
| 119 | fi |
| 120 | |
| 121 | offset_hex="0x$(printf '%x' $offset)" |
| 122 | |
| 123 | test_success "--condition on-event probe by symbol with offset" \ |
| 124 | --condition on-event -k --probe="${base_symbol}+${offset_hex}" my_$base_symbol \ |
| 125 | --action notify |
| 126 | |
| 127 | test_success "--condition on-event probe by address" \ |
| 128 | --condition on-event -k "--probe=0x${channel_enable_addr}" my_channel_enable \ |
| 129 | --action notify |
| 130 | } |
| 131 | |
| 132 | skip $ist_root "non-root user: skipping uprobe tests" 6 || { |
| 133 | test_success "--condition on-event uprobe" \ |
| 134 | --condition on-event -k --userspace-probe=${uprobe_elf_binary}:test_function ma-probe \ |
| 135 | --action notify |
| 136 | |
| 137 | test_success "--condition on-event uprobe with elf prefix" \ |
| 138 | --condition on-event -k --userspace-probe=elf:${uprobe_elf_binary}:test_function ma-probe-2 \ |
| 139 | --action notify |
| 140 | } |
| 141 | |
| 142 | skip $ist_root "non-root user: skipping syscall tests" 9 || { |
| 143 | test_success "--condition on-event syscall" \ |
| 144 | --condition on-event -k --syscall open \ |
| 145 | --action notify |
| 146 | |
| 147 | test_success "--condition on-event syscall -a" \ |
| 148 | --condition on-event -k --syscall -a \ |
| 149 | --action notify |
| 150 | |
| 151 | test_success "--condition on-event syscall with filter" \ |
| 152 | --condition on-event -k --syscall --filter 'a > 2' open \ |
| 153 | --action notify |
| 154 | } |
| 155 | |
| 156 | # `--action notify` successes |
| 157 | test_success "--action notify" \ |
| 158 | --condition on-event some-event-notify -u \ |
| 159 | --action notify |
| 160 | |
| 161 | # `--action start-session` successes |
| 162 | test_success "--action start-session" \ |
| 163 | --condition on-event some-event-start-session -u \ |
| 164 | --action start-session ze-session |
| 165 | |
| 166 | # `--action stop-session` successes |
| 167 | test_success "--action stop-session foo" \ |
| 168 | --condition on-event some-event-stop-session -u \ |
| 169 | --action stop-session ze-session |
| 170 | |
| 171 | # `--action rotate-session` successes |
| 172 | test_success "--action rotate-session foo" \ |
| 173 | --condition on-event some-event-rotate-session -u \ |
| 174 | --action rotate-session ze-session |
| 175 | |
| 176 | # `--action snapshot-session` successes |
| 177 | test_success "--action snapshot-session foo" \ |
| 178 | --condition on-event some-event-snapshot-session -u \ |
| 179 | --action snapshot-session ze-session |
| 180 | |
| 181 | test_success "--action snapshot-session with file URI" \ |
| 182 | --condition on-event some-event-snapshot-session2 -u \ |
| 183 | --action snapshot-session ze-session --path /hello |
| 184 | |
| 185 | test_success "--action snapshot-session with net URI" \ |
| 186 | --condition on-event some-event-snapshot-session3 -u \ |
| 187 | --action snapshot-session ze-session --url net://1.2.3.4 |
| 188 | |
| 189 | test_success "--action snapshot-session with ctrl/data URIs" \ |
| 190 | --condition on-event some-event-snapshot-session4 -u \ |
| 191 | --action snapshot-session ze-session --ctrl-url=tcp://1.2.3.4:1234 --data-url=tcp://1.2.3.4:1235 |
| 192 | |
| 193 | # top-level failures |
| 194 | test_failure "no args" "Error: Missing --condition." |
| 195 | |
| 196 | test_failure "unknown option" \ |
| 197 | "Error: Unknown option \`--hello\`" \ |
| 198 | --hello |
| 199 | |
| 200 | test_failure "missing --action" \ |
| 201 | "Error: Need at least one --action." \ |
| 202 | --condition on-event hello -u |
| 203 | |
| 204 | test_failure "two --condition" \ |
| 205 | "Error: A --condition was already given." \ |
| 206 | --condition on-event aaa -u \ |
| 207 | --condition on-event bbb -u \ |
| 208 | --action notify |
| 209 | |
| 210 | test_failure "missing argument to --id" \ |
| 211 | "Error: While parsing argument #1 (\`--id\`): Missing required argument for option \`--id\`" \ |
| 212 | --id |
| 213 | |
| 214 | for cmd in fire-once-after fire-every; do |
| 215 | test_failure "missing argument to --${cmd}" \ |
| 216 | "Error: While parsing argument #1 (\`--${cmd}\`): Missing required argument for option \`--${cmd}\`" \ |
| 217 | --condition on-event -u -a --action notify \ |
| 218 | --${cmd} |
| 219 | |
| 220 | test_failure "invalid argument to --${cmd}: non-digit character" \ |
| 221 | "Error: Failed to parse \`123bob\` as an integer." \ |
| 222 | --condition on-event -u -a --action notify \ |
| 223 | --${cmd} 123bob |
| 224 | |
| 225 | test_failure "invalid argument to --${cmd}: empty string" \ |
| 226 | "Error: Failed to parse \`\` as an integer." \ |
| 227 | --condition on-event -u -a --action notify \ |
| 228 | --${cmd} "" |
| 229 | done |
| 230 | |
| 231 | # `--condition` failures |
| 232 | test_failure "missing args after --condition" \ |
| 233 | "Error: Missing condition name." \ |
| 234 | --condition |
| 235 | test_failure "unknown --condition" \ |
| 236 | "Error: Unknown condition name 'zoofest'" \ |
| 237 | --condition zoofest |
| 238 | |
| 239 | # `--condition on-event` failures |
| 240 | test_failure "missing args after --condition on-event" \ |
| 241 | "Error: Need to provide either a tracepoint name or -a/--all." \ |
| 242 | --condition on-event |
| 243 | test_failure "missing domain in --condition on-event" \ |
| 244 | "Error: Please specify a domain (--kernel/--userspace/--jul/--log4j/--python)." \ |
| 245 | --condition on-event -a |
| 246 | test_failure "extra args after --condition on-event" \ |
| 247 | "Error: Unexpected argument 'bozo'" \ |
| 248 | --condition on-event foo -u bozo |
| 249 | test_failure "--condition on-event: --all with --probe" \ |
| 250 | "Error: Can't use -a/--all with probe event rules." \ |
| 251 | --condition on-event --probe=do_sys_open --all |
| 252 | test_failure "--condition on-event: missing tracepoint name with --probe" \ |
| 253 | "Error: Need to provide either a tracepoint name or -a/--all." \ |
| 254 | --condition on-event -k --probe do_sys_open |
| 255 | |
| 256 | test_failure "--condition on-event: missing tracepoint name with --userspace-probe" \ |
| 257 | "Error: Need to provide either a tracepoint name or -a/--all." \ |
| 258 | --condition on-event -k --userspace-probe=${uprobe_elf_binary}:test_function |
| 259 | |
| 260 | test_failure "--condition on-event: extra argument with --userspace-probe" \ |
| 261 | "Error: Unexpected argument 'world'" \ |
| 262 | --condition on-event -k --userspace-probe=${uprobe_elf_binary}:test_failure hello world |
| 263 | |
| 264 | test_failure "--condition on-event: missing tracepoint name with --syscall" \ |
| 265 | "Error: Need to provide either a tracepoint name or -a/--all." \ |
| 266 | --condition on-event -k --syscall |
| 267 | |
| 268 | test_failure "--condition on-event: extra argument with --syscall" \ |
| 269 | "Error: Unexpected argument 'open'" \ |
| 270 | --condition on-event -k --syscall open open |
| 271 | |
| 272 | test_failure "--condition on-event: both -a and a tracepoint name with --syscall" \ |
| 273 | "Error: Can't provide a tracepoint name with -a/--all." \ |
| 274 | --condition on-event -k --syscall -a open |
| 275 | |
| 276 | # `--action` failures |
| 277 | test_failure "missing args after --action" \ |
| 278 | "Error: Missing action name." \ |
| 279 | --condition on-event -u -a \ |
| 280 | --action |
| 281 | |
| 282 | # `--action notify` failures |
| 283 | test_failure "extra arg after --action notify" \ |
| 284 | "Error: Unexpected argument \`bob\`." \ |
| 285 | --condition on-event -u -a \ |
| 286 | --action notify bob |
| 287 | |
| 288 | # `--action start-session` failures |
| 289 | test_failure "missing arg after --action start-session" \ |
| 290 | "Error: Missing session name." \ |
| 291 | --condition on-event some-event-start-session -u \ |
| 292 | --action start-session |
| 293 | test_failure "extra arg after --action start-session" \ |
| 294 | "Error: Unexpected argument \`bob\`." \ |
| 295 | --condition on-event some-event-start-session -u \ |
| 296 | --action start-session ze-session bob |
| 297 | |
| 298 | # `--action stop-session` failures |
| 299 | test_failure "missing arg after --action stop-session" \ |
| 300 | "Error: Missing session name." \ |
| 301 | --condition on-event some-event-stop-session -u \ |
| 302 | --action stop-session |
| 303 | test_failure "extra arg after --action stop-session" \ |
| 304 | "Error: Unexpected argument \`bob\`." \ |
| 305 | --condition on-event some-event-stop-session -u \ |
| 306 | --action stop-session ze-session bob |
| 307 | |
| 308 | # `--action rotate-session` failures |
| 309 | test_failure "missing arg after --action rotate-session" \ |
| 310 | "Error: Missing session name." \ |
| 311 | --condition on-event some-event-rotate-session -u \ |
| 312 | --action rotate-session |
| 313 | test_failure "extra arg after --action rotate-session" \ |
| 314 | "Error: Unexpected argument \`bob\`." \ |
| 315 | --condition on-event some-event-rotate-session -u \ |
| 316 | --action rotate-session ze-session bob |
| 317 | |
| 318 | # `--action snapshot-session` failures |
| 319 | test_failure "missing arg after --action snapshot-session" \ |
| 320 | "Error: Missing session name." \ |
| 321 | --condition on-event some-event-snapshot-session -u \ |
| 322 | --action snapshot-session |
| 323 | test_failure "extra arg after --action snapshot-session" \ |
| 324 | "Error: Unexpected argument \`bob\`." \ |
| 325 | --condition on-event some-event-snapshot-session -u \ |
| 326 | --action snapshot-session ze-session bob |
| 327 | test_failure "snapshot-session action, --max-size without destination" \ |
| 328 | "Error: Can't provide a snapshot output max size without a snapshot output destination." \ |
| 329 | --condition on-event some-event-snapshot-session -u \ |
| 330 | --action snapshot-session ze-session --max-size 10M |
| 331 | test_failure "snapshot-session action, --name without destination" \ |
| 332 | "Error: Can't provide a snapshot output name without a snapshot output destination." \ |
| 333 | --condition on-event some-event-snapshot-session -u \ |
| 334 | --action snapshot-session ze-session --name hallo |
| 335 | test_failure "snapshot-session action, --name with-local-path-instead-of-url" \ |
| 336 | "Error: Failed to parse '/something/that/looks/like/a/path' as an URL." \ |
| 337 | --condition on-event some-event-snapshot-session -u \ |
| 338 | --action snapshot-session ze-session --name hallo --url /something/that/looks/like/a/path |
| 339 | test_failure "snapshot-session action, --name with-net-url-instead-of-path" \ |
| 340 | "Error: Failed to parse 'net://8.8.8.8/' as a local path." \ |
| 341 | --condition on-event some-event-snapshot-session -u \ |
| 342 | --action snapshot-session ze-session --name hallo --path net://8.8.8.8/ |
| 343 | |
| 344 | # Cleanup |
| 345 | stop_lttng_sessiond_notap |
| 346 | rm -f "${tmp_stdout}" |
| 347 | rm -f "${tmp_stderr}" |