axon 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +9 -3
- data/README.rdoc +29 -36
- data/Rakefile +26 -21
- data/TODO.rdoc +1 -6
- data/ext/axon/axon.c +6 -15
- data/ext/axon/extconf.rb +19 -9
- data/ext/axon/interpolation.c +147 -0
- data/ext/axon/jpeg.c +1207 -0
- data/ext/axon/png.c +542 -0
- data/lib/axon.rb +235 -32
- data/lib/axon/cropper.rb +80 -18
- data/lib/axon/fit.rb +69 -19
- data/lib/axon/generators.rb +109 -0
- data/lib/axon/scalers.rb +160 -0
- data/test/helper.rb +151 -6
- data/test/reader_tests.rb +37 -82
- data/test/scaler_tests.rb +102 -0
- data/test/stress_helper.rb +58 -0
- data/test/stress_tests.rb +8 -5
- data/test/test_bilinear_scaler.rb +60 -2
- data/test/test_cropper.rb +68 -1
- data/test/test_fit.rb +35 -0
- data/test/test_generators.rb +21 -0
- data/test/test_image.rb +61 -0
- data/test/test_jpeg_reader.rb +96 -94
- data/test/test_jpeg_writer.rb +95 -8
- data/test/test_nearest_neighbor_scaler.rb +28 -4
- data/test/test_png_reader.rb +12 -8
- data/test/test_png_writer.rb +8 -6
- data/test/writer_tests.rb +129 -111
- metadata +71 -128
- data/.gemtest +0 -0
- data/ext/axon/bilinear_interpolation.c +0 -115
- data/ext/axon/interpolation.h +0 -7
- data/ext/axon/jpeg_common.c +0 -118
- data/ext/axon/jpeg_common.h +0 -37
- data/ext/axon/jpeg_native_writer.c +0 -248
- data/ext/axon/jpeg_reader.c +0 -774
- data/ext/axon/nearest_neighbor_interpolation.c +0 -50
- data/ext/axon/png_common.c +0 -21
- data/ext/axon/png_common.h +0 -18
- data/ext/axon/png_native_writer.c +0 -166
- data/ext/axon/png_reader.c +0 -381
- data/lib/axon/axon.so +0 -0
- data/lib/axon/bilinear_scaler.rb +0 -60
- data/lib/axon/jpeg_writer.rb +0 -41
- data/lib/axon/nearest_neighbor_scaler.rb +0 -39
- data/lib/axon/png_writer.rb +0 -35
- data/lib/axon/scaler.rb +0 -41
- data/lib/axon/solid.rb +0 -23
- data/test/_test_readme.rb +0 -34
- data/test/test_exif.rb +0 -39
- data/test/test_generator.rb +0 -10
- data/test/test_icc.rb +0 -18
- data/test/test_jpeg.rb +0 -9
- data/test/test_png.rb +0 -9
@@ -0,0 +1,109 @@
|
|
1
|
+
module Axon
|
2
|
+
# == A Noise Image Generator
|
3
|
+
#
|
4
|
+
# Axon::Noise will generate images with random pixel color values.
|
5
|
+
#
|
6
|
+
# == Example
|
7
|
+
#
|
8
|
+
# Axon::Noise.new(100, 200, :components => 1)
|
9
|
+
#
|
10
|
+
class Noise
|
11
|
+
# The width of the generated image.
|
12
|
+
attr_reader :width
|
13
|
+
|
14
|
+
# The height of the generated image.
|
15
|
+
attr_reader :height
|
16
|
+
|
17
|
+
# The color model of the generated image.
|
18
|
+
attr_reader :color_model
|
19
|
+
|
20
|
+
# The components in the generated image.
|
21
|
+
attr_reader :components
|
22
|
+
|
23
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
24
|
+
attr_reader :lineno
|
25
|
+
|
26
|
+
# :call-seq:
|
27
|
+
# Noise.new(width, height, options = {})
|
28
|
+
#
|
29
|
+
# Creates a new noise image object with dimensions +width+ x +height+.
|
30
|
+
#
|
31
|
+
# +options+ may contain the following optional hash key values:
|
32
|
+
#
|
33
|
+
# * :color_model -- The color model of the generated image.
|
34
|
+
# * :components -- The number of components in the generated image.
|
35
|
+
#
|
36
|
+
def initialize(width, height, options=nil)
|
37
|
+
options ||= {}
|
38
|
+
|
39
|
+
@width = width
|
40
|
+
@height = height
|
41
|
+
@color_model = options[:color_model] || :RGB
|
42
|
+
@components = options[:components] || 3
|
43
|
+
@lineno = 0
|
44
|
+
@empty_string = String.new
|
45
|
+
if @empty_string.respond_to? :force_encoding
|
46
|
+
@empty_string.force_encoding('BINARY')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Gets the next scanline from the generated image.
|
51
|
+
#
|
52
|
+
def gets
|
53
|
+
return nil if @lineno >= @height
|
54
|
+
sl = @empty_string.dup
|
55
|
+
(@width * @components).times{ sl << rand(2**8) }
|
56
|
+
@lineno += 1
|
57
|
+
sl
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# == A Solid Color Image Generator
|
62
|
+
#
|
63
|
+
# Axon::Solid will generate images with a solid color value.
|
64
|
+
#
|
65
|
+
# == Example
|
66
|
+
#
|
67
|
+
# Axon::Solid.new(100, 200, "\x0A\x14\x69")
|
68
|
+
#
|
69
|
+
class Solid
|
70
|
+
# The width of the generated image.
|
71
|
+
attr_reader :width
|
72
|
+
|
73
|
+
# The height of the generated image.
|
74
|
+
attr_reader :height
|
75
|
+
|
76
|
+
# The color model of the generated image.
|
77
|
+
attr_reader :color_model
|
78
|
+
|
79
|
+
# The components in the generated image.
|
80
|
+
attr_reader :components
|
81
|
+
|
82
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
83
|
+
attr_reader :lineno
|
84
|
+
|
85
|
+
# :call-seq:
|
86
|
+
# Solid.new(width, height, color = "\x00\x00\x00", color_model = :RGB)
|
87
|
+
#
|
88
|
+
# Creates a new solid color image object with dimensions +width+ x +height+.
|
89
|
+
#
|
90
|
+
# The optional argument +color+ is the binary value that will be assigned
|
91
|
+
# to each pixel.
|
92
|
+
#
|
93
|
+
def initialize(width, height, color=nil, color_model=nil)
|
94
|
+
@width, @height = width, height
|
95
|
+
@color = color || "\x00\x00\x00"
|
96
|
+
@color_model = color_model || :RGB
|
97
|
+
@components = @color.size
|
98
|
+
@lineno = 0
|
99
|
+
end
|
100
|
+
|
101
|
+
# Gets the next scanline from the generated image.
|
102
|
+
#
|
103
|
+
def gets
|
104
|
+
return nil if @lineno >= @height
|
105
|
+
@lineno += 1
|
106
|
+
@color * width
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/axon/scalers.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
module Axon
|
2
|
+
# == A Nearest-neighbor Image Scaler
|
3
|
+
#
|
4
|
+
# Axon::NearestNeighborScaler scales images quickly using the nearest-neighbor
|
5
|
+
# interpolation method.
|
6
|
+
#
|
7
|
+
# Nearest-neighbor interpolation selects the value of the nearest pixel when
|
8
|
+
# calculating colors in the scaled image.
|
9
|
+
#
|
10
|
+
# == Example
|
11
|
+
#
|
12
|
+
# n = Axon::NearestNeighborScaler.new(image_in, 50, 75)
|
13
|
+
# n.width # => 50
|
14
|
+
# n.height # => 75
|
15
|
+
# n.gets # => String
|
16
|
+
#
|
17
|
+
class NearestNeighborScaler
|
18
|
+
# The width of the generated image.
|
19
|
+
attr_reader :width
|
20
|
+
|
21
|
+
# The height of the generated image.
|
22
|
+
attr_reader :height
|
23
|
+
|
24
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
25
|
+
attr_reader :lineno
|
26
|
+
|
27
|
+
# :call-seq:
|
28
|
+
# NearestNeighborScaler.new(image_in, width, height)
|
29
|
+
#
|
30
|
+
# Scales +image_in+ to the size +width+ x +height+ using the
|
31
|
+
# nearest-neighbor interpolation method.
|
32
|
+
#
|
33
|
+
def initialize(source, width, height)
|
34
|
+
raise ArgumentError if width < 1 || height < 1
|
35
|
+
@width = width
|
36
|
+
@height = height
|
37
|
+
@source = source
|
38
|
+
@lineno = 0
|
39
|
+
@buf = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Gets the components in the scaled image. Same as the components of the
|
43
|
+
# source image.
|
44
|
+
#
|
45
|
+
def components
|
46
|
+
@source.components
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gets the color model of the scaled image. Same as the color model of the
|
50
|
+
# source image.
|
51
|
+
#
|
52
|
+
def color_model
|
53
|
+
@source.color_model
|
54
|
+
end
|
55
|
+
|
56
|
+
# Gets the next scanline from the cropped image.
|
57
|
+
#
|
58
|
+
def gets
|
59
|
+
return nil if @lineno >= @height
|
60
|
+
sample = (@lineno * @source.height / @height.to_f).floor
|
61
|
+
@lineno += 1
|
62
|
+
Interpolation.nearest(get_buf(sample), @width, components)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def get_buf(line)
|
68
|
+
@buf ||= @source.gets
|
69
|
+
(line + 1 - @source.lineno).times{ @buf = @source.gets }
|
70
|
+
@buf
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# == A Bilinear Image Scaler
|
75
|
+
#
|
76
|
+
# Axon::BilinearScaler scales images using the bilinear interpolation method.
|
77
|
+
#
|
78
|
+
# Bilinear interpolation calculates the color values in the resulting image by
|
79
|
+
# looking at the four nearest pixels for each pixel in the resulting image.
|
80
|
+
#
|
81
|
+
# This gives a more accurate representation than nearest-neighbor
|
82
|
+
# interpolation, at the expense of slightly blurring the resulting image.
|
83
|
+
#
|
84
|
+
# == Example
|
85
|
+
#
|
86
|
+
# n = Axon::BilinearScaler.new(image_in, 50, 75)
|
87
|
+
# n.width # => 50
|
88
|
+
# n.height # => 75
|
89
|
+
# n.gets # => String
|
90
|
+
#
|
91
|
+
class BilinearScaler
|
92
|
+
# The width of the generated image.
|
93
|
+
attr_reader :width
|
94
|
+
|
95
|
+
# The height of the generated image.
|
96
|
+
attr_reader :height
|
97
|
+
|
98
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
99
|
+
attr_reader :lineno
|
100
|
+
|
101
|
+
# :call-seq:
|
102
|
+
# BilinearScaler.new(image_in, width, height)
|
103
|
+
#
|
104
|
+
# Scales +image_in+ to the size +width+ x +height+ using the bilinear
|
105
|
+
# interpolation method.
|
106
|
+
#
|
107
|
+
def initialize(source, width, height)
|
108
|
+
raise ArgumentError if width < 1 || height < 1
|
109
|
+
@width = width
|
110
|
+
@height = height
|
111
|
+
@source = source
|
112
|
+
@lineno = 0
|
113
|
+
@buf1 = nil
|
114
|
+
@buf2 = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
# Gets the components in the scaled image. Same as the components of the
|
118
|
+
# source image.
|
119
|
+
#
|
120
|
+
def components
|
121
|
+
@source.components
|
122
|
+
end
|
123
|
+
|
124
|
+
# Gets the color model of the scaled image. Same as the color model of the
|
125
|
+
# source image.
|
126
|
+
#
|
127
|
+
def color_model
|
128
|
+
@source.color_model
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gets the next scanline from the cropped image.
|
132
|
+
#
|
133
|
+
def gets
|
134
|
+
return nil if @lineno >= @height
|
135
|
+
sample = @lineno * @source.height / @height.to_f
|
136
|
+
sample_i = sample.to_i
|
137
|
+
ty = sample - sample_i
|
138
|
+
@lineno += 1
|
139
|
+
get_buf(sample_i)
|
140
|
+
|
141
|
+
Interpolation.bilinear(@buf1, @buf2, @width, ty, components)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def get_buf(line)
|
147
|
+
@buf1 = @buf2 = read_with_padding unless @buf2
|
148
|
+
(line + 2 - @source.lineno).times do
|
149
|
+
@buf1 = @buf2
|
150
|
+
@buf2 = read_with_padding if @source.lineno < @source.height
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def read_with_padding
|
155
|
+
line = @source.gets
|
156
|
+
line << line[-@source.components, @source.components]
|
157
|
+
line
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,17 +1,162 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'minitest/autorun'
|
2
3
|
require 'axon'
|
3
4
|
require 'stringio'
|
4
|
-
require 'reader_tests'
|
5
|
-
require 'writer_tests'
|
6
5
|
|
7
6
|
module Axon
|
8
7
|
class AxonTestCase < MiniTest::Unit::TestCase
|
9
|
-
|
10
|
-
# Generate a solid velvet JPEG
|
8
|
+
# Generate a solid velvet image
|
11
9
|
def setup
|
12
|
-
|
13
|
-
@image = Solid.new 10, 15,
|
10
|
+
super
|
11
|
+
@image = Solid.new 10, 15, "\x0A\x14\x69"
|
14
12
|
@io_out = StringIO.new
|
13
|
+
@io_out.set_encoding 'ASCII-8BIT' if @io_out.respond_to?(:set_encoding)
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_image_dimensions(image, width, height)
|
17
|
+
cmp = image.components
|
18
|
+
|
19
|
+
assert_equal width, image.width
|
20
|
+
assert_equal height, image.height
|
21
|
+
|
22
|
+
height.times do |i|
|
23
|
+
assert_equal i, image.lineno
|
24
|
+
assert_equal width * cmp, image.gets.size, 'image.gets should return scanlines with length width'
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_equal height, image.lineno
|
28
|
+
assert_nil image.gets, 'image.gets should be nil after reading height lines'
|
29
|
+
assert_equal height, image.lineno
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class CustomError < RuntimeError; end
|
34
|
+
|
35
|
+
module CallOrReturnValue
|
36
|
+
def call_or_return(*args)
|
37
|
+
@custom.respond_to?(:call) ? @custom.call(@parent, *args) : @custom
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class CustomImage
|
42
|
+
include CallOrReturnValue
|
43
|
+
|
44
|
+
def initialize(custom)
|
45
|
+
@parent = Solid.new 100, 200
|
46
|
+
@custom = custom
|
47
|
+
end
|
48
|
+
|
49
|
+
def height; @parent.height; end
|
50
|
+
def width; @parent.width; end
|
51
|
+
def color_model; @parent.color_model; end
|
52
|
+
def components; @parent.components; end
|
53
|
+
def gets; @parent.gets; end
|
54
|
+
def lineno; @parent.lineno; end
|
55
|
+
end
|
56
|
+
|
57
|
+
class CustomHeightImage < CustomImage
|
58
|
+
def height; call_or_return; end
|
59
|
+
end
|
60
|
+
|
61
|
+
class CustomWidthImage < CustomImage
|
62
|
+
def width; call_or_return; end
|
63
|
+
end
|
64
|
+
|
65
|
+
class CustomColorModelImage < CustomImage
|
66
|
+
def color_model; call_or_return; end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CustomComponentsImage < CustomImage
|
70
|
+
def components; call_or_return; end
|
71
|
+
end
|
72
|
+
|
73
|
+
class CustomLinenoImage < CustomImage
|
74
|
+
def lineno; call_or_return; end
|
75
|
+
end
|
76
|
+
|
77
|
+
class CustomGetsImage < CustomImage
|
78
|
+
def gets; call_or_return; end
|
79
|
+
end
|
80
|
+
|
81
|
+
class CustomIO
|
82
|
+
include CallOrReturnValue
|
83
|
+
|
84
|
+
attr_accessor :custom
|
85
|
+
|
86
|
+
def initialize(custom, *args)
|
87
|
+
@parent = StringIO.new(*args)
|
88
|
+
@custom = custom
|
89
|
+
end
|
90
|
+
|
91
|
+
def write(*args); call_or_return(*args); end
|
92
|
+
def read(*args); call_or_return(*args); end
|
93
|
+
def string; @parent.string; end
|
94
|
+
end
|
95
|
+
|
96
|
+
class ArrayWrapper
|
97
|
+
attr_reader :lineno, :components, :color_model
|
98
|
+
|
99
|
+
def initialize(ary, components=nil, color_model=nil)
|
100
|
+
@ary = ary
|
101
|
+
@components = components || 3
|
102
|
+
@color_model = color_model || :RGB
|
103
|
+
@lineno = 0
|
104
|
+
end
|
105
|
+
|
106
|
+
def width
|
107
|
+
@ary[0].size
|
108
|
+
end
|
109
|
+
|
110
|
+
def height
|
111
|
+
@ary.size
|
112
|
+
end
|
113
|
+
|
114
|
+
def gets
|
115
|
+
return nil if @lineno > @ary.size
|
116
|
+
res = @ary[@lineno]
|
117
|
+
@lineno += 1
|
118
|
+
res
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class Repeater
|
123
|
+
attr_reader :lineno
|
124
|
+
|
125
|
+
def initialize(source)
|
126
|
+
@source = source
|
127
|
+
@data = []
|
128
|
+
@lineno = 0
|
129
|
+
end
|
130
|
+
|
131
|
+
def components
|
132
|
+
@source.components
|
133
|
+
end
|
134
|
+
|
135
|
+
def color_model
|
136
|
+
@source.color_model
|
137
|
+
end
|
138
|
+
|
139
|
+
def height
|
140
|
+
@source.height
|
141
|
+
end
|
142
|
+
|
143
|
+
def width
|
144
|
+
@source.width
|
145
|
+
end
|
146
|
+
|
147
|
+
def gets
|
148
|
+
if @data.size <= @lineno
|
149
|
+
res = @source.gets.dup
|
150
|
+
return nil unless res
|
151
|
+
@data << res
|
152
|
+
end
|
153
|
+
|
154
|
+
@lineno += 1
|
155
|
+
@data[@lineno - 1].dup
|
156
|
+
end
|
157
|
+
|
158
|
+
def rewind
|
159
|
+
@lineno = 0
|
15
160
|
end
|
16
161
|
end
|
17
162
|
end
|
data/test/reader_tests.rb
CHANGED
@@ -1,115 +1,70 @@
|
|
1
1
|
module Axon
|
2
2
|
module ReaderTests
|
3
|
-
def
|
4
|
-
assert_equal
|
5
|
-
assert_equal
|
3
|
+
def test_header_dimensions
|
4
|
+
assert_equal @image.width, @reader.width
|
5
|
+
assert_equal @image.height, @reader.height
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
assert_equal
|
10
|
-
assert_equal 15, @reader.height
|
8
|
+
def test_header_components
|
9
|
+
assert_equal @image.components, @reader.components
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
14
|
-
assert_equal
|
12
|
+
def test_header_color_model
|
13
|
+
assert_equal @image.color_model, @reader.color_model
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
class DoubleIO < StringIO
|
22
|
-
def read(*args)
|
23
|
-
s = super
|
24
|
-
s[0..20] * 100
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_io_returns_too_much
|
29
|
-
f = DoubleIO.new @data
|
30
|
-
assert_raises(RuntimeError) { @readerclass.new f }
|
31
|
-
end
|
32
|
-
|
33
|
-
class NilIO
|
34
|
-
def read(*args); end
|
16
|
+
def test_io_returns_too_much_data
|
17
|
+
io = CustomIO.new(Proc.new{ |io, *args| io.read(*args)[0..20] * 100 }, @data)
|
18
|
+
assert_raises(RuntimeError) { @readerclass.new io }
|
35
19
|
end
|
36
20
|
|
37
21
|
def test_io_returns_nil
|
38
|
-
assert_raises(RuntimeError) { @readerclass.new
|
22
|
+
assert_raises(RuntimeError) { @readerclass.new(CustomIO.new(nil)) }
|
39
23
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_io_raises_exception
|
48
|
-
assert_raises(RuntimeError) { @readerclass.new RaiseIO.new }
|
24
|
+
|
25
|
+
def test_io_returns_one_byte_at_a_time
|
26
|
+
io = CustomIO.new(Proc.new{ |io, len| io.read(len || 1) }, @data)
|
27
|
+
r = @readerclass.new(io)
|
28
|
+
r.gets
|
49
29
|
end
|
50
30
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
31
|
+
def test_io_raises_exception
|
32
|
+
io = CustomIO.new(Proc.new{ raise CustomError }, @data)
|
33
|
+
assert_raises(CustomError) { @readerclass.new io }
|
55
34
|
end
|
56
35
|
|
57
36
|
def test_empty_string_io
|
58
|
-
assert_raises(RuntimeError) { @readerclass.new
|
59
|
-
end
|
60
|
-
|
61
|
-
class ThatsNotAStringIO
|
62
|
-
def read(*args)
|
63
|
-
:this_should_be_a_string
|
64
|
-
end
|
37
|
+
assert_raises(RuntimeError) { @readerclass.new(CustomIO.new("")) }
|
65
38
|
end
|
66
39
|
|
67
40
|
def test_not_a_string_io
|
68
|
-
assert_raises(TypeError) { @readerclass.new
|
41
|
+
assert_raises(TypeError) { @readerclass.new(CustomIO.new(:foo)) }
|
69
42
|
end
|
70
|
-
|
71
|
-
def test_each
|
72
|
-
size = @reader.width * @reader.components
|
73
43
|
|
74
|
-
|
75
|
-
|
44
|
+
def test_lineno
|
45
|
+
assert_equal 0, @reader.lineno
|
46
|
+
@reader.height.times do |i|
|
47
|
+
assert_equal i, @reader.lineno
|
48
|
+
@reader.gets
|
76
49
|
end
|
50
|
+
assert_equal nil, @reader.gets
|
51
|
+
assert_equal @reader.height, @reader.lineno
|
77
52
|
end
|
78
53
|
|
79
|
-
def
|
80
|
-
@reader.
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class OneExceptionIO < StringIO
|
87
|
-
def initialize(*args)
|
88
|
-
@raised_exception = false
|
89
|
-
super
|
90
|
-
end
|
91
|
-
|
92
|
-
def read(*args)
|
93
|
-
unless @raised_exception
|
94
|
-
@raised_exception = true
|
95
|
-
raise 'heck'
|
96
|
-
end
|
97
|
-
super
|
54
|
+
def test_gets
|
55
|
+
size = @reader.width * @reader.components
|
56
|
+
@reader.height.times do
|
57
|
+
assert_equal size, @reader.gets.size
|
98
58
|
end
|
59
|
+
assert_equal nil, @reader.gets
|
99
60
|
end
|
100
61
|
|
101
62
|
def test_recovers_from_initial_io_exception
|
102
|
-
|
63
|
+
ex_io = CustomIO.new(Proc.new{ raise CustomError }, @data)
|
103
64
|
r = @readerclass.allocate
|
104
|
-
assert_raises(
|
105
|
-
r.send(:initialize,
|
106
|
-
r.
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_multiple_each_calls
|
110
|
-
@reader.each{ }
|
111
|
-
@io_in.rewind
|
112
|
-
@reader.each{ }
|
65
|
+
assert_raises(CustomError) { r.send(:initialize, ex_io) }
|
66
|
+
r.send(:initialize, StringIO.new(@data))
|
67
|
+
r.gets
|
113
68
|
end
|
114
69
|
end
|
115
70
|
end
|