2015-07-22 06:57:21 +00:00
|
|
|
// Copyright 2015 Google Inc. All rights reserved.
|
|
|
|
//
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file or at
|
|
|
|
// https://developers.google.com/open-source/licenses/bsd
|
|
|
|
|
|
|
|
#include <gmock/gmock.h>
|
2017-12-14 01:00:11 +00:00
|
|
|
#include <google/protobuf/util/message_differencer.h>
|
2015-07-22 06:57:21 +00:00
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
|
|
|
#include "packager/base/files/file_path.h"
|
2015-07-22 23:40:45 +00:00
|
|
|
#include "packager/base/files/file_util.h"
|
2015-07-22 06:57:21 +00:00
|
|
|
#include "packager/mpd/base/dash_iop_mpd_notifier.h"
|
|
|
|
#include "packager/mpd/base/mock_mpd_builder.h"
|
|
|
|
#include "packager/mpd/base/mpd_builder.h"
|
|
|
|
#include "packager/mpd/test/mpd_builder_test_helper.h"
|
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
namespace shaka {
|
2015-07-22 06:57:21 +00:00
|
|
|
|
|
|
|
using ::testing::_;
|
2017-12-14 01:00:11 +00:00
|
|
|
using ::testing::AnyOf;
|
2015-07-22 06:57:21 +00:00
|
|
|
using ::testing::Eq;
|
|
|
|
using ::testing::Return;
|
2015-09-22 23:17:22 +00:00
|
|
|
using ::testing::StrEq;
|
2015-07-22 06:57:21 +00:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
const uint32_t kDefaultAdaptationSetId = 0u;
|
|
|
|
const uint32_t kDefaultRepresentationId = 1u;
|
2017-12-14 01:00:11 +00:00
|
|
|
const bool kContentProtectionInAdaptationSet = true;
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
MATCHER_P(EqualsProto, message, "") {
|
|
|
|
return ::google::protobuf::util::MessageDifferencer::Equals(arg, message);
|
2015-07-22 06:57:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
// TODO(rkuroiwa): This is almost exactly the same as SimpleMpdNotifierTest but
|
|
|
|
// replaced all SimpleMpd with DashIopMpd,
|
|
|
|
// use typed tests
|
|
|
|
// (https://code.google.com/p/googletest/wiki/AdvancedGuide#Typed_Tests);
|
|
|
|
// also because SimpleMpdNotifier and DashIopMpdNotifier have common behavior
|
|
|
|
// for most of the public functions.
|
2016-12-21 23:28:56 +00:00
|
|
|
class DashIopMpdNotifierTest : public ::testing::Test {
|
2015-07-22 06:57:21 +00:00
|
|
|
protected:
|
|
|
|
DashIopMpdNotifierTest()
|
2017-12-14 01:00:11 +00:00
|
|
|
: default_mock_period_(new MockPeriod),
|
|
|
|
default_mock_adaptation_set_(
|
2015-07-22 06:57:21 +00:00
|
|
|
new MockAdaptationSet(kDefaultAdaptationSetId)),
|
|
|
|
default_mock_representation_(
|
|
|
|
new MockRepresentation(kDefaultRepresentationId)) {}
|
|
|
|
|
2015-07-22 23:40:45 +00:00
|
|
|
void SetUp() override {
|
2015-07-22 06:57:21 +00:00
|
|
|
ASSERT_TRUE(base::CreateTemporaryFile(&temp_file_path_));
|
2017-07-27 18:49:50 +00:00
|
|
|
empty_mpd_option_.mpd_params.mpd_output = temp_file_path_.AsUTF8Unsafe();
|
2017-12-14 01:00:11 +00:00
|
|
|
|
|
|
|
// Three valid media info. The actual data does not matter.
|
|
|
|
const char kValidMediaInfo[] =
|
|
|
|
"video_info {\n"
|
|
|
|
" codec: 'avc1'\n"
|
|
|
|
" width: 1280\n"
|
|
|
|
" height: 720\n"
|
|
|
|
" time_scale: 10\n"
|
|
|
|
" frame_duration: 10\n"
|
|
|
|
" pixel_width: 1\n"
|
|
|
|
" pixel_height: 1\n"
|
|
|
|
"}\n"
|
|
|
|
"container_type: 1\n";
|
|
|
|
valid_media_info1_ = ConvertToMediaInfo(kValidMediaInfo);
|
|
|
|
valid_media_info2_ = valid_media_info1_;
|
|
|
|
valid_media_info2_.mutable_video_info()->set_width(960);
|
|
|
|
valid_media_info3_ = valid_media_info1_;
|
|
|
|
valid_media_info3_.mutable_video_info()->set_width(480);
|
2015-07-22 06:57:21 +00:00
|
|
|
}
|
|
|
|
|
2015-07-22 23:40:45 +00:00
|
|
|
void TearDown() override {
|
2015-07-22 06:57:21 +00:00
|
|
|
base::DeleteFile(temp_file_path_, false /* non recursive, just 1 file */);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetMpdBuilder(DashIopMpdNotifier* notifier,
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<MpdBuilder> mpd_builder) {
|
|
|
|
notifier->SetMpdBuilderForTesting(std::move(mpd_builder));
|
2015-07-22 06:57:21 +00:00
|
|
|
}
|
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
protected:
|
2017-07-27 18:49:50 +00:00
|
|
|
// Empty mpd options except with output path specified, so that
|
2015-07-22 06:57:21 +00:00
|
|
|
// WriteMpdToFile() doesn't crash.
|
2017-07-27 18:49:50 +00:00
|
|
|
MpdOptions empty_mpd_option_;
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2015-10-29 20:58:36 +00:00
|
|
|
// Default mocks that can be used for the tests.
|
|
|
|
// IOW, if a test only requires one instance of
|
2017-12-14 01:00:11 +00:00
|
|
|
// Mock{Period,AdaptationSet,Representation}, these can be used.
|
|
|
|
std::unique_ptr<MockPeriod> default_mock_period_;
|
2016-08-17 17:41:40 +00:00
|
|
|
std::unique_ptr<MockAdaptationSet> default_mock_adaptation_set_;
|
|
|
|
std::unique_ptr<MockRepresentation> default_mock_representation_;
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
// Three valid media info. The actual content does not matter.
|
|
|
|
MediaInfo valid_media_info1_;
|
|
|
|
MediaInfo valid_media_info2_;
|
|
|
|
MediaInfo valid_media_info3_;
|
|
|
|
|
2015-07-22 06:57:21 +00:00
|
|
|
private:
|
|
|
|
base::FilePath temp_file_path_;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Verify that basic VOD NotifyNewContainer() operation works.
|
|
|
|
// No encrypted contents.
|
2016-12-21 23:28:56 +00:00
|
|
|
TEST_F(DashIopMpdNotifierTest, NotifyNewContainer) {
|
2017-07-27 18:49:50 +00:00
|
|
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2016-12-21 23:28:56 +00:00
|
|
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
|
|
.WillOnce(Return(default_mock_period_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_period_,
|
|
|
|
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_),
|
|
|
|
Eq(kContentProtectionInAdaptationSet)))
|
2015-10-29 20:58:36 +00:00
|
|
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
|
|
.WillOnce(Return(default_mock_representation_.get()));
|
|
|
|
|
|
|
|
// This is for the Flush() below but adding expectation here because the next
|
2016-08-17 17:41:40 +00:00
|
|
|
// std::move(lines) the pointer.
|
2015-10-29 20:58:36 +00:00
|
|
|
EXPECT_CALL(*mock_mpd_builder, ToString(_)).WillOnce(Return(true));
|
|
|
|
|
|
|
|
uint32_t unused_container_id;
|
2016-08-17 17:41:40 +00:00
|
|
|
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_TRUE(
|
|
|
|
notifier.NotifyNewContainer(valid_media_info1_, &unused_container_id));
|
2015-10-29 20:58:36 +00:00
|
|
|
EXPECT_TRUE(notifier.Flush());
|
|
|
|
}
|
|
|
|
|
2015-07-22 06:57:21 +00:00
|
|
|
// AddContentProtection() should not work and should always return false.
|
2016-12-21 23:28:56 +00:00
|
|
|
TEST_F(DashIopMpdNotifierTest, AddContentProtection) {
|
2017-07-27 18:49:50 +00:00
|
|
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2016-12-21 23:28:56 +00:00
|
|
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
2015-07-22 06:57:21 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
|
|
.WillOnce(Return(default_mock_period_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
2015-07-22 06:57:21 +00:00
|
|
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
|
|
.WillOnce(Return(default_mock_representation_.get()));
|
|
|
|
|
|
|
|
uint32_t container_id;
|
2016-08-17 17:41:40 +00:00
|
|
|
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
2015-07-22 06:57:21 +00:00
|
|
|
|
|
|
|
ContentProtectionElement empty_content_protection_element;
|
|
|
|
EXPECT_FALSE(notifier.AddContentProtectionElement(
|
|
|
|
container_id, empty_content_protection_element));
|
|
|
|
}
|
|
|
|
|
2016-12-21 23:28:56 +00:00
|
|
|
TEST_F(DashIopMpdNotifierTest, UpdateEncryption) {
|
2017-07-27 18:49:50 +00:00
|
|
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
2015-08-26 20:25:29 +00:00
|
|
|
|
2016-12-21 23:28:56 +00:00
|
|
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
2015-08-26 20:25:29 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
|
|
.WillOnce(Return(default_mock_period_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_period_, GetOrCreateAdaptationSet(_, _))
|
2015-08-26 20:25:29 +00:00
|
|
|
.WillOnce(Return(default_mock_adaptation_set_.get()));
|
|
|
|
EXPECT_CALL(*default_mock_adaptation_set_, AddRepresentation(_))
|
|
|
|
.WillOnce(Return(default_mock_representation_.get()));
|
|
|
|
|
|
|
|
uint32_t container_id;
|
2016-08-17 17:41:40 +00:00
|
|
|
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
2015-08-26 20:25:29 +00:00
|
|
|
|
|
|
|
::testing::Mock::VerifyAndClearExpectations(
|
|
|
|
default_mock_adaptation_set_.get());
|
|
|
|
|
|
|
|
const uint8_t kBogusNewPssh[] = {// "psshsomethingelse" as uint8 array.
|
|
|
|
0x70, 0x73, 0x73, 0x68, 0x73, 0x6f,
|
|
|
|
0x6d, 0x65, 0x74, 0x68, 0x69, 0x6e,
|
|
|
|
0x67, 0x65, 0x6c, 0x73, 0x65};
|
|
|
|
const std::vector<uint8_t> kBogusNewPsshVector(
|
|
|
|
kBogusNewPssh, kBogusNewPssh + arraysize(kBogusNewPssh));
|
|
|
|
const char kBogusNewPsshInBase64[] = "cHNzaHNvbWV0aGluZ2Vsc2U=";
|
|
|
|
|
|
|
|
EXPECT_CALL(*default_mock_adaptation_set_,
|
2015-09-24 22:03:52 +00:00
|
|
|
UpdateContentProtectionPssh(StrEq("myuuid"),
|
|
|
|
StrEq(kBogusNewPsshInBase64)));
|
2015-08-26 20:25:29 +00:00
|
|
|
EXPECT_TRUE(notifier.NotifyEncryptionUpdate(
|
2015-09-24 22:03:52 +00:00
|
|
|
container_id, "myuuid", std::vector<uint8_t>(), kBogusNewPsshVector));
|
2015-08-26 20:25:29 +00:00
|
|
|
}
|
|
|
|
|
2015-11-12 21:40:52 +00:00
|
|
|
// This test is mainly for tsan. Using both the notifier and the MpdBuilder.
|
|
|
|
// Although locks in MpdBuilder have been removed,
|
2016-05-20 21:28:13 +00:00
|
|
|
// https://github.com/google/shaka-packager/issues/45
|
2015-11-12 21:40:52 +00:00
|
|
|
// This issue identified a bug where using SimpleMpdNotifier with multiple
|
|
|
|
// threads causes a deadlock. This tests with DashIopMpdNotifier.
|
|
|
|
TEST_F(DashIopMpdNotifierTest, NotifyNewContainerAndSampleDurationNoMock) {
|
2017-07-27 18:49:50 +00:00
|
|
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
2015-11-12 21:40:52 +00:00
|
|
|
uint32_t container_id;
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_TRUE(notifier.NotifyNewContainer(valid_media_info1_, &container_id));
|
2015-11-12 21:40:52 +00:00
|
|
|
const uint32_t kAnySampleDuration = 1000;
|
|
|
|
EXPECT_TRUE(notifier.NotifySampleDuration(container_id, kAnySampleDuration));
|
|
|
|
EXPECT_TRUE(notifier.Flush());
|
|
|
|
}
|
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
// Test multiple media info with some belongs to the same AdaptationSets.
|
|
|
|
TEST_F(DashIopMpdNotifierTest, MultipleMediaInfo) {
|
2017-07-27 18:49:50 +00:00
|
|
|
DashIopMpdNotifier notifier(empty_mpd_option_);
|
2016-12-21 23:28:56 +00:00
|
|
|
std::unique_ptr<MockMpdBuilder> mock_mpd_builder(new MockMpdBuilder());
|
2016-08-17 17:41:40 +00:00
|
|
|
|
|
|
|
std::unique_ptr<MockAdaptationSet> adaptation_set1(new MockAdaptationSet(1));
|
|
|
|
std::unique_ptr<MockAdaptationSet> adaptation_set2(new MockAdaptationSet(2));
|
|
|
|
|
|
|
|
std::unique_ptr<MockRepresentation> representation1(
|
|
|
|
new MockRepresentation(1));
|
|
|
|
std::unique_ptr<MockRepresentation> representation2(
|
|
|
|
new MockRepresentation(2));
|
|
|
|
std::unique_ptr<MockRepresentation> representation3(
|
|
|
|
new MockRepresentation(3));
|
2016-03-08 19:19:12 +00:00
|
|
|
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_CALL(*mock_mpd_builder, AddPeriod())
|
|
|
|
.WillOnce(Return(default_mock_period_.get()));
|
|
|
|
|
|
|
|
EXPECT_CALL(*default_mock_period_,
|
|
|
|
GetOrCreateAdaptationSet(EqualsProto(valid_media_info1_), _))
|
|
|
|
.WillOnce(Return(adaptation_set1.get()));
|
|
|
|
EXPECT_CALL(*adaptation_set1,
|
|
|
|
AddRepresentation(EqualsProto(valid_media_info1_)))
|
2016-03-08 19:19:12 +00:00
|
|
|
.WillOnce(Return(representation1.get()));
|
2017-12-14 01:00:11 +00:00
|
|
|
// Return the same adaptation set for |valid_media_info2_| and
|
|
|
|
// |valid_media_info3_|. This results in AddRepresentation to be called twice
|
|
|
|
// on |adaptation_set2|.
|
|
|
|
EXPECT_CALL(*default_mock_period_,
|
|
|
|
GetOrCreateAdaptationSet(AnyOf(EqualsProto(valid_media_info2_),
|
|
|
|
EqualsProto(valid_media_info3_)),
|
|
|
|
_))
|
|
|
|
.WillOnce(Return(adaptation_set2.get()))
|
|
|
|
.WillOnce(Return(adaptation_set2.get()));
|
|
|
|
EXPECT_CALL(*adaptation_set2,
|
|
|
|
AddRepresentation(AnyOf(EqualsProto(valid_media_info2_),
|
|
|
|
EqualsProto(valid_media_info3_))))
|
|
|
|
.WillOnce(Return(representation2.get()))
|
|
|
|
.WillOnce(Return(representation3.get()));
|
2016-03-08 19:19:12 +00:00
|
|
|
|
|
|
|
uint32_t unused_container_id;
|
2016-08-17 17:41:40 +00:00
|
|
|
SetMpdBuilder(¬ifier, std::move(mock_mpd_builder));
|
2017-12-14 01:00:11 +00:00
|
|
|
EXPECT_TRUE(
|
|
|
|
notifier.NotifyNewContainer(valid_media_info1_, &unused_container_id));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
notifier.NotifyNewContainer(valid_media_info2_, &unused_container_id));
|
|
|
|
EXPECT_TRUE(
|
|
|
|
notifier.NotifyNewContainer(valid_media_info3_, &unused_container_id));
|
2016-03-08 19:19:12 +00:00
|
|
|
}
|
|
|
|
|
2016-05-20 21:19:33 +00:00
|
|
|
} // namespace shaka
|