1 // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 #include "src/master_value_parser.h"
9
10 #include "gmock/gmock.h"
11 #include "gtest/gtest.h"
12
13 #include "src/int_parser.h"
14 #include "test_utils/element_parser_test.h"
15 #include "webm/element.h"
16 #include "webm/id.h"
17 #include "webm/status.h"
18
19 using testing::_;
20 using testing::DoAll;
21 using testing::InSequence;
22 using testing::NotNull;
23 using testing::Return;
24 using testing::SetArgPointee;
25
26 using webm::Action;
27 using webm::Callback;
28 using webm::Cluster;
29 using webm::ElementMetadata;
30 using webm::ElementParserTest;
31 using webm::Id;
32 using webm::MasterValueParser;
33 using webm::Status;
34 using webm::UnsignedIntParser;
35
36 namespace {
37
38 // An instance of MasterValueParser that can actually be used in the tests to
39 // parse Cluster structures.
40 class FakeClusterParser : public MasterValueParser<Cluster> {
41 public:
FakeClusterParser()42 FakeClusterParser()
43 : MasterValueParser(
44 MakeChild<UnsignedIntParser>(Id::kTimecode, &Cluster::timecode),
45 MakeChild<UnsignedIntParser>(Id::kPrevSize, &Cluster::previous_size)
46 .UseAsStartEvent()) {}
47
48 protected:
OnParseStarted(Callback * callback,Action * action)49 Status OnParseStarted(Callback* callback, Action* action) override {
50 return callback->OnClusterBegin(metadata(Id::kCluster), value(), action);
51 }
52
OnParseCompleted(Callback * callback)53 Status OnParseCompleted(Callback* callback) override {
54 return callback->OnClusterEnd(metadata(Id::kCluster), value());
55 }
56 };
57
58 class MasterValueParserTest
59 : public ElementParserTest<FakeClusterParser, Id::kCluster> {};
60
TEST_F(MasterValueParserTest,InvalidId)61 TEST_F(MasterValueParserTest, InvalidId) {
62 SetReaderData({
63 0x00, // Invalid ID.
64 });
65
66 ParseAndExpectResult(Status::kInvalidElementId);
67 }
68
TEST_F(MasterValueParserTest,InvalidSize)69 TEST_F(MasterValueParserTest, InvalidSize) {
70 SetReaderData({
71 0xE7, // ID = 0xE7 (Timecode).
72 0xFF, // Size = unknown.
73 });
74
75 ParseAndExpectResult(Status::kInvalidElementSize);
76 }
77
TEST_F(MasterValueParserTest,DefaultParse)78 TEST_F(MasterValueParserTest, DefaultParse) {
79 {
80 InSequence dummy;
81
82 EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
83 .Times(1);
84
85 EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
86 }
87
88 ParseAndVerify();
89 }
90
TEST_F(MasterValueParserTest,DefaultValues)91 TEST_F(MasterValueParserTest, DefaultValues) {
92 SetReaderData({
93 0xE7, // ID = 0xE7 (Timecode).
94 0x80, // Size = 0.
95
96 0xAB, // ID = 0xAB (PrevSize).
97 0x80, // Size = 0.
98 });
99
100 {
101 InSequence dummy;
102
103 Cluster cluster{};
104 cluster.timecode.Set(0, true);
105
106 ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
107 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
108
109 child_metadata = {Id::kPrevSize, 2, 0, 2};
110 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
111
112 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
113 .Times(1);
114
115 cluster.previous_size.Set(0, true);
116 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
117 }
118
119 ParseAndVerify();
120 }
121
TEST_F(MasterValueParserTest,CustomValues)122 TEST_F(MasterValueParserTest, CustomValues) {
123 SetReaderData({
124 0xE7, // ID = 0xE7 (Timecode).
125 0x82, // Size = 2.
126 0x04, 0x00, // Body (value = 1024).
127
128 0xAB, // ID = 0xAB (PrevSize).
129 0x40, 0x01, // Size = 1.
130 0x01, // Body (value = 1).
131 });
132
133 {
134 InSequence dummy;
135
136 Cluster cluster{};
137 cluster.timecode.Set(1024, true);
138
139 ElementMetadata child_metadata = {Id::kTimecode, 2, 2, 0};
140 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
141
142 child_metadata = {Id::kPrevSize, 3, 1, 4};
143 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
144
145 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
146 .Times(1);
147
148 cluster.previous_size.Set(1, true);
149 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
150 }
151
152 ParseAndVerify();
153 }
154
TEST_F(MasterValueParserTest,IncrementalParse)155 TEST_F(MasterValueParserTest, IncrementalParse) {
156 SetReaderData({
157 0xE7, // ID = 0xE7 (Timecode).
158 0x40, 0x02, // Size = 2.
159 0x04, 0x00, // Body (value = 1024).
160
161 0x40, 0x00, // ID = 0x4000 (Unknown).
162 0x40, 0x02, // Size = 2.
163 0x00, 0x00, // Body.
164
165 0xAB, // ID = 0xAB (PrevSize).
166 0x40, 0x02, // Size = 2.
167 0x00, 0x01, // Body (value = 1).
168 });
169
170 {
171 InSequence dummy;
172
173 Cluster cluster{};
174 cluster.timecode.Set(1024, true);
175
176 ElementMetadata child_metadata = {Id::kTimecode, 3, 2, 0};
177 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
178
179 child_metadata = {static_cast<Id>(0x4000), 4, 2, 5};
180 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
181 EXPECT_CALL(callback_,
182 OnUnknownElement(child_metadata, NotNull(), NotNull()))
183 .Times(3);
184
185 child_metadata = {Id::kPrevSize, 3, 2, 11};
186 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
187
188 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
189 .Times(1);
190
191 cluster.previous_size.Set(1, true);
192 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
193 }
194
195 IncrementalParseAndVerify();
196 }
197
TEST_F(MasterValueParserTest,StartEventWithoutPreviousSize)198 TEST_F(MasterValueParserTest, StartEventWithoutPreviousSize) {
199 SetReaderData({
200 0xE7, // ID = 0xE7 (Timecode).
201 0x80, // Size = 0.
202 });
203
204 {
205 InSequence dummy;
206
207 Cluster cluster{};
208
209 const ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
210 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
211
212 cluster.timecode.Set(0, true);
213 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
214 .Times(1);
215
216 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
217 }
218
219 ParseAndVerify();
220 }
221
TEST_F(MasterValueParserTest,StartEventWithPreviousSize)222 TEST_F(MasterValueParserTest, StartEventWithPreviousSize) {
223 SetReaderData({
224 0xAB, // ID = 0xAB (PrevSize).
225 0x80, // Size = 0.
226
227 0xE7, // ID = 0xE7 (Timecode).
228 0x80, // Size = 0.
229 });
230
231 {
232 InSequence dummy;
233
234 Cluster cluster{};
235
236 ElementMetadata child_metadata = {Id::kPrevSize, 2, 0, 0};
237 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
238
239 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
240 .Times(1);
241
242 child_metadata = {Id::kTimecode, 2, 0, 2};
243 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
244
245 cluster.previous_size.Set(0, true);
246 cluster.timecode.Set(0, true);
247 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
248 }
249
250 ParseAndVerify();
251 }
252
TEST_F(MasterValueParserTest,PartialStartThenRead)253 TEST_F(MasterValueParserTest, PartialStartThenRead) {
254 SetReaderData({
255 0xAB, // ID = 0xAB (PrevSize).
256 0x81, // Size = 1.
257 0x01, // Body (value = 1).
258
259 0xE7, // ID = 0xE7 (Timecode).
260 0x81, // Size = 1.
261 0x01, // Body (value = 1).
262 });
263
264 {
265 InSequence dummy;
266
267 Cluster cluster{};
268
269 ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
270 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
271
272 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
273 .WillOnce(Return(Status(Status::kOkPartial)))
274 .WillOnce(DoAll(SetArgPointee<2>(Action::kRead),
275 Return(Status(Status::kOkCompleted))));
276
277 child_metadata = {Id::kTimecode, 2, 1, 3};
278 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
279
280 cluster.previous_size.Set(1, true);
281 cluster.timecode.Set(1, true);
282 EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
283 }
284
285 IncrementalParseAndVerify();
286 }
287
TEST_F(MasterValueParserTest,EmptySkip)288 TEST_F(MasterValueParserTest, EmptySkip) {
289 const Cluster cluster{};
290
291 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
292 .WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
293 Return(Status(Status::kOkCompleted))));
294
295 EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
296 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
297
298 ParseAndVerify();
299
300 EXPECT_EQ(cluster, parser_.value());
301 }
302
TEST_F(MasterValueParserTest,Skip)303 TEST_F(MasterValueParserTest, Skip) {
304 SetReaderData({
305 0xAB, // ID = 0xAB (PrevSize).
306 0x81, // Size = 1.
307 0x01, // Body (value = 1).
308
309 0xE7, // ID = 0xE7 (Timecode).
310 0x81, // Size = 1.
311 0x01, // Body (value = 1).
312 });
313
314 const Cluster cluster{};
315
316 {
317 InSequence dummy;
318
319 const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
320 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
321
322 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
323 .WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
324 Return(Status(Status::kOkCompleted))));
325
326 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
327 }
328
329 ParseAndVerify();
330
331 EXPECT_EQ(cluster, parser_.value());
332 }
333
TEST_F(MasterValueParserTest,PartialStartThenSkip)334 TEST_F(MasterValueParserTest, PartialStartThenSkip) {
335 SetReaderData({
336 0xAB, // ID = 0xAB (PrevSize).
337 0x81, // Size = 1.
338 0x01, // Body (value = 1).
339
340 0xE7, // ID = 0xE7 (Timecode).
341 0x81, // Size = 1.
342 0x01, // Body (value = 1).
343 });
344
345 const Cluster cluster{};
346
347 {
348 InSequence dummy;
349
350 const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
351 EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
352
353 EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
354 .WillOnce(Return(Status(Status::kOkPartial)))
355 .WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
356 Return(Status(Status::kOkCompleted))));
357
358 EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
359 }
360
361 IncrementalParseAndVerify();
362
363 EXPECT_EQ(cluster, parser_.value());
364 }
365
366 } // namespace
367