All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Jeff Hostetler via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: jeffhost@microsoft.com, Junio C Hamano <gitster@pobox.com>,
	Jeff Hostetler <jeffhost@microsoft.com>
Subject: [PATCH v2 14/14] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh
Date: Mon, 28 Jan 2019 13:47:52 -0800 (PST)	[thread overview]
Message-ID: <851aa8f34d7223a3d872033abf2f2a95517b3b23.1548712060.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.108.v2.git.gitgitgadget@gmail.com>

From: Jeff Hostetler <jeffhost@microsoft.com>

Create unit tests for Trace2.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
---
 Makefile                  |   1 +
 t/helper/test-tool.c      |   1 +
 t/helper/test-tool.h      |   1 +
 t/helper/test-trace2.c    | 273 ++++++++++++++++++++++++++++++++++++++
 t/t0210-trace2-normal.sh  | 147 ++++++++++++++++++++
 t/t0210/scrub_normal.perl |  48 +++++++
 t/t0211-trace2-perf.sh    | 163 +++++++++++++++++++++++
 t/t0211/scrub_perf.perl   |  76 +++++++++++
 t/t0212-trace2-event.sh   | 246 ++++++++++++++++++++++++++++++++++
 t/t0212/parse_events.perl | 251 +++++++++++++++++++++++++++++++++++
 10 files changed, 1207 insertions(+)
 create mode 100644 t/helper/test-trace2.c
 create mode 100755 t/t0210-trace2-normal.sh
 create mode 100644 t/t0210/scrub_normal.perl
 create mode 100755 t/t0211-trace2-perf.sh
 create mode 100644 t/t0211/scrub_perf.perl
 create mode 100755 t/t0212-trace2-event.sh
 create mode 100644 t/t0212/parse_events.perl

diff --git a/Makefile b/Makefile
index 5d4e993cdc..8100364023 100644
--- a/Makefile
+++ b/Makefile
@@ -753,6 +753,7 @@ TEST_BUILTINS_OBJS += test-string-list.o
 TEST_BUILTINS_OBJS += test-submodule-config.o
 TEST_BUILTINS_OBJS += test-submodule-nested-repo-config.o
 TEST_BUILTINS_OBJS += test-subprocess.o
+TEST_BUILTINS_OBJS += test-trace2.o
 TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
 TEST_BUILTINS_OBJS += test-wildmatch.o
 TEST_BUILTINS_OBJS += test-windows-named-pipe.o
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index 85d1f812fe..3d591c00ac 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -49,6 +49,7 @@ static struct test_cmd cmds[] = {
 	{ "submodule-config", cmd__submodule_config },
 	{ "submodule-nested-repo-config", cmd__submodule_nested_repo_config },
 	{ "subprocess", cmd__subprocess },
+	{ "trace2", cmd__trace2 },
 	{ "urlmatch-normalization", cmd__urlmatch_normalization },
 	{ "wildmatch", cmd__wildmatch },
 #ifdef GIT_WINDOWS_NATIVE
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 042f12464b..226b86aca9 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -44,6 +44,7 @@ int cmd__string_list(int argc, const char **argv);
 int cmd__submodule_config(int argc, const char **argv);
 int cmd__submodule_nested_repo_config(int argc, const char **argv);
 int cmd__subprocess(int argc, const char **argv);
+int cmd__trace2(int argc, const char **argv);
 int cmd__urlmatch_normalization(int argc, const char **argv);
 int cmd__wildmatch(int argc, const char **argv);
 #ifdef GIT_WINDOWS_NATIVE
diff --git a/t/helper/test-trace2.c b/t/helper/test-trace2.c
new file mode 100644
index 0000000000..b867f58d32
--- /dev/null
+++ b/t/helper/test-trace2.c
@@ -0,0 +1,273 @@
+#include "test-tool.h"
+#include "cache.h"
+#include "argv-array.h"
+#include "run-command.h"
+#include "exec-cmd.h"
+#include "config.h"
+
+typedef int (fn_unit_test)(int argc, const char **argv);
+
+struct unit_test 
+{
+	fn_unit_test *ut_fn;
+	const char   *ut_name;
+	const char   *ut_usage;
+};
+
+#define MyOk    0
+#define MyError 1
+
+static int get_i(int *p_value, const char *data)
+{
+	char *endptr;
+
+	if (!data || !*data)
+		return MyError;
+
+	*p_value = strtol(data, &endptr, 10);
+	if (*endptr || errno == ERANGE)
+		return MyError;
+
+	return MyOk;
+}
+
+/*
+ * Cause process to exit with the requested value via "return".
+ *
+ * Rely on test-tool.c:cmd_main() to call trace2_cmd_exit()
+ * with our result.
+ *
+ * Test harness can confirm:
+ * [] the process-exit value.
+ * [] the "code" field in the "exit" trace2 event.
+ * [] the "code" field in the "atexit" trace2 event.
+ * [] the "name" field in the "cmd_verb" trace2 event.
+ * [] "def_param" events for all of the "interesting" pre-defined config settings.
+ */
+static int ut_001return(int argc, const char **argv)
+{
+	int rc;
+
+	if (get_i(&rc, argv[0]))
+		die("expect <exit_code>");
+
+	return rc;
+}
+
+/*
+ * Cause the process to exit with the requested value via "exit()".
+ *
+ * Test harness can confirm:
+ * [] the "code" field in the "exit" trace2 event.
+ * [] the "code" field in the "atexit" trace2 event.
+ * [] the "name" field in the "cmd_verb" trace2 event.
+ * [] "def_param" events for all of the "interesting" pre-defined config settings.
+ */
+static int ut_002exit(int argc, const char **argv)
+{
+	int rc;
+
+	if (get_i(&rc, argv[0]))
+		die("expect <exit_code>");
+
+	exit(rc);
+}
+
+/*
+ * Send an "error" event with each value in argv.  Normally, git only issues
+ * a single "error" event immediately before issuing an "exit" event (such
+ * as in die() or BUG()), but multiple "error" events are allowed.
+ *
+ * Test harness can confirm:
+ * [] a trace2 "error" event for each value in argv.
+ * [] the "name" field in the "cmd_verb" trace2 event.
+ * [] (optional) the file:line in the "exit" event refers to this function.
+ */
+static int ut_003error(int argc, const char **argv)
+{
+	int k;
+
+	if (!argv[0] || !*argv[0])
+		die("expect <error_message>");
+
+	for (k = 0; k < argc; k++)
+		error("%s", argv[k]);
+
+	return 0;
+}
+
+/*
+ * Run a child process and wait for it to finish and exit with its return code.
+ * test-tool trace2 004child [<child-command-line>]
+ *
+ * For example:
+ * test-tool trace2 004child git version
+ * test-tool trace2 004child test-tool trace2 001return 0
+ * test-tool trace2 004child test-tool trace2 004child test-tool trace2 004child
+ * test-tool trace2 004child git -c alias.xyz=version xyz
+ *
+ * Test harness can confirm:
+ * [] the "name" field in the "cmd_verb" trace2 event.
+ * [] that the outer process has a single component SID (or depth "d0" in
+ *    the PERF stream).
+ * [] that "child_start" and "child_exit" events are generated for the child.
+ * [] if the child process is an instrumented executable:
+ *    [] that "version", "start", ..., "exit", and "atexit" events are
+ *       generated by the child process.
+ *    [] that the child process events have a multiple component SID (or
+ *       depth "dN+1" in the PERF stream).
+ * [] that the child exit code is propagated to the parent process "exit"
+ *    and "atexit" events..
+ * [] (optional) that the "t_abs" field in the child process "atexit" event
+ *    is less than the "t_rel" field in the "child_exit" event of the parent
+ *    process.
+ * [] if the child process is like the alias example above,
+ *    [] (optional) the child process attempts to run "git-xyx" as a dashed
+ *       command.
+ *    [] the child process emits an "alias" event with "xyz" => "version"
+ *    [] the child process runs "git version" as a child process.
+ *    [] the child process has a 3 component SID (or depth "d2" in the PERF
+ *       stream).
+ */
+static int ut_004child(int argc, const char **argv)
+{
+	int result;
+
+	/*
+	 * Allow empty <child_command_line> so we can do arbitrarily deep
+	 * command nesting and let the last one be null.
+	 */
+	if (!argc)
+		return 0;
+
+	result = run_command_v_opt(argv, 0);
+	exit(result);
+}
+
+/*
+ * Exec a git command.  This may either create a child process (Windows)
+ * or replace the existing process.
+ * test-tool trace2 005exec <git_command_args>
+ *
+ * For example:
+ * test-tool trace2 005exec version
+ *
+ * Test harness can confirm (on Windows):
+ * [] the "name" field in the "cmd_verb" trace2 event.
+ * [] that the outer process has a single component SID (or depth "d0" in
+ *    the PERF stream).
+ * [] that "exec" and "exec_result" events are generated for the child
+ *    process (since the Windows compatibility layer fakes an exec() with
+ *    a CreateProcess(), WaitForSingleObject(), and exit()).
+ * [] that the child process has multiple component SID (or depth "dN+1"
+ *    in the PERF stream).
+ *
+ * Test harness can confirm (on platforms with a real exec() function):
+ * [] TODO talk about process replacement and how it affects SID.
+ */ 
+static int ut_005exec(int argc, const char **argv)
+{
+	int result;
+
+	if (!argc)
+		return 0;
+
+	result = execv_git_cmd(argv);
+	return result;
+}
+
+static int ut_006data(int argc, const char **argv)
+{
+	const char *usage_error =
+		"expect <cat0> <k0> <v0> [<cat1> <k1> <v1> [...]]";
+
+	if (argc % 3 != 0)
+		die("%s", usage_error);
+
+	while (argc) {
+		if (!argv[0] || !*argv[0] ||
+		    !argv[1] || !*argv[1] ||
+		    !argv[2] || !*argv[2])
+			die("%s", usage_error);
+
+		trace2_data_string(argv[0], the_repository, argv[1], argv[2]);
+		argv += 3;
+		argc -= 3;
+	}
+
+	return 0;
+}
+
+/*
+ * Usage:
+ *     test-tool trace2 <ut_name_1> <ut_usage_1>
+ *     test-tool trace2 <ut_name_2> <ut_usage_2>
+ *     ...
+ */ 
+#define USAGE_PREFIX "test-tool trace2"
+
+static struct unit_test ut_table[] = {
+	{ ut_001return,   "001return", "<exit_code>" },
+	{ ut_002exit,     "002exit",   "<exit_code>" },
+	{ ut_003error,    "003error",  "<error_message>+" },
+	{ ut_004child,    "004child",  "[<child_command_line>]" },
+	{ ut_005exec,     "005exec",   "<git_command_args>" },
+	{ ut_006data,     "006data",   "[<category> <key> <value>]+" },
+};
+
+#define for_each_ut(k, ut_k)			\
+	for (k = 0, ut_k = &ut_table[k];	\
+	     k < ARRAY_SIZE(ut_table);		\
+	     k++, ut_k = &ut_table[k])
+
+static int print_usage(void)
+{
+	int k;
+	struct unit_test *ut_k;
+
+	fprintf(stderr, "usage:\n");
+	for_each_ut(k, ut_k) {
+		fprintf(stderr, "\t%s %s %s\n",
+			USAGE_PREFIX, ut_k->ut_name, ut_k->ut_usage);
+	}
+
+	return 129;
+}
+
+/*
+ * Issue various trace2 events for testing.
+ *
+ * We assume that these trace2 routines has already been called:
+ *    [] trace2_initialize()      [common-main.c:main()]
+ *    [] trace2_cmd_start()       [common-main.c:main()]
+ *    [] trace2_cmd_verb()        [test-tool.c:cmd_main()]
+ *    [] tracd2_cmd_list_config() [test-tool.c:cmd_main()]
+ * So that:
+ *    [] the various trace2 streams are open.
+ *    [] the process SID has been created.
+ *    [] the "version" event has been generated.
+ *    [] the "start" event has been generated.
+ *    [] the "verb" event has been generated.
+ *    [] this writes various "def_param" events for interesting config values.
+ *
+ * We further assume that if we return (rather than exit()), trace2_cmd_exit()
+ * will be called by test-tool.c:cmd_main().
+ */
+int cmd__trace2(int argc, const char **argv)
+{
+	int k;
+	struct unit_test *ut_k;
+
+	argc--;	/* skip over "trace2" arg */
+	argv++;
+
+	if (argc) {
+		for_each_ut(k, ut_k) {
+			if (!strcmp(argv[0], ut_k->ut_name))
+				return ut_k->ut_fn(argc - 1, argv + 1);
+		}
+	}
+
+	return print_usage();
+}
+
diff --git a/t/t0210-trace2-normal.sh b/t/t0210-trace2-normal.sh
new file mode 100755
index 0000000000..f5790d565e
--- /dev/null
+++ b/t/t0210-trace2-normal.sh
@@ -0,0 +1,147 @@
+#!/bin/sh
+
+test_description='test trace2 facility (normal target)'
+. ./test-lib.sh
+
+# Add t/helper directory to PATH so that we can use a relative
+# path to run nested instances of test-tool.exe (see 004child).
+# This helps with HEREDOC comparisons later.
+TTDIR="$GIT_BUILD_DIR/t/helper/" && export TTDIR
+PATH="$TTDIR:$PATH" && export PATH
+
+TT="test-tool" && export TT
+
+# Warning: use of 'test_cmp' may run test-tool.exe and/or git.exe
+# Warning: to do the actual diff/comparison, so the HEREDOCs here
+# Warning: only cover our actual calls to test-tool and/or git.
+# Warning: So you may see extra lines in artifact files when
+# Warning: interactively debugging.
+
+# Turn off any inherited trace2 settings for this test.
+unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+unset GIT_TR2_BRIEF
+unset GIT_TR2_CONFIG_PARAMS
+
+V=$(git version | sed -e 's/^git version //') && export V
+
+# There are multiple trace2 targets: normal, perf, and event.
+# Trace2 events will/can be written to each active target (subject
+# to whatever filtering that target decides to do).
+# This script tests the normal target in isolation.
+#
+# Defer setting GIT_TR2 until the actual command line we want to test
+# because hidden git and test-tool commands run by the test harness
+# can contaminate our output.
+
+# Enable "brief" feature which turns off "<clock> <file>:<line> " prefix.
+GIT_TR2_BRIEF=1 && export GIT_TR2_BRIEF
+
+# Basic tests of the trace2 normal stream.  Since this stream is used
+# primarily with printf-style debugging/tracing, we do limited testing
+# here.
+#
+# We do confirm the following API features:
+# [] the 'version <v>' event
+# [] the 'start <argv>' event
+# [] the 'cmd_verb <verb>' event
+# [] the 'exit <time> code:<code>' event
+# [] the 'atexit <time> code:<code>' event
+#
+# Fields of the form _FIELD_ are tokens that have been replaced (such
+# as the elapsed time).
+
+# Verb 001return
+#
+# Implicit return from cmd_<verb> function propagates <code>.
+
+test_expect_success 'normal stream, return code 0' '
+	test_when_finished "rm trace.normal actual expect" &&
+	GIT_TR2="$(pwd)/trace.normal" && export GIT_TR2 &&
+	$TT trace2 001return 0 &&
+	unset GIT_TR2 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 0
+		cmd_verb trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'normal stream, return code 1' '
+	test_when_finished "rm trace.normal actual expect" &&
+	GIT_TR2="$(pwd)/trace.normal" && export GIT_TR2 &&
+	test_must_fail $TT trace2 001return 1 &&
+	unset GIT_TR2 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 001return 1
+		cmd_verb trace2 (trace2)
+		exit elapsed:_TIME_ code:1
+		atexit elapsed:_TIME_ code:1
+	EOF
+	test_cmp expect actual
+'
+
+# Verb 002exit
+#
+# Explicit exit(code) from within cmd_<verb> propagates <code>.
+
+test_expect_success 'normal stream, exit code 0' '
+	test_when_finished "rm trace.normal actual expect" &&
+	GIT_TR2="$(pwd)/trace.normal" && export GIT_TR2 &&
+	$TT trace2 002exit 0 &&
+	unset GIT_TR2 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 002exit 0
+		cmd_verb trace2 (trace2)
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'normal stream, exit code 1' '
+	test_when_finished "rm trace.normal actual expect" &&
+	GIT_TR2="$(pwd)/trace.normal" && export GIT_TR2 &&
+	test_must_fail $TT trace2 002exit 1 &&
+	unset GIT_TR2 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 002exit 1
+		cmd_verb trace2 (trace2)
+		exit elapsed:_TIME_ code:1
+		atexit elapsed:_TIME_ code:1
+	EOF
+	test_cmp expect actual
+'
+
+# Verb 003error
+#
+# To the above, add multiple 'error <msg>' events
+
+test_expect_success 'normal stream, error event' '
+	test_when_finished "rm trace.normal actual expect" &&
+	GIT_TR2="$(pwd)/trace.normal" && export GIT_TR2 &&
+	$TT trace2 003error "hello world" "this is a test" &&
+	unset GIT_TR2 &&
+	perl "$TEST_DIRECTORY/t0210/scrub_normal.perl" <trace.normal >actual &&
+	cat >expect <<-EOF &&
+		version $V
+		start _EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\''
+		cmd_verb trace2 (trace2)
+		error hello world
+		error this is a test
+		exit elapsed:_TIME_ code:0
+		atexit elapsed:_TIME_ code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0210/scrub_normal.perl b/t/t0210/scrub_normal.perl
new file mode 100644
index 0000000000..c65d1a815e
--- /dev/null
+++ b/t/t0210/scrub_normal.perl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+#
+# Scrub the variable fields from the normal trace2 output to
+# make testing easier.
+
+use strict;
+use warnings;
+
+my $float = '[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?';
+
+# This code assumes that the trace2 data was written with bare
+# turned on (which omits the "<clock> <file>:<line>" prefix.
+
+while (<>) {
+    # Various messages include an elapsed time in the middle
+    # of the message.  Replace the time with a placeholder to
+    # simplify our HEREDOC in the test script.
+    s/elapsed:$float/elapsed:_TIME_/g;
+
+    my $line = $_;
+
+    # we expect:
+    #    start <argv0> [<argv1> [<argv2> [...]]]
+    #
+    # where argv0 might be a relative or absolute path, with
+    # or without quotes, and platform dependent.  Replace argv0
+    # with a token for HEREDOC matching in the test script.
+
+    if ($line =~ m/^start/) {
+	$line =~ /^start\s+(.*)/;
+	my $argv = $1;
+	$argv =~ m/(\'[^\']*\'|[^ ]+)\s+(.*)/;
+	my $argv_0 = $1;
+	my $argv_rest = $2;
+
+	print "start _EXE_ $argv_rest\n";
+    }
+    elsif ($line =~ m/^cmd_path/) {
+	# Likewise, the 'cmd_path' message breaks out argv[0].
+	#
+	# This line is only emitted when RUNTIME_PREFIX is defined,
+	# so just omit it for testing purposes.
+	# print "cmd_path _EXE_\n";
+    }
+    else {
+	print "$line";
+    }
+}
diff --git a/t/t0211-trace2-perf.sh b/t/t0211-trace2-perf.sh
new file mode 100755
index 0000000000..b24104557c
--- /dev/null
+++ b/t/t0211-trace2-perf.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='test trace2 facility (perf target)'
+. ./test-lib.sh
+
+# Add t/helper directory to PATH so that we can use a relative
+# path to run nested instances of test-tool.exe (see 004child).
+# This helps with HEREDOC comparisons later.
+TTDIR="$GIT_BUILD_DIR/t/helper/" && export TTDIR
+PATH="$TTDIR:$PATH" && export PATH
+
+TT="test-tool" && export TT
+
+# Warning: use of 'test_cmp' may run test-tool.exe and/or git.exe
+# Warning: to do the actual diff/comparison, so the HEREDOCs here
+# Warning: only cover our actual calls to test-tool and/or git.
+# Warning: So you may see extra lines in artifact files when
+# Warning: interactively debugging.
+
+# Turn off any inherited trace2 settings for this test.
+unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+unset GIT_TR2_PERF_BRIEF
+unset GIT_TR2_CONFIG_PARAMS
+
+V=$(git version | sed -e 's/^git version //') && export V
+
+# There are multiple trace2 targets: normal, perf, and event.
+# Trace2 events will/can be written to each active target (subject
+# to whatever filtering that target decides to do).
+# Test each target independently.
+#
+# Defer setting GIT_TR2_PERF until the actual command we want to
+# test because hidden git and test-tool commands in the test
+# harness can contaminate our output.
+
+# Enable "brief" feature which turns off the prefix:
+#     "<clock> <file>:<line> | <nr_parents> | "
+GIT_TR2_PERF_BRIEF=1 && export GIT_TR2_PERF_BRIEF
+
+# Repeat some of the t0210 tests using the perf target stream instead of
+# the normal stream.
+#
+# Tokens here of the form _FIELD_ have been replaced in the observed output.
+
+# Verb 001return
+#
+# Implicit return from cmd_<verb> function propagates <code>.
+
+test_expect_success 'perf stream, return code 0' '
+	test_when_finished "rm trace.perf actual expect" &&
+	GIT_TR2_PERF="$(pwd)/trace.perf" && export GIT_TR2_PERF &&
+	$TT trace2 001return 0 &&
+	unset GIT_TR2_PERF &&
+	perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+	cat >expect <<-EOF &&
+		d0|main|version|||||$V
+		d0|main|start|||||_EXE_ trace2 001return 0
+		d0|main|cmd_verb|||||trace2 (trace2)
+		d0|main|exit||_T_ABS_|||code:0
+		d0|main|atexit||_T_ABS_|||code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'perf stream, return code 1' '
+	test_when_finished "rm trace.perf actual expect" &&
+	GIT_TR2_PERF="$(pwd)/trace.perf" && export GIT_TR2_PERF &&
+	test_must_fail $TT trace2 001return 1 &&
+	unset GIT_TR2_PERF &&
+	perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+	cat >expect <<-EOF &&
+		d0|main|version|||||$V
+		d0|main|start|||||_EXE_ trace2 001return 1
+		d0|main|cmd_verb|||||trace2 (trace2)
+		d0|main|exit||_T_ABS_|||code:1
+		d0|main|atexit||_T_ABS_|||code:1
+	EOF
+	test_cmp expect actual
+'
+
+# Verb 003error
+#
+# To the above, add multiple 'error <msg>' events
+
+test_expect_success 'perf stream, error event' '
+	test_when_finished "rm trace.perf actual expect" &&
+	GIT_TR2_PERF="$(pwd)/trace.perf" && export GIT_TR2_PERF &&
+	$TT trace2 003error "hello world" "this is a test" &&
+	unset GIT_TR2_PERF &&
+	perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+	cat >expect <<-EOF &&
+		d0|main|version|||||$V
+		d0|main|start|||||_EXE_ trace2 003error '\''hello world'\'' '\''this is a test'\''
+		d0|main|cmd_verb|||||trace2 (trace2)
+		d0|main|error|||||hello world
+		d0|main|error|||||this is a test
+		d0|main|exit||_T_ABS_|||code:0
+		d0|main|atexit||_T_ABS_|||code:0
+	EOF
+	test_cmp expect actual
+'
+
+# Verb 004child
+#
+# Test nested spawning of child processes.
+#
+# Conceptually, this looks like:
+#    P1: TT trace2 004child
+#    P2: |--- TT trace2 004child
+#    P3:      |--- TT trace2 001return 0
+#
+# Which should generate events:
+#    P1: version
+#    P1: start
+#    P1: cmd_verb
+#    P1: child_start
+#        P2: version
+#        P2: start
+#        P2: cmd_verb
+#        P2: child_start
+#            P3: version
+#            P3: start
+#            P3: cmd_verb
+#            P3: exit
+#            P3: atexit
+#        P2: child_exit
+#        P2: exit
+#        P2: atexit
+#    P1: child_exit
+#    P1: exit
+#    P1: atexit
+
+test_expect_success 'perf stream, child processes' '
+	test_when_finished "rm trace.perf actual expect" &&
+	GIT_TR2_PERF="$(pwd)/trace.perf" && export GIT_TR2_PERF &&
+	$TT trace2 004child $TT trace2 004child $TT trace2 001return 0 &&
+	unset GIT_TR2_PERF &&
+	perl "$TEST_DIRECTORY/t0211/scrub_perf.perl" <trace.perf >actual &&
+	cat >expect <<-EOF &&
+		d0|main|version|||||$V
+		d0|main|start|||||_EXE_ trace2 004child $TT trace2 004child $TT trace2 001return 0
+		d0|main|cmd_verb|||||trace2 (trace2)
+		d0|main|child_start||_T_ABS_|||[ch0] class:? argv: $TT trace2 004child $TT trace2 001return 0
+		d1|main|version|||||$V
+		d1|main|start|||||_EXE_ trace2 004child $TT trace2 001return 0
+		d1|main|cmd_verb|||||trace2 (trace2/trace2)
+		d1|main|child_start||_T_ABS_|||[ch0] class:? argv: $TT trace2 001return 0
+		d2|main|version|||||$V
+		d2|main|start|||||_EXE_ trace2 001return 0
+		d2|main|cmd_verb|||||trace2 (trace2/trace2/trace2)
+		d2|main|exit||_T_ABS_|||code:0
+		d2|main|atexit||_T_ABS_|||code:0
+		d1|main|child_exit||_T_ABS_|_T_REL_||[ch0] pid:_PID_ code:0
+		d1|main|exit||_T_ABS_|||code:0
+		d1|main|atexit||_T_ABS_|||code:0
+		d0|main|child_exit||_T_ABS_|_T_REL_||[ch0] pid:_PID_ code:0
+		d0|main|exit||_T_ABS_|||code:0
+		d0|main|atexit||_T_ABS_|||code:0
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0211/scrub_perf.perl b/t/t0211/scrub_perf.perl
new file mode 100644
index 0000000000..351af7844e
--- /dev/null
+++ b/t/t0211/scrub_perf.perl
@@ -0,0 +1,76 @@
+#!/usr/bin/perl
+#
+# Scrub the variable fields from the perf trace2 output to
+# make testing easier.
+
+use strict;
+use warnings;
+
+my $qpath = '\'[^\']*\'|[^ ]*';
+
+my $col_depth=0;
+my $col_thread=1;
+my $col_event=2;
+my $col_repo=3;
+my $col_t_abs=4;
+my $col_t_rel=5;
+my $col_category=6;
+my $col_rest=7;
+
+# This code assumes that the trace2 data was written with bare
+# turned on (which omits the "<clock> <file>:<line> | <parents>"
+# prefix.
+
+while (<>) {
+    my @tokens = split /\|/;
+
+    foreach my $col (@tokens) { $col =~ s/^\s+|\s+$//g; }
+
+    if ($tokens[$col_event] =~ m/^start/) {
+	# The 'start' message lists the contents of argv in $col_rest.
+	# On some platforms (Windows), argv[0] is *sometimes* a canonical
+	# absolute path to the EXE rather than the value passed in the
+	# shell script.  Replace it with a placeholder to simplify our
+	# HEREDOC in the test script.
+	my $argv0;
+	my $argvRest;
+	$tokens[$col_rest] =~ s/^($qpath)\W*(.*)/_EXE_ $2/;
+    }
+    elsif ($tokens[$col_event] =~ m/cmd_path/) {
+	# Likewise, the 'cmd_path' message breaks out argv[0].
+	#
+	# This line is only emitted when RUNTIME_PREFIX is defined,
+	# so just omit it for testing purposes.
+	# $tokens[$col_rest] = "_EXE_";
+	goto SKIP_LINE;
+    }
+    elsif ($tokens[$col_event] =~ m/child_exit/) {
+	$tokens[$col_rest] =~ s/ pid:\d* / pid:_PID_ /;
+    }
+    elsif ($tokens[$col_event] =~ m/data/) {
+	if ($tokens[$col_category] =~ m/process/) {
+	    # 'data' and 'data_json' events containing 'process'
+	    # category data are assumed to be platform-specific
+	    # and highly variable.  Just omit them.
+	    goto SKIP_LINE;
+	}
+    }
+
+    # t_abs and t_rel are either blank or a float.  Replace the float
+    # with a constant for matching the HEREDOC in the test script.
+    if ($tokens[$col_t_abs] =~ m/\d/) {
+	$tokens[$col_t_abs] = "_T_ABS_";
+    }
+    if ($tokens[$col_t_rel] =~ m/\d/) {
+	$tokens[$col_t_rel] = "_T_REL_";
+    }
+
+    my $out;
+
+    $out = join('|', @tokens);
+    print "$out\n";
+
+  SKIP_LINE:
+}
+
+
diff --git a/t/t0212-trace2-event.sh b/t/t0212-trace2-event.sh
new file mode 100755
index 0000000000..995bc5e1b3
--- /dev/null
+++ b/t/t0212-trace2-event.sh
@@ -0,0 +1,246 @@
+#!/bin/sh
+
+test_description='test trace2 facility'
+. ./test-lib.sh
+
+# Add t/helper directory to PATH so that we can use a relative
+# path to run nested instances of test-tool.exe (see 004child).
+# This helps with HEREDOC comparisons later.
+TTDIR="$GIT_BUILD_DIR/t/helper/" && export TTDIR
+PATH="$TTDIR:$PATH" && export PATH
+
+TT="test-tool" && export TT
+
+# Warning: use of 'test_cmp' may run test-tool.exe and/or git.exe
+# Warning: to do the actual diff/comparison, so the HEREDOCs here
+# Warning: only cover our actual calls to test-tool and/or git.
+# Warning: So you may see extra lines in artifact files when
+# Warning: interactively debugging.
+
+# Turn off any inherited trace2 settings for this test.
+unset GIT_TR2 GIT_TR2_PERF GIT_TR2_EVENT
+unset GIT_TR2_BARE
+unset GIT_TR2_CONFIG_PARAMS
+
+V=$(git version | sed -e 's/^git version //') && export V
+
+# There are multiple trace2 targets: normal, perf, and event.
+# Trace2 events will/can be written to each active target (subject
+# to whatever filtering that target decides to do).
+# Test each target independently.
+#
+# Defer setting GIT_TR2_PERF until the actual command we want to
+# test because hidden git and test-tool commands in the test
+# harness can contaminate our output.
+
+# We don't bother repeating the 001return and 002exit tests, since they
+# have coverage in the normal and perf targets.
+
+# Verb 003error
+#
+# To the above, add multiple 'error <msg>' events
+
+test_expect_success 'event stream, error event' '
+	test_when_finished "rm trace.event actual expect" &&
+	GIT_TR2_EVENT="$(pwd)/trace.event" && export GIT_TR2_EVENT &&
+	$TT trace2 003error "hello world" "this is a test" &&
+	unset GIT_TR2_EVENT &&
+	perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
+	sed -e "s/^|//" >expect <<-EOF &&
+	|VAR1 = {
+	|  "_SID0_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "003error",
+	|      "hello world",
+	|      "this is a test"
+	|    ],
+	|    "errors":[
+	|      "%s",
+	|      "%s"
+	|    ],
+	|    "exit_code":0,
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2",
+	|    "version":"$V"
+	|  }
+	|};
+	EOF
+	test_cmp expect actual
+'
+
+# Verb 004child
+#
+# Test nested spawning of child processes.
+#
+# Conceptually, this looks like:
+#    P1: TT trace2 004child
+#    P2: |--- TT trace2 004child
+#    P3:      |--- TT trace2 001return 0
+
+test_expect_success 'event stream, return code 0' '
+#	test_when_finished "rm trace.event actual expect" &&
+	GIT_TR2_EVENT="$(pwd)/trace.event" && export GIT_TR2_EVENT &&
+	$TT trace2 004child $TT trace2 004child $TT trace2 001return 0 &&
+	unset GIT_TR2_EVENT &&
+	perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
+	sed -e "s/^|//" >expect <<-EOF &&
+	|VAR1 = {
+	|  "_SID0_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "004child",
+	|      "$TT",
+	|      "trace2",
+	|      "004child",
+	|      "$TT",
+	|      "trace2",
+	|      "001return",
+	|      "0"
+	|    ],
+	|    "child":{
+	|      "0":{
+	|        "child_argv":[
+	|          "_EXE_",
+	|          "trace2",
+	|          "004child",
+	|          "$TT",
+	|          "trace2",
+	|          "001return",
+	|          "0"
+	|        ],
+	|        "child_class":"?",
+	|        "child_code":0,
+	|        "use_shell":0
+	|      }
+	|    },
+	|    "exit_code":0,
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2",
+	|    "version":"$V"
+	|  },
+	|  "_SID0_/_SID1_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "004child",
+	|      "$TT",
+	|      "trace2",
+	|      "001return",
+	|      "0"
+	|    ],
+	|    "child":{
+	|      "0":{
+	|        "child_argv":[
+	|          "_EXE_",
+	|          "trace2",
+	|          "001return",
+	|          "0"
+	|        ],
+	|        "child_class":"?",
+	|        "child_code":0,
+	|        "use_shell":0
+	|      }
+	|    },
+	|    "exit_code":0,
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2/trace2",
+	|    "version":"$V"
+	|  },
+	|  "_SID0_/_SID1_/_SID2_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "001return",
+	|      "0"
+	|    ],
+	|    "exit_code":0,
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2/trace2/trace2",
+	|    "version":"$V"
+	|  }
+	|};
+	EOF
+	test_cmp expect actual
+'
+
+# Test listing of all "interesting" config settings.
+
+test_expect_success 'event stream, list config' '
+	test_when_finished "rm trace.event actual expect" &&
+	git config --local t0212.abc 1 &&
+	git config --local t0212.def "hello world" &&
+	# delete events generated by the above config commands
+	rm trace.event &&
+	GIT_TR2_EVENT="$(pwd)/trace.event" && export GIT_TR2_EVENT &&
+	GIT_TR2_CONFIG_PARAMS="t0212.*" $TT trace2 001return 0 &&
+	unset GIT_TR2_EVENT &&
+	perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
+	sed -e "s/^|//" >expect <<-EOF &&
+	|VAR1 = {
+	|  "_SID0_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "001return",
+	|      "0"
+	|    ],
+	|    "exit_code":0,
+	|    "params":[
+	|      {
+	|        "param":"t0212.abc",
+	|        "value":"1"
+	|      },
+	|      {
+	|        "param":"t0212.def",
+	|        "value":"hello world"
+	|      }
+	|    ],
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2",
+	|    "version":"$V"
+	|  }
+	|};
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'basic trace2_data' '
+	test_when_finished "rm trace.event actual expect" &&
+	GIT_TR2_EVENT="$(pwd)/trace.event" && export GIT_TR2_EVENT &&
+	$TT trace2 006data test_category k1 v1 test_category k2 v2 &&
+	unset GIT_TR2_EVENT &&
+	perl "$TEST_DIRECTORY/t0212/parse_events.perl" <trace.event >actual &&
+	sed -e "s/^|//" >expect <<-EOF &&
+	|VAR1 = {
+	|  "_SID0_":{
+	|    "argv":[
+	|      "_EXE_",
+	|      "trace2",
+	|      "006data",
+	|      "test_category",
+	|      "k1",
+	|      "v1",
+	|      "test_category",
+	|      "k2",
+	|      "v2"
+	|    ],
+	|    "data":{
+	|      "test_category":{
+	|        "k1":"v1",
+	|        "k2":"v2"
+	|      }
+	|    },
+	|    "exit_code":0,
+	|    "verb":"trace2",
+	|    "verb_hierarchy":"trace2",
+	|    "version":"$V"
+	|  }
+	|};
+	EOF
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0212/parse_events.perl b/t/t0212/parse_events.perl
new file mode 100644
index 0000000000..0e38fa6db6
--- /dev/null
+++ b/t/t0212/parse_events.perl
@@ -0,0 +1,251 @@
+#!/usr/bin/perl
+#
+# Parse event stream and convert individual events into a summary
+# record for the process.
+#
+# Git.exe generates one or more "event" records for each API method,
+# such as "start <argv>" and "exit <code>", during the life of the git
+# process.  Additionally, the input may contain interleaved events
+# from multiple concurrent git processes and/or multiple threads from
+# within a git process.
+#
+# Accumulate events for each process (based on its unique SID) in a
+# dictionary and emit process summary records.
+#
+# Convert some of the variable fields (such as elapsed time) into
+# placeholders (or omit them) to make HEREDOC comparisons easier in
+# the test scripts.
+#
+# We may also omit fields not (currently) useful for testing purposes.
+
+use strict;
+use warnings;
+use JSON::PP;
+use Data::Dumper;
+use Getopt::Long;
+
+# The version of the trace2 event target format that we understand.
+# This is reported in the 'version' event in the 'evt' field.
+# It comes from the GIT_TR2_EVENT_VERSION macro in trace2/tr2_tgt_event.c
+my $evt_version = '1';
+
+my $show_children = 1;
+my $show_exec     = 1;
+my $show_threads  = 1;
+
+# A hack to generate test HEREDOC data for pasting into the test script.
+# Usage:
+#    cd "t/trash directory.t0212-trace2-event"
+#    $TT trace ... >trace.event
+#    VV=$(../../git.exe version | sed -e 's/^git version //')
+#    perl ../t0212/parse_events.perl --HEREDOC --VERSION=$VV <trace.event >heredoc
+# Then paste heredoc into your new test.
+
+my $gen_heredoc = 0;
+my $gen_version = '';
+
+GetOptions("children!" => \$show_children,
+	   "exec!"     => \$show_exec,
+	   "threads!"  => \$show_threads,
+	   "HEREDOC!"  => \$gen_heredoc,
+	   "VERSION=s" => \$gen_version    )
+    or die("Error in command line arguments\n");
+
+
+# SIDs contains timestamps and PIDs of the process and its parents.
+# This makes it difficult to match up in a HEREDOC in the test script.
+# Build a map from actual SIDs to predictable constant values and yet
+# keep the parent/child relationships.  For example:
+# {..., "sid":"1539706952458276-8652", ...}
+# {..., "sid":"1539706952458276-8652/1539706952649493-15452", ...}
+# becomes:
+# {..., "sid":"_SID1_", ...}
+# {..., "sid":"_SID1_/_SID2_", ...}
+my $sid_map;
+my $sid_count = 0;
+
+my $processes;
+
+while (<>) {
+    my $line = decode_json( $_ );
+
+    my $sid = "";
+    my $sid_sep = "";
+
+    my $raw_sid = $line->{'sid'};
+    my @raw_sid_parts = split /\//, $raw_sid;
+    foreach my $raw_sid_k (@raw_sid_parts) {
+	if (!exists $sid_map->{$raw_sid_k}) {
+	    $sid_map->{$raw_sid_k} = '_SID' . $sid_count . '_';
+	    $sid_count++;
+	}
+	$sid = $sid . $sid_sep . $sid_map->{$raw_sid_k};
+	$sid_sep = '/';
+    }
+    
+    my $event = $line->{'event'};
+
+    if ($event eq 'version') {
+	$processes->{$sid}->{'version'} = $line->{'exe'};
+	if ($gen_heredoc == 1 && $gen_version eq $line->{'exe'}) {
+	    # If we are generating data FOR the test script, replace
+	    # the reported git.exe version with a reference to an
+	    # environment variable.  When our output is pasted into
+	    # the test script, it will then be expanded in future
+	    # test runs to the THEN current version of git.exe.
+	    # We assume that the test script uses env var $V.
+	    $processes->{$sid}->{'version'} = "\$V";
+	}
+    }
+
+    elsif ($event eq 'start') {
+	$processes->{$sid}->{'argv'} = $line->{'argv'};
+	$processes->{$sid}->{'argv'}[0] = "_EXE_";
+    }
+
+    elsif ($event eq 'exit') {
+	$processes->{$sid}->{'exit_code'} = $line->{'code'};
+    }
+
+    elsif ($event eq 'atexit') {
+	$processes->{$sid}->{'exit_code'} = $line->{'code'};
+    }
+
+    elsif ($event eq 'error') {
+	# For HEREDOC purposes, use the error message format string if
+	# available, rather than the formatted message (which probably
+	# has an absolute pathname).
+	if (exists $line->{'fmt'}) {
+	    push( @{$processes->{$sid}->{'errors'}}, $line->{'fmt'} );
+	}
+	elsif (exists $line->{'msg'}) {
+	    push( @{$processes->{$sid}->{'errors'}}, $line->{'msg'} );
+	}
+    }
+
+    elsif ($event eq 'cmd_path') {
+	## $processes->{$sid}->{'path'} = $line->{'path'};
+	#
+	# Like in the 'start' event, we need to replace the value of
+	# argv[0] with a token for HEREDOC purposes.  However, the
+	# event is only emitted when RUNTIME_PREFIX is defined, so
+	# just omit it for testing purposes.
+	# $processes->{$sid}->{'path'} = "_EXE_";
+    }
+    
+    elsif ($event eq 'cmd_verb') {
+	$processes->{$sid}->{'verb'} = $line->{'name'};
+	$processes->{$sid}->{'verb_hierarchy'} = $line->{'hierarchy'};
+    }
+
+    elsif ($event eq 'alias') {
+	$processes->{$sid}->{'alias'}->{'key'} = $line->{'alias'};
+	$processes->{$sid}->{'alias'}->{'argv'} = $line->{'argv'};
+    }
+
+    elsif ($event eq 'def_param') {
+	my $kv;
+	$kv->{'param'} = $line->{'param'};
+	$kv->{'value'} = $line->{'value'};
+	push( @{$processes->{$sid}->{'params'}}, $kv );
+    }
+
+    elsif ($event eq 'child_start') {
+	if ($show_children == 1) {
+	    $processes->{$sid}->{'child'}->{$line->{'child_id'}}->{'child_class'} = $line->{'child_class'};
+	    $processes->{$sid}->{'child'}->{$line->{'child_id'}}->{'child_argv'} = $line->{'argv'};
+	    $processes->{$sid}->{'child'}->{$line->{'child_id'}}->{'child_argv'}[0] = "_EXE_";
+	    $processes->{$sid}->{'child'}->{$line->{'child_id'}}->{'use_shell'} = $line->{'use_shell'} ? 1 : 0;
+	}
+    }
+
+    elsif ($event eq 'child_exit') {
+	if ($show_children == 1) {
+	    $processes->{$sid}->{'child'}->{$line->{'child_id'}}->{'child_code'} = $line->{'code'};
+	}
+    }
+
+    # TODO decide what information we want to test from thread events.
+
+    elsif ($event eq 'thread_start') {
+	if ($show_threads == 1) {
+	}
+    }
+
+    elsif ($event eq 'thread_exit') {
+	if ($show_threads == 1) {
+	}
+    }
+
+    # TODO decide what information we want to test from exec events.
+
+    elsif ($event eq 'exec') {
+	if ($show_exec == 1) {
+	}
+    }
+
+    elsif ($event eq 'exec_result') {
+	if ($show_exec == 1) {
+	}
+    }
+
+    elsif ($event eq 'def_param') {
+	# Accumulate parameter key/value pairs by key rather than in an array
+	# so that we get overwrite (last one wins) effects.
+	$processes->{$sid}->{'params'}->{$line->{'param'}} = $line->{'value'};
+    }
+
+    elsif ($event eq 'def_repo') {
+	# $processes->{$sid}->{'repos'}->{$line->{'repo'}} = $line->{'worktree'};
+	$processes->{$sid}->{'repos'}->{$line->{'repo'}} = "_WORKTREE_";
+    }
+
+    # A series of potentially nested and threaded region and data events
+    # is fundamentally incompatibile with the type of summary record we
+    # are building in this script.  Since they are intended for
+    # perf-trace-like analysis rather than a result summary, we ignore
+    # most of them here.
+
+    # elsif ($event eq 'region_enter') {
+    # }
+    # elsif ($event eq 'region_leave') {
+    # }
+
+    elsif ($event eq 'data') {
+	my $cat = $line->{'category'};
+	if ($cat eq 'test_category') {
+	    
+	    my $key = $line->{'key'};
+	    my $value = $line->{'value'};
+	    $processes->{$sid}->{'data'}->{$cat}->{$key} = $value;
+	}
+    }
+
+    # This trace2 target does not emit 'printf' events.
+    #
+    # elsif ($event eq 'printf') {
+    # }
+}
+
+# Dump the resulting hash into something that we can compare against
+# in the test script.  These options make Dumper output look a little
+# bit like JSON.  Also convert variable references of the form "$VAR*"
+# so that the matching HEREDOC doesn't need to escape it.
+
+$Data::Dumper::Sortkeys = 1;
+$Data::Dumper::Indent = 1;
+$Data::Dumper::Purity = 1;
+$Data::Dumper::Pair = ':';
+
+my $out = Dumper($processes);
+$out =~ s/'/"/g;
+$out =~ s/\$VAR/VAR/g;
+
+# Finally, if we're running this script to generate (manually confirmed)
+# data to add to the test script, guard the indentation.
+
+if ($gen_heredoc == 1) {
+    $out =~ s/^/\t\|/gms;
+}
+
+print $out;
-- 
gitgitgadget

  parent reply	other threads:[~2019-01-28 21:47 UTC|newest]

Thread overview: 154+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-22 21:22 [PATCH 00/14] Trace2 tracing facility Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 01/14] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-01-23 20:51   ` Junio C Hamano
2019-01-25 21:13     ` Jeff Hostetler
2019-01-25 13:19   ` SZEDER Gábor
2019-01-25 17:53     ` Josh Steadmon
2019-01-22 21:22 ` [PATCH 02/14] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-01-25 11:22   ` SZEDER Gábor
2019-01-25 19:13     ` Junio C Hamano
2019-01-22 21:22 ` [PATCH 04/14] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 03/14] trace2: collect platform-specific process information Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 05/14] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 06/14] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 07/14] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 08/14] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 09/14] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 10/14] pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-01-23  1:19   ` Derrick Stolee
2019-01-22 21:22 ` [PATCH 11/14] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 12/14] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 13/14] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-01-22 21:22 ` [PATCH 14/14] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-01-22 23:21 ` [PATCH 00/14] Trace2 tracing facility Junio C Hamano
2019-01-25 20:03 ` Josh Steadmon
2019-01-30 18:45   ` Jeff Hostetler
2019-01-28 16:15 ` Jeff Hostetler
2019-01-28 18:07   ` Junio C Hamano
2019-01-28 21:47 ` [PATCH v2 " Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 01/14] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 02/14] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 03/14] trace2: collect platform-specific process information Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 04/14] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 05/14] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 06/14] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 07/14] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 08/14] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 09/14] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 10/14] pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 11/14] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 12/14] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` [PATCH v2 13/14] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-01-28 21:47   ` Jeff Hostetler via GitGitGadget [this message]
2019-01-28 22:23     ` [PATCH v2 14/14] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Junio C Hamano
2019-01-29 22:08       ` Jeff Hostetler
2019-01-30 19:51   ` [PATCH v3 00/14] Trace2 tracing facility Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 01/14] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 02/14] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 04/14] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 03/14] trace2: collect platform-specific process information Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 06/14] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 05/14] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 07/14] trace2:data: add trace2 transport " Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 08/14] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 09/14] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 10/14] pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 12/14] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 11/14] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 13/14] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-01-30 19:51     ` [PATCH v3 14/14] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-01-30 20:56     ` [PATCH v4 00/14] Trace2 tracing facility Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 01/14] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-01-31 14:11         ` SZEDER Gábor
2019-01-31 22:33           ` Jeff Hostetler
2019-01-31 23:39             ` Junio C Hamano
2019-01-30 20:56       ` [PATCH v4 02/14] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 03/14] trace2: collect platform-specific process information Jeff Hostetler via GitGitGadget
2019-01-31 23:15         ` SZEDER Gábor
2019-02-01 11:12           ` Jeff Hostetler
2019-01-30 20:56       ` [PATCH v4 04/14] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 05/14] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 06/14] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 07/14] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 08/14] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 09/14] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 10/14] pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 11/14] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 12/14] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 13/14] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-01-30 20:56       ` [PATCH v4 14/14] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-01-31 23:28         ` SZEDER Gábor
2019-01-31 23:41           ` Junio C Hamano
2019-02-01 11:08             ` Jeff Hostetler
2019-01-31 18:46       ` [PATCH v4 00/14] Trace2 tracing facility Junio C Hamano
2019-02-01 17:58       ` [PATCH v5 00/15] " Jeff Hostetler via GitGitGadget
2019-02-01 17:58         ` [PATCH v5 01/15] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 02/15] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 03/15] trace2: collect Windows-specific process information Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 04/15] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 05/15] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 06/15] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 07/15] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 08/15] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 09/15] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 10/15] trace2:data: pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 11/15] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 12/15] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 14/15] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-02-13 13:15           ` Ævar Arnfjörð Bjarmason
2019-02-01 17:59         ` [PATCH v5 13/15] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-02-01 17:59         ` [PATCH v5 15/15] trace2: add for_each macros to clang-format Jeff Hostetler via GitGitGadget
2019-02-06 17:15         ` [PATCH v6 00/15] Trace2 tracing facility Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 01/15] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 02/15] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-02-15 16:00             ` Ævar Arnfjörð Bjarmason
2019-02-15 17:57               ` Jeff Hostetler
2019-02-06 17:15           ` [PATCH v6 03/15] trace2: collect Windows-specific process information Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 04/15] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 05/15] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 06/15] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-02-06 17:15           ` [PATCH v6 07/15] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 09/15] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 08/15] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 10/15] trace2:data: pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 11/15] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 12/15] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 13/15] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 14/15] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-02-06 17:16           ` [PATCH v6 15/15] trace2: add for_each macros to clang-format Jeff Hostetler via GitGitGadget
2019-02-14 12:33           ` [PATCH v6 00/15] Trace2 tracing facility Ævar Arnfjörð Bjarmason
2019-02-15 17:25             ` Jeff Hostetler
2019-03-17 14:22               ` Ævar Arnfjörð Bjarmason
2019-03-21 14:30                 ` Johannes Schindelin
2019-03-21 14:48                   ` Ævar Arnfjörð Bjarmason
2019-03-22 13:17                     ` Johannes Schindelin
2019-03-22 14:01                       ` Jeff Hostetler
2019-03-22 14:53                         ` Ævar Arnfjörð Bjarmason
2019-03-22 15:21                           ` Jeff Hostetler
2019-02-22 22:24           ` [PATCH v7 " Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 01/15] trace2: Documentation/technical/api-trace2.txt Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 02/15] trace2: create new combined trace facility Jeff Hostetler via GitGitGadget
2019-05-10 17:28               ` SZEDER Gábor
2019-05-10 19:54                 ` Derrick Stolee
2019-02-22 22:25             ` [PATCH v7 03/15] trace2: collect Windows-specific process information Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 04/15] trace2:data: add trace2 regions to wt-status Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 05/15] trace2:data: add editor/pager child classification Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 06/15] trace2:data: add trace2 sub-process classification Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 07/15] trace2:data: add trace2 transport child classification Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 08/15] trace2:data: add trace2 hook classification Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 09/15] trace2:data: add trace2 instrumentation to index read/write Jeff Hostetler via GitGitGadget
2019-05-10 13:37               ` [PATCH] trace2: fix up a missing "leave" entry point Ævar Arnfjörð Bjarmason
2019-05-10 13:45                 ` Derrick Stolee
2019-05-20 16:50                 ` Jeff Hostetler
2019-02-22 22:25             ` [PATCH v7 10/15] trace2:data: pack-objects: add trace2 regions Derrick Stolee via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 11/15] trace2:data: add subverb to checkout command Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 12/15] trace2:data: add subverb to reset command Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 14/15] trace2: t/helper/test-trace2, t0210.sh, t0211.sh, t0212.sh Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 13/15] trace2:data: add subverb for rebase Jeff Hostetler via GitGitGadget
2019-02-22 22:25             ` [PATCH v7 15/15] trace2: add for_each macros to clang-format Jeff Hostetler via GitGitGadget
2019-01-31 14:38     ` [PATCH v3 00/14] Trace2 tracing facility SZEDER Gábor
2019-01-31 14:53       ` Jeff Hostetler
2019-01-31 18:51         ` Junio C Hamano
2019-01-31 19:45           ` Jeff Hostetler
2019-01-31 22:11             ` Jeff Hostetler
2019-01-31 23:30               ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=851aa8f34d7223a3d872033abf2f2a95517b3b23.1548712060.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jeffhost@microsoft.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.