format_parser 2.3.0 → 2.4.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,14 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FormatParser::ISOBaseMediaFileFormat::Decoder do
4
- context 'when build_atom_tree is called' do
5
- context 'with no io' do
6
- it 'raises an error' do
7
- expect { subject.build_atom_tree(0x0) }.to raise_error(/IO missing - supply a valid IO object/)
4
+ describe '#build_box_tree' do
5
+ context 'when IO not provided' do
6
+ context 'when IO not previously provided' do
7
+ it 'raises an error' do
8
+ expect { subject.build_box_tree(0x0) }.to raise_error(/IO missing - supply a valid IO object/)
9
+ end
10
+ end
11
+
12
+ context 'when IO previously provided' do
13
+ let(:io) { StringIO.new('') }
14
+ it 'does not raise an error' do
15
+ expect(subject.build_box_tree(0x0, io)).to eq([])
16
+ expect(subject.build_box_tree(0x0)).to eq([])
17
+ end
8
18
  end
9
19
  end
10
20
 
11
- context('with a max_read smaller than the length of the IO') do
21
+ context 'when max_read smaller than IO length' do
12
22
  let(:io) do
13
23
  # moov
14
24
  # moov
@@ -17,41 +27,53 @@ describe FormatParser::ISOBaseMediaFileFormat::Decoder do
17
27
  end
18
28
 
19
29
  it 'stops building the tree' do
20
- expect(subject.build_atom_tree(0x0, io).length).to eq(0)
30
+ expect(subject.build_box_tree(0x0, io).length).to eq(0)
21
31
  expect(io.pos).to eq(0)
22
32
 
23
- expect(subject.build_atom_tree(0x8, io).length).to eq(1)
33
+ expect(subject.build_box_tree(0x8, io).length).to eq(1)
24
34
  expect(io.pos).to eq(0x8)
25
35
  io.seek(0)
26
36
 
27
- expect(subject.build_atom_tree(0x10, io).length).to eq(2)
37
+ expect(subject.build_box_tree(0x10, io).length).to eq(2)
28
38
  expect(io.pos).to eq(0x10)
29
39
  end
30
40
  end
31
41
 
32
- context 'when parsing an unknown atom' do
42
+ context 'when parsing unknown box' do
33
43
  let(:io) do
34
44
  # foo
35
45
  # |-> moov
36
46
  input = [0x14].pack('N') + 'foo ' + [0x1].pack('N') + [0x8].pack('N') + 'moov'
37
47
  StringIO.new(input)
38
48
  end
49
+ let(:result) { subject.build_box_tree(0xFF, io) }
39
50
 
40
- it 'parses only the type, position and size, and skips any fields and children' do
41
- result = subject.build_atom_tree(0xFF, io)
51
+ it 'parses successfully' do
42
52
  expect(result.length).to eq(1)
43
- expect(io.pos).to eq(0x14)
53
+ end
54
+
55
+ it 'parses the correct type' do
56
+ expect(result[0].type).to eq('foo ')
57
+ end
58
+
59
+ it 'parses the correct position' do
60
+ expect(result[0].position).to eq(0)
61
+ end
62
+
63
+ it 'parses the correct size' do
64
+ expect(result[0].size).to eq(0x14)
65
+ end
44
66
 
45
- foo_atom = result[0]
46
- expect(foo_atom.type).to eq('foo ')
47
- expect(foo_atom.position).to eq(0)
48
- expect(foo_atom.size).to eq(0x14)
49
- expect(foo_atom.fields).to eq({})
50
- expect(foo_atom.children).to eq([])
67
+ it 'skips additional fields' do
68
+ expect(result[0].fields).to eq({})
69
+ end
70
+
71
+ it 'skips children' do
72
+ expect(result[0].children).to eq([])
51
73
  end
52
74
  end
53
75
 
54
- context 'when parsing a container atom' do
76
+ context 'when parsing a container box' do
55
77
  let(:io) do
56
78
  # moov
57
79
  # |-> foo
@@ -59,183 +81,127 @@ describe FormatParser::ISOBaseMediaFileFormat::Decoder do
59
81
  input = [0x18].pack('N') + 'moov' + [0x8].pack('N') + 'foo ' + [0x8].pack('N') + 'bar '
60
82
  StringIO.new(input)
61
83
  end
84
+ let(:result) { subject.build_box_tree(0xFF, io) }
62
85
 
63
- it 'parses type, position, size and children' do
64
- result = subject.build_atom_tree(0xFF, io)
86
+ it 'parses successfully' do
65
87
  expect(result.length).to eq(1)
66
- expect(io.pos).to eq(0x18)
88
+ end
67
89
 
68
- moov_atom = result[0]
69
- expect(moov_atom.type).to eq('moov')
70
- expect(moov_atom.position).to eq(0)
71
- expect(moov_atom.size).to eq(0x18)
72
- expect(moov_atom.fields).to eq({})
73
- expect(moov_atom.children.length).to eq(2)
90
+ it 'parses the correct type' do
91
+ expect(result[0].type).to eq('moov')
74
92
  end
75
- end
76
93
 
77
- context 'when parsing an empty atom' do
78
- let(:io) do
79
- # nmhd
80
- # |-> foo
81
- input = [0x18].pack('N') + 'nmhd' + [0x1].pack('c') + 'fla' + [0x2].pack('N') + [0x8].pack('N') + 'foo '
82
- StringIO.new(input)
94
+ it 'parses the correct position' do
95
+ expect(result[0].position).to eq(0)
83
96
  end
84
97
 
85
- it 'parses type, position, size, version and flags, and skips any other fields or children' do
86
- result = subject.build_atom_tree(0xFF, io)
87
- expect(result.length).to eq(1)
88
- expect(io.pos).to eq(0x18)
98
+ it 'parses the correct size' do
99
+ expect(result[0].size).to eq(0x18)
100
+ end
89
101
 
90
- nmhd_atom = result[0]
91
- expect(nmhd_atom.type).to eq('nmhd')
92
- expect(nmhd_atom.position).to eq(0)
93
- expect(nmhd_atom.size).to eq(0x18)
94
- expect(nmhd_atom.fields).to include({
95
- version: 1,
96
- flags: 'fla'
97
- })
98
- expect(nmhd_atom.children).to eq([])
102
+ it 'skips additional fields' do
103
+ expect(result[0].fields).to eq({})
104
+ end
105
+
106
+ it 'parses children' do
107
+ expect(result[0].children.length).to eq(2)
99
108
  end
100
109
  end
101
110
 
102
- context 'when parsing a uuid atom' do
103
- let(:usertype) { '90f7c66ec2db476b977461e796f0dd4b' }
111
+ context 'when parsing an empty box' do
104
112
  let(:io) do
105
- input = [0x20].pack('N') + 'uuid' + [usertype].pack('H*') + [0x8].pack('N') + 'foo '
113
+ # nmhd
114
+ # |-> foo
115
+ input = [0x18].pack('N') + 'nmhd' + [0x1].pack('c') + 'fla' + [0x2].pack('N') + [0x8].pack('N') + 'foo '
106
116
  StringIO.new(input)
107
117
  end
118
+ let(:result) { subject.build_box_tree(0xFF, io) }
108
119
 
109
- it 'parses type, position, size and usertype, and skips any other fields or children' do
110
- # uuid
111
- # |-> foo
112
- result = subject.build_atom_tree(0xFF, io)
120
+ it 'parses successfully' do
113
121
  expect(result.length).to eq(1)
114
- expect(io.pos).to eq(0x20)
115
-
116
- nmhd_atom = result[0]
117
- expect(nmhd_atom.type).to eq('uuid')
118
- expect(nmhd_atom.position).to eq(0)
119
- expect(nmhd_atom.size).to eq(0x20)
120
- expect(nmhd_atom.fields).to include({
121
- usertype: usertype,
122
- })
123
- expect(nmhd_atom.children).to eq([])
124
122
  end
125
- end
126
- end
127
- end
128
123
 
129
- describe FormatParser::ISOBaseMediaFileFormat::Decoder::Atom do
130
- context 'when initialized' do
131
- context 'without fields and/or children' do
132
- subject { described_class.new('foo', 0, 0) }
133
-
134
- it 'sets them as an empty array/hash' do
135
- expect(subject.type).to eq('foo')
136
- expect(subject.position).to eq(0)
137
- expect(subject.size).to eq(0)
138
- expect(subject.fields).to eq({})
139
- expect(subject.children).to eq([])
124
+ it 'parses the correct type' do
125
+ expect(result[0].type).to eq('nmhd')
140
126
  end
141
- end
142
127
 
143
- context 'with fields and/or children' do
144
- let(:fields) { { foo: 1, bar: 'bar' } }
145
- let(:children) { [described_class.new('bar', 0, 0)] }
128
+ it 'parses the correct position' do
129
+ expect(result[0].position).to eq(0)
130
+ end
146
131
 
147
- subject { described_class.new('foo', 0, 0, fields, children) }
132
+ it 'parses the correct size' do
133
+ expect(result[0].size).to eq(0x18)
134
+ end
148
135
 
149
- it 'sets them correctly' do
150
- expect(subject.type).to eq('foo')
151
- expect(subject.position).to eq(0)
152
- expect(subject.size).to eq(0)
153
- expect(subject.fields).to eq(fields)
154
- expect(subject.children).to eq(children)
136
+ it 'parses version and flags' do
137
+ expect(result[0].fields).to include({
138
+ version: 1,
139
+ flags: 'fla'
140
+ })
155
141
  end
156
- end
157
- end
158
142
 
159
- context 'when find_first_descendent is called' do
160
- context 'with no children' do
161
- subject { described_class.new('root', 0, 0) }
162
- it 'returns nil' do
163
- expect(subject.find_first_descendent(%w[root foo])).to be_nil
143
+ it 'skips children' do
144
+ expect(result[0].children).to eq([])
164
145
  end
165
146
  end
166
147
 
167
- context 'with no descendents of the given type(s)' do
168
- subject do
169
- described_class.new('root', 0, 0, nil, [
170
- described_class.new('foo', 0, 0),
171
- described_class.new('bar', 0, 0, nil, [
172
- described_class.new('baz', 0, 0)
173
- ])
174
- ])
148
+ context 'when parsing a uuid box' do
149
+ let(:usertype) { '90f7c66ec2db476b977461e796f0dd4b' }
150
+ let(:io) do
151
+ # uuid
152
+ # |-> foo
153
+ input = [0x20].pack('N') + 'uuid' + [usertype].pack('H*') + [0x8].pack('N') + 'foo '
154
+ StringIO.new(input)
175
155
  end
156
+ let(:result) { subject.build_box_tree(0xFF, io) }
176
157
 
177
- it 'returns nil' do
178
- expect(subject.find_first_descendent(%w[root qux])).to be_nil
158
+ it 'parses successfully' do
159
+ expect(result.length).to eq(1)
179
160
  end
180
- end
181
-
182
- context 'with multiple descendents of the given type(s)' do
183
- let(:descendent) { described_class.new('bar', 0, 0) }
184
161
 
185
- subject do
186
- described_class.new('root', 0, 0, nil, [
187
- described_class.new('foo', 0, 0, nil, [
188
- descendent
189
- ]),
190
- described_class.new('bar', 0, 0),
191
- ])
162
+ it 'parses the correct type' do
163
+ expect(result[0].type).to eq('uuid')
192
164
  end
193
165
 
194
- it 'returns the first relevant descendent in order of appearance' do
195
- expect(subject.find_first_descendent(%w[bar])).to be(descendent)
166
+ it 'parses the correct position' do
167
+ expect(result[0].position).to eq(0)
196
168
  end
197
- end
198
- end
199
169
 
200
- context 'when select_descendents is called' do
201
- context 'with no children' do
202
- subject { described_class.new('root', 0, 0) }
203
- it 'returns an empty array' do
204
- expect(subject.select_descendents(%w[root foo])).to eq([])
170
+ it 'parses the correct size' do
171
+ expect(result[0].size).to eq(0x20)
205
172
  end
206
- end
207
173
 
208
- context 'with no descendents of the given type(s)' do
209
- subject do
210
- described_class.new('root', 0, 0, nil, [
211
- described_class.new('foo', 0, 0),
212
- described_class.new('bar', 0, 0, nil, [
213
- described_class.new('baz', 0, 0)
214
- ])
215
- ])
174
+ it 'parses usertype' do
175
+ expect(result[0].fields).to include({ usertype: usertype })
216
176
  end
217
177
 
218
- it 'returns an empty array' do
219
- expect(subject.select_descendents(%w[root qux])).to eq([])
178
+ it 'skips children' do
179
+ expect(result[0].children).to eq([])
220
180
  end
221
181
  end
222
182
 
223
- context 'with multiple descendents of the given type(s)' do
224
- let(:descendent_1) { described_class.new('bar', 0, 0) }
225
- let(:descendent_3) { described_class.new('bar', 20, 20) }
226
- let(:descendent_2) { described_class.new('baz', 10, 10, nil, [descendent_3]) }
183
+ context 'when parsing a box with 0 size' do
184
+ let(:io) do
185
+ # foo
186
+ # moov
187
+ # |-> bar
188
+ # |-> baz
189
+ input = [0x8].pack('N') + 'foo ' + [0x0].pack('N') + 'moov' + [0x8].pack('N') + 'bar ' + [0x8].pack('N') + 'baz '
190
+ StringIO.new(input)
191
+ end
192
+ let(:result) { subject.build_box_tree(0xFF, io) }
227
193
 
228
- subject do
229
- described_class.new('root', 0, 0, nil, [
230
- described_class.new('foo', 0, 0, nil, [
231
- descendent_1
232
- ]),
233
- descendent_2,
234
- ])
194
+ it 'reads the rest of the file' do
195
+ expect(result.length).to eq(2)
196
+ expect(io.pos).to eq(0x20)
235
197
  end
236
198
 
237
- it 'returns all relevant descendents' do
238
- expect(subject.select_descendents(%w[bar baz])).to match_array([descendent_1, descendent_2, descendent_3])
199
+ it 'parses correctly' do
200
+ expect(result[0].type).to eq('foo ')
201
+ expect(result[1].type).to eq('moov')
202
+ expect(result[1].children.length).to eq(2)
203
+ expect(result[1].children[0].type).to eq('bar ')
204
+ expect(result[1].children[1].type).to eq('baz ')
239
205
  end
240
206
  end
241
207
  end