README: update with extra disclaimer
[raindrops.git] / test / test_raindrops.rb
blob165766ebbbd9c119ea6898db85e9f79b2b2d155c
1 # -*- encoding: binary -*-
2 # frozen_string_literal: false
3 require 'test/unit'
4 require 'raindrops'
5 require 'tempfile'
7 class TestRaindrops < Test::Unit::TestCase
9   def test_raindrop_counter_max
10     assert_kind_of Integer, Raindrops::MAX
11     assert Raindrops::MAX > 0
12     printf "Raindrops::MAX = 0x%x\n", Raindrops::MAX
13   end
15   def test_raindrop_size
16     assert_kind_of Integer, Raindrops::SIZE
17     assert Raindrops::SIZE > 0
18     puts "Raindrops::SIZE = #{Raindrops::SIZE}"
19   end
21   def test_page_size
22     assert_kind_of Integer, Raindrops::PAGE_SIZE
23     assert Raindrops::PAGE_SIZE > Raindrops::SIZE
24   end
26   def test_size_and_capa
27     rd = Raindrops.new(4)
28     assert_equal 4, rd.size
29     assert rd.capa >= rd.size
30   end
32   def test_ary
33     rd = Raindrops.new(4)
34     assert_equal [0, 0, 0, 0] , rd.to_ary
35   end
37   def test_incr_no_args
38     rd = Raindrops.new(4)
39     assert_equal 1, rd.incr(0)
40     assert_equal [1, 0, 0, 0], rd.to_ary
41   end
43   def test_incr_args
44     rd = Raindrops.new(4)
45     assert_equal 6, rd.incr(3, 6)
46     assert_equal [0, 0, 0, 6], rd.to_ary
47   end
49   def test_decr_args
50     rd = Raindrops.new(4)
51     rd[3] = 6
52     assert_equal 5, rd.decr(3, 1)
53     assert_equal [0, 0, 0, 5], rd.to_ary
54   end
56   def test_incr_shared
57     rd = Raindrops.new(2)
58     5.times do
59       pid = fork { rd.incr(1) }
60       _, status = Process.waitpid2(pid)
61       assert status.success?
62     end
63     assert_equal [0, 5], rd.to_ary
64   end
66   def test_incr_decr
67     rd = Raindrops.new(1)
68     fork { 1000000.times { rd.incr(0) } }
69     1000.times { rd.decr(0) }
70     statuses = Process.waitall
71     statuses.each { |pid, status| assert status.success? }
72     assert_equal [999000], rd.to_ary
73   end
75   def test_bad_incr
76     rd = Raindrops.new(1)
77     assert_raises(ArgumentError) { rd.incr(-1) }
78     assert_raises(ArgumentError) { rd.incr(2) }
79     assert_raises(ArgumentError) { rd.incr(0xffffffff) }
80   end
82   def test_dup
83     @rd = Raindrops.new(1)
84     rd = @rd.dup
85     assert_equal 1, @rd.incr(0)
86     assert_equal 1, rd.incr(0)
87     assert_equal 2, rd.incr(0)
88     assert_equal 2, rd[0]
89     assert_equal 1, @rd[0]
90   end
92   def test_clone
93     @rd = Raindrops.new(1)
94     rd = @rd.clone
95     assert_equal 1, @rd.incr(0)
96     assert_equal 1, rd.incr(0)
97     assert_equal 2, rd.incr(0)
98     assert_equal 2, rd[0]
99     assert_equal 1, @rd[0]
100   end
102   def test_big
103     expect = (1..256).map { 0 }
104     rd = Raindrops.new(256)
105     assert_equal expect, rd.to_ary
106     assert_nothing_raised { rd[255] = 5 }
107     assert_equal 5, rd[255]
108     assert_nothing_raised { rd[2] = 2 }
110     expect[255] = 5
111     expect[2] = 2
112     assert_equal expect, rd.to_ary
113   end
115   def test_resize
116     rd = Raindrops.new(4)
117     assert_equal 4, rd.size
118     assert_equal rd.capa, rd.size = rd.capa
119     assert_equal rd.capa, rd.to_ary.size
120     assert_equal 0, rd[rd.capa - 1]
121     assert_equal 1, rd.incr(rd.capa - 1)
122     assert_raises(ArgumentError) { rd[rd.capa] }
123   end
125   def test_resize_mremap
126     rd = Raindrops.new(4)
127     assert_equal 4, rd.size
128     old_capa = rd.capa
129     rd.size = rd.capa + 1
130     assert_equal old_capa * 2, rd.capa
132     # mremap() is currently broken with MAP_SHARED
133     # https://bugzilla.kernel.org/show_bug.cgi?id=8691
134     assert_equal 0, rd[old_capa]
135     assert_equal rd.capa, rd.to_ary.size
136     assert_equal 0, rd[rd.capa - 1]
137     assert_equal 1, rd.incr(rd.capa - 1)
138     assert_raises(ArgumentError) { rd[rd.capa] }
139   rescue RangeError
140   end # if RUBY_PLATFORM =~ /linux/
142   def test_evaporate
143     rd = Raindrops.new 1
144     assert_nil rd.evaporate!
145     assert_raises(StandardError) { rd.evaporate! }
146   end
148   def test_evaporate_with_fork
149     tmp = Raindrops.new 2
150     pid = fork do
151       tmp.incr 0
152       exit(tmp.evaporate! == nil)
153     end
154     _, status = Process.waitpid2(pid)
155     assert status.success?
156     assert_equal [ 1, 0 ], tmp.to_ary
157     tmp.incr 1
158     assert_equal [ 1, 1 ], tmp.to_ary
159     pid = fork do
160       tmp.incr 1
161       exit([ 1, 2 ] == tmp.to_ary)
162     end
163     _, status = Process.waitpid2(pid)
164     assert status.success?
165     assert_equal [ 1, 2 ], tmp.to_ary
166   end
168   def test_io_backed
169     file = Tempfile.new('test_io_backed')
170     rd = Raindrops.new(4, io: file, zero: true)
171     rd[0] = 123
172     rd[1] = 456
174     assert_equal 123, rd[0]
175     assert_equal 456, rd[1]
177     rd.evaporate!
179     file.rewind
180     data = file.read
181     assert_equal 123, data.unpack('L!')[0]
182     assert_equal 456, data[Raindrops::SIZE..data.size].unpack('L!')[0]
183   end
185   def test_io_backed_reuse
186     file = Tempfile.new('test_io_backed')
187     rd = Raindrops.new(4, io: file, zero: true)
188     rd[0] = 123
189     rd[1] = 456
190     rd.evaporate!
192     rd = Raindrops.new(4, io: file, zero: false)
193     assert_equal 123, rd[0]
194     assert_equal 456, rd[1]
195   end
197   def test_iobacked_noreuse
198     file = Tempfile.new('test_io_backed')
199     rd = Raindrops.new(4, io: file, zero: true)
200     rd[0] = 123
201     rd[1] = 456
202     rd.evaporate!
204     rd = Raindrops.new(4, io: file, zero: true)
205     assert_equal 0, rd[0]
206     assert_equal 0, rd[1]
207   end