diff --git a/mpd/base/mpd_builder_unittest.cc b/mpd/base/mpd_builder_unittest.cc index edf9f78ce7..6c15653fa5 100644 --- a/mpd/base/mpd_builder_unittest.cc +++ b/mpd/base/mpd_builder_unittest.cc @@ -6,148 +6,59 @@ #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 "mpd/test/mpd_builder_test_helper.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) { +TEST(MpdBuilderTest, VOD_Video) { MpdBuilder mpd(MpdBuilder::kStatic); - AdaptationSet* adaptation_set = mpd.AddAdaptationSet(); - ASSERT_TRUE(adaptation_set); + MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); - AdaptationSet* adaptation_set2 = mpd.AddAdaptationSet(); - ASSERT_TRUE(adaptation_set2); + AdaptationSet* video_adaptation_set = mpd.AddAdaptationSet(); + ASSERT_TRUE(video_adaptation_set); - MediaInfo media_info; - media_info.set_bandwidth(100); - ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); - ASSERT_TRUE(adaptation_set2->AddRepresentation(media_info)); + Representation* video_representation = + video_adaptation_set->AddRepresentation(video_media_info); + ASSERT_TRUE(video_adaptation_set); std::string mpd_doc; ASSERT_TRUE(mpd.ToString(&mpd_doc)); ASSERT_TRUE(ValidateMpdSchema(mpd_doc)); + + EXPECT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( + mpd_doc, kFileNameExpectedMpdOutputVideo1)); } -// Different media duration should not error. -TEST(MpdBuilder, DISABLED_VOD_DifferentMediaDuration) { +TEST(MpdBuilderTest, VOD_VideoAndAudio) { MpdBuilder mpd(MpdBuilder::kStatic); - AdaptationSet* adaptation_set = mpd.AddAdaptationSet(); - ASSERT_TRUE(adaptation_set); + MediaInfo video_media_info = GetTestMediaInfo(kFileNameVideoMediaInfo1); + MediaInfo audio_media_info = GetTestMediaInfo(kFileNameAudioMediaInfo1); - MediaInfo media_info; - media_info.set_bandwidth(20000); - media_info.set_media_duration_seconds(100); - ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); + // The order matters here to check against expected output. + // TODO(rkuroiwa): Investigate if I can deal with IDs and order elements + // deterministically. + AdaptationSet* video_adaptation_set = mpd.AddAdaptationSet(); + ASSERT_TRUE(video_adaptation_set); - media_info.set_media_duration_seconds(101); - ASSERT_TRUE(adaptation_set->AddRepresentation(media_info)); + AdaptationSet* audio_adaptation_set = mpd.AddAdaptationSet(); + ASSERT_TRUE(audio_adaptation_set); + + Representation* audio_representation = + audio_adaptation_set->AddRepresentation(audio_media_info); + ASSERT_TRUE(audio_representation); + + Representation* video_representation = + video_adaptation_set->AddRepresentation(video_media_info); + ASSERT_TRUE(video_adaptation_set); std::string mpd_doc; ASSERT_TRUE(mpd.ToString(&mpd_doc)); ASSERT_TRUE(ValidateMpdSchema(mpd_doc)); + + EXPECT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( + mpd_doc, kFileNameExpectedMpdOutputAudio1AndVideo1)); } } // namespace dash_packager diff --git a/mpd/mpd.gyp b/mpd/mpd.gyp index f90ce22704..b9a35bd7b1 100644 --- a/mpd/mpd.gyp +++ b/mpd/mpd.gyp @@ -62,6 +62,8 @@ 'sources': [ 'base/mpd_builder_unittest.cc', 'base/xml/xml_node_unittest.cc', + 'test/mpd_builder_test_helper.cc', + 'test/mpd_builder_test_helper.h', 'util/mpd_writer_unittest.cc', ], 'dependencies': [ diff --git a/mpd/test/mpd_builder_test_helper.cc b/mpd/test/mpd_builder_test_helper.cc new file mode 100644 index 0000000000..aeeda5ff64 --- /dev/null +++ b/mpd/test/mpd_builder_test_helper.cc @@ -0,0 +1,112 @@ +// 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 "mpd/test/mpd_builder_test_helper.h" + +#include "base/file_util.h" +#include "base/path_service.h" +#include "mpd/base/media_info.pb.h" +#include "mpd/base/xml/scoped_xml_ptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/protobuf/src/google/protobuf/text_format.h" + +namespace dash_packager { + +base::FilePath GetTestDataFilePath(const std::string& file_name) { + 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("data")) + .AppendASCII(file_name); + return file_path; +} + +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; +} + +MediaInfo ConvertToMediaInfo(const std::string& media_info_string) { + MediaInfo media_info; + CHECK(::google::protobuf::TextFormat::ParseFromString(media_info_string, + &media_info)); + return media_info; +} + +MediaInfo GetTestMediaInfo(const std::string& media_info_file_name) { + return ConvertToMediaInfo( + GetPathContent(GetTestDataFilePath(media_info_file_name))); +} + +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; +} + +void ExpectMpdToEqualExpectedOutputFile( + const std::string& mpd_string, + const std::string& expected_output_file) { + std::string expected_mpd; + ASSERT_TRUE(file_util::ReadFileToString( + GetTestDataFilePath(expected_output_file), &expected_mpd)) + << "Failed to read: " << expected_output_file; + + // Adding extra << here to get a formatted output. + ASSERT_EQ(expected_mpd, mpd_string) << "Expected:" << std::endl + << expected_mpd << std::endl + << "Actual:" << std::endl + << mpd_string; +} + +} // namespace dash_packager diff --git a/mpd/test/mpd_builder_test_helper.h b/mpd/test/mpd_builder_test_helper.h new file mode 100644 index 0000000000..9d211414f2 --- /dev/null +++ b/mpd/test/mpd_builder_test_helper.h @@ -0,0 +1,69 @@ +// 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 + +#ifndef MPD_TEST_MPD_BUILDER_TEST_HELPER_H_ +#define MPD_TEST_MPD_BUILDER_TEST_HELPER_H_ + +#include + +namespace base { +class FilePath; +} + +namespace dash_packager { + +class MediaInfo; + +// File names that could be used to call GetTestDataFilePath(). +const char kFileNameVideoMediaInfo1[] = "video_media_info1.txt"; +const char kFileNameVideoMediaInfo2[] = "video_media_info2.txt"; +const char kFileNameAudioMediaInfo1[] = "audio_media_info1.txt"; + +// These are the expected output files. +const char kFileNameExpectedMpdOutputVideo1[] = + "video_media_info1_expected_mpd_output.txt"; + +const char kFileNameExpectedMpdOutputVideo1And2[] = + "video_media_info1and2_expected_mpd_output.txt"; + +const char kFileNameExpectedMpdOutputAudio1[] = + "audio_media_info1_expected_mpd_output.txt"; + +const char kFileNameExpectedMpdOutputAudio1AndVideo1[] = + "audio_media_info1_video_media_info1_expected_mpd_output.txt"; + +// Returns the path to test data with |file_name|. Use constants above to get +// path to the test files. +base::FilePath GetTestDataFilePath(const std::string& file_name); + +// Get path to DASH MPD schema. +base::FilePath GetSchemaPath(); + +// Get the content of |file_path|. Returns empty string on error. +std::string GetPathContent(const base::FilePath& file_path); + +// Convert |media_info_string| to MediaInfo. +MediaInfo ConvertToMediaInfo(const std::string& media_info_string); + +// This is equivalent to +// return input_file >>= GetTestDataFilePath >>= GetPathContent >>= GetMediaInfo +// i.e. calling the functions with |media_info_file_name|. +MediaInfo GetTestMediaInfo(const std::string& media_info_file_name); + +// Return true if |mpd| is a valid MPD. +bool ValidateMpdSchema(const std::string& mpd); + +// |expected_output_file| should be the file name that has expected output in +// test data dir. +// This checks if |mpd_string| and the content of |expected_output_file| are +// equal. +void ExpectMpdToEqualExpectedOutputFile( + const std::string& mpd_string, + const std::string& expected_output_file); + +} // namespace dash_packager + +#endif // MPD_TEST_MPD_BUILDER_TEST_HELPER_H_ diff --git a/mpd/util/mpd_writer_unittest.cc b/mpd/util/mpd_writer_unittest.cc index b0eb07a0f1..418ebfa13b 100644 --- a/mpd/util/mpd_writer_unittest.cc +++ b/mpd/util/mpd_writer_unittest.cc @@ -6,96 +6,76 @@ #include "base/file_util.h" #include "base/path_service.h" +#include "mpd/test/mpd_builder_test_helper.h" #include "mpd/util/mpd_writer.h" #include "testing/gtest/include/gtest/gtest.h" -// TODO(rkuroiwa): Move schema check function in mpd_builder_unittest.cc to -// another file so that this file can use it as well. namespace dash_packager { -namespace { -base::FilePath GetTestDataFilePath(const std::string& file_name) { - 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("data")) - .AppendASCII(file_name); - return file_path; -} - -void ExpectToEqualExpectedOutputFile( - const std::string& mpd_string, - const base::FilePath& expected_output_file) { - std::string expected_mpd; - ASSERT_TRUE(file_util::ReadFileToString(expected_output_file, &expected_mpd)) - << "Failed to read: " << expected_output_file.value(); - ASSERT_EQ(expected_mpd, mpd_string); -} -} // namespace - TEST(MpdWriterTest, ReadMediaInfoFile_VideoMediaInfo) { MpdWriter mpd_writer; - base::FilePath media_info_file = GetTestDataFilePath("video_media_info1.txt"); + base::FilePath media_info_file = GetTestDataFilePath(kFileNameVideoMediaInfo1); ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str())); std::string generated_mpd; ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd)); + ASSERT_TRUE(ValidateMpdSchema(generated_mpd)); - ASSERT_NO_FATAL_FAILURE(ExpectToEqualExpectedOutputFile( + ASSERT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( generated_mpd, - GetTestDataFilePath("video_media_info1_expected_mpd_output.txt"))); + kFileNameExpectedMpdOutputVideo1)); } TEST(MpdWriterTest, ReadMediaInfoFile_TwoVideoMediaInfo) { MpdWriter mpd_writer; base::FilePath media_info_file1 = - GetTestDataFilePath("video_media_info1.txt"); + GetTestDataFilePath(kFileNameVideoMediaInfo1); base::FilePath media_info_file2 = - GetTestDataFilePath("video_media_info2.txt"); + GetTestDataFilePath(kFileNameVideoMediaInfo2); ASSERT_TRUE(mpd_writer.AddFile(media_info_file1.value().c_str())); ASSERT_TRUE(mpd_writer.AddFile(media_info_file2.value().c_str())); std::string generated_mpd; ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd)); + ASSERT_TRUE(ValidateMpdSchema(generated_mpd)); - ASSERT_NO_FATAL_FAILURE(ExpectToEqualExpectedOutputFile( + ASSERT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( generated_mpd, - GetTestDataFilePath("video_media_info1and2_expected_mpd_output.txt"))); + kFileNameExpectedMpdOutputVideo1And2)); } TEST(MpdWriterTest, ReadMediaInfoFile_AudioMediaInfo) { MpdWriter mpd_writer; - base::FilePath media_info_file = GetTestDataFilePath("audio_media_info1.txt"); + base::FilePath media_info_file = GetTestDataFilePath(kFileNameAudioMediaInfo1); ASSERT_TRUE(mpd_writer.AddFile(media_info_file.value().c_str())); std::string generated_mpd; ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd)); + ASSERT_TRUE(ValidateMpdSchema(generated_mpd)); - ASSERT_NO_FATAL_FAILURE(ExpectToEqualExpectedOutputFile( + ASSERT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( generated_mpd, - GetTestDataFilePath("audio_media_info1_expected_mpd_output.txt"))); + kFileNameExpectedMpdOutputAudio1)); } TEST(MpdWriterTest, ReadMediaInfoFile_VideoAudioMediaInfo) { MpdWriter mpd_writer; base::FilePath audio_media_info = - GetTestDataFilePath("audio_media_info1.txt"); + GetTestDataFilePath(kFileNameAudioMediaInfo1); base::FilePath video_media_info = - GetTestDataFilePath("video_media_info1.txt"); + GetTestDataFilePath(kFileNameVideoMediaInfo1); ASSERT_TRUE(mpd_writer.AddFile(audio_media_info.value().c_str())); ASSERT_TRUE(mpd_writer.AddFile(video_media_info.value().c_str())); std::string generated_mpd; ASSERT_TRUE(mpd_writer.WriteMpdToString(&generated_mpd)); + ASSERT_TRUE(ValidateMpdSchema(generated_mpd)); - ASSERT_NO_FATAL_FAILURE(ExpectToEqualExpectedOutputFile( + ASSERT_NO_FATAL_FAILURE(ExpectMpdToEqualExpectedOutputFile( generated_mpd, - GetTestDataFilePath( - "audio_media_info1_video_media_info1_expected_mpd_output.txt"))); + kFileNameExpectedMpdOutputAudio1AndVideo1)); } } // namespace dash_packager