xref: /freebsd/usr.bin/patch/tests/unified_patch_test.sh (revision 851a9da38f070675c42a6d69c41c47a5d29ee3d0)
1b2752497SKyle Evans#
24d846d26SWarner Losh# SPDX-License-Identifier: BSD-2-Clause
3b2752497SKyle Evans#
4b2752497SKyle Evans# Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
5b2752497SKyle Evans#
6b2752497SKyle Evans# Redistribution and use in source and binary forms, with or without
7b2752497SKyle Evans# modification, are permitted provided that the following conditions
8b2752497SKyle Evans# are met:
9b2752497SKyle Evans# 1. Redistributions of source code must retain the above copyright
10b2752497SKyle Evans#    notice, this list of conditions and the following disclaimer.
11b2752497SKyle Evans# 2. Redistributions in binary form must reproduce the above copyright
12b2752497SKyle Evans#    notice, this list of conditions and the following disclaimer in the
13b2752497SKyle Evans#    documentation and/or other materials provided with the distribution.
14b2752497SKyle Evans#
15b2752497SKyle Evans# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16b2752497SKyle Evans# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17b2752497SKyle Evans# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18b2752497SKyle Evans# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19b2752497SKyle Evans# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20b2752497SKyle Evans# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21b2752497SKyle Evans# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22b2752497SKyle Evans# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23b2752497SKyle Evans# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24b2752497SKyle Evans# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25b2752497SKyle Evans# SUCH DAMAGE.
26b2752497SKyle Evans#
27b2752497SKyle Evans
28b2752497SKyle Evansatf_test_case basic
29b2752497SKyle Evansbasic_body()
30b2752497SKyle Evans{
31b2752497SKyle Evans	printf "a\nb\nc\nd\ne\nf\ng\nh\ni\n" > foo_full
32b2752497SKyle Evans	printf "a\nb\nc\n" > foo_start
33b2752497SKyle Evans	printf "g\nh\ni\n" > foo_end
34b2752497SKyle Evans	printf "d\ne\nf\n" > foo_middle
35b2752497SKyle Evans
36b2752497SKyle Evans	diff -u foo_start foo_full > foo_start2full.diff
37b2752497SKyle Evans	diff -u foo_end foo_full > foo_end2full.diff
38b2752497SKyle Evans	diff -u foo_middle foo_full > foo_mid2full.diff
39b2752497SKyle Evans
40b2752497SKyle Evans	# Check lengths... each should have all 9 lines + 3 line header
41b2752497SKyle Evans	atf_check -o inline:"12" -x \
42b2752497SKyle Evans	    "cat foo_start2full.diff | wc -l | tr -d '[:space:]'"
43b2752497SKyle Evans	atf_check -o inline:"12" -x \
44b2752497SKyle Evans	    "cat foo_end2full.diff | wc -l | tr -d '[:space:]'"
45b2752497SKyle Evans	atf_check -o inline:"12" -x \
46b2752497SKyle Evans	    "cat foo_mid2full.diff | wc -l | tr -d '[:space:]'"
47b2752497SKyle Evans
48b2752497SKyle Evans	# Apply the patch! Should succeed
49b2752497SKyle Evans	atf_check -o ignore patch foo_start foo_start2full.diff \
50b2752497SKyle Evans	    -o foo_start2full
51b2752497SKyle Evans	atf_check -o ignore patch foo_end foo_end2full.diff \
52b2752497SKyle Evans	    -o foo_end2full
53b2752497SKyle Evans	atf_check -o ignore patch foo_middle foo_mid2full.diff \
54b2752497SKyle Evans	    -o foo_mid2full
55b2752497SKyle Evans
56b2752497SKyle Evans	# And these should all produce equivalent to the original full
57b2752497SKyle Evans	atf_check -o ignore diff foo_start2full foo_full
58b2752497SKyle Evans	atf_check -o ignore diff foo_end2full foo_full
59b2752497SKyle Evans	atf_check -o ignore diff foo_mid2full foo_full
60b2752497SKyle Evans}
61b2752497SKyle Evans
62b2752497SKyle Evansatf_test_case limited_ctx
63b2752497SKyle Evanslimited_ctx_head()
64b2752497SKyle Evans{
65b2752497SKyle Evans	atf_set "descr" "Verify correct behavior with limited context (PR 74127)"
66b2752497SKyle Evans}
67b2752497SKyle Evanslimited_ctx_body()
68b2752497SKyle Evans{
69b2752497SKyle Evans
70b2752497SKyle Evans	# First; PR74127-repro.diff should not have applied, but it instead
71b2752497SKyle Evans	# assumed a match and added the modified line at the offset specified...
72b2752497SKyle Evans	atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
73b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
74b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-repro.diff"
75b2752497SKyle Evans
76b2752497SKyle Evans	# Let's extend that and make sure a similarly ill-contexted diff does
77b2752497SKyle Evans	# not apply even with the correct line number
78b2752497SKyle Evans	atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
79b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
80b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-line.diff"
81b2752497SKyle Evans
82b2752497SKyle Evans	# Correct line number and correct old line should always work
83b2752497SKyle Evans	atf_check -o ignore -e ignore patch -o _.out \
84b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
85b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-good.diff"
86b2752497SKyle Evans}
87b2752497SKyle Evans
88b2752497SKyle Evansatf_test_case file_creation
89b2752497SKyle Evansfile_creation_body()
90b2752497SKyle Evans{
91b2752497SKyle Evans
92b2752497SKyle Evans	echo "x" > foo
93b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
94b2752497SKyle Evans	rm foo
95b2752497SKyle Evans
96b2752497SKyle Evans	atf_check -x "patch -s < foo.diff"
97b2752497SKyle Evans	atf_check -o ignore stat foo
98b2752497SKyle Evans}
99b2752497SKyle Evans
100b2752497SKyle Evans# This test is motivated by long-standing bugs that occasionally slip by in
101b2752497SKyle Evans# commits.  If a file is created by a diff, patch(1) will happily duplicate the
102b2752497SKyle Evans# contents as many times as you apply the diff.  It should instead detect that
103b2752497SKyle Evans# a source of /dev/null creates the file, so it shouldn't exist.  Furthermore,
10489b5571eSKyle Evans# the reverse of creation is deletion -- hence the next test, which ensures that
10550dacbf6SKyle Evans# the file is removed if it's empty once the patch is reversed.  The size checks
10650dacbf6SKyle Evans# are scattered throughout to make sure that we didn't get some kind of false
10750dacbf6SKyle Evans# error, and the first size check is merely a sanity check that should be
10850dacbf6SKyle Evans# trivially true as this is executed in a sandbox.
109b2752497SKyle Evansatf_test_case file_nodupe
110b2752497SKyle Evansfile_nodupe_body()
111b2752497SKyle Evans{
112b2752497SKyle Evans
113b2752497SKyle Evans	echo "x" > foo
114b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
115b2752497SKyle Evans
11650dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
11750dacbf6SKyle Evans	atf_check -s not-exit:0 -o ignore -x "patch -Ns < foo.diff"
11850dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
11950dacbf6SKyle Evans	atf_check -s not-exit:0 -o ignore -x "patch -fs < foo.diff"
12050dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
121b2752497SKyle Evans}
122b2752497SKyle Evans
123b2752497SKyle Evansatf_test_case file_removal
124b2752497SKyle Evansfile_removal_body()
125b2752497SKyle Evans{
126b2752497SKyle Evans
127b2752497SKyle Evans	echo "x" > foo
128b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
129b2752497SKyle Evans
13089b5571eSKyle Evans	# Check that the file is removed completely if it was sourced from
13189b5571eSKyle Evans	# /dev/null
132b2752497SKyle Evans	atf_check -x "patch -Rs < foo.diff"
13389b5571eSKyle Evans	atf_check -s not-exit:0 -e ignore stat foo
13489b5571eSKyle Evans
13589b5571eSKyle Evans	# But if it had been modified, we'll only remove the portion that the
13689b5571eSKyle Evans	# patch would have created.  This makes us compatible with GNU patch's
13789b5571eSKyle Evans	# behavior, at least.  Whether that is the sane action or not is a
13889b5571eSKyle Evans	# question for further study, and then this comment may be removed.
13989b5571eSKyle Evans	printf "x\ny\n" > foo
14089b5571eSKyle Evans	atf_check -x "patch -Rs < foo.diff"
14189b5571eSKyle Evans	atf_check -o inline:"y\n" cat foo
142b2752497SKyle Evans}
143b2752497SKyle Evans
144*851a9da3SDag-Erling Smørgravatf_test_case plinelen
145*851a9da3SDag-Erling Smørgravplinelen_body()
146*851a9da3SDag-Erling Smørgrav{
147*851a9da3SDag-Erling Smørgrav	hello="$(jot -b hello -s, 20000 | tee foo.txt)"
148*851a9da3SDag-Erling Smørgrav	cp foo.txt bar.txt
149*851a9da3SDag-Erling Smørgrav	echo "world" >>bar.txt
150*851a9da3SDag-Erling Smørgrav	cat >foo.diff <<EOF
151*851a9da3SDag-Erling Smørgrav--- foo.txt.orig
152*851a9da3SDag-Erling Smørgrav+++ foo.txt
153*851a9da3SDag-Erling Smørgrav@@ -1,1 +1,2 @@
154*851a9da3SDag-Erling Smørgrav $hello
155*851a9da3SDag-Erling Smørgrav+world
156*851a9da3SDag-Erling SmørgravEOF
157*851a9da3SDag-Erling Smørgrav	atf_check -o match:"Hunk #1 succeeded" \
158*851a9da3SDag-Erling Smørgrav		  patch <foo.diff
159*851a9da3SDag-Erling Smørgrav	atf_check -o file:bar.txt cat foo.txt
160*851a9da3SDag-Erling Smørgrav}
161*851a9da3SDag-Erling Smørgrav
162b2752497SKyle Evansatf_init_test_cases()
163b2752497SKyle Evans{
164b2752497SKyle Evans	atf_add_test_case basic
165b2752497SKyle Evans	atf_add_test_case limited_ctx
166b2752497SKyle Evans	atf_add_test_case file_creation
167b2752497SKyle Evans	atf_add_test_case file_nodupe
168b2752497SKyle Evans	atf_add_test_case file_removal
169*851a9da3SDag-Erling Smørgrav	atf_add_test_case plinelen
170b2752497SKyle Evans}
171