From: Jonathan Nieder <jrnieder@gmail.com>
To: git@vger.kernel.org
Cc: Sebastian Celis <sebastian@sebastiancelis.com>,
Jeff King <peff@peff.net>, Junio C Hamano <gitster@pobox.com>,
Johannes Sixt <j6t@kdbg.org>
Subject: [PATCH/RFC 7/7] t7006-pager: if stdout is not a terminal, make a new one
Date: Fri, 19 Feb 2010 01:23:31 -0600 [thread overview]
Message-ID: <20100219072331.GG29916@progeny.tock> (raw)
In-Reply-To: <20100219065010.GA22258@progeny.tock>
Test t7006-pager skips most of its tests except when running with
--verbose, for lack of a terminal to use. Thus many of the tests
would not get much coverage, since whole testsuite runs with --verbose
are rare. Redirecting output to /dev/tty would be problematic because
(1) there really could be no controlling terminal and (2) test
breakage might manifest itself by the producing extraneous output.
Luckily, there is a way around this: Unix98-style pseudo-terminals
allow us to create a fake terminal on the fly and capture its output.
Do so. The new test-terminal command to accomplish this uses
posix_openpt (from SuSv3) to create a terminal because that is good
enough on Linux. I would like some feedback on what platforms are
missing that function and thus what alternate interfaces are worth
supporting. The perl IO::Tty module could take care of this for us,
but I do not think it is worth the extra dependency.
The test-terminal facility can be disabled by passing
NO_POSIX_OPENPT=YesPlease to the makefile, in which case the test
will revert to its old behavior (skipping most tests unless
GIT_TEST_OPTS includes --verbose).
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Requiring users to add NO_POSIX_OPENPT themselves doesn’t seem so
great. I did it that way just so I could send something and get
some feedback; a more suitable version would need a way to detect
missing openpt on the fly, for example by noticing the compilation
failure and continuing anyway.
.gitignore | 1 +
Makefile | 6 +++++
| 28 +++++++++++++++--------
test-terminal.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 10 deletions(-)
create mode 100644 test-terminal.c
diff --git a/.gitignore b/.gitignore
index 8df8f88..6b405ba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,6 +169,7 @@
/test-run-command
/test-sha1
/test-sigchain
+/test-terminal
/common-cmds.h
*.tar.gz
*.dsc
diff --git a/Makefile b/Makefile
index 7bf2fca..9c900a7 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,8 @@ all::
#
# Define NO_MEMMEM if you don't have memmem.
#
+# Define NO_POSIX_OPENPT if you don't have posix_openpt (for tests).
+#
# Define NO_STRLCPY if you don't have strlcpy.
#
# Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@@ -1727,6 +1729,10 @@ TEST_PROGRAMS_NEED_X += test-sha1
TEST_PROGRAMS_NEED_X += test-sigchain
TEST_PROGRAMS_NEED_X += test-index-version
+ifndef NO_POSIX_OPENPT
+TEST_PROGRAMS_NEED_X += test-terminal
+endif
+
TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
--git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 2e9cb9d..21788e3 100644
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -5,18 +5,26 @@ test_description='Test automatic use of a pager.'
. ./test-lib.sh
rm -f stdout_is_tty
-test_expect_success 'is stdout a terminal?' '
+test_expect_success 'set up terminal for tests' '
if test -t 1
then
: > stdout_is_tty
+ elif test-terminal sh -c "test -t 1"
+ then
+ : > test_terminal_works
fi
'
if test -e stdout_is_tty
then
+ test_terminal() { "$@"; }
+ test_set_prereq TTY
+elif test -e test_terminal_works
+then
+ test_terminal() { test-terminal "$@"; }
test_set_prereq TTY
else
- say stdout is not a terminal, so skipping some tests.
+ say no usable terminal, so skipping some tests
fi
unset GIT_PAGER GIT_PAGER_IN_USE
@@ -30,13 +38,13 @@ test_expect_success 'setup' '
rm -f paginated.out
test_expect_success TTY 'some commands use a pager' '
- git log &&
+ test_terminal git log &&
test -e paginated.out
'
rm -f paginated.out
test_expect_success TTY 'some commands do not use a pager' '
- git rev-list HEAD &&
+ test_terminal git rev-list HEAD &&
! test -e paginated.out
'
@@ -54,7 +62,7 @@ test_expect_success 'no pager when stdout is a regular file' '
rm -f paginated.out
test_expect_success TTY 'git --paginate rev-list uses a pager' '
- git --paginate rev-list HEAD &&
+ test_terminal git --paginate rev-list HEAD &&
test -e paginated.out
'
@@ -66,7 +74,7 @@ test_expect_success 'no pager even with --paginate when stdout is a pipe' '
rm -f paginated.out
test_expect_success TTY 'no pager with --no-pager' '
- git --no-pager log &&
+ test_terminal git --no-pager log &&
! test -e paginated.out
'
@@ -127,7 +135,7 @@ test_expect_success SIMPLEPAGER 'default pager is used by default' '
: > default_pager_used
EOF
chmod +x $less &&
- PATH=.:$PATH git log &&
+ PATH=.:$PATH test_terminal git log &&
test -e default_pager_used
'
@@ -137,7 +145,7 @@ rm -f PAGER_used
test_expect_success TTY 'PAGER overrides default pager' '
PAGER=": > PAGER_used" &&
export PAGER &&
- git log &&
+ test_terminal git log &&
test -e PAGER_used
'
@@ -147,7 +155,7 @@ test_expect_success TTY 'core.pager overrides PAGER' '
PAGER=: &&
export PAGER &&
git config core.pager ": > core.pager_used" &&
- git log &&
+ test_terminal git log &&
test -e core.pager_used
'
@@ -156,7 +164,7 @@ test_expect_success TTY 'GIT_PAGER overrides core.pager' '
git config core.pager : &&
GIT_PAGER=": > GIT_PAGER_used" &&
export GIT_PAGER &&
- git log &&
+ test_terminal git log &&
test -e GIT_PAGER_used
'
diff --git a/test-terminal.c b/test-terminal.c
new file mode 100644
index 0000000..f4d6a71
--- /dev/null
+++ b/test-terminal.c
@@ -0,0 +1,62 @@
+#include "cache.h"
+#include "run-command.h"
+
+static void newtty(int *master, int *slave)
+{
+ int fd;
+ const char *term;
+
+ fd = posix_openpt(O_RDWR|O_NOCTTY);
+ if (fd == -1 || grantpt(fd) || unlockpt(fd) || !(term = ptsname(fd)))
+ die_errno("Could not allocate a new pseudo-terminal");
+ *master = fd;
+ *slave = open(term, O_RDWR|O_NOCTTY);
+ if (*slave == -1)
+ die_errno("Could not open pseudo-terminal: %s", term);
+}
+
+static void setup_child(struct child_process *chld,
+ const char **args, int out)
+{
+ memset(chld, 0, sizeof(*chld));
+ chld->argv = args;
+ chld->out = out;
+}
+
+static void xsendfile(int out_fd, int in_fd)
+{
+ char buf[BUFSIZ];
+
+ /* Note: the real sendfile() cannot read from a terminal. */
+ for (;;) {
+ ssize_t n = xread(in_fd, buf, sizeof(buf));
+
+ /*
+ * It is unspecified by POSIX whether reads
+ * from a disconnected terminal will return
+ * EIO (as in AIX 4.x, IRIX, and Linux) or
+ * end-of-file. Either is fine.
+ */
+ if (n == 0 || (n == -1 && errno == EIO))
+ break;
+ if (n == -1)
+ die_errno("cannot read from child");
+ write_or_die(out_fd, buf, n);
+ }
+}
+
+int main(int argc, const char **argv)
+{
+ int masterfd, slavefd;
+ struct child_process chld;
+
+ if (argc < 2 || (argc == 2 && !strcmp(argv[1], "-h")))
+ usage("test-terminal program args");
+
+ newtty(&masterfd, &slavefd);
+ setup_child(&chld, argv + 1, slavefd);
+ if (start_command(&chld))
+ return error("failed to execute child");
+ xsendfile(1, masterfd);
+ return finish_command(&chld);
+}
--
1.7.0
next prev parent reply other threads:[~2010-02-19 7:23 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-19 6:50 [PATCH v2 0/7] Re: 'git svn log' no longer uses the pager Jonathan Nieder
2010-02-19 6:51 ` [PATCH 1/7] Fix 'git var' usage synopsis Jonathan Nieder
2010-02-19 7:00 ` [PATCH 2/7] Make 'git var GIT_PAGER' always print the configured pager Jonathan Nieder
2010-02-19 7:06 ` [PATCH 3/7] git.1: Clarify the behavior of the --paginate option Jonathan Nieder
2010-02-19 7:09 ` [PATCH 4/7] git svn: Fix launching of pager Jonathan Nieder
2010-02-19 7:12 ` [PATCH 5/7] am: " Jonathan Nieder
2010-02-19 7:18 ` [PATCH 6/7] tests: Add tests for automatic use " Jonathan Nieder
2010-02-20 17:33 ` Junio C Hamano
2010-02-21 2:03 ` [PATCH v2 " Jonathan Nieder
2010-02-21 2:09 ` [PATCH v4 7/7] t7006-pager: if stdout is not a terminal, make a new one Jonathan Nieder
2010-02-21 7:30 ` Jeff King
2010-02-22 8:19 ` [PATCH v2 6/7] tests: Add tests for automatic use of pager Johannes Sixt
2010-02-22 8:46 ` [PATCH 8/7] tests: Fix race condition in t7006-pager Jonathan Nieder
2010-02-22 9:12 ` Jonathan Nieder
2010-02-19 7:23 ` Jonathan Nieder [this message]
2010-02-19 8:08 ` [PATCH/RFC 7/7] t7006-pager: if stdout is not a terminal, make a new one Jeff King
2010-02-19 8:19 ` Jonathan Nieder
2010-02-19 8:34 ` Jeff King
2010-02-19 16:25 ` Brandon Casey
2010-02-20 0:29 ` Brandon Casey
2010-02-20 0:39 ` Jonathan Nieder
2010-02-20 3:42 ` Brandon Casey
2010-02-20 5:25 ` [PATCH v2 " Jonathan Nieder
2010-02-20 6:53 ` Junio C Hamano
2010-02-20 8:50 ` [PATCH v3 " Jonathan Nieder
2010-02-20 9:48 ` [PATCH squash] Simplify test-terminal.perl Jonathan Nieder
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=20100219072331.GG29916@progeny.tock \
--to=jrnieder@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=j6t@kdbg.org \
--cc=peff@peff.net \
--cc=sebastian@sebastiancelis.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).