Skip to content

Commit 0ee13b2

Browse files
committed
test(conftest): prepare temporary file for HISTFILE
[Problem] We have previously set HISTFILE=/dev/null to leave user's history file alone in the test, but it turned out to break the system. When the number of history entries reach HISTFILESIZE, Bash tries to replace the entity at $HISTFILE with a regular file. HISTFILE=/dev/null causes the removal of the device /dev/null and creation of a regular file at /dev/null. This Bash behavior was fixed in Bash 4.4 after the following bug-bash discussion: https://lists.gnu.org/archive/html/bug-bash/2015-01/msg00138.html [Solution] As a workaround, we prepare an empty temporary file for each test. [Remark] Another possible solution was to unset HISTFILE in test/config/bashrc. However test/config/bashrc is sourced after the first prompt is shown, i.e., after the user's history file is loaded. This doesn't necessarily cause problems, but we rather use an empty file for the history to perform tests in a unqiue condition.
1 parent a6bb6f4 commit 0ee13b2

File tree

1 file changed

+44
-13
lines changed

1 file changed

+44
-13
lines changed

test/t/conftest.py

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -186,29 +186,55 @@ def partialize(
186186
def bash(request) -> pexpect.spawn:
187187

188188
logfile = None
189+
histfile = None
190+
tmpdir = None
191+
bash = None
192+
189193
if os.environ.get("BASHCOMP_TEST_LOGFILE"):
190194
logfile = open(os.environ["BASHCOMP_TEST_LOGFILE"], "w")
191195
elif os.environ.get("CI"):
192196
logfile = sys.stdout
197+
193198
testdir = os.path.abspath(
194199
os.path.join(os.path.dirname(__file__), os.pardir)
195200
)
196-
env = os.environ.copy()
197-
env.update(
198-
dict(
199-
SRCDIR=testdir, # TODO needed at least by bashrc
200-
SRCDIRABS=testdir,
201-
PS1=PS1,
202-
INPUTRC="%s/config/inputrc" % testdir,
203-
TERM="dumb",
204-
LC_COLLATE="C", # to match Python's default locale unaware sort
205-
HISTFILE="/dev/null", # to leave user's history file alone
206-
)
201+
202+
# Create an empty temporary file for HISTFILE.
203+
#
204+
# To prevent the tested Bash processes from writing to the user's
205+
# history file or any other files, we prepare an empty temporary
206+
# file for each test.
207+
#
208+
# - Note that HISTFILE=/dev/null may not work. It results in the
209+
# removal of the device /dev/null and the creation of a regular
210+
# file at /dev/null when the number of commands reach
211+
# HISTFILESIZE by Bash-4.3's bug. This causes the executation
212+
# of garbages through BASH_COMPLETION_USER_FILE=/dev/null.
213+
# - Note also that "unset -v HISTFILE" in "test/config/bashrc" was
214+
# not adopted because "test/config/bashrc" is loaded after the
215+
# history is read from the history file.
216+
#
217+
histfile = tempfile.NamedTemporaryFile(
218+
prefix="bash-completion-test_", delete=False
207219
)
208220

209-
tmpdir = None
210-
bash = None
211221
try:
222+
# release the file handle so that Bash can open the file.
223+
histfile.close()
224+
225+
env = os.environ.copy()
226+
env.update(
227+
dict(
228+
SRCDIR=testdir, # TODO needed at least by bashrc
229+
SRCDIRABS=testdir,
230+
PS1=PS1,
231+
INPUTRC="%s/config/inputrc" % testdir,
232+
TERM="dumb",
233+
LC_COLLATE="C", # to match Python's default locale unaware sort
234+
HISTFILE=histfile.name,
235+
)
236+
)
237+
212238
marker = request.node.get_closest_marker("bashcomp")
213239

214240
# Set up the current working directory
@@ -306,6 +332,11 @@ def bash(request) -> pexpect.spawn:
306332
bash.close()
307333
if tmpdir:
308334
tmpdir.cleanup()
335+
if histfile:
336+
try:
337+
os.remove(histfile.name)
338+
except OSError:
339+
pass
309340
if logfile and logfile != sys.stdout:
310341
logfile.close()
311342

0 commit comments

Comments
 (0)