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
+# Determine if cmd_ancestry is supported on this platform.
35
+test_expect_success 'detect cmd_ancestry support' '
36
+ test_when_finished "rm -f trace.detect" &&
37
+ GIT_TRACE2_BRIEF=1 GIT_TRACE2="$(pwd)/trace.detect" \
38
+ test-tool trace2 001return 0 &&
39
+ if grep -q "^cmd_ancestry" trace.detect
40
+ then
41
+ test_set_prereq TRACE2_ANCESTRY
42
+ fi
43
+'
44
+
45
+# Filter functions for each trace2 target format.
46
+#
47
+# Each extracts cmd_ancestry events, strips format-specific syntax,
48
+# and truncates the ancestor list at the outermost "test-tool"
49
+# (or "test-tool.exe" on Windows), discarding any higher-level
50
+# (uncontrolled) ancestors.
51
+#
52
+# Output is a space-separated list of ancestor names, one line per
53
+# cmd_ancestry event, with the immediate parent listed first:
54
+#
55
+# test-tool (or: test-tool.exe)
56
+# git test-tool (or: git.exe test-tool.exe)
57
+# git test-tool test-tool (or: git.exe test-tool.exe test-tool.exe)
58
+
59
+if test_have_prereq MINGW
60
+then
61
+ TT=test-tool$X
62
+else
63
+ TT=test-tool
64
+fi
65
+
66
+filter_ancestry_normal () {
67
+ sed -n '/^cmd_ancestry/{
68
+ s/^cmd_ancestry //
69
+ s/ <- / /g
70
+ s/\(.*'"$TT"'\) .*/\1/
71
+ p
72
+ }'
73
+}
74
+
75
+filter_ancestry_perf () {
76
+ sed -n '/cmd_ancestry/{
77
+ s/.*ancestry:\[//
78
+ s/\]//
79
+ s/\(.*'"$TT"'\) .*/\1/
80
+ p
81
+ }'
82
+}
83
+
84
+filter_ancestry_event () {
85
+ sed -n '/"cmd_ancestry"/{
86
+ s/.*"ancestry":\[//
87
+ s/\].*//
88
+ s/"//g
89
+ s/,/ /g
90
+ s/\(.*'"$TT"'\) .*/\1/
91
+ p
92
+ }'
93
+}
94
+
95
+# On Windows (MINGW) when running with the bin-wrappers, we also see "sh.exe" in
96
+# the ancestry. We must therefore account for this expected ancestry element in
97
+# the expected output of the tests.
98
+if test_have_prereq MINGW && test -z "$no_bin_wrappers"; then
99
+ SH_TT="sh$X $TT"
100
+else
101
+ SH_TT="$TT"
102
+fi
103
+
104
+# Git alias resolution spawns the target command as a child process.
105
+# Using "git -c alias.xyz=version xyz" creates a two-level chain:
106
+#
107
+# test-tool (400ancestry)
108
+# -> git (resolves alias xyz -> version)
109
+# -> git (version)
110
+#
111
+# Both git processes are instrumented and emit cmd_ancestry. After
112
+# filtering out ancestors above test-tool, we get:
113
+#
114
+# test-tool (from git alias resolver)
115
+# git test-tool (from git version)
116
+
117
+test_expect_success TRACE2_ANCESTRY 'normal: git alias chain, 2 levels' '
118
+ test_when_finished "rm -f trace.normal actual expect" &&
119
+ test-tool trace2 400ancestry normal "$(pwd)/trace.normal" \
120
+ git -c alias.xyz=version xyz &&
121
+ filter_ancestry_normal <trace.normal >actual &&
122
+ cat >expect <<-EOF &&
123
+ $SH_TT
124
+ git$X $SH_TT
125
+ EOF
126
+ test_cmp expect actual
127
+'
128
+
129
+test_expect_success TRACE2_ANCESTRY 'perf: git alias chain, 2 levels' '
130
+ test_when_finished "rm -f trace.perf actual expect" &&
131
+ test-tool trace2 400ancestry perf "$(pwd)/trace.perf" \
132
+ git -c alias.xyz=version xyz &&
133
+ filter_ancestry_perf <trace.perf >actual &&
134
+ cat >expect <<-EOF &&
135
+ $SH_TT
136
+ git$X $SH_TT
137
+ EOF
138
+ test_cmp expect actual
139
+'
140
+
141
+test_expect_success TRACE2_ANCESTRY 'event: git alias chain, 2 levels' '
142
+ test_when_finished "rm -f trace.event actual expect" &&
143
+ test-tool trace2 400ancestry event "$(pwd)/trace.event" \
144
+ git -c alias.xyz=version xyz &&
145
+ filter_ancestry_event <trace.event >actual &&
146
+ cat >expect <<-EOF &&
147
+ $SH_TT
148
+ git$X $SH_TT
149
+ EOF
150
+ test_cmp expect actual
151
+'
152
+
153
+# Use 004child to add a test-tool layer, creating a three-level chain:
154
+#
155
+# test-tool (400ancestry)
156
+# -> test-tool (004child)
157
+# -> git (resolves alias xyz -> version)
158
+# -> git (version)
159
+#
160
+# Three instrumented processes emit cmd_ancestry. After filtering:
161
+#
162
+# test-tool (from test-tool 004child)
163
+# test-tool test-tool (from git alias resolver)
164
+# git test-tool test-tool (from git version)
165
+
166
+test_expect_success TRACE2_ANCESTRY 'normal: deeper chain, 3 levels' '
167
+ test_when_finished "rm -f trace.normal actual expect" &&
168
+ test-tool trace2 400ancestry normal "$(pwd)/trace.normal" \
169
+ test-tool trace2 004child \
170
+ git -c alias.xyz=version xyz &&
171
+ filter_ancestry_normal <trace.normal >actual &&
172
+ cat >expect <<-EOF &&
173
+ $TT
174
+ $SH_TT $TT
175
+ git$X $SH_TT $TT
176
+ EOF
177
+ test_cmp expect actual
178
+'
179
+
180
+test_done