xref: /freebsd/usr.bin/patch/tests/unified_patch_test.sh (revision 50dacbf6c2a3d32f7e3f20ca98cda23f38817e7f)
1b2752497SKyle Evans#
2b2752497SKyle Evans# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
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# $FreeBSD$
28b2752497SKyle Evans
29b2752497SKyle Evansatf_test_case basic
30b2752497SKyle Evansbasic_body()
31b2752497SKyle Evans{
32b2752497SKyle Evans	printf "a\nb\nc\nd\ne\nf\ng\nh\ni\n" > foo_full
33b2752497SKyle Evans	printf "a\nb\nc\n" > foo_start
34b2752497SKyle Evans	printf "g\nh\ni\n" > foo_end
35b2752497SKyle Evans	printf "d\ne\nf\n" > foo_middle
36b2752497SKyle Evans
37b2752497SKyle Evans	diff -u foo_start foo_full > foo_start2full.diff
38b2752497SKyle Evans	diff -u foo_end foo_full > foo_end2full.diff
39b2752497SKyle Evans	diff -u foo_middle foo_full > foo_mid2full.diff
40b2752497SKyle Evans
41b2752497SKyle Evans	# Check lengths... each should have all 9 lines + 3 line header
42b2752497SKyle Evans	atf_check -o inline:"12" -x \
43b2752497SKyle Evans	    "cat foo_start2full.diff | wc -l | tr -d '[:space:]'"
44b2752497SKyle Evans	atf_check -o inline:"12" -x \
45b2752497SKyle Evans	    "cat foo_end2full.diff | wc -l | tr -d '[:space:]'"
46b2752497SKyle Evans	atf_check -o inline:"12" -x \
47b2752497SKyle Evans	    "cat foo_mid2full.diff | wc -l | tr -d '[:space:]'"
48b2752497SKyle Evans
49b2752497SKyle Evans	# Apply the patch! Should succeed
50b2752497SKyle Evans	atf_check -o ignore patch foo_start foo_start2full.diff \
51b2752497SKyle Evans	    -o foo_start2full
52b2752497SKyle Evans	atf_check -o ignore patch foo_end foo_end2full.diff \
53b2752497SKyle Evans	    -o foo_end2full
54b2752497SKyle Evans	atf_check -o ignore patch foo_middle foo_mid2full.diff \
55b2752497SKyle Evans	    -o foo_mid2full
56b2752497SKyle Evans
57b2752497SKyle Evans	# And these should all produce equivalent to the original full
58b2752497SKyle Evans	atf_check -o ignore diff foo_start2full foo_full
59b2752497SKyle Evans	atf_check -o ignore diff foo_end2full foo_full
60b2752497SKyle Evans	atf_check -o ignore diff foo_mid2full foo_full
61b2752497SKyle Evans}
62b2752497SKyle Evans
63b2752497SKyle Evansatf_test_case limited_ctx
64b2752497SKyle Evanslimited_ctx_head()
65b2752497SKyle Evans{
66b2752497SKyle Evans	atf_set "descr" "Verify correct behavior with limited context (PR 74127)"
67b2752497SKyle Evans}
68b2752497SKyle Evanslimited_ctx_body()
69b2752497SKyle Evans{
70b2752497SKyle Evans
71b2752497SKyle Evans	# First; PR74127-repro.diff should not have applied, but it instead
72b2752497SKyle Evans	# assumed a match and added the modified line at the offset specified...
73b2752497SKyle Evans	atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
74b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
75b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-repro.diff"
76b2752497SKyle Evans
77b2752497SKyle Evans	# Let's extend that and make sure a similarly ill-contexted diff does
78b2752497SKyle Evans	# not apply even with the correct line number
79b2752497SKyle Evans	atf_check -s not-exit:0 -o ignore -e ignore patch -o _.out \
80b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
81b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-line.diff"
82b2752497SKyle Evans
83b2752497SKyle Evans	# Correct line number and correct old line should always work
84b2752497SKyle Evans	atf_check -o ignore -e ignore patch -o _.out \
85b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127.in" \
86b2752497SKyle Evans	    "$(atf_get_srcdir)/PR74127-good.diff"
87b2752497SKyle Evans}
88b2752497SKyle Evans
89b2752497SKyle Evansatf_test_case file_creation
90b2752497SKyle Evansfile_creation_body()
91b2752497SKyle Evans{
92b2752497SKyle Evans
93b2752497SKyle Evans	echo "x" > foo
94b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
95b2752497SKyle Evans	rm foo
96b2752497SKyle Evans
97b2752497SKyle Evans	atf_check -x "patch -s < foo.diff"
98b2752497SKyle Evans	atf_check -o ignore stat foo
99b2752497SKyle Evans}
100b2752497SKyle Evans
101b2752497SKyle Evans# This test is motivated by long-standing bugs that occasionally slip by in
102b2752497SKyle Evans# commits.  If a file is created by a diff, patch(1) will happily duplicate the
103b2752497SKyle Evans# contents as many times as you apply the diff.  It should instead detect that
104b2752497SKyle Evans# a source of /dev/null creates the file, so it shouldn't exist.  Furthermore,
10589b5571eSKyle Evans# the reverse of creation is deletion -- hence the next test, which ensures that
106*50dacbf6SKyle Evans# the file is removed if it's empty once the patch is reversed.  The size checks
107*50dacbf6SKyle Evans# are scattered throughout to make sure that we didn't get some kind of false
108*50dacbf6SKyle Evans# error, and the first size check is merely a sanity check that should be
109*50dacbf6SKyle Evans# trivially true as this is executed in a sandbox.
110b2752497SKyle Evansatf_test_case file_nodupe
111b2752497SKyle Evansfile_nodupe_body()
112b2752497SKyle Evans{
113b2752497SKyle Evans
114b2752497SKyle Evans	echo "x" > foo
115b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
116b2752497SKyle Evans
117*50dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
118*50dacbf6SKyle Evans	atf_check -s not-exit:0 -o ignore -x "patch -Ns < foo.diff"
119*50dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
120*50dacbf6SKyle Evans	atf_check -s not-exit:0 -o ignore -x "patch -fs < foo.diff"
121*50dacbf6SKyle Evans	atf_check -o inline:"2\n" stat -f "%z" foo
122b2752497SKyle Evans}
123b2752497SKyle Evans
124b2752497SKyle Evansatf_test_case file_removal
125b2752497SKyle Evansfile_removal_body()
126b2752497SKyle Evans{
127b2752497SKyle Evans
128b2752497SKyle Evans	echo "x" > foo
129b2752497SKyle Evans	diff -u /dev/null foo > foo.diff
130b2752497SKyle Evans
13189b5571eSKyle Evans	# Check that the file is removed completely if it was sourced from
13289b5571eSKyle Evans	# /dev/null
133b2752497SKyle Evans	atf_check -x "patch -Rs < foo.diff"
13489b5571eSKyle Evans	atf_check -s not-exit:0 -e ignore stat foo
13589b5571eSKyle Evans
13689b5571eSKyle Evans	# But if it had been modified, we'll only remove the portion that the
13789b5571eSKyle Evans	# patch would have created.  This makes us compatible with GNU patch's
13889b5571eSKyle Evans	# behavior, at least.  Whether that is the sane action or not is a
13989b5571eSKyle Evans	# question for further study, and then this comment may be removed.
14089b5571eSKyle Evans	printf "x\ny\n" > foo
14189b5571eSKyle Evans	atf_check -x "patch -Rs < foo.diff"
14289b5571eSKyle Evans	atf_check -o inline:"y\n" cat foo
143b2752497SKyle Evans}
144b2752497SKyle Evans
145b2752497SKyle Evansatf_init_test_cases()
146b2752497SKyle Evans{
147b2752497SKyle Evans	atf_add_test_case basic
148b2752497SKyle Evans	atf_add_test_case limited_ctx
149b2752497SKyle Evans	atf_add_test_case file_creation
150b2752497SKyle Evans	atf_add_test_case file_nodupe
151b2752497SKyle Evans	atf_add_test_case file_removal
152b2752497SKyle Evans}
153