From 327537df3649e45bf80fac3c34be3ff2da8809e7 Mon Sep 17 00:00:00 2001 From: KongQun Yang Date: Wed, 13 Dec 2017 22:33:47 -0800 Subject: [PATCH] Clean up mpd_unittest Added gMock matchers for matching xmlNodePtr and its attributes. Clean up mpd_unittests to make it easier to separate adaptation set tests and representation tests. Change-Id: I31816b06e9c76f92d4a82656c659f3b9acae8cb5 --- packager/mpd/base/mpd_builder_unittest.cc | 854 +++++++------------- packager/mpd/base/xml/xml_node_unittest.cc | 124 +-- packager/mpd/test/mpd_builder_test_helper.h | 1 + packager/mpd/test/xml_compare.cc | 37 +- packager/mpd/test/xml_compare.h | 36 + 5 files changed, 385 insertions(+), 667 deletions(-) diff --git a/packager/mpd/base/mpd_builder_unittest.cc b/packager/mpd/base/mpd_builder_unittest.cc index 2e12ed7098..382fdd276f 100644 --- a/packager/mpd/base/mpd_builder_unittest.cc +++ b/packager/mpd/base/mpd_builder_unittest.cc @@ -27,12 +27,14 @@ namespace shaka { using base::FilePath; +using ::testing::Not; namespace { // Any number for {AdaptationSet,Representation} ID. Required to create // either objects. Not checked in test. const uint32_t kAnyRepresentationId = 1; const uint32_t kAnyAdaptationSetId = 1; +const char kNoLanguage[] = ""; const char kSElementTemplate[] = "\n"; const char kSElementTemplateWithoutR[] = @@ -49,49 +51,6 @@ class TestClock : public base::Clock { base::Time time_; }; -// Get 'id' attribute from |node|, convert it to std::string and convert it to a -// number. -void ExpectXmlElementIdEqual(xmlNodePtr node, uint32_t id) { - const char kId[] = "id"; - xml::scoped_xml_ptr id_attribute_xml_str( - xmlGetProp(node, BAD_CAST kId)); - ASSERT_TRUE(id_attribute_xml_str); - - unsigned id_attribute_unsigned = 0; - std::string id_attribute_str = - reinterpret_cast(id_attribute_xml_str.get()); - ASSERT_TRUE(base::StringToUint(id_attribute_str, &id_attribute_unsigned)); - - ASSERT_EQ(id, id_attribute_unsigned); -} - -// Using template to support both AdaptationSet and Representation. -template -void CheckIdEqual(uint32_t expected_id, T* node) { - ASSERT_EQ(expected_id, node->id()); - - // Also check if the XML generated by libxml2 has the correct id attribute. - xml::scoped_xml_ptr node_xml(node->GetXml()); - ASSERT_NO_FATAL_FAILURE(ExpectXmlElementIdEqual(node_xml.get(), expected_id)); -} - -void ExpectAttributeEqString(base::StringPiece attribute, - base::StringPiece expected_value, - xmlNodePtr node) { - xml::scoped_xml_ptr attribute_xml_str( - xmlGetProp(node, BAD_CAST attribute.data())); - ASSERT_TRUE(attribute_xml_str); - EXPECT_STREQ(expected_value.data(), - reinterpret_cast(attribute_xml_str.get())); -} - -// |attribute| should not be set in |node|. -void ExpectAttributeNotSet(base::StringPiece attribute, xmlNodePtr node) { - xml::scoped_xml_ptr attribute_xml_str( - xmlGetProp(node, BAD_CAST attribute.data())); - ASSERT_FALSE(attribute_xml_str); -} - class MockRepresentationStateChangeListener : public RepresentationStateChangeListener { public: @@ -110,6 +69,7 @@ template class MpdBuilderTest : public ::testing::Test { public: MpdBuilderTest() : mpd_(MpdOptions()), representation_() { + mpd_options_.dash_profile = profile; mpd_.mpd_options_.dash_profile = profile; } ~MpdBuilderTest() override {} @@ -152,12 +112,10 @@ class MpdBuilderTest : public ::testing::Test { std::move(state_change_listener))); } - std::unique_ptr CreateAdaptationSet( - uint32_t adaptation_set_id, - const std::string& lang, - base::AtomicSequenceNumber* representation_counter) { + std::unique_ptr CreateAdaptationSet(uint32_t adaptation_set_id, + const std::string& lang) { return std::unique_ptr(new AdaptationSet( - adaptation_set_id, lang, mpd_options_, representation_counter)); + adaptation_set_id, lang, mpd_options_, &representation_counter_)); } // Helper function to return an empty listener for tests that don't need @@ -173,6 +131,7 @@ class MpdBuilderTest : public ::testing::Test { private: MpdOptions mpd_options_; + base::AtomicSequenceNumber representation_counter_; DISALLOW_COPY_AND_ASSIGN(MpdBuilderTest); }; @@ -410,38 +369,20 @@ class TimeShiftBufferDepthTest : public SegmentTemplateTest { }; TEST_F(CommonMpdBuilderTest, AddAdaptationSetSwitching) { - MpdBuilder mpd_builder(MpdOptions{}); - AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); adaptation_set->AddAdaptationSetSwitching(1); adaptation_set->AddAdaptationSetSwitching(2); adaptation_set->AddAdaptationSetSwitching(8); - xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); // The empty contentType is sort of a side effect of being able to generate an // MPD without adding any Representations. const char kExpectedOutput[] = - "\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; - std::string mpd_output; - EXPECT_TRUE(mpd_builder.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput, mpd_output)) - << "Expected " << kExpectedOutput << std::endl - << "Actual: " << mpd_output; + "" + " " + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } // Verify that Representation::Init() works with all "required" fields of @@ -531,18 +472,13 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoReflectedInXml) { "container_type: 1\n"; auto representation = CreateRepresentation( ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - xml::scoped_xml_ptr node_xml(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("codecs", "avc1", node_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("width", "1280", node_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("height", "720", node_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("sar", "1:1", node_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "10/10", node_xml.get())); + ASSERT_TRUE(representation->Init()); + const char kExpectedOutput[] = + ""; + EXPECT_THAT(representation->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInMp4) { @@ -560,10 +496,9 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInMp4) { auto representation = CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - xml::scoped_xml_ptr node_xml(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("codecs", "vp08.00.00.08.01.01.00.00", node_xml.get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), + AttributeEqual("codecs", "vp08.00.00.08.01.01.00.00")); } // Check that vp8 codec string will be updated for backward compatibility @@ -583,10 +518,8 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp8CodecInWebm) { auto representation = CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp8), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - xml::scoped_xml_ptr node_xml(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("codecs", "vp8", node_xml.get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), AttributeEqual("codecs", "vp8")); } // Check that vp9 codec string will be updated for backward compatibility @@ -606,10 +539,8 @@ TEST_F(CommonMpdBuilderTest, CheckVideoInfoVp9CodecInWebm) { auto representation = CreateRepresentation(ConvertToMediaInfo(kTestMediaInfoCodecVp9), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - xml::scoped_xml_ptr node_xml(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("codecs", "vp9", node_xml.get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), AttributeEqual("codecs", "vp9")); } // Make sure RepresentationStateChangeListener::OnNewSegmentForRepresentation() @@ -632,8 +563,7 @@ TEST_F(CommonMpdBuilderTest, const uint64_t kDuration = 98u; std::unique_ptr listener( new MockRepresentationStateChangeListener()); - EXPECT_CALL(*listener, - OnNewSegmentForRepresentation(kStartTime, kDuration)); + EXPECT_CALL(*listener, OnNewSegmentForRepresentation(kStartTime, kDuration)); auto representation = CreateRepresentation(ConvertToMediaInfo(kTestMediaInfo), kAnyRepresentationId, std::move(listener)); @@ -676,7 +606,6 @@ TEST_F(CommonMpdBuilderTest, // Verify that content type is set correctly if video info is present in // MediaInfo. TEST_F(CommonMpdBuilderTest, CheckAdaptationSetVideoContentType) { - base::AtomicSequenceNumber sequence_counter; const char kVideoMediaInfo[] = "video_info {\n" " codec: 'avc1'\n" @@ -689,18 +618,15 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetVideoContentType) { "}\n" "container_type: CONTAINER_MP4\n"; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo)); - - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "contentType", "video", adaptation_set->GetXml().get())); + EXPECT_THAT(adaptation_set->GetXml().get(), + AttributeEqual("contentType", "video")); } // Verify that content type is set correctly if audio info is present in // MediaInfo. TEST_F(CommonMpdBuilderTest, CheckAdaptationSetAudioContentType) { - base::AtomicSequenceNumber sequence_counter; const char kAudioMediaInfo[] = "audio_info {\n" " codec: 'mp4a.40.2'\n" @@ -710,18 +636,15 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetAudioContentType) { "}\n" "container_type: CONTAINER_MP4\n"; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); adaptation_set->AddRepresentation(ConvertToMediaInfo(kAudioMediaInfo)); - - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "contentType", "audio", adaptation_set->GetXml().get())); + EXPECT_THAT(adaptation_set->GetXml().get(), + AttributeEqual("contentType", "audio")); } // Verify that content type is set correctly if text info is present in // MediaInfo. TEST_F(CommonMpdBuilderTest, CheckAdaptationSetTextContentType) { - base::AtomicSequenceNumber sequence_counter; const char kTextMediaInfo[] = "text_info {\n" " format: 'ttml'\n" @@ -729,12 +652,10 @@ TEST_F(CommonMpdBuilderTest, CheckAdaptationSetTextContentType) { "}\n" "container_type: CONTAINER_TEXT\n"; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, "en"); adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); - - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "contentType", "text", adaptation_set->GetXml().get())); + EXPECT_THAT(adaptation_set->GetXml().get(), + AttributeEqual("contentType", "text")); } TEST_F(CommonMpdBuilderTest, TtmlXmlMimeType) { @@ -747,9 +668,9 @@ TEST_F(CommonMpdBuilderTest, TtmlXmlMimeType) { auto representation = CreateRepresentation(ConvertToMediaInfo(kTtmlXmlMediaInfo), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "mimeType", "application/ttml+xml", representation->GetXml().get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), + AttributeEqual("mimeType", "application/ttml+xml")); } TEST_F(CommonMpdBuilderTest, TtmlMp4MimeType) { @@ -762,9 +683,9 @@ TEST_F(CommonMpdBuilderTest, TtmlMp4MimeType) { auto representation = CreateRepresentation(ConvertToMediaInfo(kTtmlMp4MediaInfo), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "mimeType", "application/mp4", representation->GetXml().get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), + AttributeEqual("mimeType", "application/mp4")); } TEST_F(CommonMpdBuilderTest, WebVttMimeType) { @@ -776,96 +697,50 @@ TEST_F(CommonMpdBuilderTest, WebVttMimeType) { auto representation = CreateRepresentation( ConvertToMediaInfo(kWebVttMediaInfo), kAnyRepresentationId, NoListener()); - EXPECT_TRUE(representation->Init()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "mimeType", "text/vtt", representation->GetXml().get())); + ASSERT_TRUE(representation->Init()); + EXPECT_THAT(representation->GetXml().get(), + AttributeEqual("mimeType", "text/vtt")); } // Verify that language passed to the constructor sets the @lang field is set. TEST_F(CommonMpdBuilderTest, CheckLanguageAttributeSet) { - base::AtomicSequenceNumber sequence_counter; - // The media info doesn't really matter as long as it is valid. - const char kTextMediaInfo[] = - "text_info {\n" - " format: 'ttml'\n" - "}\n" - "container_type: CONTAINER_TEXT\n"; - - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "en", &sequence_counter); - adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); - - xml::scoped_xml_ptr node_xml(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("lang", "en", node_xml.get())); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, "en"); + EXPECT_THAT(adaptation_set->GetXml().get(), AttributeEqual("lang", "en")); } // Verify that language tags with subtags can still be converted. TEST_F(CommonMpdBuilderTest, CheckConvertLanguageWithSubtag) { - base::AtomicSequenceNumber sequence_counter; - // The media info doesn't really matter as long as it is valid. - const char kTextMediaInfo[] = - "text_info {\n" - " format: 'ttml'\n" - "}\n" - "container_type: CONTAINER_TEXT\n"; - // "por-BR" is the long tag for Brazillian Portuguese. The short tag // is "pt-BR", which is what should appear in the manifest. - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "por-BR", &sequence_counter); - adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); - - xml::scoped_xml_ptr node_xml(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("lang", "pt-BR", node_xml.get())); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, "por-BR"); + EXPECT_THAT(adaptation_set->GetXml().get(), AttributeEqual("lang", "pt-BR")); } TEST_F(CommonMpdBuilderTest, CheckAdaptationSetId) { - base::AtomicSequenceNumber sequence_counter; const uint32_t kAdaptationSetId = 42; - auto adaptation_set = - CreateAdaptationSet(kAdaptationSetId, "", &sequence_counter); - ASSERT_NO_FATAL_FAILURE(CheckIdEqual(kAdaptationSetId, adaptation_set.get())); + auto adaptation_set = CreateAdaptationSet(kAdaptationSetId, kNoLanguage); + EXPECT_THAT(adaptation_set->GetXml().get(), + AttributeEqual("id", std::to_string(kAdaptationSetId))); } // Verify AdaptationSet::AddRole() works for "main" role. TEST_F(CommonMpdBuilderTest, AdaptationAddRoleElementMain) { - MpdBuilder mpd_builder(MpdOptions{}); - AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); - + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); adaptation_set->AddRole(AdaptationSet::kRoleMain); - xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + // The empty contentType is sort of a side effect of being able to generate an // MPD without adding any Representations. const char kExpectedOutput[] = - "\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; - std::string mpd_output; - EXPECT_TRUE(mpd_builder.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput, mpd_output)) - << "Expected " << kExpectedOutput << std::endl - << "Actual: " << mpd_output; + "\n" + " \n" + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } // Add Role, ContentProtection, and Representation elements. Verify that // ContentProtection -> Role -> Representation are in order. TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) { - MpdBuilder mpd_builder(MpdOptions{}); - AdaptationSet* adaptation_set = mpd_builder.AddAdaptationSet(""); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); adaptation_set->AddRole(AdaptationSet::kRoleMain); ContentProtectionElement any_content_protection; any_content_protection.scheme_id_uri = "any_scheme"; @@ -882,34 +757,18 @@ TEST_F(CommonMpdBuilderTest, CheckContentProtectionRoleRepresentationOrder) { xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); const char kExpectedOutput[] = - "\n" - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; - std::string mpd_output; - EXPECT_TRUE(mpd_builder.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput, mpd_output)) - << "Expected " << kExpectedOutput << std::endl - << "Actual: " << mpd_output; + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } // Verify that if all video Representations in an AdaptationSet have the same @@ -933,19 +792,15 @@ TEST_F(CommonMpdBuilderTest, AdapatationSetFrameRate) { " frame_duration: 3\n" "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo1))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo2))); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo1))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo2))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "10/3", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("maxFrameRate", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("frameRate", "10/3")); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("maxFrameRate"))); } // Verify that if there are videos with different frame rates, the maxFrameRate @@ -970,26 +825,22 @@ TEST_F(CommonMpdBuilderTest, AdapatationSetMaxFrameRate) { " frame_duration: 200\n" "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo30fps))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo15fps))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString("maxFrameRate", "3000/100", - adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), + AttributeEqual("maxFrameRate", "3000/100")); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("frameRate"))); } // Verify that (max)FrameRate can be set by calling // Representation::SetSampleDuration(). TEST_F(CommonMpdBuilderTest, SetAdaptationFrameRateUsingRepresentationSetSampleDuration) { - base::AtomicSequenceNumber sequence_counter; // Note that frame duration is not set in the MediaInfos. It could be there // and should not affect the behavior of the program. // But to make it closer to a real live-profile use case, @@ -1016,8 +867,7 @@ TEST_F(CommonMpdBuilderTest, "}\n" "container_type: 1\n"; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); Representation* representation_480p = adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); Representation* representation_360p = @@ -1026,10 +876,8 @@ TEST_F(CommonMpdBuilderTest, // First, make sure that maxFrameRate nor frameRate are set because // frame durations were not provided in the MediaInfo. xml::scoped_xml_ptr no_frame_rate(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("maxFrameRate", no_frame_rate.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", no_frame_rate.get())); + EXPECT_THAT(no_frame_rate.get(), Not(AttributeSet("maxFrameRate"))); + EXPECT_THAT(no_frame_rate.get(), Not(AttributeSet("frameRate"))); // Then set same frame duration for the representations. (Given that the // time scales match). @@ -1038,10 +886,8 @@ TEST_F(CommonMpdBuilderTest, representation_360p->SetSampleDuration(kSameFrameDuration); xml::scoped_xml_ptr same_frame_rate(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("maxFrameRate", same_frame_rate.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "10/3", same_frame_rate.get())); + EXPECT_THAT(same_frame_rate.get(), Not(AttributeSet("maxFrameRate"))); + EXPECT_THAT(same_frame_rate.get(), AttributeEqual("frameRate", "10/3")); // Then set 480p to be 5fps (10/2) so that maxFrameRate is set. const uint32_t k5FPSFrameDuration = 2; @@ -1050,10 +896,8 @@ TEST_F(CommonMpdBuilderTest, representation_480p->SetSampleDuration(k5FPSFrameDuration); xml::scoped_xml_ptr max_frame_rate(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("maxFrameRate", "10/2", max_frame_rate.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", max_frame_rate.get())); + EXPECT_THAT(max_frame_rate.get(), AttributeEqual("maxFrameRate", "10/2")); + EXPECT_THAT(max_frame_rate.get(), Not(AttributeSet("frameRate"))); } // Verify that if the picture aspect ratio of all the Representations are the @@ -1107,21 +951,18 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetParAllSame) { "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k480pVideoInfo))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k720pVideoInfo))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k1080pVideoInfo))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k360pVideoInfo))); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pVideoInfo))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k720pVideoInfo))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k1080pVideoInfo))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k360pVideoInfo))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString("par", "16:9", - adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("par", "16:9")); } // Verify that adding Representations with different par will generate @@ -1151,17 +992,14 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetParDifferent) { "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k16by9VideoInfo))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(k2by1VideoInfo))); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k16by9VideoInfo))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(k2by1VideoInfo))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("par", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("par"))); } // Verify that adding Representation without pixel_width and pixel_height will @@ -1177,15 +1015,12 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetParUnknown) { "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kUknownPixelWidthAndHeight))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("par", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("par"))); } // Catch the case where it ends up wrong if integer division is used to check @@ -1213,19 +1048,15 @@ TEST_F(CommonMpdBuilderTest, " frame_duration: 3\n" "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo1))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo2))); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo1))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo2))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString("maxFrameRate", "11/3", - adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("maxFrameRate", "11/3")); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("frameRate"))); } // Verify that Suppress*() methods work. @@ -1247,28 +1078,21 @@ TEST_F(CommonMpdBuilderTest, SuppressRepresentationAttributes) { representation->SuppressOnce(Representation::kSuppressWidth); xml::scoped_xml_ptr no_width(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeNotSet("width", no_width.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("height", "480", no_width.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "10/10", no_width.get())); + EXPECT_THAT(no_width.get(), Not(AttributeSet("width"))); + EXPECT_THAT(no_width.get(), AttributeEqual("height", "480")); + EXPECT_THAT(no_width.get(), AttributeEqual("frameRate", "10/10")); representation->SuppressOnce(Representation::kSuppressHeight); xml::scoped_xml_ptr no_height(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeNotSet("height", no_height.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("width", "720", no_height.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "10/10", no_height.get())); + EXPECT_THAT(no_height.get(), Not(AttributeSet("height"))); + EXPECT_THAT(no_height.get(), AttributeEqual("width", "720")); + EXPECT_THAT(no_height.get(), AttributeEqual("frameRate", "10/10")); representation->SuppressOnce(Representation::kSuppressFrameRate); xml::scoped_xml_ptr no_frame_rate(representation->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", no_frame_rate.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("width", "720", no_frame_rate.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("height", "480", no_frame_rate.get())); + EXPECT_THAT(no_frame_rate.get(), Not(AttributeSet("frameRate"))); + EXPECT_THAT(no_frame_rate.get(), AttributeEqual("width", "720")); + EXPECT_THAT(no_frame_rate.get(), AttributeEqual("height", "480")); } // Attribute values that are common to all the children Representations should @@ -1325,56 +1149,45 @@ TEST_F(CommonMpdBuilderTest, BubbleUpAttributesToAdaptationSet) { "}\n" "container_type: 1\n"; - AdaptationSet* adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(adaptation_set); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); ASSERT_TRUE(adaptation_set->AddRepresentation(ConvertToMediaInfo(k1080p))); xml::scoped_xml_ptr all_attributes_on_adaptation_set( adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "width", "1920", all_attributes_on_adaptation_set.get())); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "height", "1080", all_attributes_on_adaptation_set.get())); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeEqString( - "frameRate", "30/1", all_attributes_on_adaptation_set.get())); + EXPECT_THAT(all_attributes_on_adaptation_set.get(), + AttributeEqual("width", "1920")); + EXPECT_THAT(all_attributes_on_adaptation_set.get(), + AttributeEqual("height", "1080")); + EXPECT_THAT(all_attributes_on_adaptation_set.get(), + AttributeEqual("frameRate", "30/1")); ASSERT_TRUE( adaptation_set->AddRepresentation(ConvertToMediaInfo(kDifferentWidth))); xml::scoped_xml_ptr width_not_set(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE(ExpectAttributeNotSet("width", width_not_set.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("height", "1080", width_not_set.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "30/1", width_not_set.get())); + EXPECT_THAT(width_not_set.get(), Not(AttributeSet("width"))); + EXPECT_THAT(width_not_set.get(), AttributeEqual("height", "1080")); + EXPECT_THAT(width_not_set.get(), AttributeEqual("frameRate", "30/1")); ASSERT_TRUE( adaptation_set->AddRepresentation(ConvertToMediaInfo(kDifferentHeight))); xml::scoped_xml_ptr width_height_not_set(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("width", width_height_not_set.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("height", width_height_not_set.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "30/1", width_height_not_set.get())); + EXPECT_THAT(width_height_not_set.get(), Not(AttributeSet("width"))); + EXPECT_THAT(width_height_not_set.get(), Not(AttributeSet("height"))); + EXPECT_THAT(width_height_not_set.get(), AttributeEqual("frameRate", "30/1")); ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kDifferentFrameRate))); xml::scoped_xml_ptr no_common_attributes(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("width", no_common_attributes.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("height", no_common_attributes.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", no_common_attributes.get())); + EXPECT_THAT(no_common_attributes.get(), Not(AttributeSet("width"))); + EXPECT_THAT(no_common_attributes.get(), Not(AttributeSet("height"))); + EXPECT_THAT(no_common_attributes.get(), Not(AttributeSet("frameRate"))); } // Verify that subsegmentAlignment is set to true if all the Representations' // segments are aligned and the MPD type is static. // Also checking that not all Representations have to be added before calling // AddNewSegment() on a Representation. -// The output MPD's schema is checked at the very end. TEST_F(OnDemandMpdBuilderTest, SubsegmentAlignment) { - base::AtomicSequenceNumber sequence_counter; const char k480pMediaInfo[] = "video_info {\n" " codec: 'avc1'\n" @@ -1404,7 +1217,7 @@ TEST_F(OnDemandMpdBuilderTest, SubsegmentAlignment) { const uint64_t kDuration = 10u; const uint64_t kAnySize = 19834u; - AdaptationSet* adaptation_set = mpd_.AddAdaptationSet(""); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); Representation* representation_480p = adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); // Add a subsegment immediately before adding the 360p Representation. @@ -1416,31 +1229,24 @@ TEST_F(OnDemandMpdBuilderTest, SubsegmentAlignment) { representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize); xml::scoped_xml_ptr aligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("subsegmentAlignment", "true", aligned.get())); + EXPECT_THAT(aligned.get(), AttributeEqual("subsegmentAlignment", "true")); // Unknown because 480p has an extra subsegments. representation_480p->AddNewSegment(11, 20, kAnySize); xml::scoped_xml_ptr alignment_unknown(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("subsegmentAlignment", alignment_unknown.get())); + EXPECT_THAT(alignment_unknown.get(), + Not(AttributeSet("subsegmentAlignment"))); // Add segments that make them not aligned. representation_360p->AddNewSegment(10, 1, kAnySize); representation_360p->AddNewSegment(11, 19, kAnySize); xml::scoped_xml_ptr unaligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("subsegmentAlignment", unaligned.get())); - - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); + EXPECT_THAT(unaligned.get(), Not(AttributeSet("subsegmentAlignment"))); } // Verify that subsegmentAlignment can be force set to true. TEST_F(OnDemandMpdBuilderTest, ForceSetsubsegmentAlignment) { - base::AtomicSequenceNumber sequence_counter; const char k480pMediaInfo[] = "video_info {\n" " codec: 'avc1'\n" @@ -1463,9 +1269,7 @@ TEST_F(OnDemandMpdBuilderTest, ForceSetsubsegmentAlignment) { " pixel_height: 1\n" "}\n" "container_type: 1\n"; - MpdOptions mpd_options; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); Representation* representation_480p = adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); Representation* representation_360p = @@ -1480,21 +1284,17 @@ TEST_F(OnDemandMpdBuilderTest, ForceSetsubsegmentAlignment) { representation_480p->AddNewSegment(kStartTime1, kDuration, kAnySize); representation_360p->AddNewSegment(kStartTime2, kDuration, kAnySize); xml::scoped_xml_ptr unaligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("subsegmentAlignment", unaligned.get())); + EXPECT_THAT(unaligned.get(), Not(AttributeSet("subsegmentAlignment"))); // Then force set the segment alignment attribute to true. adaptation_set->ForceSetSegmentAlignment(true); xml::scoped_xml_ptr aligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("subsegmentAlignment", "true", aligned.get())); + EXPECT_THAT(aligned.get(), AttributeEqual("subsegmentAlignment", "true")); } // Verify that segmentAlignment is set to true if all the Representations // segments' are aligned and the MPD type is dynamic. -// The output MPD's schema is checked at the very end. TEST_F(LiveMpdBuilderTest, SegmentAlignment) { - base::AtomicSequenceNumber sequence_counter; const char k480pMediaInfo[] = "video_info {\n" " codec: 'avc1'\n" @@ -1517,7 +1317,7 @@ TEST_F(LiveMpdBuilderTest, SegmentAlignment) { " pixel_height: 1\n" "}\n" "container_type: 1\n"; - auto adaptation_set = mpd_.AddAdaptationSet(""); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); Representation* representation_480p = adaptation_set->AddRepresentation(ConvertToMediaInfo(k480pMediaInfo)); Representation* representation_360p = @@ -1531,8 +1331,7 @@ TEST_F(LiveMpdBuilderTest, SegmentAlignment) { representation_480p->AddNewSegment(kStartTime, kDuration, kAnySize); representation_360p->AddNewSegment(kStartTime, kDuration, kAnySize); xml::scoped_xml_ptr aligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("segmentAlignment", "true", aligned.get())); + EXPECT_THAT(aligned.get(), AttributeEqual("segmentAlignment", "true")); // Add segments that make them not aligned. representation_480p->AddNewSegment(11, 20, kAnySize); @@ -1540,12 +1339,7 @@ TEST_F(LiveMpdBuilderTest, SegmentAlignment) { representation_360p->AddNewSegment(11, 19, kAnySize); xml::scoped_xml_ptr unaligned(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("subsegmentAlignment", unaligned.get())); - - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); + EXPECT_THAT(unaligned.get(), Not(AttributeSet("segmentAlignment"))); } // Verify that the width and height attribute are set if all the video @@ -1570,28 +1364,22 @@ TEST_F(OnDemandMpdBuilderTest, AdapatationSetWidthAndHeight) { " frame_duration: 200\n" "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo1))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kVideoMediaInfo2))); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo1))); + ASSERT_TRUE( + adaptation_set->AddRepresentation(ConvertToMediaInfo(kVideoMediaInfo2))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - ASSERT_NO_FATAL_FAILURE( - ExpectAttributeEqString("width", "1280", adaptation_set_xml.get())); - ASSERT_NO_FATAL_FAILURE( - ExpectAttributeEqString("height", "720", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("maxWidth", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("maxHeight", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("width", "1280")); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("height", "720")); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("maxWidth"))); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("maxHeight"))); } // Verify that the maxWidth and maxHeight attribute are set if there are // multiple video resolutions. -TEST_F(OnDemandMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) { +TEST_F(OnDemandMpdBuilderTest, AdaptationSetMaxWidthAndMaxHeight) { const char kVideoMediaInfo1080p[] = "video_info {\n" " codec: \"avc1\"\n" @@ -1610,23 +1398,17 @@ TEST_F(OnDemandMpdBuilderTest, AdapatationSetMaxWidthAndMaxHeight) { " frame_duration: 100\n" "}\n" "container_type: 1\n"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo1080p))); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo720p))); - xml::scoped_xml_ptr adaptation_set_xml( - video_adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("maxWidth", "1920", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("maxHeight", "1080", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("width", adaptation_set_xml.get())); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("height", adaptation_set_xml.get())); + xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("maxWidth", "1920")); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("maxHeight", "1080")); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("width"))); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("height"))); } TEST_F(CommonMpdBuilderTest, CheckRepresentationId) { @@ -1636,8 +1418,8 @@ TEST_F(CommonMpdBuilderTest, CheckRepresentationId) { auto representation = CreateRepresentation(video_media_info, kRepresentationId, NoListener()); EXPECT_TRUE(representation->Init()); - ASSERT_NO_FATAL_FAILURE( - CheckIdEqual(kRepresentationId, representation.get())); + EXPECT_THAT(representation->GetXml().get(), + AttributeEqual("id", std::to_string(kRepresentationId))); } // Verify that Representation::SetSampleDuration() works by checking that @@ -1653,9 +1435,7 @@ TEST_F(CommonMpdBuilderTest, SetSampleDuration) { "}\n" "container_type: 1\n"; - base::AtomicSequenceNumber sequence_counter; - auto adaptation_set = - CreateAdaptationSet(kAnyAdaptationSetId, "", &sequence_counter); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); const MediaInfo video_media_info = ConvertToMediaInfo(kVideoMediaInfo); Representation* representation = @@ -1663,13 +1443,11 @@ TEST_F(CommonMpdBuilderTest, SetSampleDuration) { EXPECT_TRUE(representation->Init()); xml::scoped_xml_ptr adaptation_set_xml(adaptation_set->GetXml()); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeNotSet("frameRate", adaptation_set_xml.get())); + EXPECT_THAT(adaptation_set_xml.get(), Not(AttributeSet("frameRate"))); representation->SetSampleDuration(2u); adaptation_set_xml = adaptation_set->GetXml(); - EXPECT_NO_FATAL_FAILURE( - ExpectAttributeEqString("frameRate", "3000/2", adaptation_set_xml.get())); + EXPECT_THAT(adaptation_set_xml.get(), AttributeEqual("frameRate", "3000/2")); } // Verify that AdaptationSet::AddContentProtection() and @@ -1693,69 +1471,41 @@ TEST_F(CommonMpdBuilderTest, AdaptationSetAddContentProtectionAndUpdate) { pssh.content = "any value"; content_protection.subelements.push_back(pssh); - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo1080p))); - video_adaptation_set->AddContentProtectionElement(content_protection); + adaptation_set->AddContentProtectionElement(content_protection); const char kExpectedOutput1[] = - "\n" - "" - " " - " " - " " - " any value" - " " - " " - " " - " " - ""; - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput1, mpd_output)); + "" + " " + " any value" + " " + " " + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput1)); - video_adaptation_set->UpdateContentProtectionPssh( + adaptation_set->UpdateContentProtectionPssh( "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed", "new pssh value"); const char kExpectedOutput2[] = - "\n" - "" - " " - " " - " " + "" + " " // TODO(rkuroiwa): Commenting this out for now because we want to remove // the PSSH from the MPD. Uncomment this when the player supports updating // pssh. - //" new pssh value" - " " - " " - " " - " " - ""; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput2, mpd_output)); + //" new pssh value" + " " + " " + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput2)); } // Verify that if the ContentProtection element for the DRM without @@ -1777,69 +1527,40 @@ TEST_F(CommonMpdBuilderTest, UpdateToRemovePsshElement) { "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"; content_protection.value = "some value"; - AdaptationSet* video_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(video_adaptation_set); - ASSERT_TRUE(video_adaptation_set->AddRepresentation( + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); + ASSERT_TRUE(adaptation_set->AddRepresentation( ConvertToMediaInfo(kVideoMediaInfo1080p))); - video_adaptation_set->AddContentProtectionElement(content_protection); + adaptation_set->AddContentProtectionElement(content_protection); const char kExpectedOutput1[] = - "\n" - "" - " " - " " - " " - " " - " " - " " - " " - ""; - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput1, mpd_output)); + "" + " " + " " + " " + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput1)); - video_adaptation_set->UpdateContentProtectionPssh( - "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed", - "added pssh value"); + adaptation_set->UpdateContentProtectionPssh( + "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed", "added pssh value"); const char kExpectedOutput2[] = - "\n" - "" - " " - " " - " " + "" + " " // TODO(rkuroiwa): Commenting this out for now because we want to remove // teh PSSH from the MPD. Uncomment this when the player supports updating // pssh. - //" added pssh value" - " " - " " - " " - " " - ""; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput2, mpd_output)); + //" added pssh value" + " " + " " + ""; + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput2)); } // Add one video check the output. @@ -1910,34 +1631,24 @@ TEST_F(OnDemandMpdBuilderTest, AudioChannelConfigurationWithContentProtection) { "container_type: CONTAINER_MP4\n"; const char kExpectedOutput[] = - "\n" - "" - " " - " " - " " - " " - " " - " anything" - " " - " encrypted_audio.mp4" - " " - " " - " " - " " - " " - " " - ""; + "" + " " + " " + " " + " anything" + " " + " encrypted_audio.mp4" + " " + " " + " " + " " + ""; ContentProtectionElement content_protection; content_protection.scheme_id_uri = "http://foo.com/"; @@ -1946,18 +1657,12 @@ TEST_F(OnDemandMpdBuilderTest, AudioChannelConfigurationWithContentProtection) { pssh.content = "anything"; content_protection.subelements.push_back(pssh); - MediaInfo audio_media_info = ConvertToMediaInfo(kTestMediaInfo); - AdaptationSet* audio_adaptation_set = mpd_.AddAdaptationSet(""); - ASSERT_TRUE(audio_adaptation_set); - + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, kNoLanguage); Representation* audio_representation = - audio_adaptation_set->AddRepresentation(audio_media_info); + adaptation_set->AddRepresentation(ConvertToMediaInfo(kTestMediaInfo)); ASSERT_TRUE(audio_representation); audio_representation->AddContentProtectionElement(content_protection); - - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput, mpd_output)); + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } // Static profile requires bandwidth to be set because it has no other way to @@ -1985,38 +1690,23 @@ TEST_F(OnDemandMpdBuilderTest, Text) { "container_type: CONTAINER_TEXT\n"; const char kExpectedOutput[] = - "\n" - "" - " " - " " - " \n" - " " - " subtitle.xml" - " " - " " - " " - ""; + "" + " \n" + " " + " subtitle.xml" + " " + ""; - AdaptationSet* text_adaptation_set = mpd_.AddAdaptationSet("en"); - ASSERT_TRUE(text_adaptation_set); - - Representation* text_representation = text_adaptation_set->AddRepresentation( - ConvertToMediaInfo(kTextMediaInfo)); + auto adaptation_set = CreateAdaptationSet(kAnyAdaptationSetId, "en"); + Representation* text_representation = + adaptation_set->AddRepresentation(ConvertToMediaInfo(kTextMediaInfo)); ASSERT_TRUE(text_representation); - std::string mpd_output; - ASSERT_TRUE(mpd_.ToString(&mpd_output)); - ASSERT_TRUE(ValidateMpdSchema(mpd_output)); - EXPECT_TRUE(XmlEqual(kExpectedOutput, mpd_output)); + EXPECT_THAT(adaptation_set->GetXml().get(), XmlNodeEqual(kExpectedOutput)); } // Check whether the attributes are set correctly for dynamic element. diff --git a/packager/mpd/base/xml/xml_node_unittest.cc b/packager/mpd/base/xml/xml_node_unittest.cc index d36bc5edde..24620cac5a 100644 --- a/packager/mpd/base/xml/xml_node_unittest.cc +++ b/packager/mpd/base/xml/xml_node_unittest.cc @@ -4,6 +4,7 @@ // license that can be found in the LICENSE file or at // https://developers.google.com/open-source/licenses/bsd +#include #include #include @@ -32,59 +33,12 @@ void AddAttribute(const std::string& name, attribute->set_value(value); } -std::string GetDocAsFlatString(xmlDocPtr doc) { - static const int kFlatFormat = 0; - int doc_str_size = 0; - xmlChar* doc_str = NULL; - xmlDocDumpFormatMemoryEnc(doc, &doc_str, &doc_str_size, "UTF-8", kFlatFormat); - DCHECK(doc_str); - - std::string output(doc_str, doc_str + doc_str_size); - xmlFree(doc_str); - return output; -} - -scoped_xml_ptr MakeDoc(scoped_xml_ptr node) { - xml::scoped_xml_ptr doc(xmlNewDoc(BAD_CAST "")); - xmlDocSetRootElement(doc.get(), node.release()); - return doc; -} - } // namespace -class RepresentationTest : public ::testing::Test { - public: - RepresentationTest() {} - ~RepresentationTest() override {} - - // Ownership transfers, IOW this function will release the resource for - // |node|. Returns |node| in string format. - // You should not call this function multiple times. - std::string GetStringFormat() { - xml::scoped_xml_ptr doc(xmlNewDoc(BAD_CAST "")); - - // Because you cannot easily get the string format of a xmlNodePtr, it gets - // attached to a temporary xml doc. - xmlDocSetRootElement(doc.get(), representation_.Release()); - std::string doc_str = GetDocAsFlatString(doc.get()); - - // GetDocAsFlatString() adds - // - // to the first line. So this removes the first line. - const size_t first_newline_char_pos = doc_str.find('\n'); - DCHECK_NE(first_newline_char_pos, std::string::npos); - return doc_str.substr(first_newline_char_pos + 1); - } - - protected: - RepresentationXmlNode representation_; - std::list segment_infos_; -}; - // Make sure XmlEqual() is functioning correctly. -// TODO(rkuroiwa): Move this to a separate file. This requires it to be TEST_F +// TODO(rkuroiwa): Move this to a separate file. This requires it to be TEST // due to gtest /test -TEST_F(RepresentationTest, MetaTestXmlElementsEqual) { +TEST(XmlNodeTest, MetaTestXmlElementsEqual) { static const char kXml1[] = "\n" " ) (for both s) will return "content1content2". // But if it is run on for the first XML, it will return "content1", but // for second XML will return "c". -TEST_F(RepresentationTest, MetaTestXmlEqualDifferentContent) { +TEST(XmlNodeTest, MetaTestXmlEqualDifferentContent) { ASSERT_FALSE(XmlEqual( "content1content2", "content1content2")); @@ -184,7 +138,7 @@ TEST_F(RepresentationTest, MetaTestXmlEqualDifferentContent) { // namespaces without context, e.g. element. // The MpdBuilderTests work because the MPD element has xmlns:cenc attribute. // Tests that have is in mpd_builder_unittest. -TEST_F(RepresentationTest, AddContentProtectionElements) { +TEST(XmlNodeTest, AddContentProtectionElements) { std::list content_protections; ContentProtectionElement content_protection_widevine; content_protection_widevine.scheme_id_uri = @@ -201,59 +155,63 @@ TEST_F(RepresentationTest, AddContentProtectionElements) { "urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b"; content_protections.push_back(content_protection_clearkey); - representation_.AddContentProtectionElements(content_protections); - scoped_xml_ptr doc(MakeDoc(representation_.PassScopedPtr())); - ASSERT_TRUE(XmlEqual( - "\n" - " \n" - " any content\n" - " \n" - " " - " \n" - "", - doc.get())); + RepresentationXmlNode representation; + representation.AddContentProtectionElements(content_protections); + EXPECT_THAT( + representation.GetRawPtr(), + XmlNodeEqual( + "\n" + " \n" + " any content\n" + " \n" + " " + " \n" + "")); } -TEST_F(RepresentationTest, AddEC3AudioInfo) { +TEST(XmlNodeTest, AddEC3AudioInfo) { MediaInfo::AudioInfo audio_info; audio_info.set_codec("ec-3"); audio_info.set_sampling_frequency(44100); audio_info.mutable_codec_specific_data()->set_ec3_channel_map(0xF801); - representation_.AddAudioInfo(audio_info); - scoped_xml_ptr doc(MakeDoc(representation_.PassScopedPtr())); - ASSERT_TRUE(XmlEqual( - "\n" - " \n" - "\n", - doc.get())); + RepresentationXmlNode representation; + representation.AddAudioInfo(audio_info); + EXPECT_THAT( + representation.GetRawPtr(), + XmlNodeEqual( + "\n" + " \n" + "\n")); } // Some template names cannot be used for init segment name. -TEST_F(RepresentationTest, InvalidLiveInitSegmentName) { +TEST(XmlNodeTest, InvalidLiveInitSegmentName) { MediaInfo media_info; const uint32_t kDefaultStartNumber = 1; + std::list segment_infos; + RepresentationXmlNode representation; // $Number$ cannot be used for segment name. media_info.set_init_segment_name("$Number$.mp4"); - ASSERT_FALSE(representation_.AddLiveOnlyInfo( - media_info, segment_infos_, kDefaultStartNumber)); + ASSERT_FALSE(representation.AddLiveOnlyInfo(media_info, segment_infos, + kDefaultStartNumber)); // $Time$ as well. media_info.set_init_segment_name("$Time$.mp4"); - ASSERT_FALSE(representation_.AddLiveOnlyInfo( - media_info, segment_infos_, kDefaultStartNumber)); + ASSERT_FALSE(representation.AddLiveOnlyInfo(media_info, segment_infos, + kDefaultStartNumber)); // This should be valid. media_info.set_init_segment_name("some_non_template_name.mp4"); - ASSERT_TRUE(representation_.AddLiveOnlyInfo( - media_info, segment_infos_, kDefaultStartNumber)); + ASSERT_TRUE(representation.AddLiveOnlyInfo(media_info, segment_infos, + kDefaultStartNumber)); } } // namespace xml diff --git a/packager/mpd/test/mpd_builder_test_helper.h b/packager/mpd/test/mpd_builder_test_helper.h index 7dec152d69..2584224b3f 100644 --- a/packager/mpd/test/mpd_builder_test_helper.h +++ b/packager/mpd/test/mpd_builder_test_helper.h @@ -10,6 +10,7 @@ #include #include "packager/base/files/file_path.h" +#include "packager/mpd/base/media_info.pb.h" namespace shaka { diff --git a/packager/mpd/test/xml_compare.cc b/packager/mpd/test/xml_compare.cc index 9f34bbfa24..accbea628a 100644 --- a/packager/mpd/test/xml_compare.cc +++ b/packager/mpd/test/xml_compare.cc @@ -10,7 +10,6 @@ #include "packager/base/logging.h" #include "packager/base/strings/string_util.h" -#include "packager/mpd/base/xml/scoped_xml_ptr.h" namespace shaka { @@ -154,7 +153,7 @@ bool XmlEqual(const std::string& xml1, xmlDocPtr xml2) { } bool XmlEqual(xmlDocPtr xml1, xmlDocPtr xml2) { - if (!xml1|| !xml2) { + if (!xml1 || !xml2) { LOG(ERROR) << "xml1 and/or xml2 are not valid XML."; return false; } @@ -167,4 +166,38 @@ bool XmlEqual(xmlDocPtr xml1, xmlDocPtr xml2) { return CompareNodes(xml1_root_element, xml2_root_element); } +bool XmlEqual(const std::string& xml1, xmlNodePtr xml2) { + xml::scoped_xml_ptr xml1_doc(GetDocFromString(xml1)); + if (!xml1_doc) { + LOG(ERROR) << "xml1 are not valid XML."; + return false; + } + xmlNodePtr xml1_root_element = xmlDocGetRootElement(xml1_doc.get()); + if (!xml1_root_element) + return false; + return CompareNodes(xml1_root_element, xml2); +} + +std::string XmlNodeToString(xmlNodePtr xml_node) { + // Create an xmlDoc from xmlNodePtr. The node is copied so ownership does not + // transfer. + xml::scoped_xml_ptr doc(xmlNewDoc(BAD_CAST "")); + xmlDocSetRootElement(doc.get(), xmlCopyNode(xml_node, true)); + + // Format the xmlDoc to string. + static const int kNiceFormat = 1; + int doc_str_size = 0; + xmlChar* doc_str = nullptr; + xmlDocDumpFormatMemoryEnc(doc.get(), &doc_str, &doc_str_size, "UTF-8", + kNiceFormat); + std::string output(doc_str, doc_str + doc_str_size); + xmlFree(doc_str); + + // Remove the first line from the formatted string: + // + const size_t first_newline_char_pos = output.find('\n'); + DCHECK_NE(first_newline_char_pos, std::string::npos); + return output.substr(first_newline_char_pos + 1); +} + } // namespace shaka diff --git a/packager/mpd/test/xml_compare.h b/packager/mpd/test/xml_compare.h index 4c01be3d9a..721c2480bc 100644 --- a/packager/mpd/test/xml_compare.h +++ b/packager/mpd/test/xml_compare.h @@ -1,10 +1,13 @@ #ifndef MPD_TEST_XML_COMPARE_H_ #define MPD_TEST_XML_COMPARE_H_ +#include #include #include +#include "packager/mpd/base/xml/scoped_xml_ptr.h" + namespace shaka { /// Checks whether the XMLs are equivalent. An XML schema can specify strict @@ -18,7 +21,40 @@ namespace shaka { bool XmlEqual(const std::string& xml1, const std::string& xml2); bool XmlEqual(const std::string& xml1, xmlDocPtr xml2); bool XmlEqual(xmlDocPtr xml1, xmlDocPtr xml2); +bool XmlEqual(const std::string& xml1, xmlNodePtr xml2); +/// Get string representation of the xml node. +/// Note that the ownership is not transferred. +std::string XmlNodeToString(xmlNodePtr xml_node); + +/// Match an xmlNodePtr with an xml in string representation. +MATCHER_P(XmlNodeEqual, xml, "") { + *result_listener << "\n" << XmlNodeToString(arg); + return XmlEqual(xml, arg); +} + +/// Match the attribute of an xmlNodePtr with expected value. +/// Note that the ownership is not transferred. +MATCHER_P2(AttributeEqual, attribute, expected_value, "") { + xml::scoped_xml_ptr attribute_xml_str( + xmlGetProp(arg, BAD_CAST attribute)); + if (!attribute_xml_str) { + *result_listener << "no attribute '" << attribute << "'"; + return false; + } + std::string actual_value = + reinterpret_cast(attribute_xml_str.get()); + *result_listener << actual_value; + return expected_value == actual_value; +} + +/// Check if the attribute is set in an xmlNodePtr. +/// Note that the ownership is not transferred. +MATCHER_P(AttributeSet, attribute, "") { + xml::scoped_xml_ptr attribute_xml_str( + xmlGetProp(arg, BAD_CAST attribute)); + return attribute_xml_str != nullptr; +} } // namespace shaka #endif // MPD_TEST_XML_COMPARE_H_