Chromium Code Reviews| Index: media/webm/webm_parser_unittest.cc |
| diff --git a/media/webm/webm_parser_unittest.cc b/media/webm/webm_parser_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..5e74a94ebaf79f3157f939b9774732bea8cd9527 |
| --- /dev/null |
| +++ b/media/webm/webm_parser_unittest.cc |
| @@ -0,0 +1,289 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "media/webm/cluster_builder.h" |
| +#include "media/webm/webm_constants.h" |
| +#include "media/webm/webm_parser.h" |
| +#include "testing/gmock/include/gmock/gmock.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +using ::testing::InSequence; |
| +using ::testing::Return; |
| +using ::testing::StrictMock; |
| +using ::testing::_; |
| + |
| +namespace media { |
| + |
| +class MockWebMParserClient : public WebMParserClient { |
| + public: |
| + virtual ~MockWebMParserClient() {} |
| + |
| + // WebMParserClient methods. |
| + MOCK_METHOD1(OnListStart, bool(int)); |
| + MOCK_METHOD1(OnListEnd, bool(int)); |
| + MOCK_METHOD2(OnUInt, bool(int, int64)); |
| + MOCK_METHOD2(OnFloat, bool(int, double)); |
| + MOCK_METHOD3(OnBinary, bool(int, const uint8*, int)); |
| + MOCK_METHOD2(OnString, bool(int, const std::string&)); |
| + MOCK_METHOD5(OnSimpleBlock, bool(int, int, int, const uint8*, int)); |
| +}; |
| + |
| +class WebMParserTest : public testing::Test { |
| + protected: |
| + struct SimpleBlockInfo { |
| + int track_num; |
| + int timestamp; |
| + }; |
| + |
| + static void AddSimpleBlock(ClusterBuilder* cb, int track_num, |
|
scherkus (not reviewing)
2011/12/09 21:36:03
nit: move all these static methods to outside the
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done.
|
| + int64 timecode) { |
| + uint8 data[] = { 0x00 }; |
| + cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); |
| + } |
| + |
| + static Cluster* CreateCluster(int timecode, |
| + const SimpleBlockInfo* block_info, |
| + int block_count) { |
| + ClusterBuilder cb; |
| + cb.SetClusterTimecode(0); |
| + |
| + for (int i = 0; i < block_count; i++) |
| + AddSimpleBlock(&cb, block_info[i].track_num, block_info[i].timestamp); |
| + |
| + return cb.Finish(); |
| + } |
| + |
| + static void CreateClusterExpectations(int timecode, |
| + const SimpleBlockInfo* block_info, |
| + int block_count, |
| + MockWebMParserClient* client) { |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnUInt(kWebMIdTimecode, 0)).WillOnce(Return(true)); |
| + |
| + for (int i = 0; i < block_count; i++) { |
| + EXPECT_CALL(*client, OnSimpleBlock(block_info[i].track_num, |
| + block_info[i].timestamp, |
| + _, _, _) |
| + ).WillOnce(Return(true)); |
|
scherkus (not reviewing)
2011/12/09 21:36:03
nit: move ) to previous line and have this .WillOn
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done. Not sure why I did that in the first place.
|
| + } |
| + |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
| + } |
| +}; |
| + |
| +TEST_F(WebMParserTest, EmptyCluster) { |
| + const uint8 kEmptyCluster[] = { |
| + 0x1F, 0x43, 0xB6, 0x75, 0x80 // CLUSTER (size = 0) |
| + }; |
| + int size = sizeof(kEmptyCluster); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
|
scherkus (not reviewing)
2011/12/09 21:36:03
nit: does this need to be a pointer? Looks like st
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done. Removed pointer and placed it in WebMParserT
|
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdCluster); |
| + int result = parser.Parse(kEmptyCluster, size, client.get()); |
| + EXPECT_EQ(size, result); |
| + EXPECT_TRUE(parser.IsParsingComplete()); |
| +} |
| + |
| +TEST_F(WebMParserTest, EmptyClusterInSegment) { |
| + const uint8 kBuffer[] = { |
| + 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) |
| + 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) |
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdSegment); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(size, result); |
| + EXPECT_TRUE(parser.IsParsingComplete()); |
| +} |
| + |
| +// Test the case where a non-list child element has a size |
| +// that is beyond the end of the parent. |
| +TEST_F(WebMParserTest, ChildNonListLargerThanParent) { |
| + const uint8 kBuffer[] = { |
| + 0x1F, 0x43, 0xB6, 0x75, 0x81, // CLUSTER (size = 1) |
| + 0xE7, 0x81, 0x01, // Timecode (size=1, value=1) |
|
scherkus (not reviewing)
2011/12/09 21:36:03
two space
acolwell GONE FROM CHROMIUM
2011/12/09 22:53:53
Done.
|
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdCluster); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(-1, result); |
| + EXPECT_FALSE(parser.IsParsingComplete()); |
| +} |
| + |
| +// Test the case where a list child element has a size |
| +// that is beyond the end of the parent. |
| +TEST_F(WebMParserTest, ChildListLargerThanParent) { |
| + const uint8 kBuffer[] = { |
| + 0x18, 0x53, 0x80, 0x67, 0x85, // SEGMENT (size = 5) |
| + 0x1F, 0x43, 0xB6, 0x75, 0x81, 0x11 // CLUSTER (size = 1) |
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdSegment); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(-1, result); |
| + EXPECT_FALSE(parser.IsParsingComplete()); |
| +} |
| + |
| +// Expecting to parse a Cluster, but get a Segment. |
| +TEST_F(WebMParserTest, ListIdDoesNotMatch) { |
| + const uint8 kBuffer[] = { |
| + 0x18, 0x53, 0x80, 0x67, 0x80, // SEGMENT (size = 0) |
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + WebMListParser parser(kWebMIdCluster); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(-1, result); |
| + EXPECT_FALSE(parser.IsParsingComplete()); |
| +} |
| + |
| +TEST_F(WebMParserTest, InvalidElementInList) { |
| + const uint8 kBuffer[] = { |
| + 0x18, 0x53, 0x80, 0x67, 0x82, // SEGMENT (size = 2) |
| + 0xAE, 0x80, // TrackEntry (size = 0) |
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdSegment); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(-1, result); |
| + EXPECT_FALSE(parser.IsParsingComplete()); |
| +} |
| + |
| +TEST_F(WebMParserTest, VoidAndCRC32InList) { |
| + const uint8 kBuffer[] = { |
| + 0x18, 0x53, 0x80, 0x67, 0x99, // SEGMENT (size = 25) |
| + 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) |
| + 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) |
| + 0x1F, 0x43, 0xB6, 0x75, 0x8A, // CLUSTER (size = 10) |
| + 0xEC, 0x83, 0x00, 0x00, 0x00, // Void (size = 3) |
| + 0xBF, 0x83, 0x00, 0x00, 0x00, // CRC32 (size = 3) |
| + }; |
| + int size = sizeof(kBuffer); |
| + |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + InSequence s; |
| + EXPECT_CALL(*client, OnListStart(kWebMIdSegment)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListStart(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdCluster)).WillOnce(Return(true)); |
| + EXPECT_CALL(*client, OnListEnd(kWebMIdSegment)).WillOnce(Return(true)); |
| + |
| + WebMListParser parser(kWebMIdSegment); |
| + int result = parser.Parse(kBuffer, size, client.get()); |
| + EXPECT_EQ(size, result); |
| + EXPECT_TRUE(parser.IsParsingComplete()); |
| +} |
| + |
| + |
| +TEST_F(WebMParserTest, ParseListElementWithSingleCall) { |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + const SimpleBlockInfo kBlockInfo[] = { |
| + { 0, 1 }, |
| + { 1, 2 }, |
| + { 0, 3 }, |
| + { 0, 4 }, |
| + { 1, 4 }, |
| + }; |
| + int block_count = arraysize(kBlockInfo); |
| + |
| + scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| + CreateClusterExpectations(0, kBlockInfo, block_count, client.get()); |
| + |
| + WebMListParser parser(kWebMIdCluster); |
| + int result = parser.Parse(cluster->data(), cluster->size(), client.get()); |
| + EXPECT_EQ(cluster->size(), result); |
| + EXPECT_TRUE(parser.IsParsingComplete()); |
| +} |
| + |
| +TEST_F(WebMParserTest, ParseListElementWithMultipleCalls) { |
| + scoped_ptr<StrictMock<MockWebMParserClient> > client( |
| + new StrictMock<MockWebMParserClient>()); |
| + |
| + const SimpleBlockInfo kBlockInfo[] = { |
| + { 0, 1 }, |
| + { 1, 2 }, |
| + { 0, 3 }, |
| + { 0, 4 }, |
| + { 1, 4 }, |
| + }; |
| + int block_count = arraysize(kBlockInfo); |
| + |
| + scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| + CreateClusterExpectations(0, kBlockInfo, block_count, client.get()); |
| + |
| + const uint8* data = cluster->data(); |
| + int size = cluster->size(); |
| + int default_parse_size = 3; |
| + WebMListParser parser(kWebMIdCluster); |
| + int parse_size = std::min(default_parse_size, size); |
| + |
| + while (size > 0) { |
| + int result = parser.Parse(data, parse_size, client.get()); |
| + EXPECT_GE(result, 0); |
| + EXPECT_LE(result, parse_size); |
| + |
| + if (result == 0) { |
| + // The parser needs more data so increase the parse_size a little. |
| + EXPECT_FALSE(parser.IsParsingComplete()); |
| + parse_size += default_parse_size; |
| + parse_size = std::min(parse_size, size); |
| + continue; |
| + } |
| + |
| + parse_size = default_parse_size; |
| + |
| + data += result; |
| + size -= result; |
| + |
| + EXPECT_EQ((size == 0), parser.IsParsingComplete()); |
| + } |
| + EXPECT_TRUE(parser.IsParsingComplete()); |
| +} |
| + |
| +} // namespace media |