(61d00a474) v0.9.7.1

This commit is contained in:
Regalis
2020-03-04 13:04:10 +01:00
parent 3c50efa5c9
commit 3c09ebe02f
5086 changed files with 786063 additions and 295871 deletions
@@ -0,0 +1,161 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/audio_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Audio;
using webm::AudioParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class AudioParserTest : public ElementParserTest<AudioParser, Id::kAudio> {};
TEST_F(AudioParserTest, DefaultParse) {
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_FALSE(audio.sampling_frequency.is_present());
EXPECT_EQ(8000, audio.sampling_frequency.value());
EXPECT_FALSE(audio.output_frequency.is_present());
EXPECT_EQ(8000, audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), audio.bit_depth.value());
}
TEST_F(AudioParserTest, DefaultValues) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x40, 0x00, // Size = 0.
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x80, // Size = 0.
0x9F, // ID = 0x9F (Channels).
0x40, 0x00, // Size = 0.
0x62, 0x64, // ID = 0x6264 (BitDepth).
0x80, // Size = 0.
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(8000, audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(8000, audio.output_frequency.value());
EXPECT_TRUE(audio.channels.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.channels.value());
EXPECT_TRUE(audio.bit_depth.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), audio.bit_depth.value());
}
TEST_F(AudioParserTest, CustomValues) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x84, // Size = 4.
0x3F, 0xDD, 0xB3, 0xD7, // Body (value = 1.73205077648162841796875f).
0x9F, // ID = 0x9F (Channels).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x62, 0x64, // ID = 0x6264 (BitDepth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(1.73205077648162841796875, audio.output_frequency.value());
EXPECT_TRUE(audio.channels.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), audio.channels.value());
EXPECT_TRUE(audio.bit_depth.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.bit_depth.value());
}
TEST_F(AudioParserTest, AbsentOutputSamplingFrequency) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.sampling_frequency.value());
EXPECT_FALSE(audio.output_frequency.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), audio.bit_depth.value());
}
TEST_F(AudioParserTest, DefaultOutputSamplingFrequency) {
SetReaderData({
0xB5, // ID = 0x85 (SamplingFrequency).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1.0f).
0x78, 0xB5, // ID = 0x78B5 (OutputSamplingFrequency).
0x10, 0x00, 0x00, 0x00, // Size = 0.
});
ParseAndVerify();
const Audio audio = parser_.value();
EXPECT_TRUE(audio.sampling_frequency.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.sampling_frequency.value());
EXPECT_TRUE(audio.output_frequency.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.output_frequency.value());
EXPECT_FALSE(audio.channels.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), audio.channels.value());
EXPECT_FALSE(audio.bit_depth.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), audio.bit_depth.value());
}
} // namespace
@@ -0,0 +1,24 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/bit_utils.h"
#include "gtest/gtest.h"
using webm::CountLeadingZeros;
namespace {
class BitUtilsTest : public testing::Test {};
TEST_F(BitUtilsTest, CountLeadingZeros) {
EXPECT_EQ(8, CountLeadingZeros(0x00));
EXPECT_EQ(4, CountLeadingZeros(0x0f));
EXPECT_EQ(0, CountLeadingZeros(0xf0));
}
} // namespace
@@ -0,0 +1,82 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_additions_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::BlockAdditions;
using webm::BlockAdditionsParser;
using webm::BlockMore;
using webm::ElementParserTest;
using webm::Id;
namespace {
class BlockAdditionsParserTest
: public ElementParserTest<BlockAdditionsParser, Id::kBlockAdditions> {};
TEST_F(BlockAdditionsParserTest, DefaultParse) {
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
const std::size_t kExpectedBlockMoresSize = 0;
EXPECT_EQ(kExpectedBlockMoresSize, block_additions.block_mores.size());
}
TEST_F(BlockAdditionsParserTest, DefaultValues) {
SetReaderData({
0xA6, // ID = 0xA6 (BlockMore).
0x80, // Size = 0.
});
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
ASSERT_EQ(static_cast<std::size_t>(1), block_additions.block_mores.size());
EXPECT_TRUE(block_additions.block_mores[0].is_present());
EXPECT_EQ(BlockMore{}, block_additions.block_mores[0].value());
}
TEST_F(BlockAdditionsParserTest, CustomValues) {
SetReaderData({
0xA6, // ID = 0xA6 (BlockMore).
0x83, // Size = 3.
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xA6, // ID = 0xA6 (BlockMore).
0x83, // Size = 3.
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x03, // Body (value = 3).
});
ParseAndVerify();
const BlockAdditions block_additions = parser_.value();
BlockMore expected;
ASSERT_EQ(static_cast<std::size_t>(2), block_additions.block_mores.size());
expected.id.Set(2, true);
EXPECT_TRUE(block_additions.block_mores[0].is_present());
EXPECT_EQ(expected, block_additions.block_mores[0].value());
expected.id.Set(3, true);
EXPECT_TRUE(block_additions.block_mores[1].is_present());
EXPECT_EQ(expected, block_additions.block_mores[1].value());
}
} // namespace
@@ -0,0 +1,234 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_group_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using webm::Block;
using webm::BlockAdditions;
using webm::BlockGroup;
using webm::BlockGroupParser;
using webm::BlockMore;
using webm::ElementParserTest;
using webm::Id;
using webm::Slices;
using webm::Status;
using webm::TimeSlice;
using webm::VirtualBlock;
namespace {
class BlockGroupParserTest
: public ElementParserTest<BlockGroupParser, Id::kBlockGroup> {};
TEST_F(BlockGroupParserTest, InvalidBlock) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnBlockGroupBegin(_, _)).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(BlockGroupParserTest, InvalidVirtualBlock) {
SetReaderData({
0xA2, // ID = 0xA2 (BlockVirtual).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnBlockGroupBegin(_, _)).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(BlockGroupParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, BlockGroup{})).Times(1);
}
ParseAndVerify();
}
TEST_F(BlockGroupParserTest, DefaultActionIsRead) {
{
InSequence dummy;
// This intentionally does not set the action and relies on the parser using
// a default action value of kRead.
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkCompleted)));
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, BlockGroup{})).Times(1);
}
ParseAndVerify();
}
TEST_F(BlockGroupParserTest, DefaultValues) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA2, // ID = 0xA2 (BlockVirtual).
0x84, // Size = 4.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x75, 0xA1, // ID = 0x75A1 (BlockAdditions).
0x80, // Size = 0.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x00, // Size = 0.
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x00, // Size = 0.
0x75, 0xA2, // ID = 0x75A2 (DiscardPadding).
0x80, // Size = 0.
0x8E, // ID = 0x8E (Slices).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
BlockGroup block_group;
// Blocks and VirtualBlocks don't have any kind of default defined, so they
// can't have an element state of kPresentAsDefault.
Block block{};
block.track_number = 1;
block.num_frames = 1;
block.is_visible = true;
block_group.block.Set(block, true);
EXPECT_CALL(callback_, OnBlockBegin(_, block, NotNull())).Times(1);
EXPECT_CALL(callback_, OnFrame(_, NotNull(), NotNull())).Times(1);
EXPECT_CALL(callback_, OnBlockEnd(_, block_group.block.value())).Times(1);
VirtualBlock virtual_block{};
virtual_block.track_number = 1;
block_group.virtual_block.Set(virtual_block, true);
block_group.additions.Set({}, true);
block_group.duration.Set(0, true);
block_group.references.emplace_back(0, true);
block_group.discard_padding.Set(0, true);
block_group.slices.Set({}, true);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, block_group)).Times(1);
}
ParseAndVerify();
}
TEST_F(BlockGroupParserTest, CustomValues) {
SetReaderData({
0xA1, // ID = 0xA1 (Block).
0x85, // Size = 5.
0x82, // Track number = 2.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA2, // ID = 0xA2 (BlockVirtual).
0x84, // Size = 4.
0x83, // Track number = 3.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x75, 0xA1, // ID = 0x75A1 (BlockAdditions).
0x83, // Size = 3.
0xA6, // ID = 0xA6 (BlockMore).
0x40, 0x00, // Size = 0.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xFB, // ID = 0xFB (ReferenceBlock).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x75, 0xA2, // ID = 0x75A2 (DiscardPadding).
0x81, // Size = 1.
0xFF, // Body (value = -1).
0x8E, // ID = 0x8E (Slices).
0x40, 0x03, // Size = 3.
0xE8, // ID = 0xE8 (TimeSlice).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnBlockGroupBegin(metadata_, NotNull())).Times(1);
BlockGroup block_group;
// Blocks and VirtualBlocks don't have any kind of default defined, so they
// can't have an element state of kPresentAsDefault.
Block block{};
block.track_number = 2;
block.num_frames = 1;
block.is_visible = true;
block_group.block.Set(block, true);
VirtualBlock virtual_block{};
virtual_block.track_number = 3;
block_group.virtual_block.Set(virtual_block, true);
BlockAdditions block_additions;
block_additions.block_mores.emplace_back(BlockMore{}, true);
block_group.additions.Set(block_additions, true);
block_group.duration.Set(1, true);
block_group.references.emplace_back(1, true);
block_group.references.emplace_back(2, true);
block_group.discard_padding.Set(-1, true);
Slices slices;
slices.slices.emplace_back(TimeSlice{}, true);
block_group.slices.Set(slices, true);
EXPECT_CALL(callback_, OnBlockGroupEnd(metadata_, block_group)).Times(1);
}
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_header_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::BlockHeader;
using webm::BlockHeaderParser;
using webm::ParserTest;
namespace {
class BlockHeaderParserTest : public ParserTest<BlockHeaderParser> {};
TEST_F(BlockHeaderParserTest, ValidBlock) {
SetReaderData({
0x81, // Track number = 1.
0x12, 0x34, // Timecode = 4660.
0x00, // Flags.
});
ParseAndVerify();
const BlockHeader& block_header = parser_.value();
EXPECT_EQ(static_cast<std::uint64_t>(1), block_header.track_number);
EXPECT_EQ(0x1234, block_header.timecode);
EXPECT_EQ(0x00, block_header.flags);
}
TEST_F(BlockHeaderParserTest, IncrementalParse) {
SetReaderData({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Track number = 2.
0xFF, 0xFE, // Timecode = -2.
0xFF, // Flags.
});
IncrementalParseAndVerify();
const BlockHeader& block_header = parser_.value();
EXPECT_EQ(static_cast<std::uint64_t>(2), block_header.track_number);
EXPECT_EQ(-2, block_header.timecode);
EXPECT_EQ(0xFF, block_header.flags);
}
} // namespace
@@ -0,0 +1,79 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_more_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::BlockMore;
using webm::BlockMoreParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class BlockMoreParserTest
: public ElementParserTest<BlockMoreParser, Id::kBlockMore> {};
TEST_F(BlockMoreParserTest, DefaultParse) {
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_FALSE(block_more.id.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), block_more.id.value());
EXPECT_FALSE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, block_more.data.value());
}
TEST_F(BlockMoreParserTest, DefaultValues) {
SetReaderData({
0xEE, // ID = 0xEE (BlockAddID).
0x80, // Size = 0.
0xA5, // ID = 0xA5 (BlockAdditional).
0x80, // Size = 0.
});
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_TRUE(block_more.id.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), block_more.id.value());
EXPECT_TRUE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, block_more.data.value());
}
TEST_F(BlockMoreParserTest, CustomValues) {
SetReaderData({
0xEE, // ID = 0xEE (BlockAddID).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xA5, // ID = 0xA5 (BlockAdditional).
0x81, // Size = 1.
0x00, // Body.
});
ParseAndVerify();
const BlockMore block_more = parser_.value();
EXPECT_TRUE(block_more.id.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), block_more.id.value());
EXPECT_TRUE(block_more.data.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x00}, block_more.data.value());
}
} // namespace
@@ -0,0 +1,865 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/block_parser.h"
#include <cstdint>
#include <memory>
#include <type_traits>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/parser_utils.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::Between;
using testing::DoAll;
using testing::Exactly;
using testing::InSequence;
using testing::Invoke;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Block;
using webm::BlockParser;
using webm::ElementParserTest;
using webm::FrameMetadata;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Lacing;
using webm::ReadByte;
using webm::Reader;
using webm::SimpleBlock;
using webm::SimpleBlockParser;
using webm::Status;
namespace {
// Represents a single block and its expected parsing results for use in tests.
struct TestData {
// Block data.
std::vector<std::uint8_t> data;
// Expected results.
std::uint64_t expected_track_number;
std::int16_t expected_timecode;
Lacing expected_lacing;
bool expected_is_visible;
bool expected_is_key_frame;
bool expected_is_discardable;
int expected_num_frames;
std::uint64_t expected_frame_start_position;
std::vector<std::uint64_t> expected_frame_sizes;
};
// Test data for an EBML-laced block containing only one frame.
const TestData ebml_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00,
0x00, // Timecode = 0.
0x86, // Flags = key_frame | ebml_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
// Frame 0.
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kEbml, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a Xiph-laced block containing only one frame.
const TestData xiph_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00,
0x00, // Timecode = 0.
0x82, // Flags = key_frame | xiph_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
// Frame 0.
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kXiph, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a fixed-laced block containing only one frame.
const TestData fixed_lacing_one_frame = {
// Data.
{
0x81, // Track number = 1.
0x00,
0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x00, // Lace count - 1 = 0 (1 frame).
// Lace data (1 frame).
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kFixed, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for an EBML-laced block.
// clang-format off
const TestData ebml_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x86, // Flags = key_frame | ebml_lacing.
0x05, // Lace count - 1 = 5 (6 frames).
// Lace data (6 frames).
0xFF, // Lace 0 size = 127.
0x5F, 0x81, // Lace 1 size = 1.
0xC0, // Lace 2 size = 2.
0xFF, // Lace 3 size = 66.
0x81, // Lace 4 size = 4.
// Lace 5 size inferred to be 5.
// Lace data (6 frames).
// Frame 0.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Frame 1.
0x01,
// Frame 2.
0x02, 0x02,
// Frame 3.
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
// Frame 4.
0x04, 0x04, 0x04, 0x04,
// Frame 5.
0x05, 0x05, 0x05, 0x05, 0x05,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kEbml, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
6, // expected_num_frames
11, // expected_frame_start_position
// expected_frame_sizes
{127, 1, 2, 66, 4, 5},
};
// Test data for a Xiph-laced block.
const TestData xiph_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x82, // Flags = key_frame | xiph_lacing.
0x03, // Lace count - 1 = 3 (4 frames).
// Lace sizes.
0xFF, 0xFF, 0x00, // Lace 0 size = 510.
0xFF, 0x01, // Lace 1 size = 256.
0x02, // Lace 2 size = 2.
// Lace 3 size inferred to be 3.
// Lace data (4 frames).
// Frame 0.
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Frame 1.
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
// Frame 2.
0x02, 0x02,
// Frame 3.
0x03, 0x03, 0x03,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kXiph, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
4, // expected_num_frames
11, // expected_frame_start_position
// expected_frame_sizes
{510, 256, 2, 3},
};
// clang-format on
// Test data for a fixed-laced block.
const TestData fixed_lacing = {
// Data.
{
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x03, // Lace count - 1 = 3 (4 frames).
// Lace data (4 frames).
0x00, 0x00, // Frame 0.
0x01, 0x01, // Frame 1.
0x02, 0x02, // Frame 2.
0x03, 0x03, // Frame 3.
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kFixed, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
4, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{2, 2, 2, 2},
};
// Test data for a block that has no lacing.
const TestData no_lacing = {
// Data.
{
0x40, 0x01, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x80, // Flags = key_frame.
// Lace data (1 frame).
0x00, 0x00, 0x00, // Frame 0.
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kNone, // expected_lacing
true, // expected_is_visible
true, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{3},
};
// Test data for a block that has no flags set in the header.
const TestData no_flags = {
// Data.
{
0x81, // Track number = 1.
0x00,
0x00, // Timecode = 0.
0x00, // Flags = 0.
// Lace data (1 frame).
0x00,
},
// Expected results.
1, // expected_track_number
0, // expected_timecode
Lacing::kNone, // expected_lacing
true, // expected_is_visible
false, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
4, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a block that has all Block (ID = Id::kBlock (0xA1)) flags set
// in the header (and no other flags).
const TestData block_flags = {
// Data.
{
0x82, // Track number = 2.
0xFE,
0xDC, // Timecode = -292.
0x08, // Flags = invisible.
// Lace data (1 frame).
0x00,
},
// Expected results.
2, // expected_track_number
-292, // expected_timecode
Lacing::kNone, // expected_lacing
false, // expected_is_visible
false, // expected_is_key_frame
false, // expected_is_discardable
1, // expected_num_frames
4, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Test data for a block that has all SimpleBlock (ID = Id::kSimpleBlock (0xA3))
// flags set in the header.
const TestData simple_block_flags = {
// Data.
{
0x41,
0x23, // Track number = 291.
0x12,
0x34, // Timecode = 4660.
0x89, // Flags = key_frame | invisible | discardable.
// Lace data (1 frame).
0x00,
},
// Expected results.
291, // expected_track_number
4660, // expected_timecode
Lacing::kNone, // expected_lacing
false, // expected_is_visible
true, // expected_is_key_frame
true, // expected_is_discardable
1, // expected_num_frames
5, // expected_frame_start_position
// expected_frame_sizes
{1},
};
// Checks that the Block matches the expected results in the TestData.
void ValidateBlock(const TestData& test_data, const Block& actual) {
EXPECT_EQ(test_data.expected_track_number, actual.track_number);
EXPECT_EQ(test_data.expected_timecode, actual.timecode);
EXPECT_EQ(test_data.expected_is_visible, actual.is_visible);
EXPECT_EQ(test_data.expected_lacing, actual.lacing);
EXPECT_EQ(test_data.expected_num_frames, actual.num_frames);
}
// Checks that the SimpleBlock matches the expected results in the TestData.
void ValidateBlock(const TestData& test_data, const SimpleBlock& actual) {
ValidateBlock(test_data, static_cast<const Block&>(actual));
EXPECT_EQ(test_data.expected_is_key_frame, actual.is_key_frame);
EXPECT_EQ(test_data.expected_is_discardable, actual.is_discardable);
}
// Constructs a SimpleBlock populated with the expected results for this test.
SimpleBlock ExpectedSimpleBlock(const TestData& test_data) {
SimpleBlock expected;
expected.track_number = test_data.expected_track_number;
expected.timecode = test_data.expected_timecode;
expected.lacing = test_data.expected_lacing;
expected.is_visible = test_data.expected_is_visible;
expected.is_key_frame = test_data.expected_is_key_frame;
expected.is_discardable = test_data.expected_is_discardable;
expected.num_frames = test_data.expected_num_frames;
return expected;
}
// Simple functor that can be used for Callback::OnFrame() that will validate
// the frame metadata and frame byte values.
struct FrameHandler {
// The expected value for the frame metadata.
FrameMetadata expected_metadata;
// The expected value for each byte in the frame.
std::uint8_t expected_frame_byte_value;
// Can be used for Callback::OnFrame() to consume data from the reader and
// validate the results.
Status operator()(const FrameMetadata& metadata, Reader* reader,
std::uint64_t* bytes_remaining) const {
EXPECT_EQ(expected_metadata, metadata);
std::uint8_t frame_byte_value;
Status status;
do {
status = ReadByte(reader, &frame_byte_value);
if (!status.completed_ok()) {
break;
}
EXPECT_EQ(expected_frame_byte_value, frame_byte_value);
--*bytes_remaining;
} while (*bytes_remaining > 0);
return status;
}
};
template <typename T, Id id>
class BasicBlockParserTest : public ElementParserTest<T, id> {
public:
// Sets expectations for a normal (i.e. successful parse) test.
void SetExpectations(const TestData& test_data, bool incremental,
bool set_action) {
InSequence dummy;
const SimpleBlock expected_simple_block = ExpectedSimpleBlock(test_data);
const Block expected_block = ExpectedSimpleBlock(test_data);
FrameMetadata metadata = FirstFrameMetadata(test_data);
if (std::is_same<T, SimpleBlockParser>::value) {
auto& expectation = EXPECT_CALL(
callback_, OnSimpleBlockBegin(metadata.parent_element,
expected_simple_block, NotNull()));
if (set_action) {
expectation.Times(1);
} else {
expectation.WillOnce(Return(Status(Status::kOkCompleted)));
}
EXPECT_CALL(callback_, OnBlockBegin(_, _, _)).Times(0);
} else {
auto& expectation = EXPECT_CALL(
callback_,
OnBlockBegin(metadata.parent_element, expected_block, NotNull()));
if (set_action) {
expectation.Times(1);
} else {
expectation.WillOnce(Return(Status(Status::kOkCompleted)));
}
EXPECT_CALL(callback_, OnSimpleBlockBegin(_, _, _)).Times(0);
}
std::uint8_t expected_frame_byte_value = 0;
for (const std::uint64_t frame_size : test_data.expected_frame_sizes) {
metadata.size = frame_size;
const FrameHandler frame_handler = {metadata, expected_frame_byte_value};
// Incremental parsing will call OnFrame once for every byte, plus
// maybe one more time if the first call reads zero bytes (if the reader
// is blocked).
const int this_frame_size = static_cast<int>(frame_size);
EXPECT_CALL(callback_, OnFrame(metadata, NotNull(), NotNull()))
.Times(incremental ? Between(this_frame_size, this_frame_size + 1)
: Exactly(1))
.WillRepeatedly(Invoke(frame_handler));
metadata.position += metadata.size;
++expected_frame_byte_value;
}
if (std::is_same<T, SimpleBlockParser>::value) {
EXPECT_CALL(callback_, OnSimpleBlockEnd(metadata.parent_element,
expected_simple_block))
.Times(1);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
} else {
EXPECT_CALL(callback_,
OnBlockEnd(metadata.parent_element, expected_block))
.Times(1);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
}
}
// Runs a single test using the provided test data.
void RunTest(const TestData& test_data) {
SetReaderData(test_data.data);
SetExpectations(test_data, false, true);
ParseAndVerify();
ValidateBlock(test_data, parser_.value());
}
// Same as RunTest(), except it forces parsers to parse one byte at a time.
void RunIncrementalTest(const TestData& test_data) {
SetReaderData(test_data.data);
SetExpectations(test_data, true, true);
IncrementalParseAndVerify();
ValidateBlock(test_data, parser_.value());
}
// Tests invalid element sizes.
void TestInvalidElementSize() {
TestInit(0, Status::kInvalidElementSize);
TestInit(4, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
// Tests invalid blocks by feeding only the header of the block into the
// parser.
void TestInvalidHeaderOnly(const TestData& test_data) {
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
SetReaderData(test_data.data);
ParseAndExpectResult(Status::kInvalidElementValue,
test_data.expected_frame_start_position);
}
// Tests an invalid fixed-lace block that has inconsistent frame sizes.
void TestInvalidFixedLaceSizes() {
SetReaderData({
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x84, // Flags = key_frame | fixed_lacing.
0x01, // Lace count - 1 = 1 (2 frames).
// Lace data (2 frames).
0x00, 0x00, // Frame 0.
0x01, // Frame 1 (invalid: inconsistent frame size).
});
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementValue);
}
// Tests setting the action to Action::kSkip in Callback::OnSimpleBlockBegin
// for the SimpleBlockParser.
void TestSimpleBlockSkip(const TestData& test_data) {
SetReaderData(test_data.data);
const SimpleBlock expected_simple_block = ExpectedSimpleBlock(test_data);
const FrameMetadata metadata = FirstFrameMetadata(test_data);
EXPECT_CALL(callback_, OnSimpleBlockBegin(metadata.parent_element,
expected_simple_block, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnFrame(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSimpleBlockEnd(_, _)).Times(0);
IncrementalParseAndVerify();
}
protected:
using ElementParserTest<T, id>::callback_;
using ElementParserTest<T, id>::IncrementalParseAndVerify;
using ElementParserTest<T, id>::metadata_;
using ElementParserTest<T, id>::ParseAndExpectResult;
using ElementParserTest<T, id>::ParseAndVerify;
using ElementParserTest<T, id>::parser_;
using ElementParserTest<T, id>::SetReaderData;
using ElementParserTest<T, id>::TestInit;
private:
// Gets the FrameMetadata for the very first frame in the test data.
FrameMetadata FirstFrameMetadata(const TestData& test_data) {
FrameMetadata metadata;
metadata.parent_element = metadata_;
metadata.parent_element.size = test_data.data.size();
metadata.position = test_data.expected_frame_start_position +
metadata.parent_element.position +
metadata.parent_element.header_size;
metadata.size = test_data.expected_frame_sizes[0];
return metadata;
}
};
class BlockParserTest : public BasicBlockParserTest<BlockParser, Id::kBlock> {};
TEST_F(BlockParserTest, InvalidElementSize) { TestInvalidElementSize(); }
TEST_F(BlockParserTest, InvalidHeaderOnlyNoLacing) {
TestInvalidHeaderOnly(no_lacing);
}
TEST_F(BlockParserTest, InvalidHeaderOnlyFixedLacing) {
TestInvalidHeaderOnly(fixed_lacing);
}
TEST_F(BlockParserTest, InvalidFixedLaceSizes) { TestInvalidFixedLaceSizes(); }
TEST_F(BlockParserTest, BlockNoFlags) { RunTest(no_flags); }
TEST_F(BlockParserTest, BlockFlags) { RunTest(block_flags); }
TEST_F(BlockParserTest, EbmlLacingOneFrame) { RunTest(ebml_lacing_one_frame); }
TEST_F(BlockParserTest, EbmlLacing) { RunTest(ebml_lacing); }
TEST_F(BlockParserTest, XiphLacingOneFrame) { RunTest(xiph_lacing_one_frame); }
TEST_F(BlockParserTest, XiphLacing) { RunTest(xiph_lacing); }
TEST_F(BlockParserTest, FixedLacingOneFrame) {
RunTest(fixed_lacing_one_frame);
}
TEST_F(BlockParserTest, FixedLacing) { RunTest(fixed_lacing); }
TEST_F(BlockParserTest, NoLacing) { RunTest(no_lacing); }
TEST_F(BlockParserTest, BlockWithPositionAndHeaderSize) {
metadata_.position = 15;
metadata_.header_size = 3;
RunTest(no_lacing);
}
TEST_F(BlockParserTest, IncrementalBlockFlags) {
RunIncrementalTest(block_flags);
}
TEST_F(BlockParserTest, IncrementalEbmlLacingOneFrame) {
RunIncrementalTest(ebml_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalEbmlLacing) {
RunIncrementalTest(ebml_lacing);
}
TEST_F(BlockParserTest, IncrementalXiphLacingOneFrame) {
RunIncrementalTest(xiph_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalXiphLacing) {
RunIncrementalTest(xiph_lacing);
}
TEST_F(BlockParserTest, IncrementalFixedLacingOneFrame) {
RunIncrementalTest(fixed_lacing_one_frame);
}
TEST_F(BlockParserTest, IncrementalFixedLacing) {
RunIncrementalTest(fixed_lacing);
}
TEST_F(BlockParserTest, DefaultActionIsRead) {
SetReaderData(fixed_lacing_one_frame.data);
SetExpectations(fixed_lacing_one_frame, false, false);
ParseAndVerify();
ValidateBlock(fixed_lacing_one_frame, parser_.value());
}
TEST_F(BlockParserTest, IncrementalNoLacing) { RunIncrementalTest(no_lacing); }
class SimpleBlockParserTest
: public BasicBlockParserTest<SimpleBlockParser, Id::kSimpleBlock> {};
TEST_F(SimpleBlockParserTest, InvalidElementSize) { TestInvalidElementSize(); }
TEST_F(SimpleBlockParserTest, InvalidHeaderOnlyNoLacing) {
TestInvalidHeaderOnly(no_lacing);
}
TEST_F(SimpleBlockParserTest, InvalidHeaderOnlyFixedLacing) {
TestInvalidHeaderOnly(fixed_lacing);
}
TEST_F(SimpleBlockParserTest, InvalidFixedLaceSizes) {
TestInvalidFixedLaceSizes();
}
TEST_F(SimpleBlockParserTest, SimpleBlockSkip) {
TestSimpleBlockSkip(no_flags);
}
TEST_F(SimpleBlockParserTest, SimpleBlockNoFlags) { RunTest(no_flags); }
TEST_F(SimpleBlockParserTest, SimpleBlockFlags) { RunTest(simple_block_flags); }
TEST_F(SimpleBlockParserTest, EbmlLacingOneFrame) {
RunTest(ebml_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, EbmlLacing) { RunTest(ebml_lacing); }
TEST_F(SimpleBlockParserTest, XiphLacingOneFrame) {
RunTest(xiph_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, XiphLacing) { RunTest(xiph_lacing); }
TEST_F(SimpleBlockParserTest, FixedLacingOneFrame) {
RunTest(fixed_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, FixedLacing) { RunTest(fixed_lacing); }
TEST_F(SimpleBlockParserTest, NoLacing) { RunTest(no_lacing); }
TEST_F(BlockParserTest, SimpleBlockWithPositionAndHeaderSize) {
metadata_.position = 16;
metadata_.header_size = 4;
RunTest(no_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalSimpleBlockFlags) {
RunIncrementalTest(simple_block_flags);
}
TEST_F(SimpleBlockParserTest, IncrementalEbmlLacingOneFrame) {
RunIncrementalTest(ebml_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalEbmlLacing) {
RunIncrementalTest(ebml_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalXiphLacingOneFrame) {
RunIncrementalTest(xiph_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalXiphLacing) {
RunIncrementalTest(xiph_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalFixedLacingOneFrame) {
RunIncrementalTest(fixed_lacing_one_frame);
}
TEST_F(SimpleBlockParserTest, IncrementalFixedLacing) {
RunIncrementalTest(fixed_lacing);
}
TEST_F(SimpleBlockParserTest, IncrementalNoLacing) {
RunIncrementalTest(no_lacing);
}
TEST_F(SimpleBlockParserTest, DefaultActionIsRead) {
SetReaderData(fixed_lacing_one_frame.data);
SetExpectations(fixed_lacing_one_frame, false, false);
ParseAndVerify();
ValidateBlock(fixed_lacing_one_frame, parser_.value());
}
} // namespace
@@ -0,0 +1,70 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/bool_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::BoolParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class BoolParserTest : public ElementParserTest<BoolParser> {};
TEST_F(BoolParserTest, InvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(BoolParserTest, InvalidValue) {
SetReaderData({0x02});
ParseAndExpectResult(Status::kInvalidElementValue);
SetReaderData({0xFF, 0xFF});
ParseAndExpectResult(Status::kInvalidElementValue);
}
TEST_F(BoolParserTest, CustomDefault) {
ResetParser(true);
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
}
TEST_F(BoolParserTest, ValidBool) {
ParseAndVerify();
EXPECT_EQ(false, parser_.value());
SetReaderData({0x00, 0x00, 0x01});
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00});
ParseAndVerify();
EXPECT_EQ(false, parser_.value());
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
ParseAndVerify();
EXPECT_EQ(true, parser_.value());
}
TEST_F(BoolParserTest, IncrementalParse) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
IncrementalParseAndVerify();
EXPECT_EQ(false, parser_.value());
}
} // namespace
@@ -0,0 +1,165 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/buffer_reader.h"
#include <array>
#include <cstdint>
#include "gtest/gtest.h"
using webm::BufferReader;
using webm::Status;
namespace {
class BufferReaderTest : public testing::Test {};
TEST_F(BufferReaderTest, Assignment) {
// Test the reader to make sure it resets correctly when assigned.
std::array<std::uint8_t, 4> buffer;
std::uint64_t count;
Status status;
BufferReader reader({});
const std::size_t kExpectedSize = 0;
EXPECT_EQ(kExpectedSize, reader.size());
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
reader = {1, 2, 3, 4};
EXPECT_EQ(static_cast<std::size_t>(4), reader.size());
status = reader.Read(2, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
reader = {5, 6, 7, 8};
status = reader.Read(2, buffer.data() + 2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
std::array<std::uint8_t, 4> expected = {{1, 2, 5, 6}};
EXPECT_EQ(expected, buffer);
}
TEST_F(BufferReaderTest, Empty) {
// Test the reader to make sure it reports EOF on empty inputs.
std::array<std::uint8_t, 1> buffer;
std::uint64_t count;
Status status;
BufferReader reader({});
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
}
TEST_F(BufferReaderTest, Read) {
// Test the Read method to make sure it reads data correctly.
std::array<std::uint8_t, 15> buffer{};
std::uint64_t count;
Status status;
BufferReader reader({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
status = reader.Read(10, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
std::array<std::uint8_t, 15> expected = {{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
EXPECT_EQ(expected, buffer);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
}
TEST_F(BufferReaderTest, Skip) {
// Test the Skip method to make sure it skips data correctly.
std::uint64_t count;
Status status;
BufferReader reader({0, 1, 2, 3, 4, 5, 6, 7, 8, 9});
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
status = reader.Skip(10, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(7), count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
}
TEST_F(BufferReaderTest, ReadAndSkip) {
// Test the Read and Skip methods together to make sure they interact
// correclty.
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
BufferReader reader({9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
std::array<std::uint8_t, 10> expected = {{9, 8, 7, 6, 5, 1, 0, 0, 0, 0}};
EXPECT_EQ(expected, buffer);
}
TEST_F(BufferReaderTest, Position) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
BufferReader reader({9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
EXPECT_EQ(static_cast<std::uint64_t>(0), reader.Position());
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
EXPECT_EQ(static_cast<std::uint64_t>(5), reader.Position());
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
EXPECT_EQ(static_cast<std::uint64_t>(8), reader.Position());
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
EXPECT_EQ(static_cast<std::uint64_t>(10), reader.Position());
std::array<std::uint8_t, 10> expected = {{9, 8, 7, 6, 5, 1, 0, 0, 0, 0}};
EXPECT_EQ(expected, buffer);
}
} // namespace
@@ -0,0 +1,117 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/byte_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::BinaryParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
using webm::StringParser;
namespace {
class StringParserTest : public ElementParserTest<StringParser> {};
TEST_F(StringParserTest, StringInvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(StringParserTest, StringCustomDefault) {
ResetParser("foobar");
ParseAndVerify();
EXPECT_EQ("foobar", parser_.value());
}
TEST_F(StringParserTest, StringValidValue) {
ParseAndVerify();
EXPECT_EQ("", parser_.value());
SetReaderData({'!'});
ParseAndVerify();
EXPECT_EQ("!", parser_.value());
SetReaderData({'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd'});
ParseAndVerify();
EXPECT_EQ("Hello, world", parser_.value());
}
TEST_F(StringParserTest, StringTrailingNulCharacters) {
// The trailing NUL characters should be trimmed.
SetReaderData({'H', 'i', '\0', '\0'});
ParseAndVerify();
EXPECT_EQ("Hi", parser_.value());
SetReaderData({'\0'});
ParseAndVerify();
EXPECT_EQ("", parser_.value());
}
TEST_F(StringParserTest, StringIncrementalParse) {
SetReaderData({'M', 'a', 't', 'r', 'o', 's', 'k', 'a'});
IncrementalParseAndVerify();
EXPECT_EQ("Matroska", parser_.value());
}
class BinaryParserTest : public ElementParserTest<BinaryParser> {};
TEST_F(BinaryParserTest, BinaryInvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(BinaryParserTest, BinaryCustomDefault) {
std::vector<std::uint8_t> expected = {0x00, 0x02, 0x04, 0x06, 0x08};
ResetParser(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
TEST_F(BinaryParserTest, BinaryValidValue) {
std::vector<std::uint8_t> expected;
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
expected = {0x00};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
expected = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
// Unlike StringParser, the BinaryParser should not trim trailing 0-bytes.
expected = {'H', 'i', '\0', '\0'};
SetReaderData(expected);
ParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
TEST_F(BinaryParserTest, BinaryIncrementalParse) {
const std::vector<std::uint8_t> expected = {
0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
SetReaderData(expected);
IncrementalParseAndVerify();
EXPECT_EQ(expected, parser_.value());
}
} // namespace
@@ -0,0 +1,148 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/callback.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "webm/buffer_reader.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::Action;
using webm::BufferReader;
using webm::Callback;
using webm::ElementMetadata;
using webm::Reader;
using webm::Status;
namespace {
void TestCompletedOk(Status (Callback::*function)(const ElementMetadata&)) {
Callback callback;
ElementMetadata metadata{};
Status status = (callback.*function)(metadata);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
template <typename T>
void TestCompletedOk(Status (Callback::*function)(const ElementMetadata&,
const T&)) {
Callback callback;
ElementMetadata metadata{};
T object{};
Status status = (callback.*function)(metadata, object);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
void TestAction(Status (Callback::*function)(const ElementMetadata&, Action*),
Action expected) {
Callback callback;
ElementMetadata metadata{};
Action action;
Status status = (callback.*function)(metadata, &action);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(expected, action);
}
template <typename T>
void TestAction(Status (Callback::*function)(const ElementMetadata&, const T&,
Action*),
Action expected) {
Callback callback;
ElementMetadata metadata{};
T t{};
Action action;
Status status = (callback.*function)(metadata, t, &action);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(expected, action);
}
template <typename T>
void TestRead(Status (Callback::*function)(const T&, Reader*, std::uint64_t*)) {
Callback callback;
Status status;
T metadata{};
BufferReader reader = {0x00, 0x01, 0x02, 0x03};
std::uint64_t bytes_remaining = 4;
status = (callback.*function)(metadata, &reader, &bytes_remaining);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), bytes_remaining);
}
class CallbackTest : public testing::Test {};
TEST_F(CallbackTest, OnElementBegin) {
TestAction(&Callback::OnElementBegin, Action::kRead);
}
TEST_F(CallbackTest, OnUnknownElement) {
TestRead(&Callback::OnUnknownElement);
}
TEST_F(CallbackTest, OnEbml) { TestCompletedOk(&Callback::OnEbml); }
TEST_F(CallbackTest, OnVoid) { TestRead(&Callback::OnVoid); }
TEST_F(CallbackTest, OnSegmentBegin) {
TestAction(&Callback::OnSegmentBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSeek) { TestCompletedOk(&Callback::OnSeek); }
TEST_F(CallbackTest, OnInfo) { TestCompletedOk(&Callback::OnInfo); }
TEST_F(CallbackTest, OnClusterBegin) {
TestAction(&Callback::OnClusterBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSimpleBlockBegin) {
TestAction(&Callback::OnSimpleBlockBegin, Action::kRead);
}
TEST_F(CallbackTest, OnSimpleBlockEnd) {
TestCompletedOk(&Callback::OnSimpleBlockEnd);
}
TEST_F(CallbackTest, OnBlockGroupBegin) {
TestAction(&Callback::OnBlockGroupBegin, Action::kRead);
}
TEST_F(CallbackTest, OnBlockBegin) {
TestAction(&Callback::OnBlockBegin, Action::kRead);
}
TEST_F(CallbackTest, OnBlockEnd) { TestCompletedOk(&Callback::OnBlockEnd); }
TEST_F(CallbackTest, OnBlockGroupEnd) {
TestCompletedOk(&Callback::OnBlockGroupEnd);
}
TEST_F(CallbackTest, OnFrame) { TestRead(&Callback::OnFrame); }
TEST_F(CallbackTest, OnClusterEnd) { TestCompletedOk(&Callback::OnClusterEnd); }
TEST_F(CallbackTest, OnTrackEntry) { TestCompletedOk(&Callback::OnTrackEntry); }
TEST_F(CallbackTest, OnCuePoint) { TestCompletedOk(&Callback::OnCuePoint); }
TEST_F(CallbackTest, OnEditionEntry) {
TestCompletedOk(&Callback::OnEditionEntry);
}
TEST_F(CallbackTest, OnTag) { TestCompletedOk(&Callback::OnTag); }
TEST_F(CallbackTest, OnSegmentEnd) { TestCompletedOk(&Callback::OnSegmentEnd); }
} // namespace
@@ -0,0 +1,209 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapter_atom_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ChapterAtom;
using webm::ChapterAtomParser;
using webm::ChapterDisplay;
using webm::ElementParserTest;
using webm::Id;
using webm::Status;
namespace {
class ChapterAtomParserTest
: public ElementParserTest<ChapterAtomParser, Id::kChapterAtom> {};
TEST_F(ChapterAtomParserTest, DefaultParse) {
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_FALSE(chapter_atom.uid.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.uid.value());
EXPECT_FALSE(chapter_atom.string_uid.is_present());
EXPECT_EQ("", chapter_atom.string_uid.value());
EXPECT_FALSE(chapter_atom.time_start.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.time_start.value());
EXPECT_FALSE(chapter_atom.time_end.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.time_end.value());
EXPECT_EQ(static_cast<std::size_t>(0), chapter_atom.displays.size());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.atoms.size());
}
TEST_F(ChapterAtomParserTest, DefaultValues) {
SetReaderData({
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x80, // Size = 0.
0x56, 0x54, // ID = 0x73C4 (ChapterStringUID).
0x80, // Size = 0.
0x91, // ID = 0x91 (ChapterTimeStart).
0x40, 0x00, // Size = 0.
0x92, // ID = 0x91 (ChapterTimeEnd).
0x40, 0x00, // Size = 0.
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x00, // Size = 0.
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x00, // Size = 0.
});
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_TRUE(chapter_atom.uid.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.uid.value());
EXPECT_TRUE(chapter_atom.string_uid.is_present());
EXPECT_EQ("", chapter_atom.string_uid.value());
EXPECT_TRUE(chapter_atom.time_start.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.time_start.value());
EXPECT_TRUE(chapter_atom.time_end.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), chapter_atom.time_end.value());
ASSERT_EQ(static_cast<std::uint64_t>(1), chapter_atom.displays.size());
EXPECT_TRUE(chapter_atom.displays[0].is_present());
EXPECT_EQ(ChapterDisplay{}, chapter_atom.displays[0].value());
ASSERT_EQ(static_cast<std::uint64_t>(1), chapter_atom.atoms.size());
EXPECT_TRUE(chapter_atom.atoms[0].is_present());
EXPECT_EQ(ChapterAtom{}, chapter_atom.atoms[0].value());
}
TEST_F(ChapterAtomParserTest, CustomValues) {
SetReaderData({
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x56, 0x54, // ID = 0x73C4 (ChapterStringUID).
0x81, // Size = 1.
0x41, // Body (value = "A").
0x91, // ID = 0x91 (ChapterTimeStart).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x92, // ID = 0x91 (ChapterTimeEnd).
0x40, 0x01, // Size = 1.
0x03, // Body (value = 3).
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x04, // Size = 4.
0x85, // ID = 0x85 (ChapString).
0x40, 0x01, // Size = 1.
0x42, // Body (value = "B").
0x80, // ID = 0x80 (ChapterDisplay).
0x40, 0x04, // Size = 4.
0x85, // ID = 0x85 (ChapString).
0x40, 0x01, // Size = 1.
0x43, // Body (value = "C").
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x12, // Size = 18.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x04, // Body (value = 4).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x05, // Body (value = 5).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x06, // Body (value = 6).
});
ParseAndVerify();
const ChapterAtom chapter_atom = parser_.value();
EXPECT_TRUE(chapter_atom.uid.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), chapter_atom.uid.value());
EXPECT_TRUE(chapter_atom.string_uid.is_present());
EXPECT_EQ("A", chapter_atom.string_uid.value());
EXPECT_TRUE(chapter_atom.time_start.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), chapter_atom.time_start.value());
EXPECT_TRUE(chapter_atom.time_end.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(3), chapter_atom.time_end.value());
ChapterDisplay expected_chapter_display;
ASSERT_EQ(static_cast<std::size_t>(2), chapter_atom.displays.size());
expected_chapter_display.string.Set("B", true);
EXPECT_TRUE(chapter_atom.displays[0].is_present());
EXPECT_EQ(expected_chapter_display, chapter_atom.displays[0].value());
expected_chapter_display.string.Set("C", true);
EXPECT_TRUE(chapter_atom.displays[1].is_present());
EXPECT_EQ(expected_chapter_display, chapter_atom.displays[1].value());
ChapterAtom expected_chapter_atom;
expected_chapter_atom.uid.Set(4, true);
ChapterAtom tmp_atom{};
tmp_atom.uid.Set(5, true);
expected_chapter_atom.atoms.emplace_back(tmp_atom, true);
tmp_atom.uid.Set(6, true);
expected_chapter_atom.atoms.emplace_back(tmp_atom, true);
ASSERT_EQ(static_cast<std::size_t>(1), chapter_atom.atoms.size());
EXPECT_TRUE(chapter_atom.atoms[0].is_present());
EXPECT_EQ(expected_chapter_atom, chapter_atom.atoms[0].value());
}
TEST_F(ChapterAtomParserTest, ExceedMaxRecursionDepth) {
ResetParser(1);
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x80, // Size = 0.
});
ParseAndVerify();
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x82, // Size = 2.
0xB6, // ID = 0xB6 (ChapterAtom).
0x80, // Size = 0.
});
ParseAndExpectResult(Status::kExceededRecursionDepthLimit);
}
} // namespace
@@ -0,0 +1,117 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapter_display_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChapterDisplay;
using webm::ChapterDisplayParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ChapterDisplayParserTest
: public ElementParserTest<ChapterDisplayParser, Id::kChapterDisplay> {};
TEST_F(ChapterDisplayParserTest, DefaultParse) {
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_FALSE(chapter_display.string.is_present());
EXPECT_EQ("", chapter_display.string.value());
ASSERT_EQ(static_cast<std::uint64_t>(1), chapter_display.languages.size());
EXPECT_FALSE(chapter_display.languages[0].is_present());
EXPECT_EQ("eng", chapter_display.languages[0].value());
EXPECT_EQ(static_cast<std::size_t>(0), chapter_display.countries.size());
}
TEST_F(ChapterDisplayParserTest, DefaultValues) {
SetReaderData({
0x85, // ID = 0x85 (ChapString).
0x40, 0x00, // Size = 0.
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x80, // Size = 0.
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x80, // Size = 0.
});
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_TRUE(chapter_display.string.is_present());
EXPECT_EQ("", chapter_display.string.value());
ASSERT_EQ(static_cast<std::size_t>(1), chapter_display.languages.size());
EXPECT_TRUE(chapter_display.languages[0].is_present());
EXPECT_EQ("eng", chapter_display.languages[0].value());
ASSERT_EQ(static_cast<std::size_t>(1), chapter_display.countries.size());
EXPECT_TRUE(chapter_display.countries[0].is_present());
EXPECT_EQ("", chapter_display.countries[0].value());
}
TEST_F(ChapterDisplayParserTest, CustomValues) {
SetReaderData({
0x85, // ID = 0x85 (ChapString).
0x40, 0x05, // Size = 5.
0x68, 0x65, 0x6C, 0x6C, 0x6F, // Body (value = "hello").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x30, // body (value = "lang0").
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x85, // Size = 5.
0x61, 0x72, 0x65, 0x61, 0x30, // Body (value = "area0").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x31, // body (value = "lang1").
0x43, 0x7C, // ID = 0x437C (ChapLanguage).
0x85, // Size = 5.
0x6C, 0x61, 0x6E, 0x67, 0x32, // body (value = "lang2").
0x43, 0x7E, // ID = 0x437E (ChapCountry).
0x85, // Size = 5.
0x61, 0x72, 0x65, 0x61, 0x31, // Body (value = "area1").
});
ParseAndVerify();
const ChapterDisplay chapter_display = parser_.value();
EXPECT_TRUE(chapter_display.string.is_present());
EXPECT_EQ("hello", chapter_display.string.value());
ASSERT_EQ(static_cast<std::size_t>(3), chapter_display.languages.size());
EXPECT_TRUE(chapter_display.languages[0].is_present());
EXPECT_EQ("lang0", chapter_display.languages[0].value());
EXPECT_TRUE(chapter_display.languages[1].is_present());
EXPECT_EQ("lang1", chapter_display.languages[1].value());
EXPECT_TRUE(chapter_display.languages[2].is_present());
EXPECT_EQ("lang2", chapter_display.languages[2].value());
ASSERT_EQ(static_cast<std::size_t>(2), chapter_display.countries.size());
EXPECT_TRUE(chapter_display.countries[0].is_present());
EXPECT_EQ("area0", chapter_display.countries[0].value());
EXPECT_TRUE(chapter_display.countries[1].is_present());
EXPECT_EQ("area1", chapter_display.countries[1].value());
}
} // namespace
@@ -0,0 +1,54 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/chapters_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChaptersParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ChaptersParserTest
: public ElementParserTest<ChaptersParser, Id::kChapters> {};
TEST_F(ChaptersParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(ChaptersParserTest, RepeatedValues) {
SetReaderData({
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x84, // Size = 4.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x84, // Size = 4.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,266 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cluster_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Ancestory;
using webm::BlockGroup;
using webm::Cluster;
using webm::ClusterParser;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleBlock;
using webm::Status;
namespace {
class ClusterParserTest
: public ElementParserTest<ClusterParser, Id::kCluster> {};
TEST_F(ClusterParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, DefaultActionIsRead) {
{
InSequence dummy;
// This intentionally does not set the action and relies on the parser using
// a default action value of kRead.
EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
.WillOnce(Return(Status(Status::kOkCompleted)));
EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, DefaultValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x00, // Size = 0.
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x00, // Size = 0.
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x00, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(0, true);
cluster.previous_size.Set(0, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.track_number = 1;
simple_block.num_frames = 1;
simple_block.is_visible = true;
cluster.simple_blocks.emplace_back(simple_block, true);
BlockGroup block_group{};
cluster.block_groups.emplace_back(block_group, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, CustomValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x82, // Track number = 2.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1, true);
cluster.previous_size.Set(2, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.num_frames = 1;
simple_block.is_visible = true;
simple_block.track_number = 1;
cluster.simple_blocks.emplace_back(simple_block, true);
simple_block.track_number = 2;
cluster.simple_blocks.emplace_back(simple_block, true);
BlockGroup block_group{};
block_group.duration.Set(1, true);
cluster.block_groups.emplace_back(block_group, true);
block_group.duration.Set(2, true);
cluster.block_groups.emplace_back(block_group, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, SkipOnClusterBegin) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnBlockGroupBegin(_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
}
ElementMetadata child_metadata = {Id::kBlockGroup, 0, 0, 0};
Ancestory ancestory;
ASSERT_TRUE(Ancestory::ById(child_metadata.id, &ancestory));
// Skip the Segment and Cluster ancestors.
ancestory = ancestory.next().next();
parser_.InitAfterSeek(ancestory, child_metadata);
std::uint64_t num_bytes_read = 0;
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader_.size(), num_bytes_read);
}
TEST_F(ClusterParserTest, SkipSimpleBlock) {
SetReaderData({
0xA3, // ID = 0xA3 (SimpleBlock).
0x85, // Size = 5.
0x81, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags = 0.
0x00, // Frame 0.
});
{
InSequence dummy;
Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
SimpleBlock simple_block{};
simple_block.num_frames = 1;
simple_block.is_visible = true;
simple_block.track_number = 1;
EXPECT_CALL(callback_, OnSimpleBlockBegin(_, simple_block, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(ClusterParserTest, SkipBlockGroup) {
SetReaderData({
0xA0, // ID = 0xA0 (BlockGroup).
0x40, 0x04, // Size = 4.
0x9B, // ID = 0x9B (BlockDuration).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnBlockGroupBegin(_, NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,285 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/colour_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Colour;
using webm::ColourParser;
using webm::ElementParserTest;
using webm::Id;
using webm::MasteringMetadata;
using webm::MatrixCoefficients;
using webm::Primaries;
using webm::Range;
using webm::TransferCharacteristics;
namespace {
class ColourParserTest : public ElementParserTest<ColourParser, Id::kColour> {};
TEST_F(ColourParserTest, DefaultParse) {
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_FALSE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kUnspecified,
colour.matrix_coefficients.value());
EXPECT_FALSE(colour.bits_per_channel.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.bits_per_channel.value());
EXPECT_FALSE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_subsampling_x.value());
EXPECT_FALSE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_subsampling_y.value());
EXPECT_FALSE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.cb_subsampling_x.value());
EXPECT_FALSE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.cb_subsampling_y.value());
EXPECT_FALSE(colour.chroma_siting_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_siting_x.value());
EXPECT_FALSE(colour.chroma_siting_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_siting_y.value());
EXPECT_FALSE(colour.range.is_present());
EXPECT_EQ(Range::kUnspecified, colour.range.value());
EXPECT_FALSE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kUnspecified,
colour.transfer_characteristics.value());
EXPECT_FALSE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kUnspecified, colour.primaries.value());
EXPECT_FALSE(colour.max_cll.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.max_cll.value());
EXPECT_FALSE(colour.max_fall.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.max_fall.value());
EXPECT_FALSE(colour.mastering_metadata.is_present());
EXPECT_EQ(MasteringMetadata{}, colour.mastering_metadata.value());
}
TEST_F(ColourParserTest, DefaultValues) {
SetReaderData({
0x55, 0xB1, // ID = 0x55B1 (MatrixCoefficients).
0x80, // Size = 0.
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x80, // Size = 0.
0x55, 0xB3, // ID = 0x55B3 (ChromaSubsamplingHorz).
0x80, // Size = 0.
0x55, 0xB4, // ID = 0x55B4 (ChromaSubsamplingVert).
0x80, // Size = 0.
0x55, 0xB5, // ID = 0x55B5 (CbSubsamplingHorz).
0x80, // Size = 0.
0x55, 0xB6, // ID = 0x55B6 (CbSubsamplingVert).
0x80, // Size = 0.
0x55, 0xB7, // ID = 0x55B7 (ChromaSitingHorz).
0x80, // Size = 0.
0x55, 0xB8, // ID = 0x55B8 (ChromaSitingVert).
0x80, // Size = 0.
0x55, 0xB9, // ID = 0x55B9 (Range).
0x80, // Size = 0.
0x55, 0xBA, // ID = 0x55BA (TransferCharacteristics).
0x80, // Size = 0.
0x55, 0xBB, // ID = 0x55BB (Primaries).
0x80, // Size = 0.
0x55, 0xBC, // ID = 0x55BC (MaxCLL).
0x80, // Size = 0.
0x55, 0xBD, // ID = 0x55BD (MaxFALL).
0x80, // Size = 0.
0x55, 0xD0, // ID = 0x55D0 (MasteringMetadata).
0x80, // Size = 0.
});
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_TRUE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kUnspecified,
colour.matrix_coefficients.value());
EXPECT_TRUE(colour.bits_per_channel.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.bits_per_channel.value());
EXPECT_TRUE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_subsampling_x.value());
EXPECT_TRUE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_subsampling_y.value());
EXPECT_TRUE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.cb_subsampling_x.value());
EXPECT_TRUE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.cb_subsampling_y.value());
EXPECT_TRUE(colour.chroma_siting_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_siting_x.value());
EXPECT_TRUE(colour.chroma_siting_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.chroma_siting_y.value());
EXPECT_TRUE(colour.range.is_present());
EXPECT_EQ(Range::kUnspecified, colour.range.value());
EXPECT_TRUE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kUnspecified,
colour.transfer_characteristics.value());
EXPECT_TRUE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kUnspecified, colour.primaries.value());
EXPECT_TRUE(colour.max_cll.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.max_cll.value());
EXPECT_TRUE(colour.max_fall.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), colour.max_fall.value());
EXPECT_TRUE(colour.mastering_metadata.is_present());
EXPECT_EQ(MasteringMetadata{}, colour.mastering_metadata.value());
}
TEST_F(ColourParserTest, CustomValues) {
SetReaderData({
0x55, 0xB1, // ID = 0x55B1 (MatrixCoefficients).
0x81, // Size = 1.
0x01, // Body (value = BT.709).
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x55, 0xB3, // ID = 0x55B3 (ChromaSubsamplingHorz).
0x81, // Size = 1.
0x03, // Body (value = 3).
0x55, 0xB4, // ID = 0x55B4 (ChromaSubsamplingVert).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x55, 0xB5, // ID = 0x55B5 (CbSubsamplingHorz).
0x81, // Size = 1.
0x05, // Body (value = 5).
0x55, 0xB6, // ID = 0x55B6 (CbSubsamplingVert).
0x81, // Size = 1.
0x06, // Body (value = 6).
0x55, 0xB7, // ID = 0x55B7 (ChromaSitingHorz).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x55, 0xB8, // ID = 0x55B8 (ChromaSitingVert).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x55, 0xB9, // ID = 0x55B9 (Range).
0x81, // Size = 1.
0x03, // Body (value = 3 (derived)).
0x55, 0xBA, // ID = 0x55BA (TransferCharacteristics).
0x81, // Size = 1.
0x04, // Body (value = BT.4706 System M with display gamma 2.2).
0x55, 0xBB, // ID = 0x55BB (Primaries).
0x81, // Size = 1.
0x05, // Body (value = BT.4706 System B, G).
0x55, 0xBC, // ID = 0x55BC (MaxCLL).
0x81, // Size = 1.
0x06, // Body (value = 6).
0x55, 0xBD, // ID = 0x55BD (MaxFALL).
0x81, // Size = 1.
0x07, // Body (value = 7).
0x55, 0xD0, // ID = 0x55D0 (MasteringMetadata).
0x87, // Size = 7.
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1).
});
ParseAndVerify();
const Colour colour = parser_.value();
EXPECT_TRUE(colour.matrix_coefficients.is_present());
EXPECT_EQ(MatrixCoefficients::kBt709, colour.matrix_coefficients.value());
EXPECT_TRUE(colour.bits_per_channel.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), colour.bits_per_channel.value());
EXPECT_TRUE(colour.chroma_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(3), colour.chroma_subsampling_x.value());
EXPECT_TRUE(colour.chroma_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(4), colour.chroma_subsampling_y.value());
EXPECT_TRUE(colour.cb_subsampling_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(5), colour.cb_subsampling_x.value());
EXPECT_TRUE(colour.cb_subsampling_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(6), colour.cb_subsampling_y.value());
EXPECT_TRUE(colour.chroma_siting_x.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), colour.chroma_siting_x.value());
EXPECT_TRUE(colour.chroma_siting_y.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), colour.chroma_siting_y.value());
EXPECT_TRUE(colour.range.is_present());
EXPECT_EQ(Range::kDerived, colour.range.value());
EXPECT_TRUE(colour.transfer_characteristics.is_present());
EXPECT_EQ(TransferCharacteristics::kGamma22curve,
colour.transfer_characteristics.value());
EXPECT_TRUE(colour.primaries.is_present());
EXPECT_EQ(Primaries::kBt470Bg, colour.primaries.value());
EXPECT_TRUE(colour.max_cll.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(6), colour.max_cll.value());
EXPECT_TRUE(colour.max_fall.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(7), colour.max_fall.value());
MasteringMetadata mastering_metadata{};
mastering_metadata.primary_r_chromaticity_x.Set(1.0, true);
EXPECT_TRUE(colour.mastering_metadata.is_present());
EXPECT_EQ(mastering_metadata, colour.mastering_metadata.value());
}
} // namespace
@@ -0,0 +1,68 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_enc_aes_settings_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AesSettingsCipherMode;
using webm::ContentEncAesSettings;
using webm::ContentEncAesSettingsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncAesSettingsParserTest
: public ElementParserTest<ContentEncAesSettingsParser,
Id::kContentEncAesSettings> {};
TEST_F(ContentEncAesSettingsParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_FALSE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(AesSettingsCipherMode::kCtr,
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
TEST_F(ContentEncAesSettingsParserTest, DefaultValues) {
SetReaderData({
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_TRUE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(AesSettingsCipherMode::kCtr,
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
TEST_F(ContentEncAesSettingsParserTest, CustomValues) {
SetReaderData({
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x81, // Size = 1.
0x00, // Body (value = 0).
});
ParseAndVerify();
const ContentEncAesSettings content_enc_aes_settings = parser_.value();
EXPECT_TRUE(content_enc_aes_settings.aes_settings_cipher_mode.is_present());
EXPECT_EQ(static_cast<AesSettingsCipherMode>(0),
content_enc_aes_settings.aes_settings_cipher_mode.value());
}
} // namespace
@@ -0,0 +1,120 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encoding_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ContentEncAlgo;
using webm::ContentEncoding;
using webm::ContentEncodingParser;
using webm::ContentEncodingType;
using webm::ContentEncryption;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncodingParserTest
: public ElementParserTest<ContentEncodingParser, Id::kContentEncoding> {};
TEST_F(ContentEncodingParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_FALSE(content_encoding.order.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), content_encoding.order.value());
EXPECT_FALSE(content_encoding.scope.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), content_encoding.scope.value());
EXPECT_FALSE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kCompression, content_encoding.type.value());
EXPECT_FALSE(content_encoding.encryption.is_present());
EXPECT_EQ(ContentEncryption{}, content_encoding.encryption.value());
}
TEST_F(ContentEncodingParserTest, DefaultValues) {
SetReaderData({
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x80, // Size = 0.
0x50, 0x32, // ID = 0x5032 (ContentEncodingScope).
0x80, // Size = 0.
0x50, 0x33, // ID = 0x5033 (ContentEncodingType).
0x80, // Size = 0.
0x50, 0x35, // ID = 0x5035 (ContentEncryption).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_TRUE(content_encoding.order.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), content_encoding.order.value());
EXPECT_TRUE(content_encoding.scope.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), content_encoding.scope.value());
EXPECT_TRUE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kCompression, content_encoding.type.value());
EXPECT_TRUE(content_encoding.encryption.is_present());
EXPECT_EQ(ContentEncryption{}, content_encoding.encryption.value());
}
TEST_F(ContentEncodingParserTest, CustomValues) {
SetReaderData({
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x50, 0x32, // ID = 0x5032 (ContentEncodingScope).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x50, 0x33, // ID = 0x5033 (ContentEncodingType).
0x81, // Size = 1.
0x01, // Body (value = encryption).
0x50, 0x35, // ID = 0x5035 (ContentEncryption).
0x84, // Size = 4.
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x81, // Size = 1.
0x05, // Body (value = AES).
});
ParseAndVerify();
const ContentEncoding content_encoding = parser_.value();
EXPECT_TRUE(content_encoding.order.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), content_encoding.order.value());
EXPECT_TRUE(content_encoding.scope.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), content_encoding.scope.value());
EXPECT_TRUE(content_encoding.type.is_present());
EXPECT_EQ(ContentEncodingType::kEncryption, content_encoding.type.value());
ContentEncryption expected;
expected.algorithm.Set(ContentEncAlgo::kAes, true);
EXPECT_TRUE(content_encoding.encryption.is_present());
EXPECT_EQ(expected, content_encoding.encryption.value());
}
} // namespace
@@ -0,0 +1,82 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encodings_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ContentEncoding;
using webm::ContentEncodings;
using webm::ContentEncodingsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncodingsParserTest
: public ElementParserTest<ContentEncodingsParser, Id::kContentEncodings> {
};
TEST_F(ContentEncodingsParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
EXPECT_EQ(static_cast<std::size_t>(0), content_encodings.encodings.size());
}
TEST_F(ContentEncodingsParserTest, DefaultValues) {
SetReaderData({
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
ASSERT_EQ(static_cast<std::size_t>(1), content_encodings.encodings.size());
EXPECT_TRUE(content_encodings.encodings[0].is_present());
EXPECT_EQ(ContentEncoding{}, content_encodings.encodings[0].value());
}
TEST_F(ContentEncodingsParserTest, CustomValues) {
SetReaderData({
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x84, // Size = 4.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x84, // Size = 4.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const ContentEncodings content_encodings = parser_.value();
ContentEncoding expected;
ASSERT_EQ(static_cast<std::size_t>(2), content_encodings.encodings.size());
expected.order.Set(1, true);
EXPECT_TRUE(content_encodings.encodings[0].is_present());
EXPECT_EQ(expected, content_encodings.encodings[0].value());
expected.order.Set(2, true);
EXPECT_TRUE(content_encodings.encodings[1].is_present());
EXPECT_EQ(expected, content_encodings.encodings[1].value());
}
} // namespace
@@ -0,0 +1,107 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/content_encryption_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AesSettingsCipherMode;
using webm::ContentEncAesSettings;
using webm::ContentEncAlgo;
using webm::ContentEncryption;
using webm::ContentEncryptionParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class ContentEncryptionParserTest
: public ElementParserTest<ContentEncryptionParser,
Id::kContentEncryption> {};
TEST_F(ContentEncryptionParserTest, DefaultParse) {
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_FALSE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kOnlySigned, content_encryption.algorithm.value());
EXPECT_FALSE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, content_encryption.key_id.value());
EXPECT_FALSE(content_encryption.aes_settings.is_present());
EXPECT_EQ(ContentEncAesSettings{}, content_encryption.aes_settings.value());
}
TEST_F(ContentEncryptionParserTest, DefaultValues) {
SetReaderData({
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x80, // Size = 0.
0x47, 0xE2, // ID = 0x47E2 (ContentEncKeyID).
0x80, // Size = 0.
0x47, 0xE7, // ID = 0x47E7 (ContentEncAESSettings).
0x80, // Size = 0.
});
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_TRUE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kOnlySigned, content_encryption.algorithm.value());
EXPECT_TRUE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, content_encryption.key_id.value());
EXPECT_TRUE(content_encryption.aes_settings.is_present());
EXPECT_EQ(ContentEncAesSettings{}, content_encryption.aes_settings.value());
}
TEST_F(ContentEncryptionParserTest, CustomValues) {
SetReaderData({
0x47, 0xE1, // ID = 0x47E1 (ContentEncAlgo).
0x81, // Size = 1.
0x05, // Body (value = AES).
0x47, 0xE2, // ID = 0x47E2 (ContentEncKeyID).
0x81, // Size = 1.
0x00, // Body.
0x47, 0xE7, // ID = 0x47E7 (ContentEncAESSettings).
0x84, // Size = 4.
0x47, 0xE8, // ID = 0x47E8 (AESSettingsCipherMode).
0x81, // Size = 1.
0x00, // Body (value = 0).
});
ParseAndVerify();
const ContentEncryption content_encryption = parser_.value();
EXPECT_TRUE(content_encryption.algorithm.is_present());
EXPECT_EQ(ContentEncAlgo::kAes, content_encryption.algorithm.value());
EXPECT_TRUE(content_encryption.key_id.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x00}, content_encryption.key_id.value());
ContentEncAesSettings expected;
expected.aes_settings_cipher_mode.Set(static_cast<AesSettingsCipherMode>(0),
true);
EXPECT_TRUE(content_encryption.aes_settings.is_present());
EXPECT_EQ(expected, content_encryption.aes_settings.value());
}
} // namespace
@@ -0,0 +1,87 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cue_point_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CuePoint;
using webm::CuePointParser;
using webm::CueTrackPositions;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CuePointParserTest
: public ElementParserTest<CuePointParser, Id::kCuePoint> {};
TEST_F(CuePointParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnCuePoint(metadata_, CuePoint{})).Times(1);
ParseAndVerify();
}
TEST_F(CuePointParserTest, DefaultValues) {
SetReaderData({
0xB3, // ID = 0xB3 (CueTime).
0x80, // Size = 0.
0xB7, // ID = 0xB7 (CueTrackPositions).
0x80, // Size = 0.
});
CuePoint cue_point;
cue_point.time.Set(0, true);
cue_point.cue_track_positions.emplace_back();
cue_point.cue_track_positions[0].Set({}, true);
EXPECT_CALL(callback_, OnCuePoint(metadata_, cue_point)).Times(1);
ParseAndVerify();
}
TEST_F(CuePointParserTest, CustomValues) {
SetReaderData({
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xB7, // ID = 0xB7 (CueTrackPositions).
0x83, // Size = 3.
0xF1, // ID = 0xF1 (CueClusterPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xB7, // ID = 0xB7 (CueTrackPositions).
0x83, // Size = 3.
0xF7, // ID = 0xF7 (CueTrack).
0x81, // Size = 1.
0x03, // Body (value = 3).
});
CuePoint cue_point;
cue_point.time.Set(1, true);
CueTrackPositions cue_track_positions;
cue_track_positions.cluster_position.Set(2, true);
cue_point.cue_track_positions.emplace_back(cue_track_positions, true);
cue_track_positions = {};
cue_track_positions.track.Set(3, true);
cue_point.cue_track_positions.emplace_back(cue_track_positions, true);
EXPECT_CALL(callback_, OnCuePoint(metadata_, cue_point)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,140 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cue_track_positions_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CueTrackPositions;
using webm::CueTrackPositionsParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CueTrackPositionsParserTest
: public ElementParserTest<CueTrackPositionsParser,
Id::kCueTrackPositions> {};
TEST_F(CueTrackPositionsParserTest, DefaultParse) {
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_FALSE(cue_track_positions.track.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), cue_track_positions.track.value());
EXPECT_FALSE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.cluster_position.value());
EXPECT_FALSE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.relative_position.value());
EXPECT_FALSE(cue_track_positions.duration.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.duration.value());
EXPECT_FALSE(cue_track_positions.block_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1),
cue_track_positions.block_number.value());
}
TEST_F(CueTrackPositionsParserTest, DefaultValues) {
SetReaderData({
0xF7, // ID = 0xF7 (CueTrack).
0x40, 0x00, // Size = 0.
0xF1, // ID = 0xF1 (CueClusterPosition).
0x40, 0x00, // Size = 0.
0xF0, // ID = 0xF0 (CueRelativePosition).
0x40, 0x00, // Size = 0.
0xB2, // ID = 0xB2 (CueDuration).
0x40, 0x00, // Size = 0.
0x53, 0x78, // ID = 0x5378 (CueBlockNumber).
0x80, // Size = 0.
});
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_TRUE(cue_track_positions.track.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), cue_track_positions.track.value());
EXPECT_TRUE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.cluster_position.value());
EXPECT_TRUE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.relative_position.value());
EXPECT_TRUE(cue_track_positions.duration.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0),
cue_track_positions.duration.value());
EXPECT_TRUE(cue_track_positions.block_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1),
cue_track_positions.block_number.value());
}
TEST_F(CueTrackPositionsParserTest, CustomValues) {
SetReaderData({
0xF7, // ID = 0xF7 (CueTrack).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xF1, // ID = 0xF1 (CueClusterPosition).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0xF0, // ID = 0xF0 (CueRelativePosition).
0x40, 0x01, // Size = 1.
0x03, // Body (value = 3).
0xB2, // ID = 0xB2 (CueDuration).
0x40, 0x01, // Size = 1.
0x04, // Body (value = 4).
0x53, 0x78, // ID = 0x5378 (CueBlockNumber).
0x81, // Size = 1.
0x05, // Body (value = 5).
});
ParseAndVerify();
const CueTrackPositions cue_track_positions = parser_.value();
EXPECT_TRUE(cue_track_positions.track.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), cue_track_positions.track.value());
EXPECT_TRUE(cue_track_positions.cluster_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2),
cue_track_positions.cluster_position.value());
EXPECT_TRUE(cue_track_positions.relative_position.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(3),
cue_track_positions.relative_position.value());
EXPECT_TRUE(cue_track_positions.duration.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(4),
cue_track_positions.duration.value());
EXPECT_TRUE(cue_track_positions.block_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(5),
cue_track_positions.block_number.value());
}
} // namespace
@@ -0,0 +1,53 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/cues_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::CuesParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class CuesParserTest : public ElementParserTest<CuesParser, Id::kCues> {};
TEST_F(CuesParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0xBB, // ID = 0xBB (CuePoint).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(CuesParserTest, RepeatedValues) {
SetReaderData({
0xBB, // ID = 0xBB (CuePoint).
0x83, // Size = 3.
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xBB, // ID = 0xBB (CuePoint).
0x83, // Size = 3.
0xB3, // ID = 0xB3 (CueTime).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/date_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::DateParser;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class DateParserTest : public ElementParserTest<DateParser> {};
TEST_F(DateParserTest, InvalidSize) {
TestInit(4, Status::kInvalidElementSize);
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(DateParserTest, CustomDefault) {
ResetParser(-1);
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
}
TEST_F(DateParserTest, ValidDate) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDEF0, parser_.value());
}
TEST_F(DateParserTest, IncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10});
IncrementalParseAndVerify();
EXPECT_EQ(static_cast<std::int64_t>(0xFEDCBA9876543210), parser_.value());
}
} // namespace
@@ -0,0 +1,128 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/ebml_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Ebml;
using webm::EbmlParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class EbmlParserTest : public ElementParserTest<EbmlParser, Id::kEbml> {};
TEST_F(EbmlParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnEbml(metadata_, Ebml{})).Times(1);
ParseAndVerify();
}
TEST_F(EbmlParserTest, DefaultValues) {
SetReaderData({
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x80, // Size = 0.
0x42, 0xF7, // ID = 0x42F7 (EBMLReadVersion).
0x80, // Size = 0.
0x42, 0xF2, // ID = 0x42F2 (EBMLMaxIDLength).
0x40, 0x00, // Size = 0.
0x42, 0xF3, // ID = 0x42F3 (EBMLMaxSizeLength).
0x80, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x40, 0x00, // Size = 0.
0x42, 0x82, // ID = 0x4282 (DocType).
0x40, 0x00, // Size = 0.
0x42, 0x87, // ID = 0x4287 (DocTypeVersion).
0x80, // Size = 0.
0x42, 0x85, // ID = 0x4285 (DocTypeReadVersion).
0x80, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x01, 0x02, // Body.
});
Ebml ebml;
ebml.ebml_version.Set(1, true);
ebml.ebml_read_version.Set(1, true);
ebml.ebml_max_id_length.Set(4, true);
ebml.ebml_max_size_length.Set(8, true);
ebml.doc_type.Set("matroska", true);
ebml.doc_type_version.Set(1, true);
ebml.doc_type_read_version.Set(1, true);
EXPECT_CALL(callback_, OnEbml(metadata_, ebml)).Times(1);
ParseAndVerify();
}
TEST_F(EbmlParserTest, CustomValues) {
SetReaderData({
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x81, // Size = 1.
0x02, // Body (value = 2).
0x42, 0xF7, // ID = 0x42F7 (EBMLReadVersion).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x42, 0xF2, // ID = 0x42F2 (EBMLMaxIDLength).
0x40, 0x02, // Size = 2.
0x00, 0x02, // Body (value = 2).
0x42, 0xF3, // ID = 0x42F3 (EBMLMaxSizeLength).
0x81, // Size = 1.
0x04, // Body (value = 4).
0xEC, // ID = 0xEC (Void).
0x40, 0x00, // Size = 0.
0x42, 0x82, // ID = 0x4282 (DocType).
0x40, 0x02, // Size = 2.
0x48, 0x69, // Body (value = "Hi").
0x42, 0x87, // ID = 0x4287 (DocTypeVersion).
0x81, // Size = 1.
0xFF, // Body (value = 255).
0x42, 0x85, // ID = 0x4285 (DocTypeReadVersion).
0x81, // Size = 1.
0x02, // Body (value = 2).
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x01, 0x02, // Body.
});
Ebml ebml;
ebml.ebml_version.Set(2, true);
ebml.ebml_read_version.Set(4, true);
ebml.ebml_max_id_length.Set(2, true);
ebml.ebml_max_size_length.Set(4, true);
ebml.doc_type.Set("Hi", true);
ebml.doc_type_version.Set(255, true);
ebml.doc_type_read_version.Set(2, true);
EXPECT_CALL(callback_, OnEbml(metadata_, ebml)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,77 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/edition_entry_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ChapterAtom;
using webm::EditionEntry;
using webm::EditionEntryParser;
using webm::ElementParserTest;
using webm::Id;
namespace {
class EditionEntryParserTest
: public ElementParserTest<EditionEntryParser, Id::kEditionEntry> {};
TEST_F(EditionEntryParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnEditionEntry(metadata_, EditionEntry{})).Times(1);
ParseAndVerify();
}
TEST_F(EditionEntryParserTest, DefaultValues) {
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x80, // Size = 0.
});
EditionEntry edition_entry;
edition_entry.atoms.emplace_back();
edition_entry.atoms[0].Set({}, true);
EXPECT_CALL(callback_, OnEditionEntry(metadata_, edition_entry)).Times(1);
ParseAndVerify();
}
TEST_F(EditionEntryParserTest, CustomValues) {
SetReaderData({
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xB6, // ID = 0xB6 (ChapterAtom).
0x40, 0x04, // Size = 4.
0x73, 0xC4, // ID = 0x73C4 (ChapterUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
EditionEntry edition_entry;
ChapterAtom chapter_atom;
chapter_atom.uid.Set(1, true);
edition_entry.atoms.emplace_back(chapter_atom, true);
chapter_atom.uid.Set(2, true);
edition_entry.atoms.emplace_back(chapter_atom, true);
EXPECT_CALL(callback_, OnEditionEntry(metadata_, edition_entry)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,47 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/element.h"
#include <string>
#include <utility>
#include "gtest/gtest.h"
using webm::Element;
namespace {
class ElementTest : public testing::Test {};
TEST_F(ElementTest, Construction) {
Element<int> value_initialized;
EXPECT_EQ(false, value_initialized.is_present());
EXPECT_EQ(0, value_initialized.value());
Element<int> absent_custom_default(1);
EXPECT_EQ(false, absent_custom_default.is_present());
EXPECT_EQ(1, absent_custom_default.value());
Element<int> present(2, true);
EXPECT_EQ(true, present.is_present());
EXPECT_EQ(2, present.value());
}
TEST_F(ElementTest, Assignment) {
Element<int> e;
e.Set(42, true);
EXPECT_EQ(true, e.is_present());
EXPECT_EQ(42, e.value());
*e.mutable_value() = 0;
EXPECT_EQ(true, e.is_present());
EXPECT_EQ(0, e.value());
}
} // namespace
@@ -0,0 +1,63 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/float_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::FloatParser;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class FloatParserTest : public ElementParserTest<FloatParser> {};
TEST_F(FloatParserTest, InvalidSize) {
TestInit(1, Status::kInvalidElementSize);
TestInit(5, Status::kInvalidElementSize);
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(FloatParserTest, CustomDefault) {
const double sqrt2 = 1.4142135623730951454746218587388284504413604736328125;
ResetParser(sqrt2);
ParseAndVerify();
EXPECT_EQ(sqrt2, parser_.value());
}
TEST_F(FloatParserTest, ValidFloat) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x40, 0xC9, 0x0F, 0xDB});
ParseAndVerify();
EXPECT_EQ(6.283185482025146484375, parser_.value());
SetReaderData({0x40, 0x05, 0xBF, 0x0A, 0x8B, 0x14, 0x57, 0x69});
ParseAndVerify();
EXPECT_EQ(2.718281828459045090795598298427648842334747314453125,
parser_.value());
}
TEST_F(FloatParserTest, IncrementalParse) {
SetReaderData({0x3F, 0xF9, 0xE3, 0x77, 0x9B, 0x97, 0xF4, 0xA8});
IncrementalParseAndVerify();
EXPECT_EQ(1.6180339887498949025257388711906969547271728515625,
parser_.value());
}
} // namespace
@@ -0,0 +1,51 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/id_element_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::Id;
using webm::IdElementParser;
using webm::kUnknownElementSize;
using webm::Status;
namespace {
class IdElementParserTest : public ElementParserTest<IdElementParser> {};
TEST_F(IdElementParserTest, InvalidSize) {
TestInit(0, Status::kInvalidElementSize);
TestInit(5, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(IdElementParserTest, ValidId) {
SetReaderData({0xEC});
ParseAndVerify();
EXPECT_EQ(Id::kVoid, parser_.value());
SetReaderData({0x1F, 0x43, 0xB6, 0x75});
ParseAndVerify();
EXPECT_EQ(Id::kCluster, parser_.value());
}
TEST_F(IdElementParserTest, IncrementalParse) {
SetReaderData({0x2A, 0xD7, 0xB1});
IncrementalParseAndVerify();
EXPECT_EQ(Id::kTimecodeScale, parser_.value());
}
} // namespace
@@ -0,0 +1,56 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/id_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::Id;
using webm::IdParser;
using webm::ParserTest;
using webm::Status;
namespace {
class IdParserTest : public ParserTest<IdParser> {};
TEST_F(IdParserTest, InvalidId) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementId);
ResetParser();
SetReaderData({0x0F});
ParseAndExpectResult(Status::kInvalidElementId);
}
TEST_F(IdParserTest, EarlyEndOfFile) {
SetReaderData({0x40});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(IdParserTest, ValidId) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(static_cast<Id>(0x80), parser_.id());
ResetParser();
SetReaderData({0x1F, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(static_cast<Id>(0x1FFFFFFF), parser_.id());
}
TEST_F(IdParserTest, IncrementalParse) {
SetReaderData({0x1A, 0x45, 0xDF, 0xA3});
IncrementalParseAndVerify();
EXPECT_EQ(Id::kEbml, parser_.id());
}
} // namespace
@@ -0,0 +1,105 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/info_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Info;
using webm::InfoParser;
namespace {
class InfoParserTest : public ElementParserTest<InfoParser, Id::kInfo> {};
TEST_F(InfoParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnInfo(metadata_, Info{})).Times(1);
ParseAndVerify();
}
TEST_F(InfoParserTest, DefaultValues) {
SetReaderData({
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x80, // Size = 0.
0x44, 0x89, // ID = 0x4489 (Duration).
0x20, 0x00, 0x00, // Size = 0.
0x44, 0x61, // ID = 0x4461 (DateUTC).
0x20, 0x00, 0x00, // Size = 0.
0x7B, 0xA9, // ID = 0x7BA9 (Title).
0x20, 0x00, 0x00, // Size = 0.
0x4D, 0x80, // ID = 0x4D80 (MuxingApp).
0x20, 0x00, 0x00, // Size = 0.
0x57, 0x41, // ID = 0x5741 (WritingApp).
0x20, 0x00, 0x00, // Size = 0.
});
Info info;
info.timecode_scale.Set(1000000, true);
info.duration.Set(0, true);
info.date_utc.Set(0, true);
info.title.Set("", true);
info.muxing_app.Set("", true);
info.writing_app.Set("", true);
EXPECT_CALL(callback_, OnInfo(metadata_, info)).Times(1);
ParseAndVerify();
}
TEST_F(InfoParserTest, CustomValues) {
SetReaderData({
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x44, 0x89, // ID = 0x4489 (Duration).
0x84, // Size = 4.
0x4D, 0x8E, 0xF3, 0xC2, // Body (value = 299792448.0f).
0x44, 0x61, // ID = 0x4461 (DateUTC).
0x88, // Size = 8.
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Body (value = -1).
0x7B, 0xA9, // ID = 0x7BA9 (Title).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x66, 0x6F, 0x6F, // Body (value = "foo").
0x4D, 0x80, // ID = 0x4D80 (MuxingApp).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x62, 0x61, 0x72, // Body (value = "bar").
0x57, 0x41, // ID = 0x5741 (WritingApp).
0x10, 0x00, 0x00, 0x03, // Size = 3.
0x62, 0x61, 0x7A, // Body (value = "baz").
});
Info info;
info.timecode_scale.Set(1, true);
info.duration.Set(299792448.0f, true);
info.date_utc.Set(-1, true);
info.title.Set("foo", true);
info.muxing_app.Set("bar", true);
info.writing_app.Set("baz", true);
EXPECT_CALL(callback_, OnInfo(metadata_, info)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,113 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/int_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::SignedIntParser;
using webm::Status;
using webm::UnsignedIntParser;
namespace {
class UnsignedIntParserTest : public ElementParserTest<UnsignedIntParser> {};
TEST_F(UnsignedIntParserTest, UnsignedInvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(UnsignedIntParserTest, UnsignedCustomDefault) {
ResetParser(1);
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(1), parser_.value());
}
TEST_F(UnsignedIntParserTest, UnsignedValidInt) {
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0), parser_.value());
SetReaderData({0x01, 0x02, 0x03});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x010203), parser_.value());
SetReaderData({0xFF, 0xFF, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0xFFFFFFFFFF), parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x123456789ABCDEF0), parser_.value());
}
TEST_F(UnsignedIntParserTest, UnsignedIncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10});
IncrementalParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0xFEDCBA9876543210), parser_.value());
}
class SignedIntParserTest : public ElementParserTest<SignedIntParser> {};
TEST_F(SignedIntParserTest, SignedInvalidSize) {
TestInit(9, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(SignedIntParserTest, SignedCustomDefault) {
ResetParser(-1);
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
}
TEST_F(SignedIntParserTest, SignedValidPositiveInt) {
ParseAndVerify();
EXPECT_EQ(0, parser_.value());
SetReaderData({0x7f});
ParseAndVerify();
EXPECT_EQ(0x7f, parser_.value());
SetReaderData({0x12, 0xD6, 0x87});
ParseAndVerify();
EXPECT_EQ(1234567, parser_.value());
SetReaderData({0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0});
ParseAndVerify();
EXPECT_EQ(0x123456789ABCDEF0, parser_.value());
}
TEST_F(SignedIntParserTest, SignedValidNegativeInt) {
SetReaderData({0xFF});
ParseAndVerify();
EXPECT_EQ(-1, parser_.value());
SetReaderData({0xF8, 0xA4, 0x32, 0xEB});
ParseAndVerify();
EXPECT_EQ(-123456789, parser_.value());
}
TEST_F(SignedIntParserTest, SignedIncrementalParse) {
SetReaderData({0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11});
IncrementalParseAndVerify();
EXPECT_EQ(-81985529216486895, parser_.value());
}
} // namespace
@@ -0,0 +1,131 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/istream_reader.h"
#include <algorithm>
#include <array>
#include <cstdint>
#include <sstream>
#include <type_traits>
#include "gtest/gtest.h"
using webm::IstreamReader;
using webm::Status;
namespace {
// Creates a std::array from a string literal (and omits the trailing
// NUL-character).
template <std::size_t N>
std::array<std::uint8_t, N - 1> ArrayFromString(const char (&string)[N]) {
std::array<std::uint8_t, N - 1> array;
std::copy_n(string, N - 1, array.begin());
return array;
}
class IstreamReaderTest : public testing::Test {};
TEST_F(IstreamReaderTest, Read) {
std::array<std::uint8_t, 15> buffer{};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("abcdefghij");
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
status = reader.Read(10, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
std::array<std::uint8_t, 15> expected =
ArrayFromString("abcdefghij\0\0\0\0\0");
EXPECT_EQ(expected, buffer);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
}
TEST_F(IstreamReaderTest, Skip) {
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("abcdefghij");
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
status = reader.Skip(10, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(7), count);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
}
TEST_F(IstreamReaderTest, ReadAndSkip) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("AaBbCcDdEe");
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
std::array<std::uint8_t, 10> expected = ArrayFromString("AaBbCEe\0\0\0");
EXPECT_EQ(expected, buffer);
}
TEST_F(IstreamReaderTest, Position) {
std::array<std::uint8_t, 10> buffer = {};
std::uint64_t count;
Status status;
IstreamReader reader =
IstreamReader::Emplace<std::istringstream>("AaBbCcDdEe");
EXPECT_EQ(static_cast<std::uint64_t>(0), reader.Position());
status = reader.Read(5, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(5), count);
EXPECT_EQ(static_cast<std::uint64_t>(5), reader.Position());
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), count);
EXPECT_EQ(static_cast<std::uint64_t>(8), reader.Position());
status = reader.Read(5, buffer.data() + 5, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
EXPECT_EQ(static_cast<std::uint64_t>(10), reader.Position());
std::array<std::uint8_t, 10> expected = ArrayFromString("AaBbCEe\0\0\0");
EXPECT_EQ(expected, buffer);
}
} // namespace
@@ -0,0 +1,250 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "test_utils/limited_reader.h"
#include <array>
#include <cstdint>
#include <memory>
#include "gtest/gtest.h"
#include "webm/buffer_reader.h"
#include "webm/reader.h"
#include "webm/status.h"
using webm::BufferReader;
using webm::LimitedReader;
using webm::Reader;
using webm::Status;
namespace {
class LimitedReaderTest : public testing::Test {};
TEST_F(LimitedReaderTest, UnlimitedRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(4), count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, UnlimitedSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(4), count);
}
TEST_F(LimitedReaderTest, Position) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
EXPECT_EQ(static_cast<std::uint64_t>(0), reader.Position());
status = reader.Read(2, buffer.data(), &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
status = reader.Skip(2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
EXPECT_EQ(static_cast<std::uint64_t>(4), reader.Position());
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 0, 0}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitIndividualRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_single_read_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
status = reader.Read(buffer.size() + 1, buffer.data() + 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
reader.set_single_read_limit(2);
status = reader.Read(buffer.size() - 2, buffer.data() + 2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitIndividualSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_single_skip_limit(1);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
reader.set_single_skip_limit(2);
status = reader.Skip(2, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
}
TEST_F(LimitedReaderTest, LimitRepeatedRead) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_read_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
reader.set_total_read_limit(2);
status = reader.Read(buffer.size() - 1, buffer.data() + 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
reader.set_total_read_limit(1);
status = reader.Read(buffer.size() - 3, buffer.data() + 3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
std::array<std::uint8_t, 4> expected_buffer = {{1, 2, 3, 4}};
EXPECT_EQ(expected_buffer, buffer);
}
TEST_F(LimitedReaderTest, LimitRepeatedSkip) {
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_skip_limit(1);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
status = reader.Skip(4, &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
reader.set_total_skip_limit(2);
status = reader.Skip(3, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
reader.set_total_skip_limit(1);
status = reader.Skip(1, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
}
TEST_F(LimitedReaderTest, LimitReadsAndSkips) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
reader.set_total_read_skip_limit(1);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), count);
reader.set_total_read_skip_limit(2);
status = reader.Skip(buffer.size() - 1, &count);
EXPECT_EQ(Status::kOkPartial, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(2), count);
reader.set_total_read_skip_limit(1);
status = reader.Read(buffer.size() - 3, buffer.data() + 3, &count);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), count);
std::array<std::uint8_t, 4> expected = {{1, 0, 0, 4}};
EXPECT_EQ(expected, buffer);
}
TEST_F(LimitedReaderTest, CustomStatusWhenBlocked) {
std::array<std::uint8_t, 4> buffer = {{0, 0, 0, 0}};
LimitedReader reader(std::unique_ptr<Reader>(new BufferReader({1, 2, 3, 4})));
std::uint64_t count;
Status status;
Status expected_status = Status(-123);
const std::uint64_t kZeroCount = 0;
reader.set_single_read_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(kZeroCount, count);
reader.set_return_status_when_blocked(expected_status);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
reader.set_single_read_limit(std::numeric_limits<std::size_t>::max());
reader.set_total_read_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
reader.set_single_skip_limit(0);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
reader.set_single_skip_limit(std::numeric_limits<std::uint64_t>::max());
reader.set_total_skip_limit(0);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
reader.set_total_skip_limit(std::numeric_limits<std::uint64_t>::max());
reader.set_total_read_skip_limit(0);
status = reader.Read(buffer.size(), buffer.data(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
status = reader.Skip(buffer.size(), &count);
EXPECT_EQ(expected_status.code, status.code);
EXPECT_EQ(kZeroCount, count);
std::array<std::uint8_t, 4> expected_buffer = {{0, 0, 0, 0}};
EXPECT_EQ(expected_buffer, buffer);
}
} // namespace
@@ -0,0 +1,382 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/master_parser.h"
#include <cstdint>
#include <memory>
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/byte_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::BinaryParser;
using webm::ElementMetadata;
using webm::ElementParser;
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::LimitedReader;
using webm::MasterParser;
using webm::Status;
namespace {
// Simple helper method that just takes an Id and ElementParser* and returns
// them in a std::pair<Id, std::unique_ptr<ElementParser>>. Provided just for
// simplifying some statements.
std::pair<Id, std::unique_ptr<ElementParser>> ParserForId(
Id id, ElementParser* parser) {
return {id, std::unique_ptr<ElementParser>(parser)};
}
class MasterParserTest : public ElementParserTest<MasterParser> {};
// Errors parsing an ID should be returned to the caller.
TEST_F(MasterParserTest, BadId) {
SetReaderData({
0x00, // Invalid ID.
0x80, // ID = 0x80 (unknown).
0x80, // Size = 0.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndExpectResult(Status::kInvalidElementId);
}
// Errors from a child parser's Init should be returned to the caller.
TEST_F(MasterParserTest, ChildInitFails) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0xFF, // Size = unknown.
});
const ElementMetadata metadata = {Id::kVoid, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
ParseAndExpectResult(Status::kInvalidElementSize);
}
// Indefinite unknown children should result in an error.
TEST_F(MasterParserTest, IndefiniteUnknownChild) {
SetReaderData({
0x80, // ID = 0x80 (unknown).
0xFF, // Size = unknown.
0x00, 0x00, // Body.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndExpectResult(Status::kIndefiniteUnknownElement);
}
// Child elements that overflow the master element's size should be detected.
TEST_F(MasterParserTest, ChildOverflow) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0x82, // Size = 2.
0x00, 0x00, // Body.
});
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
ParseAndExpectResult(Status::kElementOverflow, reader_.size() - 1);
}
// Child elements with an unknown size can't be naively checked to see if they
// overflow the master element's size. Make sure the overflow is still detected.
TEST_F(MasterParserTest, ChildOverflowWithUnknownSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndExpectResult(Status::kElementOverflow, 4);
}
// An element with an unknown size should be terminated by its parents bounds.
TEST_F(MasterParserTest, ChildWithUnknownSizeBoundedByParentSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0x00, // Invalid ID. This should not be read.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 2};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndVerify(reader_.size() - 1);
}
// An empty master element is okay.
TEST_F(MasterParserTest, Empty) {
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
ParseAndVerify();
}
TEST_F(MasterParserTest, DefaultActionIsRead) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0x80, // Size = 0.
});
{
InSequence dummy;
const ElementMetadata metadata = {Id::kVoid, 2, 0, 0};
// This intentionally does not set the action and relies on the parser using
// a default action value of kRead.
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
.WillOnce(Return(Status(Status::kOkCompleted)));
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ParseAndVerify();
}
// Unrecognized children should be skipped over.
TEST_F(MasterParserTest, UnknownChildren) {
SetReaderData({
0x40, 0x00, // ID = 0x4000 (unknown).
0x80, // Size = 0.
0x80, // ID = 0x80 (unknown).
0x40, 0x00, // Size = 0.
});
EXPECT_CALL(callback_, OnVoid(_, _, _)).Times(0);
{
InSequence dummy;
ElementMetadata metadata = {static_cast<Id>(0x4000), 3, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {static_cast<Id>(0x80), 3, 0, 3};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
}
ParseAndVerify();
}
// A master element with unknown size is terminated by the first element that is
// not a valid child.
TEST_F(MasterParserTest, UnknownSize) {
SetReaderData({
// Void elements may appear anywhere in a master element and should not
// terminate the parse for a master element with an unknown size. In other
// words, they're always valid children.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
// This element marks the end for the parser since this is the first
// unrecognized element. The ID and size should be read (which the parser
// uses to determine the end has been reached), but nothing more.
0x80, // ID = 0x80 (unknown).
0x81, // Size = 1.
0x12, // Body.
});
{
InSequence dummy;
const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ParseAndVerify(kUnknownElementSize);
EXPECT_EQ(static_cast<std::uint64_t>(5), reader_.Position());
}
// Consecutive elements with unknown size should parse without issues, despite
// the internal parsers having to read ahead into the next (non-child) element.
TEST_F(MasterParserTest, MultipleUnknownChildSize) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x13, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, kUnknownElementSize, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 2};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
metadata = {Id::kBlock, 2, kUnknownElementSize, 5};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 7};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
ParseAndVerify();
}
// Reaching the end of the file while reading an element with unknown size
// should return Status::kOkCompleted instead of Status::kEndOfFile.
TEST_F(MasterParserTest, UnknownSizeToFileEnd) {
SetReaderData({
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
});
{
InSequence dummy;
const ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(1);
}
ParseAndVerify();
}
// Parsing one byte at a time is okay.
TEST_F(MasterParserTest, IncrementalParse) {
SetReaderData({
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x08, 0x00, 0x00, 0x00, 0x06, // Size = 6.
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Body.
});
const ElementMetadata metadata = {Id::kEbml, 9, 6, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
BinaryParser* binary_parser = new BinaryParser;
ResetParser(ParserForId(Id::kEbml, binary_parser));
IncrementalParseAndVerify();
std::vector<std::uint8_t> expected = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
EXPECT_EQ(expected, binary_parser->value());
}
// Alternating actions between skip and read is okay. The parser should remember
// the requested action between repeated calls to Feed.
TEST_F(MasterParserTest, IncrementalSkipThenReadThenSkip) {
SetReaderData({
0xA1, // ID = 0xA1 (Block) (master).
0x83, // Size = 3.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x12, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0x83, // Size = 3.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x13, // Body.
0xA1, // ID = 0xA1 (Block) (master).
0xFF, // Size = unknown.
0xEC, // ID = 0xEC (Void) (child).
0x81, // Size = 1.
0x14, // Body.
});
{
InSequence dummy;
ElementMetadata metadata = {Id::kBlock, 2, 3, 0};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
metadata = {Id::kBlock, 2, 3, 5};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kVoid, 2, 1, 7};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
// Expect to get called twice because we'll cap the LimitedReader to 1-byte
// reads. The first attempt to read will fail because we'll have already
// reached the 1-byte max.
EXPECT_CALL(callback_, OnVoid(metadata, NotNull(), NotNull())).Times(2);
metadata = {Id::kBlock, 2, kUnknownElementSize, 10};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull()))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
}
ResetParser(ParserForId(Id::kBlock, new MasterParser));
IncrementalParseAndVerify();
}
} // namespace
@@ -0,0 +1,366 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/master_value_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "src/int_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Callback;
using webm::Cluster;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::MasterValueParser;
using webm::Status;
using webm::UnsignedIntParser;
namespace {
// An instance of MasterValueParser that can actually be used in the tests to
// parse Cluster structures.
class FakeClusterParser : public MasterValueParser<Cluster> {
public:
FakeClusterParser()
: MasterValueParser(
MakeChild<UnsignedIntParser>(Id::kTimecode, &Cluster::timecode),
MakeChild<UnsignedIntParser>(Id::kPrevSize, &Cluster::previous_size)
.UseAsStartEvent()) {}
protected:
Status OnParseStarted(Callback* callback, Action* action) override {
return callback->OnClusterBegin(metadata(Id::kCluster), value(), action);
}
Status OnParseCompleted(Callback* callback) override {
return callback->OnClusterEnd(metadata(Id::kCluster), value());
}
};
class MasterValueParserTest
: public ElementParserTest<FakeClusterParser, Id::kCluster> {};
TEST_F(MasterValueParserTest, InvalidId) {
SetReaderData({
0x00, // Invalid ID.
});
ParseAndExpectResult(Status::kInvalidElementId);
}
TEST_F(MasterValueParserTest, InvalidSize) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0xFF, // Size = unknown.
});
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(MasterValueParserTest, DefaultParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnClusterBegin(metadata_, Cluster{}, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, Cluster{})).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, DefaultValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
0xAB, // ID = 0xAB (PrevSize).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(0, true);
ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {Id::kPrevSize, 2, 0, 2};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(0, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, CustomValues) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x82, // Size = 2.
0x04, 0x00, // Body (value = 1024).
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1024, true);
ElementMetadata child_metadata = {Id::kTimecode, 2, 2, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {Id::kPrevSize, 3, 1, 4};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, IncrementalParse) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x40, 0x02, // Size = 2.
0x04, 0x00, // Body (value = 1024).
0x40, 0x00, // ID = 0x4000 (Unknown).
0x40, 0x02, // Size = 2.
0x00, 0x00, // Body.
0xAB, // ID = 0xAB (PrevSize).
0x40, 0x02, // Size = 2.
0x00, 0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
cluster.timecode.Set(1024, true);
ElementMetadata child_metadata = {Id::kTimecode, 3, 2, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
child_metadata = {static_cast<Id>(0x4000), 4, 2, 5};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_,
OnUnknownElement(child_metadata, NotNull(), NotNull()))
.Times(3);
child_metadata = {Id::kPrevSize, 3, 2, 11};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
cluster.previous_size.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(MasterValueParserTest, StartEventWithoutPreviousSize) {
SetReaderData({
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
const ElementMetadata child_metadata = {Id::kTimecode, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.timecode.Set(0, true);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, StartEventWithPreviousSize) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x80, // Size = 0.
0xE7, // ID = 0xE7 (Timecode).
0x80, // Size = 0.
});
{
InSequence dummy;
Cluster cluster{};
ElementMetadata child_metadata = {Id::kPrevSize, 2, 0, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.Times(1);
child_metadata = {Id::kTimecode, 2, 0, 2};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.previous_size.Set(0, true);
cluster.timecode.Set(0, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
ParseAndVerify();
}
TEST_F(MasterValueParserTest, PartialStartThenRead) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
{
InSequence dummy;
Cluster cluster{};
ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kRead),
Return(Status(Status::kOkCompleted))));
child_metadata = {Id::kTimecode, 2, 1, 3};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
cluster.previous_size.Set(1, true);
cluster.timecode.Set(1, true);
EXPECT_CALL(callback_, OnClusterEnd(metadata_, cluster)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(MasterValueParserTest, EmptySkip) {
const Cluster cluster{};
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnElementBegin(_, _)).Times(0);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
ParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
TEST_F(MasterValueParserTest, Skip) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
const Cluster cluster{};
{
InSequence dummy;
const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
}
ParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
TEST_F(MasterValueParserTest, PartialStartThenSkip) {
SetReaderData({
0xAB, // ID = 0xAB (PrevSize).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE7, // ID = 0xE7 (Timecode).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
const Cluster cluster{};
{
InSequence dummy;
const ElementMetadata child_metadata = {Id::kPrevSize, 2, 1, 0};
EXPECT_CALL(callback_, OnElementBegin(child_metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(metadata_, cluster, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<2>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
}
IncrementalParseAndVerify();
EXPECT_EQ(cluster, parser_.value());
}
} // namespace
@@ -0,0 +1,208 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/mastering_metadata_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::MasteringMetadata;
using webm::MasteringMetadataParser;
namespace {
class MasteringMetadataParserTest
: public ElementParserTest<MasteringMetadataParser,
Id::kMasteringMetadata> {};
TEST_F(MasteringMetadataParserTest, DefaultParse) {
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_FALSE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_FALSE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_FALSE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_max.value());
EXPECT_FALSE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_min.value());
}
TEST_F(MasteringMetadataParserTest, DefaultValues) {
SetReaderData({
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x80, // Size = 0.
0x55, 0xD2, // ID = 0x55D2 (PrimaryRChromaticityY).
0x80, // Size = 0.
0x55, 0xD3, // ID = 0x55D3 (PrimaryGChromaticityX).
0x80, // Size = 0.
0x55, 0xD4, // ID = 0x55D4 (PrimaryGChromaticityY).
0x80, // Size = 0.
0x55, 0xD5, // ID = 0x55D5 (PrimaryBChromaticityX).
0x80, // Size = 0.
0x55, 0xD6, // ID = 0x55D6 (PrimaryBChromaticityY).
0x80, // Size = 0.
0x55, 0xD7, // ID = 0x55D7 (WhitePointChromaticityX).
0x80, // Size = 0.
0x55, 0xD8, // ID = 0x55D8 (WhitePointChromaticityY).
0x80, // Size = 0.
0x55, 0xD9, // ID = 0x55D9 (LuminanceMax).
0x80, // Size = 0.
0x55, 0xDA, // ID = 0x55DA (LuminanceMin).
0x80, // Size = 0.
});
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_max.value());
EXPECT_TRUE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(0, mastering_metadata.luminance_min.value());
}
TEST_F(MasteringMetadataParserTest, CustomValues) {
SetReaderData({
0x55, 0xD1, // ID = 0x55D1 (PrimaryRChromaticityX).
0x84, // Size = 4.
0x3E, 0x00, 0x00, 0x00, // Body (value = 0.125).
0x55, 0xD2, // ID = 0x55D2 (PrimaryRChromaticityY).
0x84, // Size = 4.
0x3E, 0x80, 0x00, 0x00, // Body (value = 0.25).
0x55, 0xD3, // ID = 0x55D3 (PrimaryGChromaticityX).
0x84, // Size = 4.
0x3E, 0xC0, 0x00, 0x00, // Body (value = 0.375).
0x55, 0xD4, // ID = 0x55D4 (PrimaryGChromaticityY).
0x84, // Size = 4.
0x3F, 0x00, 0x00, 0x00, // Body (value = 0.5).
0x55, 0xD5, // ID = 0x55D5 (PrimaryBChromaticityX).
0x84, // Size = 4.
0x3F, 0x20, 0x00, 0x00, // Body (value = 0.625).
0x55, 0xD6, // ID = 0x55D6 (PrimaryBChromaticityY).
0x84, // Size = 4.
0x3F, 0x40, 0x00, 0x00, // Body (value = 0.75).
0x55, 0xD7, // ID = 0x55D7 (WhitePointChromaticityX).
0x84, // Size = 4.
0x3F, 0x60, 0x00, 0x00, // Body (value = 0.875).
0x55, 0xD8, // ID = 0x55D8 (WhitePointChromaticityY).
0x84, // Size = 4.
0x3F, 0x80, 0x00, 0x00, // Body (value = 1).
0x55, 0xD9, // ID = 0x55D9 (LuminanceMax).
0x84, // Size = 4.
0x40, 0x00, 0x00, 0x00, // Body (value = 2).
0x55, 0xDA, // ID = 0x55DA (LuminanceMin).
0x84, // Size = 4.
0x40, 0x40, 0x00, 0x00, // Body (value = 3).
});
ParseAndVerify();
const MasteringMetadata mastering_metadata = parser_.value();
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_x.is_present());
EXPECT_EQ(0.125, mastering_metadata.primary_r_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_r_chromaticity_y.is_present());
EXPECT_EQ(0.25, mastering_metadata.primary_r_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_x.is_present());
EXPECT_EQ(0.375, mastering_metadata.primary_g_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_g_chromaticity_y.is_present());
EXPECT_EQ(0.5, mastering_metadata.primary_g_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_x.is_present());
EXPECT_EQ(0.625, mastering_metadata.primary_b_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.primary_b_chromaticity_y.is_present());
EXPECT_EQ(0.75, mastering_metadata.primary_b_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_x.is_present());
EXPECT_EQ(0.875, mastering_metadata.white_point_chromaticity_x.value());
EXPECT_TRUE(mastering_metadata.white_point_chromaticity_y.is_present());
EXPECT_EQ(1.0, mastering_metadata.white_point_chromaticity_y.value());
EXPECT_TRUE(mastering_metadata.luminance_max.is_present());
EXPECT_EQ(2.0, mastering_metadata.luminance_max.value());
EXPECT_TRUE(mastering_metadata.luminance_min.is_present());
EXPECT_EQ(3.0, mastering_metadata.luminance_min.value());
}
} // namespace
@@ -0,0 +1,100 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/parser_utils.h"
#include <cstdint>
#include <limits>
#include <memory>
#include "gtest/gtest.h"
#include "test_utils/limited_reader.h"
#include "webm/buffer_reader.h"
#include "webm/reader.h"
#include "webm/status.h"
using webm::BufferReader;
using webm::LimitedReader;
using webm::Reader;
using webm::Status;
namespace {
class ParserUtilsTest : public testing::Test {};
TEST_F(ParserUtilsTest, ReadByte) {
LimitedReader reader(
std::unique_ptr<Reader>(new BufferReader({0x12, 0x34, 0x56, 0x78})));
Status status;
std::uint8_t byte;
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x12, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x34, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x56, byte);
reader.set_total_read_limit(0);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(0x56, byte);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(0x78, byte);
status = ReadByte(&reader, &byte);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(0x78, byte);
}
TEST_F(ParserUtilsTest, AccumulateIntegerBytes) {
LimitedReader reader(
std::unique_ptr<Reader>(new BufferReader({0x12, 0x34, 0x56, 0x78})));
std::uint32_t integer = 0;
Status status;
std::uint64_t num_bytes_actually_read;
reader.set_total_read_limit(1);
status =
AccumulateIntegerBytes(4, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kWouldBlock, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), num_bytes_actually_read);
EXPECT_EQ(static_cast<std::uint32_t>(0x12), integer);
reader.set_total_read_limit(std::numeric_limits<std::size_t>::max());
status =
AccumulateIntegerBytes(3, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(3), num_bytes_actually_read);
EXPECT_EQ(static_cast<std::uint32_t>(0x12345678), integer);
// Make sure calling with num_bytes_remaining == 0 is a no-op.
status =
AccumulateIntegerBytes(0, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), num_bytes_actually_read);
EXPECT_EQ(static_cast<std::uint32_t>(0x12345678), integer);
status =
AccumulateIntegerBytes(4, &reader, &integer, &num_bytes_actually_read);
EXPECT_EQ(Status::kEndOfFile, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(0), num_bytes_actually_read);
EXPECT_EQ(static_cast<std::uint32_t>(0x12345678), integer);
}
} // namespace
@@ -0,0 +1,144 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/projection_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Projection;
using webm::ProjectionParser;
using webm::ProjectionType;
namespace {
class ProjectionParserTest
: public ElementParserTest<ProjectionParser, Id::kProjection> {};
TEST_F(ProjectionParserTest, DefaultParse) {
ParseAndVerify();
const Projection projection = parser_.value();
EXPECT_FALSE(projection.type.is_present());
EXPECT_EQ(ProjectionType::kRectangular, projection.type.value());
EXPECT_FALSE(projection.projection_private.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, projection.projection_private.value());
EXPECT_FALSE(projection.pose_yaw.is_present());
EXPECT_EQ(0.0, projection.pose_yaw.value());
EXPECT_FALSE(projection.pose_pitch.is_present());
EXPECT_EQ(0.0, projection.pose_pitch.value());
EXPECT_FALSE(projection.pose_roll.is_present());
EXPECT_EQ(0.0, projection.pose_roll.value());
}
TEST_F(ProjectionParserTest, DefaultValues) {
SetReaderData({
0x76, 0x71, // ID = 0x7671 (ProjectionType).
0x80, // Size = 0.
0x76, 0x72, // ID = 0x7672 (ProjectionPrivate).
0x80, // Size = 0.
0x76, 0x73, // ID = 0x7673 (ProjectionPoseYaw).
0x80, // Size = 0.
0x76, 0x74, // ID = 0x7674 (ProjectionPosePitch).
0x80, // Size = 0.
0x76, 0x75, // ID = 0x7675 (ProjectionPoseRoll).
0x80, // Size = 0.
});
ParseAndVerify();
const Projection projection = parser_.value();
EXPECT_TRUE(projection.type.is_present());
EXPECT_EQ(ProjectionType::kRectangular, projection.type.value());
EXPECT_TRUE(projection.projection_private.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, projection.projection_private.value());
EXPECT_TRUE(projection.pose_yaw.is_present());
EXPECT_EQ(0.0, projection.pose_yaw.value());
EXPECT_TRUE(projection.pose_pitch.is_present());
EXPECT_EQ(0.0, projection.pose_pitch.value());
EXPECT_TRUE(projection.pose_roll.is_present());
EXPECT_EQ(0.0, projection.pose_roll.value());
}
TEST_F(ProjectionParserTest, CustomValues) {
SetReaderData({
0x76, 0x71, // ID = 0x7671 (ProjectionType).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = equirectangular).
0x76, 0x72, // ID = 0x7672 (ProjectionPrivate).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x00, // Body.
0x76, 0x73, // ID = 0x7673 (ProjectionPoseYaw).
0x10, 0x00, 0x00, 0x04, // Size = 4.
0x3f, 0x80, 0x00, 0x00, // Body (value = 1.0).
0x76, 0x74, // ID = 0x7674 (ProjectionPosePitch).
0x10, 0x00, 0x00, 0x04, // Size = 4.
0x40, 0x00, 0x00, 0x00, // Body (value = 2.0).
0x76, 0x75, // ID = 0x7675 (ProjectionPoseRoll).
0x10, 0x00, 0x00, 0x04, // Size = 4.
0x40, 0x80, 0x00, 0x00, // Body (value = 4.0).
});
ParseAndVerify();
const Projection projection = parser_.value();
EXPECT_TRUE(projection.type.is_present());
EXPECT_EQ(ProjectionType::kEquirectangular, projection.type.value());
EXPECT_TRUE(projection.projection_private.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x00},
projection.projection_private.value());
EXPECT_TRUE(projection.pose_yaw.is_present());
EXPECT_EQ(1.0, projection.pose_yaw.value());
EXPECT_TRUE(projection.pose_pitch.is_present());
EXPECT_EQ(2.0, projection.pose_pitch.value());
EXPECT_TRUE(projection.pose_roll.is_present());
EXPECT_EQ(4.0, projection.pose_roll.value());
}
TEST_F(ProjectionParserTest, MeshProjection) {
SetReaderData({
0x76, 0x71, // ID = 0x7671 (ProjectionType).
0x81, // Size = 1.
0x03, // Body (value = mesh).
});
ParseAndVerify();
const Projection projection = parser_.value();
EXPECT_TRUE(projection.type.is_present());
EXPECT_EQ(ProjectionType::kMesh, projection.type.value());
}
} // namespace
@@ -0,0 +1,90 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/recursive_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "src/byte_parser.h"
#include "src/element_parser.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::Callback;
using webm::ElementMetadata;
using webm::ElementParser;
using webm::ElementParserTest;
using webm::Reader;
using webm::RecursiveParser;
using webm::Status;
using webm::StringParser;
namespace {
class FailParser : public ElementParser {
public:
explicit FailParser(std::size_t /* max_recursion_depth */) { ADD_FAILURE(); }
Status Init(const ElementMetadata& /* metadata */,
std::uint64_t /* max_size */) override {
ADD_FAILURE();
return Status(Status::kInvalidElementSize);
}
Status Feed(Callback* /* callback */, Reader* /* reader */,
std::uint64_t* num_bytes_read) override {
ADD_FAILURE();
*num_bytes_read = 0;
return Status(Status::kInvalidElementSize);
}
int value() const {
ADD_FAILURE();
return 0;
}
int* mutable_value() {
ADD_FAILURE();
return nullptr;
}
};
class StringParserWrapper : public StringParser {
public:
explicit StringParserWrapper(std::size_t max_recursion_depth) {
EXPECT_EQ(max_recursion_depth, 24);
}
};
class RecursiveFailParserTest
: public ElementParserTest<RecursiveParser<FailParser>> {};
TEST_F(RecursiveFailParserTest, NoConstruction) {
RecursiveParser<FailParser> parser;
}
class RecursiveStringParserTest
: public ElementParserTest<RecursiveParser<StringParserWrapper>> {};
TEST_F(RecursiveStringParserTest, ParsesOkay) {
ParseAndVerify();
EXPECT_EQ("", parser_.value());
SetReaderData({0x48, 0x69}); // "Hi".
ParseAndVerify();
EXPECT_EQ("Hi", parser_.value());
}
TEST_F(RecursiveStringParserTest, ExceedMaxRecursionDepth) {
ResetParser(0);
TestInit(0, Status::kExceededRecursionDepthLimit);
}
} // namespace
@@ -0,0 +1,54 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/seek_head_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SeekHeadParser;
namespace {
class SeekHeadParserTest
: public ElementParserTest<SeekHeadParser, Id::kSeekHead> {};
TEST_F(SeekHeadParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(SeekHeadParserTest, RepeatedValues) {
SetReaderData({
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x84, // Size = 4.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x84, // Size = 4.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,67 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/seek_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Seek;
using webm::SeekParser;
namespace {
class SeekParserTest : public ElementParserTest<SeekParser, Id::kSeek> {};
TEST_F(SeekParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnSeek(metadata_, Seek{})).Times(1);
ParseAndVerify();
}
TEST_F(SeekParserTest, DefaultValues) {
SetReaderData({
// A SeekID element with a length of 0 isn't valid, so we don't test it.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x80, // Size = 0.
});
Seek seek;
seek.position.Set(0, true);
EXPECT_CALL(callback_, OnSeek(metadata_, seek)).Times(1);
ParseAndVerify();
}
TEST_F(SeekParserTest, CustomValues) {
SetReaderData({
0x53, 0xAB, // ID = 0x53AB (SeekID).
0x81, // Size = 1.
0x01, // Body.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
Seek seek;
seek.id.Set(static_cast<Id>(0x01), true);
seek.position.Set(2, true);
EXPECT_CALL(callback_, OnSeek(metadata_, seek)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,369 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/segment_parser.h"
#include <cstdint>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::_;
using testing::DoAll;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using testing::SetArgPointee;
using webm::Action;
using webm::Ancestory;
using webm::ElementMetadata;
using webm::ElementParserTest;
using webm::Id;
using webm::SegmentParser;
using webm::Status;
namespace {
class SegmentParserTest
: public ElementParserTest<SegmentParser, Id::kSegment> {};
TEST_F(SegmentParserTest, EmptyParse) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, DefaultActionIsRead) {
{
InSequence dummy;
// This intentionally does not set the action and relies on the parser using
// a default action value of kRead.
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkCompleted)));
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, EmptyParseWithDelayedStart) {
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kRead),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
IncrementalParseAndVerify();
}
TEST_F(SegmentParserTest, DefaultValues) {
SetReaderData({
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x80, // Size = 0.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x80, // Size = 0.
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x80, // Size = 0.
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x80, // Size = 0.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x80, // Size = 0.
0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
0x80, // Size = 0.
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x80, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
ElementMetadata metadata = {Id::kInfo, 5, 0, 5};
EXPECT_CALL(callback_, OnInfo(metadata, _)).Times(1);
metadata = {Id::kCluster, 5, 0, 10};
EXPECT_CALL(callback_, OnClusterBegin(metadata, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(metadata, _)).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, RepeatedValues) {
SetReaderData({
// Mutliple SeekHead elements.
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x8D, // Size = 13.
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x11, 0x4D, 0x9B, 0x74, // ID = 0x114D9B74 (SeekHead).
0x8D, // Size = 13.
0x4D, 0xBB, // ID = 0x4DBB (Seek).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x53, 0xAC, // ID = 0x53AC (SeekPosition).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Info elements.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x88, // Size = 8.
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x88, // Size = 8.
0x2A, 0xD7, 0xB1, // ID = 0x2AD7B1 (TimecodeScale).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Cluster elements.
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x86, // Size = 6.
0xE7, // ID = 0xE7 (Timecode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x86, // Size = 6.
0xE7, // ID = 0xE7 (Timecode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Multiple Tracks elements.
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x8B, // Size = 11.
0xAE, // ID = 0xAE (TrackEntry).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xD7, // ID = 0xD7 (TrackNumber).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x16, 0x54, 0xAE, 0x6B, // ID = 0x1654AE6B (Tracks).
0x8B, // Size = 11.
0xAE, // ID = 0xAE (TrackEntry).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xD7, // ID = 0xD7 (TrackNumber).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
// Single Cues element.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x8B, // Size = 11.
0xBB, // ID = 0xBB (CuePoint).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xB3, // ID = 0xB3 (CueTime).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
// Single Chapters element.
0x10, 0x43, 0xA7, 0x70, // ID = 0x1043A770 (Chapters).
0x8D, // Size = 13.
0x45, 0xB9, // ID = 0x45B9 (EditionEntry).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x45, 0xBC, // ID = 0x45BC (EditionUID).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
// Multiple Tags elements.
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x93, // Size = 19.
0x73, 0x73, // ID = 0x7373 (Tag).
0x10, 0x00, 0x00, 0x0D, // Size = 13.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x12, 0x54, 0xC3, 0x67, // ID = 0x1254C367 (Tags).
0x93, // Size = 19.
0x73, 0x73, // ID = 0x7373 (Tag).
0x10, 0x00, 0x00, 0x0D, // Size = 13.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull())).Times(1);
EXPECT_CALL(callback_, OnSeek(_, _)).Times(2);
EXPECT_CALL(callback_, OnInfo(_, _)).Times(2);
EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
EXPECT_CALL(callback_, OnClusterBegin(_, _, NotNull())).Times(1);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(1);
EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(2);
EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
EXPECT_CALL(callback_, OnEditionEntry(_, _)).Times(1);
EXPECT_CALL(callback_, OnTag(_, _)).Times(2);
EXPECT_CALL(callback_, OnSegmentEnd(metadata_)).Times(1);
}
ParseAndVerify();
}
TEST_F(SegmentParserTest, Skip) {
SetReaderData({
0x1F, 0x43, 0xB6, 0x75, // ID = 0x1F43B675 (Cluster).
0x80, // Size = 0.
});
{
InSequence dummy;
EXPECT_CALL(callback_, OnSegmentBegin(metadata_, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoAll(SetArgPointee<1>(Action::kSkip),
Return(Status(Status::kOkCompleted))));
EXPECT_CALL(callback_, OnClusterBegin(_, _, _)).Times(0);
EXPECT_CALL(callback_, OnClusterEnd(_, _)).Times(0);
EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(0);
}
IncrementalParseAndVerify();
}
TEST_F(SegmentParserTest, Seek) {
SetReaderData({
// We start the reader at the beginning of a FlagInterlaced element
// (skipping its ID and size, as they're passed into InitAfterSeek).
// FlagInterlaced, StereoMode, and AlphaMode are all part of the Video
// element, with the ancestory: Segment -> Tracks -> TrackEntry -> Video.
0x01, // Body (value = 1).
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x03, // Body (value = 3).
// Single Cues element.
0x1C, 0x53, 0xBB, 0x6B, // ID = 0x1C53BB6B (Cues).
0x8B, // Size = 11.
0xBB, // ID = 0xBB (CuePoint).
0x10, 0x00, 0x00, 0x06, // Size = 6.
0xB3, // ID = 0xB3 (CueTime).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
const ElementMetadata flag_interlaced_metadata = {Id::kFlagInterlaced, 0, 1,
0};
EXPECT_CALL(callback_, OnSegmentBegin(_, _)).Times(0);
{
InSequence dummy;
EXPECT_CALL(callback_, OnElementBegin(flag_interlaced_metadata, NotNull()))
.Times(1);
ElementMetadata metadata = {Id::kStereoMode, 6, 1, 1};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kAlphaMode, 6, 1, 8};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnTrackEntry(_, _)).Times(1);
metadata = {Id::kCues, 5, 11, 15};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kCuePoint, 5, 6, 20};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kCueTime, 5, 1, 25};
EXPECT_CALL(callback_, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback_, OnCuePoint(_, _)).Times(1);
EXPECT_CALL(callback_, OnSegmentEnd(_)).Times(1);
}
Ancestory ancestory;
ASSERT_TRUE(Ancestory::ById(flag_interlaced_metadata.id, &ancestory));
ancestory = ancestory.next(); // Skip the Segment ancestor.
parser_.InitAfterSeek(ancestory, flag_interlaced_metadata);
std::uint64_t num_bytes_read = 0;
const Status status = parser_.Feed(&callback_, &reader_, &num_bytes_read);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader_.size(), num_bytes_read);
}
} // namespace
@@ -0,0 +1,205 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/simple_tag_parser.h"
#include <cstdint>
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleTag;
using webm::SimpleTagParser;
using webm::Status;
namespace {
class SimpleTagParserTest
: public ElementParserTest<SimpleTagParser, Id::kSimpleTag> {};
TEST_F(SimpleTagParserTest, DefaultParse) {
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_FALSE(simple_tag.name.is_present());
EXPECT_EQ("", simple_tag.name.value());
EXPECT_FALSE(simple_tag.language.is_present());
EXPECT_EQ("und", simple_tag.language.value());
EXPECT_FALSE(simple_tag.is_default.is_present());
EXPECT_EQ(true, simple_tag.is_default.value());
EXPECT_FALSE(simple_tag.string.is_present());
EXPECT_EQ("", simple_tag.string.value());
EXPECT_FALSE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, simple_tag.binary.value());
EXPECT_EQ(static_cast<std::size_t>(0), simple_tag.tags.size());
}
TEST_F(SimpleTagParserTest, DefaultValues) {
SetReaderData({
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x80, // Size = 0.
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x80, // Size = 0.
0x44, 0x84, // ID = 0x4484 (TagDefault).
0x80, // Size = 0.
0x44, 0x87, // ID = 0x4487 (TagString).
0x80, // Size = 0.
0x44, 0x85, // ID = 0x4485 (TagBinary).
0x80, // Size = 0.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_TRUE(simple_tag.name.is_present());
EXPECT_EQ("", simple_tag.name.value());
EXPECT_TRUE(simple_tag.language.is_present());
EXPECT_EQ("und", simple_tag.language.value());
EXPECT_TRUE(simple_tag.is_default.is_present());
EXPECT_EQ(true, simple_tag.is_default.value());
EXPECT_TRUE(simple_tag.string.is_present());
EXPECT_EQ("", simple_tag.string.value());
EXPECT_TRUE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{}, simple_tag.binary.value());
ASSERT_EQ(static_cast<std::size_t>(1), simple_tag.tags.size());
EXPECT_TRUE(simple_tag.tags[0].is_present());
EXPECT_EQ(SimpleTag{}, simple_tag.tags[0].value());
}
TEST_F(SimpleTagParserTest, CustomValues) {
SetReaderData({
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x81, // Size = 1.
0x61, // Body (value = "a").
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x81, // Size = 1.
0x62, // Body (value = "b").
0x44, 0x84, // ID = 0x4484 (TagDefault).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x63, // Body (value = "c").
0x44, 0x85, // ID = 0x4485 (TagBinary).
0x81, // Size = 1.
0x01, // Body.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x99, // Size = 25.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x64, // Body (value = "d").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x8B, // Size = 11.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x65, // Body (value = "e").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x66, // Body (value = "f").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x87, // ID = 0x4487 (TagString).
0x81, // Size = 1.
0x67, // Body (value = "g").
});
ParseAndVerify();
const SimpleTag simple_tag = parser_.value();
EXPECT_TRUE(simple_tag.name.is_present());
EXPECT_EQ("a", simple_tag.name.value());
EXPECT_TRUE(simple_tag.language.is_present());
EXPECT_EQ("b", simple_tag.language.value());
EXPECT_TRUE(simple_tag.is_default.is_present());
EXPECT_EQ(false, simple_tag.is_default.value());
EXPECT_TRUE(simple_tag.string.is_present());
EXPECT_EQ("c", simple_tag.string.value());
EXPECT_TRUE(simple_tag.binary.is_present());
EXPECT_EQ(std::vector<std::uint8_t>{0x01}, simple_tag.binary.value());
SimpleTag expected;
expected.string.Set("d", true);
SimpleTag temp{};
temp.string.Set("e", true);
expected.tags.emplace_back(temp, true);
temp.string.Set("f", true);
expected.tags[0].mutable_value()->tags.emplace_back(temp, true);
temp.string.Set("g", true);
expected.tags.emplace_back(temp, true);
ASSERT_EQ(static_cast<std::size_t>(1), simple_tag.tags.size());
EXPECT_TRUE(simple_tag.tags[0].is_present());
EXPECT_EQ(expected, simple_tag.tags[0].value());
}
TEST_F(SimpleTagParserTest, ExceedMaxRecursionDepth) {
ResetParser(1);
SetReaderData({
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
ParseAndVerify();
SetReaderData({
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x83, // Size = 3.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
ParseAndExpectResult(Status::kExceededRecursionDepthLimit);
}
} // namespace
@@ -0,0 +1,61 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/size_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::ParserTest;
using webm::SizeParser;
using webm::Status;
namespace {
class SizeParserTest : public ParserTest<SizeParser> {};
TEST_F(SizeParserTest, InvalidSize) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementSize);
}
TEST_F(SizeParserTest, EarlyEndOfFile) {
SetReaderData({0x01});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(SizeParserTest, ValidSize) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0), parser_.size());
ResetParser();
SetReaderData({0x01, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x123456789ABCDE), parser_.size());
}
TEST_F(SizeParserTest, UnknownSize) {
SetReaderData({0xFF});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0xFFFFFFFFFFFFFFFF), parser_.size());
ResetParser();
SetReaderData({0x1F, 0xFF, 0xFF, 0xFF});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0xFFFFFFFFFFFFFFFF), parser_.size());
}
TEST_F(SizeParserTest, IncrementalParse) {
SetReaderData({0x11, 0x23, 0x45, 0x67});
IncrementalParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x01234567), parser_.size());
}
} // namespace
@@ -0,0 +1,42 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/skip_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::SkipParser;
using webm::Status;
namespace {
class SkipParserTest : public ElementParserTest<SkipParser> {};
TEST_F(SkipParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(SkipParserTest, Skip) {
ParseAndVerify();
SetReaderData({0x00, 0x01, 0x02, 0x04});
ParseAndVerify();
}
TEST_F(SkipParserTest, IncrementalSkip) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10});
IncrementalParseAndVerify();
}
} // namespace
@@ -0,0 +1,80 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/slices_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Slices;
using webm::SlicesParser;
using webm::TimeSlice;
namespace {
class SlicesParserTest : public ElementParserTest<SlicesParser, Id::kSlices> {};
TEST_F(SlicesParserTest, DefaultParse) {
ParseAndVerify();
const Slices slices = parser_.value();
EXPECT_EQ(static_cast<std::size_t>(0), slices.slices.size());
}
TEST_F(SlicesParserTest, DefaultValues) {
SetReaderData({
0xE8, // ID = 0xE8 (TimeSlice).
0x80, // Size = 0.
});
ParseAndVerify();
const Slices slices = parser_.value();
ASSERT_EQ(static_cast<std::size_t>(1), slices.slices.size());
EXPECT_TRUE(slices.slices[0].is_present());
EXPECT_EQ(TimeSlice{}, slices.slices[0].value());
}
TEST_F(SlicesParserTest, CustomValues) {
SetReaderData({
0xE8, // ID = 0xE8 (TimeSlice).
0x83, // Size = 3.
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xE8, // ID = 0xE8 (TimeSlice).
0x83, // Size = 3.
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Slices slices = parser_.value();
TimeSlice expected;
ASSERT_EQ(static_cast<std::size_t>(2), slices.slices.size());
expected.lace_number.Set(1, true);
EXPECT_TRUE(slices.slices[0].is_present());
EXPECT_EQ(expected, slices.slices[0].value());
expected.lace_number.Set(2, true);
EXPECT_TRUE(slices.slices[1].is_present());
EXPECT_EQ(expected, slices.slices[1].value());
}
} // namespace
@@ -0,0 +1,92 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tag_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::SimpleTag;
using webm::Tag;
using webm::TagParser;
using webm::Targets;
namespace {
class TagParserTest : public ElementParserTest<TagParser, Id::kTag> {};
TEST_F(TagParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnTag(metadata_, Tag{})).Times(1);
ParseAndVerify();
}
TEST_F(TagParserTest, DefaultValues) {
SetReaderData({
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x80, // Size = 0.
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x80, // Size = 0.
});
Tag tag;
tag.targets.Set({}, true);
tag.tags.emplace_back();
tag.tags[0].Set({}, true);
EXPECT_CALL(callback_, OnTag(metadata_, tag)).Times(1);
ParseAndVerify();
}
TEST_F(TagParserTest, CustomValues) {
SetReaderData({
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x45, 0xA3, // ID = 0x45A3 (TagName).
0x81, // Size = 1.
0x61, // Body (value = "a").
0x67, 0xC8, // ID = 0x67C8 (SimpleTag).
0x84, // Size = 4.
0x44, 0x7A, // ID = 0x447A (TagLanguage).
0x81, // Size = 1.
0x62, // Body (value = "b").
});
Tag tag;
Targets targets;
targets.type_value.Set(0, true);
tag.targets.Set(targets, true);
SimpleTag simple_tag;
simple_tag.name.Set("a", true);
tag.tags.emplace_back(simple_tag, true);
simple_tag = {};
simple_tag.language.Set("b", true);
tag.tags.emplace_back(simple_tag, true);
EXPECT_CALL(callback_, OnTag(metadata_, tag)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,61 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tags_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TagsParser;
namespace {
class TagsParserTest : public ElementParserTest<TagsParser, Id::kTags> {};
// TODO(mjbshaw): validate results via Callback.
TEST_F(TagsParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0x73, 0x73, // ID = 0x7373 (Tag).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(TagsParserTest, RepeatedValues) {
SetReaderData({
0x73, 0x73, // ID = 0x7373 (Tag).
0x87, // Size = 7.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x73, 0x73, // ID = 0x7373 (Tag).
0x87, // Size = 7.
0x63, 0xC0, // ID = 0x63C0 (Targets).
0x84, // Size = 4.
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,102 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/targets_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::Targets;
using webm::TargetsParser;
namespace {
class TargetsParserTest
: public ElementParserTest<TargetsParser, Id::kTargets> {};
TEST_F(TargetsParserTest, DefaultParse) {
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_FALSE(targets.type_value.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(50), targets.type_value.value());
EXPECT_FALSE(targets.type.is_present());
EXPECT_EQ("", targets.type.value());
EXPECT_EQ(static_cast<std::size_t>(0), targets.track_uids.size());
}
TEST_F(TargetsParserTest, DefaultValues) {
SetReaderData({
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x80, // Size = 0.
0x63, 0xCA, // ID = 0x63CA (TargetType).
0x80, // Size = 0.
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x80, // Size = 0.
});
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_TRUE(targets.type_value.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(50), targets.type_value.value());
EXPECT_TRUE(targets.type.is_present());
EXPECT_EQ("", targets.type.value());
ASSERT_EQ(static_cast<std::size_t>(1), targets.track_uids.size());
EXPECT_TRUE(targets.track_uids[0].is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), targets.track_uids[0].value());
}
TEST_F(TargetsParserTest, CustomValues) {
SetReaderData({
0x68, 0xCA, // ID = 0x68CA (TargetTypeValue).
0x81, // Size = 1.
0x00, // Body (value = 0).
0x63, 0xCA, // ID = 0x63CA (TargetType).
0x82, // Size = 2.
0x48, 0x69, // Body (value = "Hi").
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x81, // Size = 1.
0x01, // Body (value = 1).
0x63, 0xC5, // ID = 0x63C5 (TagTrackUID).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Targets targets = parser_.value();
EXPECT_TRUE(targets.type_value.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), targets.type_value.value());
EXPECT_TRUE(targets.type.is_present());
EXPECT_EQ("Hi", targets.type.value());
ASSERT_EQ(static_cast<std::size_t>(2), targets.track_uids.size());
EXPECT_TRUE(targets.track_uids[0].is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), targets.track_uids[0].value());
EXPECT_TRUE(targets.track_uids[1].is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), targets.track_uids[1].value());
}
} // namespace
@@ -0,0 +1,63 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/time_slice_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TimeSlice;
using webm::TimeSliceParser;
namespace {
class TimeSliceParserTest
: public ElementParserTest<TimeSliceParser, Id::kTimeSlice> {};
TEST_F(TimeSliceParserTest, DefaultParse) {
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_FALSE(time_slice.lace_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), time_slice.lace_number.value());
}
TEST_F(TimeSliceParserTest, DefaultValues) {
SetReaderData({
0xCC, // ID = 0xCC (LaceNumber).
0x80, // Size = 0.
});
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_TRUE(time_slice.lace_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), time_slice.lace_number.value());
}
TEST_F(TimeSliceParserTest, CustomValues) {
SetReaderData({
0xCC, // ID = 0xCC (LaceNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
});
ParseAndVerify();
const TimeSlice time_slice = parser_.value();
EXPECT_TRUE(time_slice.lace_number.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), time_slice.lace_number.value());
}
} // namespace
@@ -0,0 +1,245 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/track_entry_parser.h"
#include <cstdint>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::Audio;
using webm::ContentEncoding;
using webm::ContentEncodings;
using webm::DisplayUnit;
using webm::ElementParserTest;
using webm::Id;
using webm::TrackEntry;
using webm::TrackEntryParser;
using webm::TrackType;
using webm::Video;
namespace {
class TrackEntryParserTest
: public ElementParserTest<TrackEntryParser, Id::kTrackEntry> {};
TEST_F(TrackEntryParserTest, DefaultParse) {
EXPECT_CALL(callback_, OnTrackEntry(metadata_, TrackEntry{})).Times(1);
ParseAndVerify();
}
TEST_F(TrackEntryParserTest, DefaultValues) {
SetReaderData({
0xD7, // ID = 0xD7 (TrackNumber).
0x20, 0x00, 0x00, // Size = 0.
0x73, 0xC5, // ID = 0x73C5 (TrackUID).
0x20, 0x00, 0x00, // Size = 0.
0x83, // ID = 0x83 (TrackType).
0x20, 0x00, 0x00, // Size = 0.
0xB9, // ID = 0xB9 (FlagEnabled).
0x20, 0x00, 0x00, // Size = 0.
0x88, // ID = 0x88 (FlagDefault).
0x20, 0x00, 0x00, // Size = 0.
0x55, 0xAA, // ID = 0x55AA (FlagForced).
0x20, 0x00, 0x00, // Size = 0.
0x9C, // ID = 0x9C (FlagLacing).
0x20, 0x00, 0x00, // Size = 0.
0x23, 0xE3, 0x83, // ID = 0x23E383 (DefaultDuration).
0x80, // Size = 0.
0x53, 0x6E, // ID = 0x536E (Name).
0x20, 0x00, 0x00, // Size = 0.
0x22, 0xB5, 0x9C, // ID = 0x22B59C (Language).
0x80, // Size = 0.
0x86, // ID = 0x86 (CodecID).
0x20, 0x00, 0x00, // Size = 0.
0x63, 0xA2, // ID = 0x63A2 (CodecPrivate).
0x20, 0x00, 0x00, // Size = 0.
0x25, 0x86, 0x88, // ID = 0x258688 (CodecName).
0x80, // Size = 0.
0x56, 0xAA, // ID = 0x56AA (CodecDelay).
0x20, 0x00, 0x00, // Size = 0.
0x56, 0xBB, // ID = 0x56BB (SeekPreRoll).
0x20, 0x00, 0x00, // Size = 0.
0xE0, // ID = 0xE0 (Video).
0x20, 0x00, 0x00, // Size = 0.
0xE1, // ID = 0xE1 (Audio).
0x20, 0x00, 0x00, // Size = 0.
0x6D, 0x80, // ID = 0x6D80 (ContentEncodings).
0x20, 0x00, 0x00, // Size = 0.
});
TrackEntry track_entry;
track_entry.track_number.Set(0, true);
track_entry.track_uid.Set(0, true);
track_entry.track_type.Set(TrackType{}, true);
track_entry.is_enabled.Set(true, true);
track_entry.is_default.Set(true, true);
track_entry.is_forced.Set(false, true);
track_entry.uses_lacing.Set(true, true);
track_entry.default_duration.Set(0, true);
track_entry.name.Set("", true);
track_entry.language.Set("eng", true);
track_entry.codec_id.Set("", true);
track_entry.codec_private.Set(std::vector<std::uint8_t>{}, true);
track_entry.codec_name.Set("", true);
track_entry.codec_delay.Set(0, true);
track_entry.seek_pre_roll.Set(0, true);
track_entry.video.Set(Video{}, true);
track_entry.audio.Set(Audio{}, true);
track_entry.content_encodings.Set(ContentEncodings{}, true);
EXPECT_CALL(callback_, OnTrackEntry(metadata_, track_entry)).Times(1);
ParseAndVerify();
}
TEST_F(TrackEntryParserTest, CustomValues) {
SetReaderData({
0xD7, // ID = 0xD7 (TrackNumber).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x73, 0xC5, // ID = 0x73C5 (TrackUID).
0x20, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x83, // ID = 0x83 (TrackType).
0x20, 0x00, 0x01, // Size = 1.
0x03, // Body (value = complex).
0xB9, // ID = 0xB9 (FlagEnabled).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x88, // ID = 0x88 (FlagDefault).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x55, 0xAA, // ID = 0x55AA (FlagForced).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x9C, // ID = 0x9C (FlagLacing).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body (value = 0).
0x23, 0xE3, 0x83, // ID = 0x23E383 (DefaultDuration).
0x81, // Size = 1.
0x04, // Body (value = 4).
0x53, 0x6E, // ID = 0x536E (Name).
0x20, 0x00, 0x01, // Size = 1.
0x41, // Body (value = "A").
0x22, 0xB5, 0x9C, // ID = 0x22B59C (Language).
0x81, // Size = 1.
0x42, // Body (value = "B").
0x86, // ID = 0x86 (CodecID).
0x20, 0x00, 0x01, // Size = 1.
0x43, // Body (value = "C").
0x63, 0xA2, // ID = 0x63A2 (CodecPrivate).
0x20, 0x00, 0x01, // Size = 1.
0x00, // Body.
0x25, 0x86, 0x88, // ID = 0x258688 (CodecName).
0x81, // Size = 1.
0x44, // Body (value = "D").
0x56, 0xAA, // ID = 0x56AA (CodecDelay).
0x20, 0x00, 0x01, // Size = 1.
0x05, // Body (value = 5).
0x56, 0xBB, // ID = 0x56BB (SeekPreRoll).
0x20, 0x00, 0x01, // Size = 1.
0x06, // Body (value = 6).
0xE0, // ID = 0xE0 (Video).
0x20, 0x00, 0x06, // Size = 6.
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x20, 0x00, 0x01, // Size = 1.
0x03, // Body (value = display aspect ratio).
0xE1, // ID = 0xE1 (Audio).
0x20, 0x00, 0x05, // Size = 5.
0x9F, // ID = 0x9F (Channels).
0x20, 0x00, 0x01, // Size = 1.
0x08, // Body (value = 8).
0x6D, 0x80, // ID = 0x6D80 (ContentEncodings).
0x20, 0x00, 0x0B, // Size = 11.
0x62, 0x40, // ID = 0x6240 (ContentEncoding).
0x20, 0x00, 0x06, // Size = 6.
0x50, 0x31, // ID = 0x5031 (ContentEncodingOrder).
0x20, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
});
TrackEntry track_entry;
track_entry.track_number.Set(1, true);
track_entry.track_uid.Set(2, true);
track_entry.track_type.Set(TrackType::kComplex, true);
track_entry.is_enabled.Set(false, true);
track_entry.is_default.Set(false, true);
track_entry.is_forced.Set(true, true);
track_entry.uses_lacing.Set(false, true);
track_entry.default_duration.Set(4, true);
track_entry.name.Set("A", true);
track_entry.language.Set("B", true);
track_entry.codec_id.Set("C", true);
track_entry.codec_private.Set(std::vector<std::uint8_t>{0x00}, true);
track_entry.codec_name.Set("D", true);
track_entry.codec_delay.Set(5, true);
track_entry.seek_pre_roll.Set(6, true);
Video expected_video;
expected_video.display_unit.Set(DisplayUnit::kDisplayAspectRatio, true);
track_entry.video.Set(expected_video, true);
Audio expected_audio;
expected_audio.channels.Set(8, true);
track_entry.audio.Set(expected_audio, true);
ContentEncoding expected_encoding;
expected_encoding.order.Set(1, true);
ContentEncodings expected_encodings;
expected_encodings.encodings.emplace_back(expected_encoding, true);
track_entry.content_encodings.Set(expected_encodings, true);
EXPECT_CALL(callback_, OnTrackEntry(metadata_, track_entry)).Times(1);
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,55 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/tracks_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/buffer_reader.h"
using webm::ElementParserTest;
using webm::Id;
using webm::TracksParser;
namespace {
class TracksParserTest : public ElementParserTest<TracksParser, Id::kTracks> {};
// TODO(mjbshaw): validate results via Callback.
TEST_F(TracksParserTest, DefaultValues) {
ParseAndVerify();
SetReaderData({
0xAE, // ID = 0xAE (TrackEntry).
0x80, // Size = 0.
});
ParseAndVerify();
}
TEST_F(TracksParserTest, RepeatedValues) {
SetReaderData({
0xAE, // ID = 0xAE (TrackEntry).
0x83, // Size = 3.
0xD7, // ID = 0xD7 (TrackNumber).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xAE, // ID = 0xAE (TrackEntry).
0x83, // Size = 3.
0xD7, // ID = 0xD7 (TrackNumber).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
}
} // namespace
@@ -0,0 +1,57 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/unknown_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/status.h"
using testing::NotNull;
using webm::ElementParserTest;
using webm::kUnknownElementSize;
using webm::Status;
using webm::UnknownParser;
namespace {
class UnknownParserTest : public ElementParserTest<UnknownParser> {};
TEST_F(UnknownParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kIndefiniteUnknownElement);
}
TEST_F(UnknownParserTest, Empty) {
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(1);
ParseAndVerify();
}
TEST_F(UnknownParserTest, Valid) {
SetReaderData({0x00, 0x01, 0x02, 0x04});
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(1);
ParseAndVerify();
}
TEST_F(UnknownParserTest, IncrementalSkip) {
SetReaderData({0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10});
EXPECT_CALL(callback_, OnUnknownElement(metadata_, NotNull(), NotNull()))
.Times(8);
IncrementalParseAndVerify();
}
} // namespace
@@ -0,0 +1,53 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/var_int_parser.h"
#include "gtest/gtest.h"
#include "test_utils/parser_test.h"
#include "webm/status.h"
using webm::ParserTest;
using webm::Status;
using webm::VarIntParser;
namespace {
class VarIntParserTest : public ParserTest<VarIntParser> {};
TEST_F(VarIntParserTest, NoMarkerBit) {
SetReaderData({0x00});
ParseAndExpectResult(Status::kInvalidElementValue);
}
TEST_F(VarIntParserTest, EarlyEndOfFile) {
SetReaderData({0x01});
ParseAndExpectResult(Status::kEndOfFile);
}
TEST_F(VarIntParserTest, ValidValue) {
SetReaderData({0x80});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0), parser_.value());
EXPECT_EQ(1, parser_.encoded_length());
ResetParser();
SetReaderData({0x01, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE});
ParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x123456789ABCDE), parser_.value());
EXPECT_EQ(8, parser_.encoded_length());
}
TEST_F(VarIntParserTest, IncrementalParse) {
SetReaderData({0x11, 0x23, 0x45, 0x67});
IncrementalParseAndVerify();
EXPECT_EQ(static_cast<std::uint64_t>(0x01234567), parser_.value());
EXPECT_EQ(4, parser_.encoded_length());
}
} // namespace
@@ -0,0 +1,446 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/video_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
using webm::AspectRatioType;
using webm::Colour;
using webm::DisplayUnit;
using webm::ElementParserTest;
using webm::FlagInterlaced;
using webm::Id;
using webm::Projection;
using webm::ProjectionType;
using webm::StereoMode;
using webm::Video;
using webm::VideoParser;
namespace {
class VideoParserTest : public ElementParserTest<VideoParser, Id::kVideo> {};
TEST_F(VideoParserTest, DefaultParse) {
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.alpha_mode.value());
EXPECT_FALSE(video.pixel_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_width.value());
EXPECT_FALSE(video.pixel_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_right.value());
EXPECT_FALSE(video.display_width.is_present());
EXPECT_EQ(video.pixel_width.value(), video.display_width.value());
EXPECT_FALSE(video.display_height.is_present());
EXPECT_EQ(video.pixel_height.value(), video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
EXPECT_FALSE(video.projection.is_present());
EXPECT_EQ(Projection{}, video.projection.value());
}
TEST_F(VideoParserTest, DefaultValues) {
SetReaderData({
0x9A, // ID = 0x9A (FlagInterlaced).
0x20, 0x00, 0x00, // Size = 0.
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x20, 0x00, 0x00, // Size = 0.
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x20, 0x00, 0x00, // Size = 0.
0xB0, // ID = 0xB0 (PixelWidth).
0x20, 0x00, 0x00, // Size = 0.
0xBA, // ID = 0xBA (PixelHeight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xAA, // ID = 0x54AA (PixelCropBottom).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xBB, // ID = 0x54BB (PixelCropTop).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xCC, // ID = 0x54CC (PixelCropLeft).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xDD, // ID = 0x54DD (PixelCropRight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x20, 0x00, 0x00, // Size = 0.
0x54, 0xB3, // ID = 0x54B3 (AspectRatioType).
0x20, 0x00, 0x00, // Size = 0.
0x23, 0x83, 0xE3, // ID = 0x2383E3 (FrameRate).
0x80, // Size = 0.
0x55, 0xB0, // ID = 0x55B0 (Colour).
0x20, 0x00, 0x00, // Size = 0.
0x76, 0x70, // ID = 0x7670 (Projection).
0x20, 0x00, 0x00, // Size = 0.
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_TRUE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_TRUE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_TRUE(video.alpha_mode.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_height.value());
EXPECT_TRUE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_bottom.value());
EXPECT_TRUE(video.pixel_crop_top.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_top.value());
EXPECT_TRUE(video.pixel_crop_left.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_left.value());
EXPECT_TRUE(video.pixel_crop_right.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(video.pixel_width.value(), video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(video.pixel_height.value(), video.display_height.value());
EXPECT_TRUE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_TRUE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_TRUE(video.frame_rate.is_present());
EXPECT_EQ(0, video.frame_rate.value());
EXPECT_TRUE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
EXPECT_TRUE(video.projection.is_present());
EXPECT_EQ(Projection{}, video.projection.value());
}
TEST_F(VideoParserTest, CustomValues) {
SetReaderData({
0x9A, // ID = 0x9A (FlagInterlaced).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = progressive).
0x53, 0xB8, // ID = 0x53B8 (StereoMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = top-bottom (right eye first)).
0x53, 0xC0, // ID = 0x53C0 (AlphaMode).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x03, // Body (value = 3).
0xB0, // ID = 0xB0 (PixelWidth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x04, // Body (value = 4).
0xBA, // ID = 0xBA (PixelHeight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x05, // Body (value = 5).
0x54, 0xAA, // ID = 0x54AA (PixelCropBottom).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x06, // Body (value = 6).
0x54, 0xBB, // ID = 0x54BB (PixelCropTop).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x07, // Body (value = 7).
0x54, 0xCC, // ID = 0x54CC (PixelCropLeft).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x08, // Body (value = 8).
0x54, 0xDD, // ID = 0x54DD (PixelCropRight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x09, // Body (value = 9).
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x0A, // Body (value = 10).
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x0B, // Body (value = 11).
0x54, 0xB2, // ID = 0x54B2 (DisplayUnit).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = inches).
0x54, 0xB3, // ID = 0x54B3 (AspectRatioType).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = keep aspect ratio).
0x23, 0x83, 0xE3, // ID = 0x2383E3 (FrameRate).
0x84, // Size = 4.
0x40, 0x0F, 0x1B, 0xBD, // Body (value = 2.2360680103302001953125f).
0x55, 0xB0, // ID = 0x55B0 (Colour).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x55, 0xB2, // ID = 0x55B2 (BitsPerChannel).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x01, // Body (value = 1).
0x76, 0x70, // ID = 0x7670 (Projection).
0x10, 0x00, 0x00, 0x07, // Size = 7.
0x76, 0x71, // ID = 0x7671 (ProjectionType).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = cube map).
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_TRUE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kProgressive, video.interlaced.value());
EXPECT_TRUE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kTopBottomRightFirst, video.stereo_mode.value());
EXPECT_TRUE(video.alpha_mode.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(3), video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(4), video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(5), video.pixel_height.value());
EXPECT_TRUE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(6), video.pixel_crop_bottom.value());
EXPECT_TRUE(video.pixel_crop_top.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(7), video.pixel_crop_top.value());
EXPECT_TRUE(video.pixel_crop_left.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(8), video.pixel_crop_left.value());
EXPECT_TRUE(video.pixel_crop_right.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(9), video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(10), video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(11), video.display_height.value());
EXPECT_TRUE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kInches, video.display_unit.value());
EXPECT_TRUE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kKeep, video.aspect_ratio_type.value());
EXPECT_TRUE(video.frame_rate.is_present());
EXPECT_EQ(2.2360680103302001953125, video.frame_rate.value());
EXPECT_TRUE(video.colour.is_present());
EXPECT_TRUE(video.colour.value().bits_per_channel.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1),
video.colour.value().bits_per_channel.value());
EXPECT_TRUE(video.projection.is_present());
EXPECT_TRUE(video.projection.value().type.is_present());
EXPECT_EQ(ProjectionType::kCubeMap, video.projection.value().type.value());
}
TEST_F(VideoParserTest, AbsentDisplaySize) {
SetReaderData({
0xB0, // ID = 0xB0 (PixelWidth).
0x81, // Size = 1.
0x01, // Body (value = 1).
0xBA, // ID = 0xBA (PixelHeight).
0x81, // Size = 1.
0x02, // Body (value = 2).
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_right.value());
EXPECT_FALSE(video.display_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), video.display_width.value());
EXPECT_FALSE(video.display_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
TEST_F(VideoParserTest, DefaultDisplaySize) {
SetReaderData({
0xB0, // ID = 0xB0 (PixelWidth).
0x40, 0x01, // Size = 1.
0x01, // Body (value = 1).
0xBA, // ID = 0xBA (PixelHeight).
0x40, 0x01, // Size = 1.
0x02, // Body (value = 2).
0x54, 0xB0, // ID = 0x54B0 (DisplayWidth).
0x40, 0x00, // Size = 0.
0x54, 0xBA, // ID = 0x54BA (DisplayHeight).
0x40, 0x00, // Size = 0.
});
ParseAndVerify();
const Video video = parser_.value();
EXPECT_FALSE(video.interlaced.is_present());
EXPECT_EQ(FlagInterlaced::kUnspecified, video.interlaced.value());
EXPECT_FALSE(video.stereo_mode.is_present());
EXPECT_EQ(StereoMode::kMono, video.stereo_mode.value());
EXPECT_FALSE(video.alpha_mode.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.alpha_mode.value());
EXPECT_TRUE(video.pixel_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), video.pixel_width.value());
EXPECT_TRUE(video.pixel_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), video.pixel_height.value());
EXPECT_FALSE(video.pixel_crop_bottom.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_bottom.value());
EXPECT_FALSE(video.pixel_crop_top.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_top.value());
EXPECT_FALSE(video.pixel_crop_left.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_left.value());
EXPECT_FALSE(video.pixel_crop_right.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.pixel_crop_right.value());
EXPECT_TRUE(video.display_width.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(1), video.display_width.value());
EXPECT_TRUE(video.display_height.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(2), video.display_height.value());
EXPECT_FALSE(video.display_unit.is_present());
EXPECT_EQ(DisplayUnit::kPixels, video.display_unit.value());
EXPECT_FALSE(video.aspect_ratio_type.is_present());
EXPECT_EQ(AspectRatioType::kFreeResizing, video.aspect_ratio_type.value());
EXPECT_FALSE(video.frame_rate.is_present());
EXPECT_EQ(static_cast<std::uint64_t>(0), video.frame_rate.value());
EXPECT_FALSE(video.colour.is_present());
EXPECT_EQ(Colour{}, video.colour.value());
}
} // namespace
@@ -0,0 +1,74 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/virtual_block_parser.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/id.h"
#include "webm/status.h"
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Status;
using webm::VirtualBlock;
using webm::VirtualBlockParser;
namespace {
class VirtualBlockParserTest
: public ElementParserTest<VirtualBlockParser, Id::kBlockVirtual> {};
TEST_F(VirtualBlockParserTest, InvalidSize) {
TestInit(3, Status::kInvalidElementSize);
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(VirtualBlockParserTest, InvalidBlock) {
SetReaderData({
0x40, 0x01, // Track number = 1.
0x00, 0x00, // Timecode = 0.
0x00, // Flags.
});
// Initialize with 1 byte short.
ParseAndExpectResult(Status::kInvalidElementValue, reader_.size() - 1);
}
TEST_F(VirtualBlockParserTest, ValidBlock) {
SetReaderData({
0x81, // Track number = 1.
0x12, 0x34, // Timecode = 4660.
0x00, // Flags.
});
ParseAndVerify();
const VirtualBlock virtual_block = parser_.value();
EXPECT_EQ(static_cast<std::uint64_t>(1), virtual_block.track_number);
EXPECT_EQ(0x1234, virtual_block.timecode);
}
TEST_F(VirtualBlockParserTest, IncrementalParse) {
SetReaderData({
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // Track number = 2.
0xFF, 0xFE, // Timecode = -2.
0x00, // Flags.
});
IncrementalParseAndVerify();
const VirtualBlock virtual_block = parser_.value();
EXPECT_EQ(static_cast<std::uint64_t>(2), virtual_block.track_number);
EXPECT_EQ(-2, virtual_block.timecode);
}
} // namespace
@@ -0,0 +1,56 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "src/void_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/element_parser_test.h"
#include "webm/element.h"
#include "webm/id.h"
#include "webm/status.h"
using testing::NotNull;
using webm::ElementParserTest;
using webm::Id;
using webm::kUnknownElementSize;
using webm::Status;
using webm::VoidParser;
namespace {
class VoidParserTest : public ElementParserTest<VoidParser, Id::kVoid> {};
TEST_F(VoidParserTest, InvalidSize) {
TestInit(kUnknownElementSize, Status::kInvalidElementSize);
}
TEST_F(VoidParserTest, Empty) {
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(1);
ParseAndVerify();
}
TEST_F(VoidParserTest, Valid) {
SetReaderData({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07});
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(1);
ParseAndVerify();
}
TEST_F(VoidParserTest, IncrementalParse) {
SetReaderData({0x00, 0x01, 0x02, 0x03});
EXPECT_CALL(callback_, OnVoid(metadata_, NotNull(), NotNull())).Times(4);
IncrementalParseAndVerify();
}
} // namespace
@@ -0,0 +1,339 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "webm/webm_parser.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "test_utils/mock_callback.h"
#include "webm/buffer_reader.h"
#include "webm/status.h"
using testing::_;
using testing::DoDefault;
using testing::InSequence;
using testing::NotNull;
using testing::Return;
using webm::BufferReader;
using webm::Ebml;
using webm::ElementMetadata;
using webm::Id;
using webm::Info;
using webm::kUnknownElementPosition;
using webm::kUnknownElementSize;
using webm::kUnknownHeaderSize;
using webm::MockCallback;
using webm::Status;
using webm::WebmParser;
namespace {
class WebmParserTest : public testing::Test {};
TEST_F(WebmParserTest, InvalidId) {
BufferReader reader = {
0x00, // IDs cannot start with 0x00.
};
MockCallback callback;
{
InSequence dummy;
EXPECT_CALL(callback, OnEbml(_, _)).Times(0);
EXPECT_CALL(callback, OnSegmentBegin(_, NotNull())).Times(0);
EXPECT_CALL(callback, OnSegmentEnd(_)).Times(0);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
}
TEST_F(WebmParserTest, InvalidSize) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x00, // Size must have 1+ bits set in the first byte.
};
MockCallback callback;
{
InSequence dummy;
EXPECT_CALL(callback, OnEbml(_, _)).Times(0);
EXPECT_CALL(callback, OnSegmentBegin(_, NotNull())).Times(0);
EXPECT_CALL(callback, OnSegmentEnd(_)).Times(0);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kInvalidElementSize, status.code);
}
TEST_F(WebmParserTest, DefaultParse) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
0x18, 0x53, 0x80, 0x67, // ID = 0x18538067 (Segment).
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kEbml, 5, 0, 0};
const Ebml ebml{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
metadata = {Id::kSegment, 5, 0, 5};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnSegmentBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnSegmentEnd(metadata)).Times(1);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
TEST_F(WebmParserTest, DefaultActionIsRead) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
const ElementMetadata metadata = {Id::kEbml, 5, 0, 0};
const Ebml ebml{};
// This intentionally does not set the action and relies on the parser using
// a default action value of kRead.
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull()))
.WillOnce(Return(Status(Status::kOkCompleted)));
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
TEST_F(WebmParserTest, UnknownElement) {
BufferReader reader = {
0x80, // ID = 0x80.
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {static_cast<Id>(0x80), 2, 0, 0};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnUnknownElement(metadata, NotNull(), NotNull()))
.Times(1);
}
WebmParser parser;
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
}
TEST_F(WebmParserTest, SeekEbml) {
BufferReader reader = {
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x87, // Size = 7.
0x42, 0x86, // ID = 0x4286 (EBMLVersion).
0x10, 0x00, 0x00, 0x01, // Size = 1.
0x02, // Body (value = 2).
};
std::uint64_t num_to_skip = 5; // Skip the starting EBML element metadata.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kEbmlVersion, 6, 1, num_to_skip};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
metadata = {Id::kEbml, kUnknownHeaderSize, kUnknownElementSize,
kUnknownElementPosition};
Ebml ebml{};
ebml.ebml_version.Set(2, true);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SeekSegment) {
BufferReader reader = {
0x18, 0x53, 0x80, 0x67, // ID = 0x18538067 (Segment).
0x85, // Size = 5.
0x15, 0x49, 0xA9, 0x66, // ID = 0x1549A966 (Info).
0x80, // Size = 0.
};
std::uint64_t num_to_skip = 5; // Skip the starting Segment element metadata.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kInfo, 5, 0, num_to_skip};
const Info info{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnInfo(metadata, info)).Times(1);
metadata = {Id::kSegment, kUnknownHeaderSize, kUnknownElementSize,
kUnknownElementPosition};
EXPECT_CALL(callback, OnSegmentEnd(metadata)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SeekVoid) {
BufferReader reader = {
0xEC, // ID = 0xEC (Void).
0x81, // Size = 0.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
};
std::uint64_t num_to_skip = 2; // Skip the first Void element.
std::uint64_t num_actually_skipped = 0;
reader.Skip(num_to_skip, &num_actually_skipped);
EXPECT_EQ(num_to_skip, num_actually_skipped);
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, num_to_skip};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnVoid(metadata, &reader, NotNull())).Times(1);
metadata = {Id::kEbml, 5, 0, 5};
const Ebml ebml{};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, ebml)).Times(1);
}
WebmParser parser;
parser.DidSeek();
Status status = parser.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, SwapAfterFailedParse) {
BufferReader reader = {
0x00, // Invalid ID.
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
};
MockCallback expect_nothing;
EXPECT_CALL(expect_nothing, OnElementBegin(_, _)).Times(0);
MockCallback expect_void;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, 1};
EXPECT_CALL(expect_void, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(expect_void, OnVoid(metadata, &reader, NotNull())).Times(1);
}
WebmParser parser1;
Status status = parser1.Feed(&expect_nothing, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), reader.Position());
// After swapping, the parser should retain its failed state and not consume
// more data.
WebmParser parser2;
parser2.Swap(&parser1);
status = parser2.Feed(&expect_nothing, &reader);
EXPECT_EQ(Status::kInvalidElementId, status.code);
EXPECT_EQ(static_cast<std::uint64_t>(1), reader.Position());
// parser1 should be a fresh/new parser after the swap, so parsing should
// succeed.
status = parser1.Feed(&expect_void, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
TEST_F(WebmParserTest, Swap) {
BufferReader reader = {
0xEC, // ID = 0xEC (Void).
0x81, // Size = 1.
0x00, // Body.
0x1A, 0x45, 0xDF, 0xA3, // ID = 0x1A45DFA3 (EBML).
0x80, // Size = 0.
};
MockCallback callback;
{
InSequence dummy;
ElementMetadata metadata = {Id::kVoid, 2, 1, 0};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnVoid(metadata, &reader, NotNull()))
.WillOnce(Return(Status(Status::kOkPartial)))
.WillOnce(DoDefault());
metadata = {Id::kEbml, 5, 0, 3};
EXPECT_CALL(callback, OnElementBegin(metadata, NotNull())).Times(1);
EXPECT_CALL(callback, OnEbml(metadata, Ebml{})).Times(1);
}
WebmParser parser1;
Status status = parser1.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkPartial, status.code);
WebmParser parser2;
swap(parser1, parser2);
status = parser2.Feed(&callback, &reader);
EXPECT_EQ(Status::kOkCompleted, status.code);
EXPECT_EQ(reader.size(), reader.Position());
}
} // namespace
@@ -0,0 +1,13 @@
// Copyright (c) 2016 The WebM project authors. All Rights Reserved.
//
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include "gtest/gtest.h"
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}