format_parser 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +2 -0
- data/.travis.yml +1 -0
- data/README.md +14 -11
- data/format_parser.gemspec +11 -10
- data/lib/care.rb +9 -17
- data/lib/format_parser.rb +11 -13
- data/lib/format_parser/version.rb +1 -1
- data/lib/io_constraint.rb +3 -3
- data/lib/io_utils.rb +4 -10
- data/lib/parsers/aiff_parser.rb +9 -10
- data/lib/parsers/dpx_parser.rb +42 -42
- data/lib/parsers/dsl.rb +2 -2
- data/lib/parsers/exif_parser.rb +3 -8
- data/lib/parsers/fdx_parser.rb +3 -3
- data/lib/parsers/gif_parser.rb +3 -5
- data/lib/parsers/jpeg_parser.rb +4 -8
- data/lib/parsers/moov_parser.rb +8 -6
- data/lib/parsers/moov_parser/decoder.rb +105 -122
- data/lib/parsers/mp3_parser.rb +36 -46
- data/lib/parsers/mp3_parser/id3_v1.rb +7 -13
- data/lib/parsers/mp3_parser/id3_v2.rb +6 -6
- data/lib/parsers/png_parser.rb +5 -12
- data/lib/parsers/psd_parser.rb +2 -2
- data/lib/parsers/tiff_parser.rb +10 -12
- data/lib/parsers/wav_parser.rb +3 -3
- data/lib/read_limiter.rb +3 -7
- data/lib/remote_io.rb +3 -6
- data/spec/care_spec.rb +10 -10
- data/spec/file_information_spec.rb +1 -3
- data/spec/format_parser_spec.rb +6 -6
- data/spec/io_utils_spec.rb +7 -7
- data/spec/parsers/exif_parser_spec.rb +2 -3
- data/spec/parsers/gif_parser_spec.rb +1 -1
- data/spec/parsers/jpeg_parser_spec.rb +0 -1
- data/spec/parsers/moov_parser_spec.rb +2 -3
- data/spec/parsers/png_parser_spec.rb +1 -1
- data/spec/parsers/tiff_parser_spec.rb +0 -1
- data/spec/parsers/wav_parser_spec.rb +3 -3
- data/spec/read_limiter_spec.rb +0 -1
- data/spec/remote_fetching_spec.rb +34 -20
- data/spec/remote_io_spec.rb +20 -21
- data/spec/spec_helper.rb +2 -2
- metadata +19 -4
data/spec/care_spec.rb
CHANGED
@@ -2,15 +2,15 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Care do
|
4
4
|
describe Care::Cache do
|
5
|
-
let(:source) { StringIO.new(
|
5
|
+
let(:source) { StringIO.new('Hello there, this is our little caching reader') }
|
6
6
|
|
7
7
|
it 'performs correct reads at various offsets' do
|
8
8
|
cache = Care::Cache.new(3)
|
9
|
-
expect(cache.byteslice(source, 0, 3)).to eq(
|
10
|
-
expect(cache.byteslice(source, 0, 7)).to eq(
|
11
|
-
expect(cache.byteslice(source, 1, 7)).to eq(
|
12
|
-
expect(cache.byteslice(source, 11, 8)).to eq(
|
13
|
-
expect(cache.byteslice(source, 12, 12)).to eq(
|
9
|
+
expect(cache.byteslice(source, 0, 3)).to eq('Hel')
|
10
|
+
expect(cache.byteslice(source, 0, 7)).to eq('Hello t')
|
11
|
+
expect(cache.byteslice(source, 1, 7)).to eq('ello th')
|
12
|
+
expect(cache.byteslice(source, 11, 8)).to eq(', this i')
|
13
|
+
expect(cache.byteslice(source, 12, 12)).to eq(' this is our')
|
14
14
|
expect(cache.byteslice(source, 120, 12)).to be_nil
|
15
15
|
end
|
16
16
|
|
@@ -23,10 +23,10 @@ describe Care do
|
|
23
23
|
|
24
24
|
it 'can be cleared' do
|
25
25
|
cache = Care::Cache.new(3)
|
26
|
-
expect(cache.byteslice(source, 0, 3)).to eq(
|
27
|
-
expect(cache.instance_variable_get(
|
26
|
+
expect(cache.byteslice(source, 0, 3)).to eq('Hel')
|
27
|
+
expect(cache.instance_variable_get('@pages')).not_to be_empty
|
28
28
|
cache.clear
|
29
|
-
expect(cache.instance_variable_get(
|
29
|
+
expect(cache.instance_variable_get('@pages')).to be_empty
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'fits all the reads into one if the input fits into one page' do
|
@@ -67,7 +67,7 @@ describe Care do
|
|
67
67
|
@recorded_calls ||= []
|
68
68
|
@recorded_calls << [io, at, n_bytes]
|
69
69
|
# Pretend reads always succeed and return the requisite number of bytes
|
70
|
-
|
70
|
+
'x' * n_bytes
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FormatParser::Image do
|
4
|
-
|
5
|
-
context "File data checks" do
|
4
|
+
context 'File data checks' do
|
6
5
|
it 'succeeds with relevant attributes' do
|
7
6
|
result = described_class.new(format: :jpg, width_px: 42, height_px: 10, image_orientation: 1)
|
8
7
|
expect(result.nature).to eq(:image)
|
@@ -12,5 +11,4 @@ describe FormatParser::Image do
|
|
12
11
|
expect(result.image_orientation).to eq(1)
|
13
12
|
end
|
14
13
|
end
|
15
|
-
|
16
14
|
end
|
data/spec/format_parser_spec.rb
CHANGED
@@ -3,12 +3,12 @@ require 'spec_helper'
|
|
3
3
|
describe FormatParser do
|
4
4
|
it 'returns nil when trying to parse an empty IO' do
|
5
5
|
d = StringIO.new('')
|
6
|
-
expect(FormatParser.parse(d)).to
|
6
|
+
expect(FormatParser.parse(d)).to be_nil
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'returns nil when parsing an IO no parser can make sense of' do
|
10
10
|
d = StringIO.new(Random.new.bytes(1))
|
11
|
-
expect(FormatParser.parse(d)).to
|
11
|
+
expect(FormatParser.parse(d)).to be_nil
|
12
12
|
end
|
13
13
|
|
14
14
|
describe 'with fuzzing' do
|
@@ -26,24 +26,24 @@ describe FormatParser do
|
|
26
26
|
let(:audio) { FormatParser::Audio.new(format: :aiff, num_audio_channels: 1) }
|
27
27
|
let(:image) { FormatParser::Image.new(format: :dpx, width_px: 1, height_px: 1) }
|
28
28
|
|
29
|
-
context '#parse called
|
29
|
+
context '#parse called hash options' do
|
30
30
|
before do
|
31
31
|
expect_any_instance_of(FormatParser::AIFFParser).to receive(:call).and_return(audio)
|
32
32
|
expect_any_instance_of(FormatParser::DPXParser).to receive(:call).and_return(image)
|
33
33
|
end
|
34
34
|
|
35
|
-
subject { FormatParser.parse(blob) }
|
35
|
+
subject { FormatParser.parse(blob, results: :all) }
|
36
36
|
|
37
37
|
it { is_expected.to include(image) }
|
38
38
|
it { is_expected.to include(audio) }
|
39
39
|
end
|
40
40
|
|
41
|
-
context '#parse called
|
41
|
+
context '#parse called without hash options' do
|
42
42
|
before do
|
43
43
|
expect_any_instance_of(FormatParser::DPXParser).to receive(:call).and_return(image)
|
44
44
|
end
|
45
45
|
|
46
|
-
subject { FormatParser.parse(blob
|
46
|
+
subject { FormatParser.parse(blob) }
|
47
47
|
|
48
48
|
it { is_expected.to eq(image) }
|
49
49
|
end
|
data/spec/io_utils_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:io) {File.open(fixtures_dir + '/test.jpg', 'rb')}
|
5
|
-
include FormatParser::IOUtils
|
3
|
+
describe 'IOUtils' do
|
4
|
+
let(:io) { File.open(fixtures_dir + '/test.jpg', 'rb') }
|
5
|
+
include FormatParser::IOUtils
|
6
6
|
|
7
7
|
describe '#safe_read' do
|
8
8
|
it 'raises if the requested bytes are past the EOF' do
|
@@ -16,12 +16,12 @@ describe "IOUtils" do
|
|
16
16
|
expect {
|
17
17
|
safe_read(io, 1_000_000)
|
18
18
|
}.to raise_error(FormatParser::IOUtils::InvalidRead)
|
19
|
-
end
|
19
|
+
end
|
20
20
|
end
|
21
21
|
|
22
22
|
describe '#safe_skip' do
|
23
23
|
it 'raises on a negative skip byte amount' do
|
24
|
-
fake_io = double
|
24
|
+
fake_io = double
|
25
25
|
expect {
|
26
26
|
safe_skip(fake_io, -5)
|
27
27
|
}.to raise_error(FormatParser::IOUtils::InvalidRead)
|
@@ -29,12 +29,12 @@ describe "IOUtils" do
|
|
29
29
|
|
30
30
|
it 'uses #pos if available on the object' do
|
31
31
|
fake_io = double(pos: 11)
|
32
|
-
expect(fake_io).to receive(:seek).with(11+5)
|
32
|
+
expect(fake_io).to receive(:seek).with(11 + 5)
|
33
33
|
safe_skip(fake_io, 5)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'uses #read if no #pos is available on the object' do
|
37
|
-
fake_io = double
|
37
|
+
fake_io = double
|
38
38
|
expect(fake_io).to receive(:read).with(5).and_return('x' * 5)
|
39
39
|
safe_skip(fake_io, 5)
|
40
40
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FormatParser::EXIFParser do
|
4
|
-
|
5
4
|
# ORIENTATIONS = [
|
6
5
|
# :top_left,
|
7
6
|
# :top_right,
|
@@ -23,7 +22,7 @@ describe FormatParser::EXIFParser do
|
|
23
22
|
|
24
23
|
expect(parser.orientation).to be_kind_of(Symbol)
|
25
24
|
# Filenames in this dir correspond with the orientation of the file
|
26
|
-
expect(filename.include?(parser.orientation.to_s)).to be true
|
25
|
+
expect(filename.include?(parser.orientation.to_s)).to be true
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
@@ -38,7 +37,7 @@ describe FormatParser::EXIFParser do
|
|
38
37
|
|
39
38
|
expect(parser.orientation).to be_kind_of(Symbol)
|
40
39
|
# Filenames in this dir correspond with the orientation of the file
|
41
|
-
expect(filename.include?(parser.orientation.to_s)).to be true
|
40
|
+
expect(filename.include?(parser.orientation.to_s)).to be true
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
@@ -23,7 +23,7 @@ describe FormatParser::GIFParser do
|
|
23
23
|
|
24
24
|
describe 'is able to correctly parse our own examples' do
|
25
25
|
it 'is able to parse the animated GIF' do
|
26
|
-
gif_path = fixtures_dir +
|
26
|
+
gif_path = fixtures_dir + 'GIF/anim.gif'
|
27
27
|
|
28
28
|
parsed = subject.call(File.open(gif_path, 'rb'))
|
29
29
|
expect(parsed).not_to be_nil
|
@@ -1,8 +1,7 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe FormatParser::MOOVParser do
|
5
|
-
|
6
5
|
def deep_print_atoms(atoms, output, swimlanes = [])
|
7
6
|
return unless atoms
|
8
7
|
|
@@ -12,7 +11,7 @@ describe FormatParser::MOOVParser do
|
|
12
11
|
vert = '│'
|
13
12
|
cdn = '┬'
|
14
13
|
n_atoms = atoms.length
|
15
|
-
|
14
|
+
|
16
15
|
atoms.each_with_index do |atom, i|
|
17
16
|
is_last_child = i == (n_atoms - 1)
|
18
17
|
has_children = atom.children && atom.children.any?
|
@@ -20,7 +20,7 @@ describe FormatParser::PNGParser do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'is able to parse an animated PNG' do
|
23
|
-
gif_path = fixtures_dir +
|
23
|
+
gif_path = fixtures_dir + 'PNG/anim.png'
|
24
24
|
|
25
25
|
parsed = subject.call(File.open(gif_path, 'rb'))
|
26
26
|
expect(parsed).not_to be_nil
|
@@ -12,7 +12,7 @@ describe FormatParser::WAVParser do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
it
|
15
|
+
it 'returns correct info about pcm files' do
|
16
16
|
parse_result = subject.call(File.open(__dir__ + '/../fixtures/WAV/c_8kmp316.wav', 'rb'))
|
17
17
|
|
18
18
|
expect(parse_result.nature).to eq(:audio)
|
@@ -23,7 +23,7 @@ describe FormatParser::WAVParser do
|
|
23
23
|
expect(parse_result.media_duration_seconds).to be_within(0.01).of(13.81)
|
24
24
|
end
|
25
25
|
|
26
|
-
it
|
26
|
+
it 'returns correct info about pcm files with more channels' do
|
27
27
|
parse_result = subject.call(File.open(__dir__ + '/../fixtures/WAV/c_39064__alienbomb__atmo-truck.wav', 'rb'))
|
28
28
|
|
29
29
|
expect(parse_result.nature).to eq(:audio)
|
@@ -34,7 +34,7 @@ describe FormatParser::WAVParser do
|
|
34
34
|
expect(parse_result.media_duration_seconds).to be_within(0.01).of(3.69)
|
35
35
|
end
|
36
36
|
|
37
|
-
it
|
37
|
+
it 'returns correct info about non pcm files' do
|
38
38
|
parse_result = subject.call(File.open(__dir__ + '/../fixtures/WAV/c_11k16bitpcm.wav', 'rb'))
|
39
39
|
|
40
40
|
expect(parse_result.nature).to eq(:audio)
|
data/spec/read_limiter_spec.rb
CHANGED
@@ -6,52 +6,67 @@ describe 'Fetching data from HTTP remotes' do
|
|
6
6
|
log_file ||= StringIO.new
|
7
7
|
log = WEBrick::Log.new(log_file)
|
8
8
|
options = {
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
Port: 9399,
|
10
|
+
Logger: log,
|
11
|
+
AccessLog: [
|
12
|
+
[log, WEBrick::AccessLog::COMMON_LOG_FORMAT],
|
13
|
+
[log, WEBrick::AccessLog::REFERER_LOG_FORMAT]
|
14
|
+
]
|
15
15
|
}
|
16
16
|
@server = WEBrick::HTTPServer.new(options)
|
17
17
|
@server.mount '/', WEBrick::HTTPServlet::FileHandler, fixtures_dir
|
18
|
-
trap(
|
18
|
+
trap('INT') { @server.stop }
|
19
19
|
@server_thread = Thread.new { @server.start }
|
20
20
|
end
|
21
21
|
|
22
|
+
it '#parse_http is called without any option' do
|
23
|
+
result = FormatParser.parse_http('http://localhost:9399/PNG/anim.png')
|
24
|
+
|
25
|
+
expect(result.format).to eq(:png)
|
26
|
+
expect(result.height_px).to eq(180)
|
27
|
+
end
|
28
|
+
|
29
|
+
it '#parse_http is called with hash options' do
|
30
|
+
expect_any_instance_of(FormatParser::AIFFParser).to receive(:call).and_return(:audio)
|
31
|
+
result = FormatParser.parse_http('http://localhost:9399/PNG/anim.png', results: :all)
|
32
|
+
|
33
|
+
expect(result.include?(:audio)).to be true
|
34
|
+
expect(result.count).to eq(2)
|
35
|
+
end
|
36
|
+
|
22
37
|
it 'parses the animated PNG over HTTP' do
|
23
38
|
file_information = FormatParser.parse_http('http://localhost:9399/PNG/anim.png')
|
24
39
|
expect(file_information).not_to be_nil
|
25
|
-
expect(file_information.
|
40
|
+
expect(file_information.nature).to eq(:image)
|
26
41
|
end
|
27
42
|
|
28
43
|
it 'parses the JPEGs exif data' do
|
29
44
|
file_information = FormatParser.parse_http('http://localhost:9399/exif-orientation-testimages/jpg/top_left.jpg')
|
30
45
|
expect(file_information).not_to be_nil
|
31
|
-
expect(file_information.
|
32
|
-
expect(file_information.
|
33
|
-
expect(file_information.
|
46
|
+
expect(file_information.nature).to eq(:image)
|
47
|
+
expect(file_information.format).to eq(:jpg)
|
48
|
+
expect(file_information.orientation).to eq(:top_left)
|
34
49
|
end
|
35
50
|
|
36
51
|
it 'parses the TIFFs exif data' do
|
37
52
|
file_information = FormatParser.parse_http('http://localhost:9399/TIFF/test.tif')
|
38
53
|
expect(file_information).not_to be_nil
|
39
|
-
expect(file_information.
|
40
|
-
expect(file_information.
|
41
|
-
expect(file_information.
|
54
|
+
expect(file_information.nature).to eq(:image)
|
55
|
+
expect(file_information.format).to eq(:tif)
|
56
|
+
expect(file_information.orientation).to eq(:top_left)
|
42
57
|
end
|
43
58
|
|
44
59
|
describe 'is able to correctly parse orientation for all remote JPEG EXIF examples from FastImage' do
|
45
60
|
Dir.glob(fixtures_dir + '/exif-orientation-testimages/jpg/*.jpg').each do |jpeg_path|
|
46
61
|
filename = File.basename(jpeg_path)
|
47
62
|
it "is able to parse #{filename}" do
|
48
|
-
remote_jpeg_path = jpeg_path.gsub(fixtures_dir,
|
63
|
+
remote_jpeg_path = jpeg_path.gsub(fixtures_dir, 'http://localhost:9399')
|
49
64
|
file_information = FormatParser.parse_http(remote_jpeg_path)
|
50
65
|
expect(file_information).not_to be_nil
|
51
66
|
|
52
|
-
expect(file_information.
|
67
|
+
expect(file_information.orientation).to be_kind_of(Symbol)
|
53
68
|
# Filenames in this dir correspond with the orientation of the file
|
54
|
-
expect(filename.include?(file_information.
|
69
|
+
expect(filename.include?(file_information.orientation.to_s)).to be true
|
55
70
|
end
|
56
71
|
end
|
57
72
|
end
|
@@ -60,15 +75,14 @@ describe 'Fetching data from HTTP remotes' do
|
|
60
75
|
Dir.glob(fixtures_dir + '/**/*.*').sort.each do |fixture_path|
|
61
76
|
filename = File.basename(fixture_path)
|
62
77
|
it "parses #{filename} without raising any errors" do
|
63
|
-
remote_fixture_path = fixture_path.gsub(fixtures_dir,
|
78
|
+
remote_fixture_path = fixture_path.gsub(fixtures_dir, 'http://localhost:9399')
|
64
79
|
# Some of the fixtures are in dirs with spaces
|
65
|
-
cleaned_remote_fixture_path = remote_fixture_path.gsub(
|
80
|
+
cleaned_remote_fixture_path = remote_fixture_path.gsub(' ', '%20')
|
66
81
|
FormatParser.parse_http(cleaned_remote_fixture_path)
|
67
82
|
end
|
68
83
|
end
|
69
84
|
end
|
70
85
|
|
71
|
-
|
72
86
|
after(:all) do
|
73
87
|
@server.stop
|
74
88
|
@server_thread.join(0.5)
|
data/spec/remote_io_spec.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe FormatParser::RemoteIO do
|
4
|
-
|
5
4
|
it_behaves_like 'an IO object compatible with IOConstraint'
|
6
5
|
|
7
6
|
it 'returns the partial content when the server supplies a 206 status' do
|
8
|
-
rio = described_class.new(
|
9
|
-
|
7
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
8
|
+
|
10
9
|
fake_resp = double(headers: {'Content-Range' => '10-109/2577'}, status: 206, body: 'This is the response')
|
11
|
-
expect(Faraday).to receive(:get).with(
|
10
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109').and_return(fake_resp)
|
12
11
|
|
13
12
|
rio.seek(10)
|
14
13
|
read_result = rio.read(100)
|
@@ -16,10 +15,10 @@ describe FormatParser::RemoteIO do
|
|
16
15
|
end
|
17
16
|
|
18
17
|
it 'returns the entire content when the server supplies the Content-Range response but sends a 200 status' do
|
19
|
-
rio = described_class.new(
|
20
|
-
|
18
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
19
|
+
|
21
20
|
fake_resp = double(headers: {'Content-Range' => '10-109/2577'}, status: 200, body: 'This is the response')
|
22
|
-
expect(Faraday).to receive(:get).with(
|
21
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=10-109').and_return(fake_resp)
|
23
22
|
|
24
23
|
rio.seek(10)
|
25
24
|
read_result = rio.read(100)
|
@@ -27,36 +26,36 @@ describe FormatParser::RemoteIO do
|
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'raises a specific error for all 4xx responses except 416' do
|
30
|
-
rio = described_class.new(
|
31
|
-
|
29
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
30
|
+
|
32
31
|
fake_resp = double(headers: {}, status: 403, body: 'Please log in')
|
33
|
-
expect(Faraday).to receive(:get).with(
|
32
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
|
34
33
|
|
35
34
|
rio.seek(100)
|
36
35
|
expect { rio.read(100) }.to raise_error(/replied with a 403 and refused/)
|
37
36
|
end
|
38
37
|
|
39
38
|
it 'returns a nil when the range cannot be satisfied and the response is 416' do
|
40
|
-
rio = described_class.new(
|
41
|
-
|
39
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
40
|
+
|
42
41
|
fake_resp = double(headers: {}, status: 416, body: 'You jumped off the end of the file maam')
|
43
|
-
expect(Faraday).to receive(:get).with(
|
42
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
|
44
43
|
|
45
44
|
rio.seek(100)
|
46
45
|
expect(rio.read(100)).to be_nil
|
47
46
|
end
|
48
47
|
|
49
48
|
it 'does not overwrite size when the range cannot be satisfied and the response is 416' do
|
50
|
-
rio = described_class.new(
|
49
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
51
50
|
|
52
51
|
fake_resp = double(headers: {'Content-Range' => 'bytes 0-0/13'}, status: 206, body: 'a')
|
53
|
-
expect(Faraday).to receive(:get).with(
|
52
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0').and_return(fake_resp)
|
54
53
|
rio.read(1)
|
55
54
|
|
56
55
|
expect(rio.size).to eq(13)
|
57
56
|
|
58
57
|
fake_resp = double(headers: {}, status: 416, body: 'You jumped off the end of the file maam')
|
59
|
-
expect(Faraday).to receive(:get).with(
|
58
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
|
60
59
|
|
61
60
|
rio.seek(100)
|
62
61
|
expect(rio.read(100)).to be_nil
|
@@ -65,22 +64,22 @@ describe FormatParser::RemoteIO do
|
|
65
64
|
end
|
66
65
|
|
67
66
|
it 'raises a specific error for all 5xx responses' do
|
68
|
-
rio = described_class.new(
|
69
|
-
|
67
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
68
|
+
|
70
69
|
fake_resp = double(headers: {}, status: 502, body: 'Guru meditation')
|
71
|
-
expect(Faraday).to receive(:get).with(
|
70
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=100-199').and_return(fake_resp)
|
72
71
|
|
73
72
|
rio.seek(100)
|
74
73
|
expect { rio.read(100) }.to raise_error(/replied with a 502 and we might want to retry/)
|
75
74
|
end
|
76
75
|
|
77
76
|
it 'maintains and exposes #pos' do
|
78
|
-
rio = described_class.new(
|
77
|
+
rio = described_class.new('https://images.invalid/img.jpg')
|
79
78
|
|
80
79
|
expect(rio.pos).to eq(0)
|
81
80
|
|
82
81
|
fake_resp = double(headers: {'Content-Range' => 'bytes 0-0/13'}, status: 206, body: 'a')
|
83
|
-
expect(Faraday).to receive(:get).with(
|
82
|
+
expect(Faraday).to receive(:get).with('https://images.invalid/img.jpg', nil, range: 'bytes=0-0').and_return(fake_resp)
|
84
83
|
rio.read(1)
|
85
84
|
|
86
85
|
expect(rio.pos).to eq(1)
|