Raw
1 #!/bin/sh
2
3 test_description='test trace2 cmd_ancestry event'
4
5 . ./test-lib.sh
6
7 # Turn off any inherited trace2 settings for this test.
8 sane_unset GIT_TRACE2 GIT_TRACE2_PERF GIT_TRACE2_EVENT
9 sane_unset GIT_TRACE2_BRIEF
10 sane_unset GIT_TRACE2_CONFIG_PARAMS
11
12 # Add t/helper directory to PATH so that we can use a relative
13 # path to run nested instances of test-tool.exe (see 004child).
14 # This helps with HEREDOC comparisons later.
15 TTDIR="$GIT_BUILD_DIR/t/helper/" && export TTDIR
16 PATH="$TTDIR:$PATH" && export PATH
17
18 # The 400ancestry helper spawns a child process so that the child
19 # sees "test-tool" in its process ancestry. We capture only the
20 # child's trace2 output to a file.
21 #
22 # The tests use git commands that spawn child git processes (e.g.,
23 # alias resolution) to create a controlled multi-level process tree.
24 # Because cmd_ancestry walks the real process tree, processes will
25 # also report ancestors above "test-tool" that depend on the test
26 # runner environment (e.g., bash, make, tmux). The filter functions
27 # below truncate the ancestry at "test-tool", discarding anything
28 # above it, so only the controlled portion is verified.
29 #
30 # On platforms without a real procinfo implementation (the stub),
31 # no cmd_ancestry event is emitted. We detect this at runtime and
32 # skip the format-specific tests accordingly.
33
34 # Enable these tests only when cmd_ancestry reports real process names.
35 # The procinfo stub emits no event; under user-mode emulation (e.g.
36 # qemu-user) /proc reports the emulator, not the guest. Spawn test-tool
37 # from test-tool and require "test-tool" in the child's ancestry.
38 test_expect_success 'detect cmd_ancestry support' '
39 test_when_finished "rm -f trace.detect" &&
40 GIT_TRACE2_BRIEF=1 GIT_TRACE2="$(pwd)/trace.detect" \
41 test-tool trace2 004child test-tool trace2 001return 0 &&
42 if grep -q "^cmd_ancestry.*test-tool" trace.detect
43 then
44 test_set_prereq TRACE2_ANCESTRY
45 fi
46 '
47
48 # Filter functions for each trace2 target format.
49 #
50 # Each extracts cmd_ancestry events, strips format-specific syntax,
51 # and truncates the ancestor list at the outermost "test-tool"
52 # (or "test-tool.exe" on Windows), discarding any higher-level
53 # (uncontrolled) ancestors.
54 #
55 # Output is a space-separated list of ancestor names, one line per
56 # cmd_ancestry event, with the immediate parent listed first:
57 #
58 # test-tool (or: test-tool.exe)
59 # git test-tool (or: git.exe test-tool.exe)
60 # git test-tool test-tool (or: git.exe test-tool.exe test-tool.exe)
61
62 if test_have_prereq MINGW
63 then
64 TT=test-tool$X
65 else
66 TT=test-tool
67 fi
68
69 filter_ancestry_normal () {
70 sed -n '/^cmd_ancestry/{
71 s/^cmd_ancestry //
72 s/ <- / /g
73 s/\(.*'"$TT"'\) .*/\1/
74 p
75 }'
76 }
77
78 filter_ancestry_perf () {
79 sed -n '/cmd_ancestry/{
80 s/.*ancestry:\[//
81 s/\]//
82 s/\(.*'"$TT"'\) .*/\1/
83 p
84 }'
85 }
86
87 filter_ancestry_event () {
88 sed -n '/"cmd_ancestry"/{
89 s/.*"ancestry":\[//
90 s/\].*//
91 s/"//g
92 s/,/ /g
93 s/\(.*'"$TT"'\) .*/\1/
94 p
95 }'
96 }
97
98 # On Windows (MINGW) when running with the bin-wrappers, we also see "sh.exe" in
99 # the ancestry. We must therefore account for this expected ancestry element in
100 # the expected output of the tests.
101 if test_have_prereq MINGW && test -z "$no_bin_wrappers"; then
102 SH_TT="sh$X $TT"
103 else
104 SH_TT="$TT"
105 fi
106
107 # Git alias resolution spawns the target command as a child process.
108 # Using "git -c alias.xyz=version xyz" creates a two-level chain:
109 #
110 # test-tool (400ancestry)
111 # -> git (resolves alias xyz -> version)
112 # -> git (version)
113 #
114 # Both git processes are instrumented and emit cmd_ancestry. After
115 # filtering out ancestors above test-tool, we get:
116 #
117 # test-tool (from git alias resolver)
118 # git test-tool (from git version)
119
120 test_expect_success TRACE2_ANCESTRY 'normal: git alias chain, 2 levels' '
121 test_when_finished "rm -f trace.normal actual expect" &&
122 test-tool trace2 400ancestry normal "$(pwd)/trace.normal" \
123 git -c alias.xyz=version xyz &&
124 filter_ancestry_normal <trace.normal >actual &&
125 cat >expect <<-EOF &&
126 $SH_TT
127 git$X $SH_TT
128 EOF
129 test_cmp expect actual
130 '
131
132 test_expect_success TRACE2_ANCESTRY 'perf: git alias chain, 2 levels' '
133 test_when_finished "rm -f trace.perf actual expect" &&
134 test-tool trace2 400ancestry perf "$(pwd)/trace.perf" \
135 git -c alias.xyz=version xyz &&
136 filter_ancestry_perf <trace.perf >actual &&
137 cat >expect <<-EOF &&
138 $SH_TT
139 git$X $SH_TT
140 EOF
141 test_cmp expect actual
142 '
143
144 test_expect_success TRACE2_ANCESTRY 'event: git alias chain, 2 levels' '
145 test_when_finished "rm -f trace.event actual expect" &&
146 test-tool trace2 400ancestry event "$(pwd)/trace.event" \
147 git -c alias.xyz=version xyz &&
148 filter_ancestry_event <trace.event >actual &&
149 cat >expect <<-EOF &&
150 $SH_TT
151 git$X $SH_TT
152 EOF
153 test_cmp expect actual
154 '
155
156 # Use 004child to add a test-tool layer, creating a three-level chain:
157 #
158 # test-tool (400ancestry)
159 # -> test-tool (004child)
160 # -> git (resolves alias xyz -> version)
161 # -> git (version)
162 #
163 # Three instrumented processes emit cmd_ancestry. After filtering:
164 #
165 # test-tool (from test-tool 004child)
166 # test-tool test-tool (from git alias resolver)
167 # git test-tool test-tool (from git version)
168
169 test_expect_success TRACE2_ANCESTRY 'normal: deeper chain, 3 levels' '
170 test_when_finished "rm -f trace.normal actual expect" &&
171 test-tool trace2 400ancestry normal "$(pwd)/trace.normal" \
172 test-tool trace2 004child \
173 git -c alias.xyz=version xyz &&
174 filter_ancestry_normal <trace.normal >actual &&
175 cat >expect <<-EOF &&
176 $TT
177 $SH_TT $TT
178 git$X $SH_TT $TT
179 EOF
180 test_cmp expect actual
181 '
182
183 test_done