mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
9299db49f5
If history file didn't exist when irb was started, @loaded_history_mtime would be nil. However, if the history file didn't exist before, but it exists when saving history, that means the history file was modified, and we should handle it the same way as we handle the other case where the history file was modified. Fixes #388 https://github.com/ruby/irb/commit/8d277aafcb
233 lines
5.3 KiB
Ruby
233 lines
5.3 KiB
Ruby
# frozen_string_literal: false
|
|
require 'test/unit'
|
|
require 'irb'
|
|
require 'irb/ext/save-history'
|
|
require 'readline'
|
|
|
|
module TestIRB
|
|
class TestHistory < Test::Unit::TestCase
|
|
def setup
|
|
IRB.conf[:RC_NAME_GENERATOR] = nil
|
|
end
|
|
|
|
def teardown
|
|
IRB.conf[:RC_NAME_GENERATOR] = nil
|
|
end
|
|
|
|
class TestInputMethod < ::IRB::InputMethod
|
|
HISTORY = Array.new
|
|
|
|
include IRB::HistorySavingAbility
|
|
|
|
attr_reader :list, :line_no
|
|
|
|
def initialize(list = [])
|
|
super("test")
|
|
@line_no = 0
|
|
@list = list
|
|
end
|
|
|
|
def gets
|
|
@list[@line_no]&.tap {@line_no += 1}
|
|
end
|
|
|
|
def eof?
|
|
@line_no >= @list.size
|
|
end
|
|
|
|
def encoding
|
|
Encoding.default_external
|
|
end
|
|
|
|
def reset
|
|
@line_no = 0
|
|
end
|
|
|
|
def winsize
|
|
[10, 20]
|
|
end
|
|
end
|
|
|
|
def test_history_save_1
|
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
|
IRB.conf[:SAVE_HISTORY] = 1
|
|
assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT)
|
|
exit
|
|
EXPECTED_HISTORY
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY
|
|
5
|
|
exit
|
|
INPUT
|
|
end
|
|
|
|
def test_history_save_100
|
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
|
IRB.conf[:SAVE_HISTORY] = 100
|
|
assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT)
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
exit
|
|
EXPECTED_HISTORY
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY
|
|
5
|
|
exit
|
|
INPUT
|
|
end
|
|
|
|
def test_history_save_bignum
|
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
|
IRB.conf[:SAVE_HISTORY] = 10 ** 19
|
|
assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT)
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
exit
|
|
EXPECTED_HISTORY
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY
|
|
5
|
|
exit
|
|
INPUT
|
|
end
|
|
|
|
def test_history_save_minus_as_infinity
|
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
|
IRB.conf[:SAVE_HISTORY] = -1 # infinity
|
|
assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT)
|
|
1
|
|
2
|
|
3
|
|
4
|
|
5
|
|
exit
|
|
EXPECTED_HISTORY
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY
|
|
5
|
|
exit
|
|
INPUT
|
|
end
|
|
|
|
def test_history_concurrent_use
|
|
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
|
|
IRB.conf[:SAVE_HISTORY] = 1
|
|
assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) do |history_file|
|
|
exit
|
|
5
|
|
exit
|
|
EXPECTED_HISTORY
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY
|
|
5
|
|
exit
|
|
INPUT
|
|
assert_history(<<~EXPECTED_HISTORY2, <<~INITIAL_HISTORY2, <<~INPUT2)
|
|
exit
|
|
EXPECTED_HISTORY2
|
|
1
|
|
2
|
|
3
|
|
4
|
|
INITIAL_HISTORY2
|
|
5
|
|
exit
|
|
INPUT2
|
|
File.utime(File.atime(history_file), File.mtime(history_file) + 2, history_file)
|
|
end
|
|
end
|
|
|
|
def test_history_concurrent_use_not_present
|
|
backup_home = ENV["HOME"]
|
|
backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
|
|
IRB.conf[:SAVE_HISTORY] = 1
|
|
Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir|
|
|
ENV["HOME"] = tmpdir
|
|
io = TestInputMethod.new
|
|
io.class::HISTORY.clear
|
|
io.load_history
|
|
io.class::HISTORY.concat(%w"line1 line2")
|
|
|
|
history_file = IRB.rc_file("_history")
|
|
assert !File.file?(history_file)
|
|
File.write(history_file, "line0\n")
|
|
io.save_history
|
|
assert_equal(%w"line0 line1 line2", File.read(history_file).split)
|
|
end
|
|
ensure
|
|
ENV["HOME"] = backup_home
|
|
ENV["XDG_CONFIG_HOME"] = backup_xdg_config_home
|
|
end
|
|
|
|
private
|
|
|
|
def assert_history(expected_history, initial_irb_history, input)
|
|
backup_verbose, $VERBOSE = $VERBOSE, nil
|
|
backup_home = ENV["HOME"]
|
|
backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
|
|
IRB.conf[:LC_MESSAGES] = IRB::Locale.new
|
|
actual_history = nil
|
|
Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir|
|
|
ENV["HOME"] = tmpdir
|
|
open(IRB.rc_file("_history"), "w") do |f|
|
|
f.write(initial_irb_history)
|
|
end
|
|
|
|
io = TestInputMethod.new
|
|
io.class::HISTORY.clear
|
|
io.load_history
|
|
if block_given?
|
|
history = io.class::HISTORY.dup
|
|
yield IRB.rc_file("_history")
|
|
io.class::HISTORY.replace(history)
|
|
end
|
|
io.class::HISTORY.concat(input.split)
|
|
io.save_history
|
|
|
|
io.load_history
|
|
open(IRB.rc_file("_history"), "r") do |f|
|
|
actual_history = f.read
|
|
end
|
|
end
|
|
assert_equal(expected_history, actual_history, <<~MESSAGE)
|
|
expected:
|
|
#{expected_history}
|
|
but actual:
|
|
#{actual_history}
|
|
MESSAGE
|
|
ensure
|
|
$VERBOSE = backup_verbose
|
|
ENV["HOME"] = backup_home
|
|
ENV["XDG_CONFIG_HOME"] = backup_xdg_config_home
|
|
end
|
|
|
|
def with_temp_stdio
|
|
Tempfile.create("test_readline_stdin") do |stdin|
|
|
Tempfile.create("test_readline_stdout") do |stdout|
|
|
yield stdin, stdout
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end if not RUBY_PLATFORM.match?(/solaris|mswin|mingw/i)
|