// Copyright 2014 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 #include #include #include #include "packager/base/logging.h" #include "packager/base/strings/string_util.h" #include "packager/mpd/base/segment_info.h" #include "packager/mpd/base/xml/xml_node.h" #include "packager/mpd/test/xml_compare.h" namespace shaka { namespace xml { namespace { // Template so that it works for ContentProtectionXml and // ContentProtectionXml::Element. template void AddAttribute(const std::string& name, const std::string& value, XmlElement* content_protection_xml) { MediaInfo::ContentProtectionXml::AttributeNameValuePair* attribute = content_protection_xml->add_attributes(); attribute->set_name(name); attribute->set_value(value); } } // namespace // Make sure XmlEqual() is functioning correctly. // TODO(rkuroiwa): Move this to a separate file. This requires it to be TEST // due to gtest /test TEST(XmlNodeTest, MetaTestXmlElementsEqual) { static const char kXml1[] = "\n" " \n" " \n" " \n" " \n" ""; // This is same as kXml1 but the attributes are reordered. Note that the // children are not reordered. static const char kXml1AttributeReorder[] = "\n" " " " \n" " \n" " \n" ""; // is before . static const char kXml1ChildrenReordered[] = "\n" " \n" " " " \n" " \n" ""; // is before . static const char kXml1RemovedAttributes[] = "\n" " " " \n" " \n" " \n" ""; static const char kXml2[] = "\n" " \n" ""; // In XML , , and mean the same thing. static const char kXml2DifferentSyntax[] = "\n" " \n" ""; static const char kXml2MoreDifferentSyntax[] = "\n" " \n" ""; // Identity. ASSERT_TRUE(XmlEqual(kXml1, kXml1)); // Equivalent. ASSERT_TRUE(XmlEqual(kXml1, kXml1AttributeReorder)); ASSERT_TRUE(XmlEqual(kXml2, kXml2DifferentSyntax)); ASSERT_TRUE(XmlEqual(kXml2, kXml2MoreDifferentSyntax)); // Different. ASSERT_FALSE(XmlEqual(kXml1, kXml2)); ASSERT_FALSE(XmlEqual(kXml1, kXml1ChildrenReordered)); ASSERT_FALSE(XmlEqual(kXml1, kXml1RemovedAttributes)); ASSERT_FALSE(XmlEqual(kXml1AttributeReorder, kXml1ChildrenReordered)); } // Verify that if contents are different, XmlEqual returns false. // This is to catch the case where just using xmlNodeGetContent() on elements // that have subelements don't quite work well. // xmlNodeGetContent() (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(XmlNodeTest, MetaTestXmlEqualDifferentContent) { ASSERT_FALSE(XmlEqual( "content1content2", "content1content2")); } // Verify that AddContentProtectionElements work. // xmlReadMemory() (used in XmlEqual()) doesn't like XML fragments that have // 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(XmlNodeTest, AddContentProtectionElements) { std::list content_protections; ContentProtectionElement content_protection_widevine; content_protection_widevine.scheme_id_uri = "urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"; content_protection_widevine.value = "SOME bogus Widevine DRM version"; Element any_element; any_element.name = "AnyElement"; any_element.content = "any content"; content_protection_widevine.subelements.push_back(any_element); content_protections.push_back(content_protection_widevine); ContentProtectionElement content_protection_clearkey; content_protection_clearkey.scheme_id_uri = "urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b"; content_protections.push_back(content_protection_clearkey); RepresentationXmlNode representation; representation.AddContentProtectionElements(content_protections); EXPECT_THAT( representation.GetRawPtr(), XmlNodeEqual( "\n" " \n" " any content\n" " \n" " " " \n" "")); } 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); 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(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)); // $Time$ as well. media_info.set_init_segment_name("$Time$.mp4"); 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)); } } // namespace xml } // namespace shaka