1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/webm/cluster_builder.h"
6 #include "media/webm/webm_constants.h"
7 #include "media/webm/webm_parser.h"
8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h"
11 using ::testing::InSequence
;
12 using ::testing::Return
;
13 using ::testing::ReturnNull
;
14 using ::testing::StrictMock
;
19 enum { kBlockCount
= 5 };
21 class MockWebMParserClient
: public WebMParserClient
{
23 virtual ~MockWebMParserClient() {}
25 // WebMParserClient methods.
26 MOCK_METHOD1(OnListStart
, WebMParserClient
*(int));
27 MOCK_METHOD1(OnListEnd
, bool(int));
28 MOCK_METHOD2(OnUInt
, bool(int, int64
));
29 MOCK_METHOD2(OnFloat
, bool(int, double));
30 MOCK_METHOD3(OnBinary
, bool(int, const uint8
*, int));
31 MOCK_METHOD2(OnString
, bool(int, const std::string
&));
34 class WebMParserTest
: public testing::Test
{
36 StrictMock
<MockWebMParserClient
> client_
;
39 static scoped_ptr
<Cluster
> CreateCluster(int block_count
) {
41 cb
.SetClusterTimecode(0);
43 for (int i
= 0; i
< block_count
; i
++) {
44 uint8 data
[] = { 0x00 };
45 cb
.AddSimpleBlock(0, i
, 0, data
, sizeof(data
));
51 static void CreateClusterExpectations(int block_count
,
52 bool is_complete_cluster
,
53 MockWebMParserClient
* client
) {
56 EXPECT_CALL(*client
, OnListStart(kWebMIdCluster
)).WillOnce(Return(client
));
57 EXPECT_CALL(*client
, OnUInt(kWebMIdTimecode
, 0))
58 .WillOnce(Return(true));
60 for (int i
= 0; i
< block_count
; i
++) {
61 EXPECT_CALL(*client
, OnBinary(kWebMIdSimpleBlock
, _
, _
))
62 .WillOnce(Return(true));
65 if (is_complete_cluster
)
66 EXPECT_CALL(*client
, OnListEnd(kWebMIdCluster
)).WillOnce(Return(true));
69 TEST_F(WebMParserTest
, EmptyCluster
) {
70 const uint8 kEmptyCluster
[] = {
71 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0)
73 int size
= sizeof(kEmptyCluster
);
76 EXPECT_CALL(client_
, OnListStart(kWebMIdCluster
)).WillOnce(Return(&client_
));
77 EXPECT_CALL(client_
, OnListEnd(kWebMIdCluster
)).WillOnce(Return(true));
79 WebMListParser
parser(kWebMIdCluster
, &client_
);
80 int result
= parser
.Parse(kEmptyCluster
, size
);
81 EXPECT_EQ(size
, result
);
82 EXPECT_TRUE(parser
.IsParsingComplete());
85 TEST_F(WebMParserTest
, EmptyClusterInSegment
) {
86 const uint8 kBuffer
[] = {
87 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
88 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0)
90 int size
= sizeof(kBuffer
);
93 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(Return(&client_
));
94 EXPECT_CALL(client_
, OnListStart(kWebMIdCluster
)).WillOnce(Return(&client_
));
95 EXPECT_CALL(client_
, OnListEnd(kWebMIdCluster
)).WillOnce(Return(true));
96 EXPECT_CALL(client_
, OnListEnd(kWebMIdSegment
)).WillOnce(Return(true));
98 WebMListParser
parser(kWebMIdSegment
, &client_
);
99 int result
= parser
.Parse(kBuffer
, size
);
100 EXPECT_EQ(size
, result
);
101 EXPECT_TRUE(parser
.IsParsingComplete());
104 // Test the case where a non-list child element has a size
105 // that is beyond the end of the parent.
106 TEST_F(WebMParserTest
, ChildNonListLargerThanParent
) {
107 const uint8 kBuffer
[] = {
108 0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1)
109 0xE7, 0x81, 0x01, // Timecode (size=1, value=1)
111 int size
= sizeof(kBuffer
);
114 EXPECT_CALL(client_
, OnListStart(kWebMIdCluster
)).WillOnce(Return(&client_
));
116 WebMListParser
parser(kWebMIdCluster
, &client_
);
117 int result
= parser
.Parse(kBuffer
, size
);
118 EXPECT_EQ(-1, result
);
119 EXPECT_FALSE(parser
.IsParsingComplete());
122 // Test the case where a list child element has a size
123 // that is beyond the end of the parent.
124 TEST_F(WebMParserTest
, ChildListLargerThanParent
) {
125 const uint8 kBuffer
[] = {
126 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5)
127 0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1)
129 int size
= sizeof(kBuffer
);
132 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(Return(&client_
));
134 WebMListParser
parser(kWebMIdSegment
, &client_
);
135 int result
= parser
.Parse(kBuffer
, size
);
136 EXPECT_EQ(-1, result
);
137 EXPECT_FALSE(parser
.IsParsingComplete());
140 // Expecting to parse a Cluster, but get a Segment.
141 TEST_F(WebMParserTest
, ListIdDoesNotMatch
) {
142 const uint8 kBuffer
[] = {
143 0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0)
145 int size
= sizeof(kBuffer
);
147 WebMListParser
parser(kWebMIdCluster
, &client_
);
148 int result
= parser
.Parse(kBuffer
, size
);
149 EXPECT_EQ(-1, result
);
150 EXPECT_FALSE(parser
.IsParsingComplete());
153 TEST_F(WebMParserTest
, InvalidElementInList
) {
154 const uint8 kBuffer
[] = {
155 0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2)
156 0xAE, 0x80, // TrackEntry (size = 0)
158 int size
= sizeof(kBuffer
);
161 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(Return(&client_
));
163 WebMListParser
parser(kWebMIdSegment
, &client_
);
164 int result
= parser
.Parse(kBuffer
, size
);
165 EXPECT_EQ(-1, result
);
166 EXPECT_FALSE(parser
.IsParsingComplete());
169 TEST_F(WebMParserTest
, VoidAndCRC32InList
) {
170 const uint8 kBuffer
[] = {
171 0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25)
172 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
173 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
174 0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10)
175 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
176 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3)
178 int size
= sizeof(kBuffer
);
181 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(Return(&client_
));
182 EXPECT_CALL(client_
, OnListStart(kWebMIdCluster
)).WillOnce(Return(&client_
));
183 EXPECT_CALL(client_
, OnListEnd(kWebMIdCluster
)).WillOnce(Return(true));
184 EXPECT_CALL(client_
, OnListEnd(kWebMIdSegment
)).WillOnce(Return(true));
186 WebMListParser
parser(kWebMIdSegment
, &client_
);
187 int result
= parser
.Parse(kBuffer
, size
);
188 EXPECT_EQ(size
, result
);
189 EXPECT_TRUE(parser
.IsParsingComplete());
193 TEST_F(WebMParserTest
, ParseListElementWithSingleCall
) {
194 scoped_ptr
<Cluster
> cluster(CreateCluster(kBlockCount
));
195 CreateClusterExpectations(kBlockCount
, true, &client_
);
197 WebMListParser
parser(kWebMIdCluster
, &client_
);
198 int result
= parser
.Parse(cluster
->data(), cluster
->size());
199 EXPECT_EQ(cluster
->size(), result
);
200 EXPECT_TRUE(parser
.IsParsingComplete());
203 TEST_F(WebMParserTest
, ParseListElementWithMultipleCalls
) {
204 scoped_ptr
<Cluster
> cluster(CreateCluster(kBlockCount
));
205 CreateClusterExpectations(kBlockCount
, true, &client_
);
207 const uint8
* data
= cluster
->data();
208 int size
= cluster
->size();
209 int default_parse_size
= 3;
210 WebMListParser
parser(kWebMIdCluster
, &client_
);
211 int parse_size
= std::min(default_parse_size
, size
);
214 int result
= parser
.Parse(data
, parse_size
);
215 ASSERT_GE(result
, 0);
216 ASSERT_LE(result
, parse_size
);
219 // The parser needs more data so increase the parse_size a little.
220 EXPECT_FALSE(parser
.IsParsingComplete());
221 parse_size
+= default_parse_size
;
222 parse_size
= std::min(parse_size
, size
);
226 parse_size
= default_parse_size
;
231 EXPECT_EQ((size
== 0), parser
.IsParsingComplete());
233 EXPECT_TRUE(parser
.IsParsingComplete());
236 TEST_F(WebMParserTest
, Reset
) {
238 scoped_ptr
<Cluster
> cluster(CreateCluster(kBlockCount
));
240 // First expect all but the last block.
241 CreateClusterExpectations(kBlockCount
- 1, false, &client_
);
243 // Now expect all blocks.
244 CreateClusterExpectations(kBlockCount
, true, &client_
);
246 WebMListParser
parser(kWebMIdCluster
, &client_
);
248 // Send slightly less than the full cluster so all but the last block is
250 int result
= parser
.Parse(cluster
->data(), cluster
->size() - 1);
251 EXPECT_GT(result
, 0);
252 EXPECT_LT(result
, cluster
->size());
253 EXPECT_FALSE(parser
.IsParsingComplete());
257 // Now parse a whole cluster to verify that all the blocks will get parsed.
258 result
= parser
.Parse(cluster
->data(), cluster
->size());
259 EXPECT_EQ(result
, cluster
->size());
260 EXPECT_TRUE(parser
.IsParsingComplete());
263 // Test the case where multiple clients are used for different lists.
264 TEST_F(WebMParserTest
, MultipleClients
) {
265 const uint8 kBuffer
[] = {
266 0x18, 0x53, 0x80, 0x67, 0x94, // SEGMENT (size = 20)
267 0x16, 0x54, 0xAE, 0x6B, 0x85, // TRACKS (size = 5)
268 0xAE, 0x83, // TRACKENTRY (size = 3)
269 0xD7, 0x81, 0x01, // TRACKNUMBER (size = 1)
270 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5)
271 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3)
273 int size
= sizeof(kBuffer
);
275 StrictMock
<MockWebMParserClient
> c1_
;
276 StrictMock
<MockWebMParserClient
> c2_
;
277 StrictMock
<MockWebMParserClient
> c3_
;
280 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(Return(&c1_
));
281 EXPECT_CALL(c1_
, OnListStart(kWebMIdTracks
)).WillOnce(Return(&c2_
));
282 EXPECT_CALL(c2_
, OnListStart(kWebMIdTrackEntry
)).WillOnce(Return(&c3_
));
283 EXPECT_CALL(c3_
, OnUInt(kWebMIdTrackNumber
, 1)).WillOnce(Return(true));
284 EXPECT_CALL(c2_
, OnListEnd(kWebMIdTrackEntry
)).WillOnce(Return(true));
285 EXPECT_CALL(c1_
, OnListEnd(kWebMIdTracks
)).WillOnce(Return(true));
286 EXPECT_CALL(c1_
, OnListStart(kWebMIdCluster
)).WillOnce(Return(&c2_
));
287 EXPECT_CALL(c1_
, OnListEnd(kWebMIdCluster
)).WillOnce(Return(true));
288 EXPECT_CALL(client_
, OnListEnd(kWebMIdSegment
)).WillOnce(Return(true));
290 WebMListParser
parser(kWebMIdSegment
, &client_
);
291 int result
= parser
.Parse(kBuffer
, size
);
292 EXPECT_EQ(size
, result
);
293 EXPECT_TRUE(parser
.IsParsingComplete());
296 // Test the case where multiple clients are used for different lists.
297 TEST_F(WebMParserTest
, InvalidClient
) {
298 const uint8 kBuffer
[] = {
299 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 20)
300 0x16, 0x54, 0xAE, 0x6B, 0x80, // TRACKS (size = 5)
302 int size
= sizeof(kBuffer
);
305 EXPECT_CALL(client_
, OnListStart(kWebMIdSegment
)).WillOnce(ReturnNull());
307 WebMListParser
parser(kWebMIdSegment
, &client_
);
308 int result
= parser
.Parse(kBuffer
, size
);
309 EXPECT_EQ(-1, result
);
310 EXPECT_FALSE(parser
.IsParsingComplete());
313 TEST_F(WebMParserTest
, ReservedIds
) {
314 const uint8 k1ByteReservedId
[] = { 0xFF, 0x81 };
315 const uint8 k2ByteReservedId
[] = { 0x7F, 0xFF, 0x81 };
316 const uint8 k3ByteReservedId
[] = { 0x3F, 0xFF, 0xFF, 0x81 };
317 const uint8 k4ByteReservedId
[] = { 0x1F, 0xFF, 0xFF, 0xFF, 0x81 };
318 const uint8
* kBuffers
[] = {
325 for (size_t i
= 0; i
< arraysize(kBuffers
); i
++) {
328 int buffer_size
= 2 + i
;
329 EXPECT_EQ(buffer_size
, WebMParseElementHeader(kBuffers
[i
], buffer_size
,
330 &id
, &element_size
));
331 EXPECT_EQ(id
, kWebMReservedId
);
332 EXPECT_EQ(element_size
, 1);
336 TEST_F(WebMParserTest
, ReservedSizes
) {
337 const uint8 k1ByteReservedSize
[] = { 0xA3, 0xFF };
338 const uint8 k2ByteReservedSize
[] = { 0xA3, 0x7F, 0xFF };
339 const uint8 k3ByteReservedSize
[] = { 0xA3, 0x3F, 0xFF, 0xFF };
340 const uint8 k4ByteReservedSize
[] = { 0xA3, 0x1F, 0xFF, 0xFF, 0xFF };
341 const uint8 k5ByteReservedSize
[] = { 0xA3, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF };
342 const uint8 k6ByteReservedSize
[] = { 0xA3, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
344 const uint8 k7ByteReservedSize
[] = { 0xA3, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
346 const uint8 k8ByteReservedSize
[] = { 0xA3, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
348 const uint8
* kBuffers
[] = {
359 for (size_t i
= 0; i
< arraysize(kBuffers
); i
++) {
362 int buffer_size
= 2 + i
;
363 EXPECT_EQ(buffer_size
, WebMParseElementHeader(kBuffers
[i
], buffer_size
,
364 &id
, &element_size
));
366 EXPECT_EQ(element_size
, kWebMUnknownSize
);
370 TEST_F(WebMParserTest
, ZeroPaddedStrings
) {
371 const uint8 kBuffer
[] = {
372 0x1A, 0x45, 0xDF, 0xA3, 0x91, // EBMLHEADER (size = 17)
373 0x42, 0x82, 0x80, // DocType (size = 0)
374 0x42, 0x82, 0x81, 0x00, // DocType (size = 1) ""
375 0x42, 0x82, 0x81, 'a', // DocType (size = 1) "a"
376 0x42, 0x82, 0x83, 'a', 0x00, 0x00 // DocType (size = 3) "a"
378 int size
= sizeof(kBuffer
);
381 EXPECT_CALL(client_
, OnListStart(kWebMIdEBMLHeader
))
382 .WillOnce(Return(&client_
));
383 EXPECT_CALL(client_
, OnString(kWebMIdDocType
, "")).WillOnce(Return(true));
384 EXPECT_CALL(client_
, OnString(kWebMIdDocType
, "")).WillOnce(Return(true));
385 EXPECT_CALL(client_
, OnString(kWebMIdDocType
, "a")).WillOnce(Return(true));
386 EXPECT_CALL(client_
, OnString(kWebMIdDocType
, "a")).WillOnce(Return(true));
387 EXPECT_CALL(client_
, OnListEnd(kWebMIdEBMLHeader
)).WillOnce(Return(true));
389 WebMListParser
parser(kWebMIdEBMLHeader
, &client_
);
390 int result
= parser
.Parse(kBuffer
, size
);
391 EXPECT_EQ(size
, result
);
392 EXPECT_TRUE(parser
.IsParsingComplete());