// 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 "base/file_util.h" #include "base/logging.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "mpd/base/mpd_builder.h" #include "mpd/base/xml/scoped_xml_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libxml/src/include/libxml/parser.h" namespace dash_packager { namespace { // This was validated at a validator site below as well. // http://www-itec.uni-klu.ac.at/dash/?page_id=605# const char kValidMpd[] = "\n\ \n\ http://cdn1.example.com/\n\ \n\ \n\ \n\ \n\ something.mp4\n\ \n\ \n\ \n\ \n\ somethingelse.mp4\n\ \n\ \n\ \n\ \n\ \n\ "; const size_t kValidMpdSize = arraysize(kValidMpd) - 1; // Exclude '\0'. base::FilePath GetSchemaPath() { base::FilePath file_path; CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); file_path = file_path.Append(FILE_PATH_LITERAL("mpd")) .Append(FILE_PATH_LITERAL("test")) .Append(FILE_PATH_LITERAL("schema")) .Append(FILE_PATH_LITERAL("DASH-MPD.xsd")); return file_path; } std::string GetPathContent(const base::FilePath& file_path) { std::string content; bool file_read_to_string = file_util::ReadFileToString(file_path, &content); DCHECK(file_read_to_string); return content; } bool ValidateMpdSchema(const std::string& mpd) { xml::ScopedXmlPtr::type doc(xmlParseMemory(mpd.data(), mpd.size())); if (!doc) { LOG(ERROR) << "Failed to parse mpd into an xml doc."; return false; } base::FilePath schema_path = GetSchemaPath(); std::string schema_str = GetPathContent(schema_path); // First, I need to load the schema as a xmlDoc so that I can pass the path of // the DASH-MPD.xsd. Then it can resolve the relative path included from the // XSD when creating xmlSchemaParserCtxt. xml::ScopedXmlPtr::type schema_as_doc( xmlReadMemory(schema_str.data(), schema_str.size(), schema_path.value().c_str(), NULL, 0)); DCHECK(schema_as_doc); xml::ScopedXmlPtr::type schema_parser_ctxt( xmlSchemaNewDocParserCtxt(schema_as_doc.get())); DCHECK(schema_parser_ctxt); xml::ScopedXmlPtr::type schema( xmlSchemaParse(schema_parser_ctxt.get())); DCHECK(schema); xml::ScopedXmlPtr::type valid_ctxt( xmlSchemaNewValidCtxt(schema.get())); DCHECK(valid_ctxt); int validation_result = xmlSchemaValidateDoc(valid_ctxt.get(), doc.get()); DLOG(INFO) << "XSD validation result: " << validation_result; return validation_result == 0; } } // namespace // Check if the schema validation works. If not, then most of the tests would // probably fail. TEST(MpdSchemaMetaTest, CheckSchemaValidatorWorks) { ASSERT_TRUE(ValidateMpdSchema(std::string(kValidMpd, kValidMpdSize))); } // TODO(rkuroiwa): MPD builder does not build a valid MPD yet. Enable these when // its done. Make sure to compare against a known MPD to validate. // A normal use case where there are 2 adaptation sets and 2 representations. TEST(MpdBuilder, DISABLED_VOD_Normal) { MpdBuilder mpd(MpdBuilder::kStatic); AdaptationSet* adaptation_set = mpd.AddAdaptationSet(); ASSERT_TRUE(adaptation_set); AdaptationSet* adaptation_set2 = mpd.AddAdaptationSet(); ASSERT_TRUE(adaptation_set2); MediaInfo media_info; media_info.set_bandwidth(100); ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); ASSERT_TRUE(adaptation_set2->AddRepresentation(media_info)); std::string mpd_doc; ASSERT_TRUE(mpd.ToString(&mpd_doc)); ASSERT_TRUE(ValidateMpdSchema(mpd_doc)); } // Different media duration should not error. TEST(MpdBuilder, DISABLED_VOD_DifferentMediaDuration) { MpdBuilder mpd(MpdBuilder::kStatic); AdaptationSet* adaptation_set = mpd.AddAdaptationSet(); ASSERT_TRUE(adaptation_set); MediaInfo media_info; media_info.set_bandwidth(20000); media_info.set_media_duration_seconds(100); ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); media_info.set_media_duration_seconds(101); ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); std::string mpd_doc; ASSERT_TRUE(mpd.ToString(&mpd_doc)); ASSERT_TRUE(ValidateMpdSchema(mpd_doc)); } } // namespace dash_packager