Skip to content

Commit

Permalink
test: upgrade test-lib
Browse files Browse the repository at this point in the history
Signed-off-by: Jiang Xin <[email protected]>
  • Loading branch information
jiangxin committed Dec 5, 2023
1 parent 521d318 commit e802a23
Show file tree
Hide file tree
Showing 35 changed files with 2,169 additions and 1,103 deletions.
6 changes: 4 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
TEST_LIB_DIRECTORY=lib
TEST_TARGET_DIRECTORY=..
export TEST_TARGET_DIRECTORY

# Import tree-wide shared Makefile behavior and libraries
include $(TEST_LIB_DIRECTORY)/shared.mak
Expand All @@ -9,7 +11,7 @@ include $(TEST_LIB_DIRECTORY)/shared.mak
#

#GIT_TEST_OPTS = --verbose --debug
SHELL_PATH ?= /bin/bash
SHELL_PATH ?= $(SHELL)
TEST_SHELL_PATH ?= $(SHELL_PATH)
PERL_PATH ?= /usr/bin/perl
TAR ?= $(TAR)
Expand All @@ -35,7 +37,7 @@ CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))

T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
TLIBS = $(sort $(wildcard $(TEST_LIB_DIRECTORY)/lib-*.sh)) $(TEST_LIB_DIRECTORY)/annotate-tests.sh
TLIBS = $(sort $(wildcard $(TEST_LIB_DIRECTORY)/lib-*.sh))
TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
CHAINLINTTESTS = $(sort $(patsubst $(TEST_LIB_DIRECTORY)/chainlint/%.test,%,$(wildcard $(TEST_LIB_DIRECTORY)/chainlint/*.test)))
CHAINLINT = '$(PERL_PATH_SQ)' $(TEST_LIB_DIRECTORY)/chainlint.pl
Expand Down
25 changes: 25 additions & 0 deletions test/lib/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
t[0-9][0-9][0-9][0-9]/* -whitespace
/chainlint/*.expect eol=lf
/t0110/url-* binary
/t3206/* eol=lf
/t3900/*.txt eol=lf
/t3901/*.txt eol=lf
/t4013/* eol=lf
/t4018/* eol=lf
/t4034/*/* eol=lf
/t4051/* eol=lf
/t4100/* eol=lf
/t4101/* eol=lf
/t4109/* eol=lf
/t4110/* eol=lf
/t4135/* eol=lf
/t4211/* eol=lf
/t4252/* eol=lf
/t4256/1/* eol=lf
/t5100/* eol=lf
/t5515/* eol=lf
/t556x_common eol=lf
/t7500/* eol=lf
/t8005/*.txt eol=lf
/t9*/*.dump eol=lf
/t0040*.sh whitespace=-indent-with-non-tab
5 changes: 5 additions & 0 deletions test/lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/trash directory*
/test-results
/.prove
/chainlinttmp
/out/
360 changes: 360 additions & 0 deletions test/lib/COPYING

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions test/lib/Makefile

This file was deleted.

4 changes: 3 additions & 1 deletion test/lib/Makefile.git
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
TEST_LIB_DIRECTORY=.
TEST_TARGET_DIRECTORY=..
export TEST_TARGET_DIRECTORY

# Import tree-wide shared Makefile behavior and libraries
include $(TEST_LIB_DIRECTORY)/shared.mak
Expand Down Expand Up @@ -35,7 +37,7 @@ CHAINLINTTMP_SQ = $(subst ','\'',$(CHAINLINTTMP))

T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
TLIBS = $(sort $(wildcard $(TEST_LIB_DIRECTORY)/lib-*.sh)) $(TEST_LIB_DIRECTORY)/annotate-tests.sh
TLIBS = $(sort $(wildcard $(TEST_LIB_DIRECTORY)/lib-*.sh))
TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
CHAINLINTTESTS = $(sort $(patsubst $(TEST_LIB_DIRECTORY)/chainlint/%.test,%,$(wildcard $(TEST_LIB_DIRECTORY)/chainlint/*.test)))
CHAINLINT = '$(PERL_PATH_SQ)' $(TEST_LIB_DIRECTORY)/chainlint.pl
Expand Down
33 changes: 16 additions & 17 deletions test/lib/README → test/lib/README.git
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ The argument for --run, <test-selector>, is a list of description
substrings or globs or individual test numbers or ranges with an
optional negation prefix (of '!') that define what tests in a test
suite to include (or exclude, if negated) in the run. A range is two
numbers separated with a dash and matches a range of tests with both
ends been included. You may omit the first or the second number to
numbers separated with a dash and specifies an inclusive range of tests
to run. You may omit the first or the second number to
mean "from the first test" or "up to the very last test" respectively.

The argument to --run is split on commas into separate strings,
Expand All @@ -274,10 +274,10 @@ text that you want to match includes a comma, use the glob character
on all tests that match either the glob *rebase* or the glob
*merge?cherry-pick*.

If --run starts with an unprefixed number or range the initial
set of tests to run is empty. If the first item starts with '!'
If --run starts with an unprefixed number or range, the initial
set of tests to run is empty. If the first item starts with '!',
all the tests are added to the initial set. After initial set is
determined every test number or range is added or excluded from
determined, every test number or range is added or excluded from
the set one by one, from left to right.

For example, to run only tests up to a specific test (21), one
Expand Down Expand Up @@ -579,11 +579,11 @@ This test harness library does the following things:

Recommended style
-----------------
Here are some recommented styles when writing test case.

- Keep test title the same line with test helper function itself.
- Keep the test_expect_* function call and test title on
the same line.

Take test_expect_success helper for example, write it like:
For example, with test_expect_success, write it like:

test_expect_success 'test title' '
... test body ...
Expand All @@ -595,10 +595,9 @@ Here are some recommented styles when writing test case.
'test title' \
'... test body ...'

- End the line with an opening single quote.

- End the line with a single quote.

- Indent the body of here-document, and use "<<-" instead of "<<"
- Indent here-document bodies, and use "<<-" instead of "<<"
to strip leading TABs used for indentation:

test_expect_success 'test something' '
Expand All @@ -624,7 +623,7 @@ Here are some recommented styles when writing test case.
'

- Quote or escape the EOF delimiter that begins a here-document if
there is no parameter and other expansion in it, to signal readers
there is no parameter or other expansion in it, to signal readers
that they can skim it more casually:

cmd <<-\EOF
Expand All @@ -638,7 +637,7 @@ Do's & don'ts
Here are a few examples of things you probably should and shouldn't do
when writing tests.

Here are the "do's:"
The "do's:"

- Put all code inside test_expect_success and other assertions.

Expand Down Expand Up @@ -888,7 +887,7 @@ see test-lib-functions.sh for the full list and their options.
rare case where your test depends on more than one:

test_expect_success PERL,PYTHON 'yo dawg' \
' test $(perl -E 'print eval "1 +" . qx[python -c "print 2"]') == "4" '
' test $(perl -E '\''print eval "1 +" . qx[python -c "print(2)"]'\'') = "4" '

- test_expect_failure [<prereq>] <message> <script>

Expand Down Expand Up @@ -1237,8 +1236,8 @@ and it knows that the object ID of an empty tree is a certain
because the things the very basic core test tries to achieve is
to serve as a basis for people who are changing the Git internals
drastically. For these people, after making certain changes,
not seeing failures from the basic test _is_ a failure. And
such drastic changes to the core Git that even changes these
not seeing failures from the basic test _is_ a failure. Any
Git core changes so drastic that they change even these
otherwise supposedly stable object IDs should be accompanied by
an update to t0000-basic.sh.

Expand All @@ -1248,7 +1247,7 @@ knowledge of the core Git internals. If all the test scripts
hardcoded the object IDs like t0000-basic.sh does, that defeats
the purpose of t0000-basic.sh, which is to isolate that level of
validation in one place. Your test also ends up needing
updating when such a change to the internal happens, so do _not_
an update whenever the internals change, so do _not_
do it and leave the low level of validation to t0000-basic.sh.

Test coverage
Expand Down
159 changes: 159 additions & 0 deletions test/lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
Test Lib From Git Core
======================

Test-lib is a test framework developed by Junio and is specifically
designed for the Git project. It allows us to write a test suite
using shell script, which contains a collection of test cases. The
output of each test suite is presented in TAP ([Test Anything
Protocol]) format. We can use test-lib or any other TAP harness
programs (e.g., prove) to run and analyze the output of the test
suites.

In order to reuse the git test framework into other projects,
the [sharness project] made a successful attempt. However, it is
based on an outdated version of git (v1.7.9), which results in
bugs and missing new features. For example:

* Commit d88785e424 (test-lib: set `BASH_XTRACEFD` automatically,
2016-05-11) and commit a5bf824f3b4d (t: prevent '-x' tracing
from interfering with test helpers' stderr, 2018-02-25) of the Git
project addressed bugs when we run test suites with "-x" option.

* Commit 0445e6f0a1 (test-lib: '--run' to run only specific tests,
2014-04-30) provided better control of the set of tests to run.

* Commit 92b269f5c5 (test-lib: turn on `GIT_TEST_CHAIN_LINT`
by default, 2015-04-22) turned on chain-lint by default to
prevent the accidental omission of "&&" between statements in
test cases. Additionally, Git offers more linter tools such as
"chainlint.pl" to help write correct test cases.

* The latest version of the Git project includes numerous test
helpers that are not present in sharness. These helpers
provide a more comprehensive and efficient testing developing
tools. E.g.: `test_bool_env`, `test_cmp_bin`, `test_commit`,
`test_config`, `test_env`, `test_file_not_empty`, `test_file_size`,
`test_line_count`, `test_oid`, `test_path_exists`,
`test_path_is_executable`, `test_path_is_missing`, `test_tick`,
`write_script`, etc.

In order to reuse the latest test framework of the Git project and
easy to maintain, use the following strategies:

1. Use [git-filter-repo] to export test-lib related files and their
commit histories from the Git project. The resulting tailored
commits are saved in the branch named "git-test-lib".

2. The test-lib test framework relies on a helper program named
"test-tool", which is written in C. To use test-lib without the
need for C compilation, re-implemented part of the "test-tool"
subcommands in Python.

3. Make some modifications to test-lib, such as sourcing "test-lib.sh"
from a subdirectory other than the current directory. Some
modifications are borrowed from Sharness.

4. The "git-test-lib" branch is continuously updated with the Git
project, and the master branch will be rebased on it, so the master
branch is not stable. For instructions on how to tailor the
test-lib framework from the Git project to update the "git-test-lib"
branch, please refer to the last section.


Install test-lib
----------------

To create test suites in shell scripts powered by test-lib, you can
follow these steps:

1. Set up a directory (such as "test") to save test suites and
files of test-lib.

$ mkdir test

2. Clone or copy the test-lib repository inside the test directory.

$ cd test
$ git clone https://github.com/jiangixn/test-lib lib

4. Copy files from the example test directory.

$ cp lib/test-example/.gitignore .
$ cp lib/test-example/.gitattributes .
$ cp lib/test-example/Makefile .

4. Start writing a test suite powered by test-lib, make sure it
sources the "test-lib.sh" file from test-lib. Refer to the example
test suite (e.g. "test/t0001-test-tool-chmtime.sh") to write
your own test suite:

test_description='My first test suite'

. lib/test-lib.sh


Usage of test-lib
-----------------

As for how to use test-lib to write, run and manage your test suites,
please see the documentation [README.git] for reference.


Filtering test-lib from the Git project
---------------------------------------

"test-lib" is part of the Git project and is stored in the "t/"
subdirectory. We use "git-filter-repo" to export test-lib related
files to the root directory of this project. We repeat this
periodically to save historical commits of test-lib in the
"git-test-lib" branch of this project. The master branch of this
project will merge with or rebase onto the "git-test-lib" branch.
As how to filter and export test-lib from the Git project, see the
steps below.

1. Make a fresh clone of the Git project before filtering.

$ git clone --single-branch --no-tags \
https://github.com/git/git.git \
git-test-lib

$ cd git-test-lib

2. Use git-filter-repo to filter and export test-lib.

$ git filter-repo \
--preserve-commit-encoding \
--prune-degenerate always \
--path COPYING \
--path shared.mak \
--path t/.gitattributes \
--path t/.gitignore \
--path t/Makefile \
--path t/README \
--path t/aggregate-results.sh \
--path t/chainlint/ \
--path t/chainlint.pl \
--path t/check-non-portable-shell.pl \
--path t/oid-info/ \
--path t/perf/.gitignore \
--path t/perf/Makefile \
--path t/perf/README \
--path t/perf/aggregate.perl \
--path t/perf/config \
--path t/perf/min_time.perl \
--path t/perf/perf-lib.sh \
--path t/perf/p0000-perf-lib-sanity.sh \
--path t/perf/run \
--path t/test-lib-functions.sh \
--path t/test-lib-github-workflow-markup.sh \
--path t/test-lib-junit.sh \
--path t/test-lib.sh \
--path t/lib-subtest.sh \
--path t/t0000-basic.sh \
--path-rename t/:


[Test Anything Protocol]: http://testanything.org/
[sharness project]: https://github.com/felipec/sharness
[git-filter-repo]: https://github.com/newren/git-filter-repo
[README.git]: ./README.git
Loading

0 comments on commit e802a23

Please sign in to comment.