1begin
2  require "readline"
3=begin
4  class << Readline::HISTORY
5    def []=(index, str)
6      raise NotImplementedError
7    end
8
9    def pop
10      raise NotImplementedError
11    end
12
13    def shift
14      raise NotImplementedError
15    end
16
17    def delete_at(index)
18      raise NotImplementedError
19    end
20  end
21=end
22
23=begin
24  class << Readline::HISTORY
25    def clear
26      raise NotImplementedError
27    end
28  end
29=end
30rescue LoadError
31else
32  require "test/unit"
33end
34
35class Readline::TestHistory < Test::Unit::TestCase
36  include Readline
37
38  def setup
39    HISTORY.clear
40  end
41
42  def test_safe_level_4
43    method_args =
44      [
45       ["[]", [0]],
46       ["[]=", [0, "s"]],
47       ["\<\<", ["s"]],
48       ["push", ["s"]],
49       ["pop", []],
50       ["shift", []],
51       ["length", []],
52       ["delete_at", [0]],
53       ["clear", []],
54      ]
55    method_args.each do |method_name, args|
56      assert_raise(SecurityError, NotImplementedError,
57                    "method=<#{method_name}>") do
58        Thread.start {
59          $SAFE = 4
60          HISTORY.send(method_name.to_sym, *args)
61          assert(true)
62        }.join
63      end
64    end
65
66    assert_raise(SecurityError, NotImplementedError,
67                  "method=<each>") do
68      Thread.start {
69        $SAFE = 4
70        HISTORY.each { |s|
71          assert(true)
72        }
73      }.join
74    end
75  end
76
77  def test_to_s
78    expected = "HISTORY"
79    assert_equal(expected, HISTORY.to_s)
80  end
81
82  def test_get
83    lines = push_history(5)
84    lines.each_with_index do |s, i|
85      assert_external_string_equal(s, HISTORY[i])
86    end
87  end
88
89  def test_get__negative
90    lines = push_history(5)
91    (1..5).each do |i|
92      assert_equal(lines[-i], HISTORY[-i])
93    end
94  end
95
96  def test_get__out_of_range
97    push_history(5)
98    invalid_indexes = [5, 6, 100, -6, -7, -100]
99    invalid_indexes.each do |i|
100      assert_raise(IndexError, "i=<#{i}>") do
101        HISTORY[i]
102      end
103    end
104
105    invalid_indexes = [100_000_000_000_000_000_000,
106                       -100_000_000_000_000_000_000]
107    invalid_indexes.each do |i|
108      assert_raise(RangeError, "i=<#{i}>") do
109        HISTORY[i]
110      end
111    end
112  end
113
114  def test_set
115    begin
116      push_history(5)
117      5.times do |i|
118        expected = "set: #{i}"
119        HISTORY[i] = expected
120        assert_external_string_equal(expected, HISTORY[i])
121      end
122    rescue NotImplementedError
123    end
124  end
125
126  def test_set__out_of_range
127    assert_raise(IndexError, NotImplementedError, "index=<0>") do
128      HISTORY[0] = "set: 0"
129    end
130
131    push_history(5)
132    invalid_indexes = [5, 6, 100, -6, -7, -100]
133    invalid_indexes.each do |i|
134      assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
135        HISTORY[i] = "set: #{i}"
136      end
137    end
138
139    invalid_indexes = [100_000_000_000_000_000_000,
140                       -100_000_000_000_000_000_000]
141    invalid_indexes.each do |i|
142      assert_raise(RangeError, NotImplementedError, "index=<#{i}>") do
143        HISTORY[i] = "set: #{i}"
144      end
145    end
146  end
147
148  def test_push
149    5.times do |i|
150      s = i.to_s
151      assert_equal(HISTORY, HISTORY.push(s))
152      assert_external_string_equal(s, HISTORY[i])
153    end
154    assert_equal(5, HISTORY.length)
155  end
156
157  def test_push__operator
158    5.times do |i|
159      s = i.to_s
160      assert_equal(HISTORY, HISTORY << s)
161      assert_external_string_equal(s, HISTORY[i])
162    end
163    assert_equal(5, HISTORY.length)
164  end
165
166  def test_push__plural
167    assert_equal(HISTORY, HISTORY.push("0", "1", "2", "3", "4"))
168    (0..4).each do |i|
169      assert_external_string_equal(i.to_s, HISTORY[i])
170    end
171    assert_equal(5, HISTORY.length)
172
173    assert_equal(HISTORY, HISTORY.push("5", "6", "7", "8", "9"))
174    (5..9).each do |i|
175      assert_external_string_equal(i.to_s, HISTORY[i])
176    end
177    assert_equal(10, HISTORY.length)
178  end
179
180  def test_pop
181    begin
182      assert_equal(nil, HISTORY.pop)
183
184      lines = push_history(5)
185      (1..5).each do |i|
186        assert_external_string_equal(lines[-i], HISTORY.pop)
187        assert_equal(lines.length - i, HISTORY.length)
188      end
189
190      assert_equal(nil, HISTORY.pop)
191    rescue NotImplementedError
192    end
193  end
194
195  def test_shift
196    begin
197      assert_equal(nil, HISTORY.shift)
198
199      lines = push_history(5)
200      (0..4).each do |i|
201        assert_external_string_equal(lines[i], HISTORY.shift)
202        assert_equal(lines.length - (i + 1), HISTORY.length)
203      end
204
205      assert_equal(nil, HISTORY.shift)
206    rescue NotImplementedError
207    end
208  end
209
210  def test_each
211    e = HISTORY.each do |s|
212      assert(false) # not reachable
213    end
214    assert_equal(HISTORY, e)
215    lines = push_history(5)
216    i = 0
217    e = HISTORY.each do |s|
218      assert_external_string_equal(HISTORY[i], s)
219      assert_external_string_equal(lines[i], s)
220      i += 1
221    end
222    assert_equal(HISTORY, e)
223  end
224
225  def test_each__enumerator
226    e = HISTORY.each
227    assert_instance_of(Enumerator, e)
228  end
229
230  def test_length
231    assert_equal(0, HISTORY.length)
232    push_history(1)
233    assert_equal(1, HISTORY.length)
234    push_history(4)
235    assert_equal(5, HISTORY.length)
236    HISTORY.clear
237    assert_equal(0, HISTORY.length)
238  end
239
240  def test_empty_p
241    2.times do
242      assert(HISTORY.empty?)
243      HISTORY.push("s")
244      assert_equal(false, HISTORY.empty?)
245      HISTORY.clear
246      assert(HISTORY.empty?)
247    end
248  end
249
250  def test_delete_at
251    begin
252      lines = push_history(5)
253      (0..4).each do |i|
254        assert_external_string_equal(lines[i], HISTORY.delete_at(0))
255      end
256      assert(HISTORY.empty?)
257
258      lines = push_history(5)
259      (1..5).each do |i|
260        assert_external_string_equal(lines[lines.length - i], HISTORY.delete_at(-1))
261      end
262      assert(HISTORY.empty?)
263
264      lines = push_history(5)
265      assert_external_string_equal(lines[0], HISTORY.delete_at(0))
266      assert_external_string_equal(lines[4], HISTORY.delete_at(3))
267      assert_external_string_equal(lines[1], HISTORY.delete_at(0))
268      assert_external_string_equal(lines[3], HISTORY.delete_at(1))
269      assert_external_string_equal(lines[2], HISTORY.delete_at(0))
270      assert(HISTORY.empty?)
271    rescue NotImplementedError
272    end
273  end
274
275  def test_delete_at__out_of_range
276    assert_raise(IndexError, NotImplementedError, "index=<0>") do
277      HISTORY.delete_at(0)
278    end
279
280    push_history(5)
281    invalid_indexes = [5, 6, 100, -6, -7, -100]
282    invalid_indexes.each do |i|
283      assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
284        HISTORY.delete_at(i)
285      end
286    end
287
288    invalid_indexes = [100_000_000_000_000_000_000,
289                       -100_000_000_000_000_000_000]
290    invalid_indexes.each do |i|
291      assert_raise(RangeError, NotImplementedError, "index=<#{i}>") do
292        HISTORY.delete_at(i)
293      end
294    end
295  end
296
297  private
298
299  def push_history(num)
300    lines = []
301    num.times do |i|
302      s = "a"
303      i.times do
304        s = s.succ
305      end
306      lines.push("#{i + 1}:#{s}")
307    end
308    HISTORY.push(*lines)
309    return lines
310  end
311
312  def assert_external_string_equal(expected, actual)
313    assert_equal(expected, actual)
314    assert_equal(get_default_internal_encoding, actual.encoding)
315  end
316
317  def get_default_internal_encoding
318    return Encoding.default_internal || Encoding.find("locale")
319  end
320end if defined?(::Readline) && defined?(::Readline::HISTORY) &&
321  (
322   begin
323     Readline::HISTORY.clear
324   rescue NotImplementedError
325     false
326   end
327   )
328