format_parser 2.3.0 → 2.4.4

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.
@@ -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