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