axon 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/test/test_jpeg_reader.rb
CHANGED
@@ -1,108 +1,110 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'reader_tests'
|
2
3
|
|
3
4
|
module Axon
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def setup
|
8
|
-
super
|
9
|
-
@readerclass = JPEGReader
|
10
|
-
@data = @image.to_jpeg.data
|
11
|
-
@io_in = StringIO.new @data
|
12
|
-
@reader = @readerclass.new(@io_in)
|
13
|
-
end
|
5
|
+
module JPEG
|
6
|
+
class TestJPEGReader < AxonTestCase
|
7
|
+
include ReaderTests
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
assert_raises(RuntimeError){ @reader.in_color_model = "foobar" }
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_set_out_color_model
|
27
|
-
@reader.color_model = :YCbCr
|
28
|
-
assert_equal :YCbCr, @reader.color_model
|
29
|
-
|
30
|
-
assert_raises(RuntimeError){ @reader.color_model = "foobar" }
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_scale_num
|
34
|
-
assert @reader.scale_num > 0
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_set_scale_num
|
38
|
-
@reader.scale_num = 5
|
39
|
-
assert_equal 5, @reader.scale_num
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_scale_denom
|
43
|
-
assert @reader.scale_denom > 0
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_set_scale_denom
|
47
|
-
@reader.scale_denom = 8
|
48
|
-
|
49
|
-
assert_equal 8, @reader.scale_denom
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_scale_denom_affects_image_size
|
53
|
-
pre_width = @reader.width
|
54
|
-
pre_height = @reader.height
|
55
|
-
|
56
|
-
@reader.scale_denom = 2
|
57
|
-
|
58
|
-
assert @reader.width < pre_width
|
59
|
-
assert @reader.height < pre_height
|
60
|
-
end
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
io = StringIO.new
|
12
|
+
JPEG.write(@image, io)
|
13
|
+
@data = io.string
|
14
|
+
@readerclass = Reader
|
15
|
+
@reader = Reader.new(StringIO.new(@data))
|
16
|
+
end
|
61
17
|
|
62
|
-
|
63
|
-
|
64
|
-
|
18
|
+
def test_in_color_model
|
19
|
+
assert_equal :YCbCr, @reader.in_color_model
|
20
|
+
end
|
65
21
|
|
66
|
-
|
67
|
-
|
22
|
+
def test_set_in_color_model
|
23
|
+
@reader.in_color_model = :RGB
|
24
|
+
assert_equal :RGB, @reader.in_color_model
|
68
25
|
|
69
|
-
|
26
|
+
assert_raises(RuntimeError){ @reader.in_color_model = "foobar" }
|
27
|
+
end
|
70
28
|
|
71
|
-
|
29
|
+
def test_set_out_color_model
|
30
|
+
@reader.color_model = :YCbCr
|
31
|
+
assert_equal :YCbCr, @reader.color_model
|
72
32
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
33
|
+
assert_raises(RuntimeError){ @reader.color_model = "foobar" }
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_scale_num
|
37
|
+
assert @reader.scale_num > 0
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_set_scale_num
|
41
|
+
@reader.scale_num = 5
|
42
|
+
assert_equal 5, @reader.scale_num
|
43
|
+
end
|
44
|
+
|
45
|
+
unless LIB_TURBO
|
46
|
+
def test_scale_denom
|
47
|
+
assert @reader.scale_denom > 0
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_set_scale_denom
|
51
|
+
@reader.scale_denom = 8
|
52
|
+
assert_equal 8, @reader.scale_denom
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_scale_denom_affects_image_size
|
56
|
+
pre_width = @reader.width
|
57
|
+
pre_height = @reader.height
|
58
|
+
|
59
|
+
@reader.scale_denom = 2
|
60
|
+
|
61
|
+
assert @reader.width < pre_width
|
62
|
+
assert @reader.height < pre_height
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_scale_denom_affects_written_image
|
66
|
+
pre_width = @reader.width
|
67
|
+
pre_height = @reader.height
|
68
|
+
|
69
|
+
@reader.scale_denom = 2
|
70
|
+
|
71
|
+
io_out = StringIO.new
|
72
|
+
JPEG.write(@reader, io_out)
|
73
|
+
io_out.rewind
|
74
|
+
|
75
|
+
new_velvet_reader = Reader.new(io_out)
|
76
|
+
|
77
|
+
assert new_velvet_reader.width < pre_width
|
78
|
+
assert new_velvet_reader.height < pre_height
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_dct_method
|
83
|
+
assert_equal Reader::DEFAULT_DCT, @reader.dct_method
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_set_dct_method
|
87
|
+
@reader.dct_method = :IFAST
|
88
|
+
assert_equal :IFAST, @reader.dct_method
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_markers_read_by_default
|
92
|
+
refute_empty @reader[:APP0]
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_empty_marker_prevents_reads
|
96
|
+
r = Reader.new StringIO.new(@data), []
|
97
|
+
assert_empty r[:APP0]
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_marker_content
|
101
|
+
assert_match(/^JFIF/, @reader[:APP0].first)
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_no_configuration_after_initiated
|
105
|
+
@reader.gets
|
103
106
|
assert_raises(RuntimeError) { @reader.dct_method = :IFAST }
|
104
107
|
assert_raises(RuntimeError) { @reader.scale_denom = 4 }
|
105
|
-
break
|
106
108
|
end
|
107
109
|
end
|
108
110
|
end
|
data/test/test_jpeg_writer.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'writer_tests'
|
2
3
|
|
3
4
|
module Axon
|
4
5
|
class TestJPEGWriter < AxonTestCase
|
@@ -6,21 +7,107 @@ module Axon
|
|
6
7
|
|
7
8
|
def setup
|
8
9
|
super
|
9
|
-
@
|
10
|
-
@writer = @image.to_jpeg
|
10
|
+
@mod = JPEG
|
11
11
|
end
|
12
12
|
|
13
13
|
def test_output_has_jpeg_header
|
14
|
-
|
15
|
-
|
16
|
-
assert_equal "\
|
17
|
-
assert_equal "JFIF\x00", string[6..10]
|
14
|
+
JPEG.write(@image, @io_out)
|
15
|
+
assert_equal "\xFF\xD8\xFF\xE0", @io_out.string[0..3]
|
16
|
+
assert_equal "JFIF\x00", @io_out.string[6..10]
|
18
17
|
end
|
19
18
|
|
20
|
-
def
|
19
|
+
def test_invalid_bufsize
|
21
20
|
assert_raises RuntimeError do
|
22
|
-
|
21
|
+
JPEG.write(@image, @io_out, :bufsize => 0)
|
22
|
+
end
|
23
|
+
|
24
|
+
assert_raises RuntimeError do
|
25
|
+
JPEG.write(@image, @io_out, :bufsize => -5)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_symbol_bufsize
|
30
|
+
assert_raises TypeError do
|
31
|
+
JPEG.write(@image, @io_out, :bufsize => :foo)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_quality_filesize
|
36
|
+
file_sizes = {}
|
37
|
+
[-10, 0, 1, 50, 100, 130].each do |q|
|
38
|
+
im = Solid.new(100, 200)
|
39
|
+
io = StringIO.new
|
40
|
+
JPEG.write(im, io, :quality => q)
|
41
|
+
file_sizes[q] = io.size
|
23
42
|
end
|
43
|
+
|
44
|
+
assert file_sizes[-10] > 1
|
45
|
+
|
46
|
+
# libjpeg treats values under 1 as 1
|
47
|
+
assert_equal file_sizes[-10], file_sizes[0]
|
48
|
+
assert_equal file_sizes[0], file_sizes[1]
|
49
|
+
|
50
|
+
assert file_sizes[50] > file_sizes[1]
|
51
|
+
assert file_sizes[100] > file_sizes[50]
|
52
|
+
|
53
|
+
# libjpeg treats values over 100 as 100
|
54
|
+
assert_equal file_sizes[130], file_sizes[100]
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_symbol_quality
|
58
|
+
assert_raises TypeError do
|
59
|
+
JPEG.write(@image, @io_out, :quality => :foo)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_exif_roundtrip
|
64
|
+
random_data = ""
|
65
|
+
(100).times do
|
66
|
+
random_data << [rand].pack('d') # 800 bytes random data
|
67
|
+
end
|
68
|
+
|
69
|
+
io_out = StringIO.new
|
70
|
+
JPEG.write(@image, io_out, :exif => random_data)
|
71
|
+
io_out.rewind
|
72
|
+
|
73
|
+
image_with_exif = JPEG::Reader.new(io_out)
|
74
|
+
assert_equal random_data, image_with_exif.exif
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_exif_with_icc_roundtrip
|
78
|
+
random_icc_data = ""
|
79
|
+
(2**16).times do # a little larger than one jpeg segment
|
80
|
+
random_icc_data << [rand].pack('d') # 8 bytes random data
|
81
|
+
end
|
82
|
+
|
83
|
+
random_exif_data = ""
|
84
|
+
(100).times do
|
85
|
+
random_exif_data << [rand].pack('d') # 800 bytes random data
|
86
|
+
end
|
87
|
+
|
88
|
+
io_out = StringIO.new
|
89
|
+
JPEG.write(@image, io_out, :icc_profile => random_icc_data,
|
90
|
+
:exif => random_exif_data)
|
91
|
+
io_out.rewind
|
92
|
+
|
93
|
+
image_with_exif_and_icc = JPEG::Reader.new(io_out)
|
94
|
+
|
95
|
+
assert_equal random_exif_data, image_with_exif_and_icc.exif
|
96
|
+
assert_equal random_icc_data, image_with_exif_and_icc.icc_profile
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_large_icc_roundtrip
|
100
|
+
random_data = ""
|
101
|
+
(2**16).times do # a little larger than one jpeg segment
|
102
|
+
random_data << [rand].pack('d') # 8 bytes random data
|
103
|
+
end
|
104
|
+
|
105
|
+
io_out = StringIO.new
|
106
|
+
JPEG.write(@image, io_out, :icc_profile => random_data)
|
107
|
+
io_out.rewind
|
108
|
+
|
109
|
+
image_with_icc = JPEG::Reader.new(io_out)
|
110
|
+
assert_equal random_data, image_with_icc.icc_profile
|
24
111
|
end
|
25
112
|
end
|
26
113
|
end
|
@@ -1,13 +1,37 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'scaler_tests'
|
2
3
|
|
3
4
|
module Axon
|
4
5
|
class TestNearestNeighborScaler < AxonTestCase
|
5
|
-
|
6
|
-
|
6
|
+
include ScalerTests
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
@scalerclass = NearestNeighborScaler
|
11
|
+
@scalertestclass = TestNearestNeighborScaler
|
7
12
|
end
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
class TestNearestNeighborScaler
|
15
|
+
def initialize(original, width, height)
|
16
|
+
@original = original
|
17
|
+
@scale_x_inv = original.width / width.to_f
|
18
|
+
@scale_y_inv = original.height / height.to_f
|
19
|
+
@data = []
|
20
|
+
@original.height.times do
|
21
|
+
sl = @original.gets
|
22
|
+
@data << sl + sl[-@original.components, @original.components]
|
23
|
+
end
|
24
|
+
@data << @data.last
|
25
|
+
end
|
26
|
+
|
27
|
+
def calc(x, y)
|
28
|
+
smp_x = (x * @scale_x_inv).floor
|
29
|
+
smp_y = (y * @scale_y_inv).floor
|
30
|
+
cmp = @original.components
|
31
|
+
@data[smp_y][smp_x * cmp, cmp].chars.map do |c|
|
32
|
+
c.respond_to?(:ord) ? c.ord : c[0]
|
33
|
+
end
|
34
|
+
end
|
11
35
|
end
|
12
36
|
end
|
13
37
|
end
|
data/test/test_png_reader.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'reader_tests'
|
2
3
|
|
3
4
|
module Axon
|
4
|
-
|
5
|
-
|
5
|
+
module PNG
|
6
|
+
class TestPNGReader < AxonTestCase
|
7
|
+
include ReaderTests
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
io = StringIO.new
|
12
|
+
PNG.write(@image, io)
|
13
|
+
@data = io.string
|
14
|
+
@readerclass = Reader
|
15
|
+
@reader = Reader.new(StringIO.new(@data))
|
16
|
+
end
|
13
17
|
end
|
14
18
|
end
|
15
19
|
end
|
data/test/test_png_writer.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
require 'helper'
|
2
|
+
require 'writer_tests'
|
2
3
|
|
3
4
|
module Axon
|
4
|
-
|
5
|
-
|
5
|
+
module PNG
|
6
|
+
class TestPNGWriter < AxonTestCase
|
7
|
+
include WriterTests
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def setup
|
10
|
+
super
|
11
|
+
@mod = PNG
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
data/test/writer_tests.rb
CHANGED
@@ -1,178 +1,196 @@
|
|
1
1
|
module Axon
|
2
2
|
module WriterTests
|
3
3
|
def test_writes_something
|
4
|
-
@
|
4
|
+
@mod.write(@image, @io_out)
|
5
5
|
refute @io_out.string.empty?
|
6
6
|
end
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
def test_returns_bytes_written
|
9
|
+
ret = @mod.write(@image, @io_out)
|
10
|
+
assert_equal @io_out.size, ret
|
10
11
|
end
|
11
12
|
|
12
|
-
|
13
|
-
|
13
|
+
def test_invalid_numeric_height
|
14
|
+
[0, -100, 0.0001].each do |h|
|
15
|
+
assert_raises RuntimeError do
|
16
|
+
@mod.write(CustomHeightImage.new(h), @io_out)
|
17
|
+
end
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
|
-
|
21
|
+
def test_invalid_height_type
|
22
|
+
[nil, :foo].each do |h|
|
23
|
+
assert_raises TypeError, "should throw a TypeError when given a #{h.class} for height." do
|
24
|
+
@mod.write(CustomHeightImage.new(h), @io_out)
|
25
|
+
end
|
26
|
+
end
|
18
27
|
end
|
19
28
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
assert_raises RuntimeError do
|
25
|
-
writer.write(@io_out)
|
29
|
+
def test_height_raises_exception
|
30
|
+
im = CustomHeightImage.new(Proc.new{ raise CustomError })
|
31
|
+
assert_raises CustomError do
|
32
|
+
@mod.write(im, @io_out)
|
26
33
|
end
|
27
|
-
|
28
|
-
i = NegativeHeightImage.new 10, 15, @velvet
|
29
|
-
writer = @writerclass.new(i)
|
34
|
+
end
|
30
35
|
|
31
|
-
|
32
|
-
|
36
|
+
def test_invalid_numeric_width
|
37
|
+
[0, -100, 0.0001].each do |w|
|
38
|
+
assert_raises RuntimeError do
|
39
|
+
@mod.write(CustomWidthImage.new(w), @io_out)
|
40
|
+
end
|
33
41
|
end
|
42
|
+
end
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
44
|
+
def test_invalid_width_type
|
45
|
+
[nil, :foo].each do |w|
|
46
|
+
assert_raises TypeError, "should throw a TypeError when given a #{w.class} for width." do
|
47
|
+
@mod.write(CustomWidthImage.new(w), @io_out)
|
48
|
+
end
|
40
49
|
end
|
41
50
|
end
|
42
51
|
|
43
|
-
|
44
|
-
|
52
|
+
def test_width_raises_exception
|
53
|
+
im = CustomWidthImage.new(Proc.new{ raise CustomError })
|
54
|
+
assert_raises CustomError do
|
55
|
+
@mod.write(im, @io_out)
|
56
|
+
end
|
45
57
|
end
|
46
58
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
assert_raises RuntimeError do
|
52
|
-
writer.write(@io_out)
|
59
|
+
def test_nil_image_color_model
|
60
|
+
assert_raises TypeError do
|
61
|
+
@mod.write(CustomColorModelImage.new(nil), @io_out)
|
53
62
|
end
|
54
63
|
end
|
55
64
|
|
56
|
-
|
57
|
-
|
65
|
+
def test_invalid_color_model
|
66
|
+
assert_raises RuntimeError do
|
67
|
+
@mod.write(CustomColorModelImage.new(:foo), @io_out)
|
68
|
+
end
|
58
69
|
end
|
59
70
|
|
60
|
-
|
61
|
-
|
71
|
+
def test_color_model_raises_exception
|
72
|
+
im = CustomColorModelImage.new(Proc.new{ raise CustomError })
|
73
|
+
assert_raises CustomError do
|
74
|
+
@mod.write(im, @io_out)
|
75
|
+
end
|
62
76
|
end
|
63
77
|
|
64
|
-
|
65
|
-
|
78
|
+
def test_invalid_image_components
|
79
|
+
[0, -100, 0.0001, 15].each do |w|
|
80
|
+
assert_raises RuntimeError do
|
81
|
+
@mod.write(CustomComponentsImage.new(w), @io_out)
|
82
|
+
end
|
83
|
+
end
|
66
84
|
end
|
67
85
|
|
68
|
-
def
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
writer.write(@io_out)
|
86
|
+
def test_invalid_components_type
|
87
|
+
[nil, :foo].each do |w|
|
88
|
+
assert_raises TypeError do
|
89
|
+
@mod.write(CustomComponentsImage.new(w), @io_out)
|
90
|
+
end
|
74
91
|
end
|
92
|
+
end
|
75
93
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
94
|
+
def test_invalid_components_type
|
95
|
+
[nil, :foo].each do |w|
|
96
|
+
assert_raises TypeError, "should throw a TypeError when given a #{w.class} for components." do
|
97
|
+
@mod.write(CustomComponentsImage.new(w), @io_out)
|
98
|
+
end
|
81
99
|
end
|
100
|
+
end
|
82
101
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
writer.write(@io_out)
|
102
|
+
def test_components_raises_exception
|
103
|
+
im = CustomComponentsImage.new(Proc.new{ raise CustomError })
|
104
|
+
assert_raises CustomError do
|
105
|
+
@mod.write(im, @io_out)
|
88
106
|
end
|
89
107
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
108
|
+
|
109
|
+
def test_invalid_lineno_type
|
110
|
+
[-1, nil, :foo].each do |l|
|
111
|
+
# we don't know if the writer will care but test anyways to detect
|
112
|
+
# interpreter crashes and mem leaks.
|
113
|
+
@mod.write(CustomLinenoImage.new(l), @io_out)
|
94
114
|
end
|
95
115
|
end
|
96
|
-
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
116
|
+
|
117
|
+
def test_odd_gets_type
|
118
|
+
[nil, :foo, 1234].each do |l|
|
119
|
+
assert_raises RuntimeError do
|
120
|
+
@mod.write(CustomGetsImage.new(l), @io_out)
|
121
|
+
end
|
102
122
|
end
|
103
123
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
124
|
+
|
125
|
+
def test_gets_raises_exception_immediately
|
126
|
+
im = CustomGetsImage.new(Proc.new{ raise CustomError })
|
127
|
+
assert_raises CustomError do
|
128
|
+
@mod.write(im, @io_out)
|
108
129
|
end
|
109
130
|
end
|
110
131
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
writer.write(@io_out)
|
132
|
+
def test_gets_raises_exception_later
|
133
|
+
proc = Proc.new{ |im| im.lineno > 3 ? raise(CustomError) : im.gets }
|
134
|
+
i = CustomGetsImage.new(proc)
|
135
|
+
assert_raises CustomError do
|
136
|
+
@mod.write(i, @io_out)
|
117
137
|
end
|
138
|
+
assert_equal 4, i.lineno
|
118
139
|
end
|
119
140
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
141
|
+
def test_gets_return_is_too_short_immediately
|
142
|
+
proc = Proc.new{ |im| im.gets[2, -1] }
|
143
|
+
assert_raises RuntimeError do
|
144
|
+
@mod.write(CustomGetsImage.new(proc), @io_out)
|
124
145
|
end
|
125
146
|
end
|
126
147
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
class TooFewScanLinesImage < Solid
|
134
|
-
def each
|
135
|
-
yield(@color * width)
|
148
|
+
def test_gets_return_is_too_short_later
|
149
|
+
proc = Proc.new{ |im| im.lineno > 3 ? im.gets[2, -1] : im.gets }
|
150
|
+
i = CustomGetsImage.new(proc)
|
151
|
+
assert_raises RuntimeError do
|
152
|
+
@mod.write(i, @io_out)
|
136
153
|
end
|
154
|
+
assert_equal 5, i.lineno
|
137
155
|
end
|
138
156
|
|
139
|
-
def
|
140
|
-
|
141
|
-
writer = @writerclass.new(image)
|
142
|
-
|
157
|
+
def test_gets_return_is_too_long_immediately
|
158
|
+
proc = Proc.new{ |im| im.gets * 2 }
|
143
159
|
assert_raises RuntimeError do
|
144
|
-
|
160
|
+
@mod.write(CustomGetsImage.new(proc), @io_out)
|
145
161
|
end
|
146
162
|
end
|
147
163
|
|
148
|
-
|
149
|
-
|
150
|
-
|
164
|
+
def test_gets_return_is_too_long_later
|
165
|
+
proc = Proc.new{ |im| im.lineno > 3 ? im.gets * 2 : im.gets }
|
166
|
+
i = CustomGetsImage.new(proc)
|
167
|
+
assert_raises RuntimeError do
|
168
|
+
@mod.write(i, @io_out)
|
151
169
|
end
|
170
|
+
assert_equal 5, i.lineno
|
152
171
|
end
|
153
|
-
|
154
|
-
def test_image_scanlines_raises_exception
|
155
|
-
image = RaisingImage.new(10, 15, @velvet)
|
156
|
-
writer = @writerclass.new(image)
|
157
172
|
|
158
|
-
|
159
|
-
|
173
|
+
def test_io_raises_exception_immediately
|
174
|
+
io = CustomIO.new(Proc.new{ raise CustomError })
|
175
|
+
assert_raises CustomError do
|
176
|
+
@mod.write(@image, io)
|
160
177
|
end
|
161
178
|
end
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
179
|
+
|
180
|
+
def test_io_returns_invalid_type
|
181
|
+
[nil, :foo, "bar"].each do |r|
|
182
|
+
im = Solid.new(200, 100)
|
183
|
+
assert_raises TypeError, "should get a TypeError when IO#write returns a #{r.class}." do
|
184
|
+
@mod.write(im, CustomIO.new(r))
|
185
|
+
end
|
167
186
|
end
|
168
187
|
end
|
169
|
-
|
170
|
-
def test_image_scanlines_returns_too_much
|
171
|
-
image = BigWidthImage.new(10, 15, @velvet)
|
172
|
-
writer = @writerclass.new(image)
|
173
188
|
|
174
|
-
|
175
|
-
|
189
|
+
def test_io_returns_invalid_length
|
190
|
+
[0, -1, -100, 2000, 1].each do |r|
|
191
|
+
assert_raises RuntimeError do
|
192
|
+
@mod.write(@image, CustomIO.new(r))
|
193
|
+
end
|
176
194
|
end
|
177
195
|
end
|
178
196
|
end
|