}
}
+ void delete_lines_after(string after, int lines_to_delete)
+ {
+ ChangeChecker cc(this);
+ auto lines = as_lines();
+ _content = "";
+ auto iter = std::find_if(lines.begin(), lines.end(), [after](string const& line) {
+ return line.find(after) != string::npos;
+ });
+ int to_delete = 0;
+ for (auto i = lines.begin(); i != lines.end(); ++i) {
+ if (i == iter) {
+ to_delete = lines_to_delete;
+ _content += *i + "\n";
+ } else if (to_delete == 0) {
+ _content += *i + "\n";
+ } else {
+ --to_delete;
+ }
+ }
+ }
+
private:
friend class ChangeChecker;
void
check_verify_result (vector<path> dir, vector<dcp::VerificationNote> test_notes)
{
- auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
+ auto notes = dcp::verify({dir}, &stage, &progress, {}, xsd_test);
std::sort (notes.begin(), notes.end());
std::sort (test_notes.begin(), test_notes.end());
string message = "\nVerification notes from test:\n";
for (auto i: notes) {
message += " " + note_to_string(i) + "\n";
+ message += dcp::String::compose(
+ " [%1 %2 %3 %4 %5]\n",
+ static_cast<int>(i.type()),
+ static_cast<int>(i.code()),
+ i.note().get_value_or("<none>"),
+ i.file().get_value_or("<none>"),
+ i.line().get_value_or(0)
+ );
}
message += "Expected:\n";
for (auto i: test_notes) {
message += " " + note_to_string(i) + "\n";
+ message += dcp::String::compose(
+ " [%1 %2 %3 %4 %5]\n",
+ static_cast<int>(i.type()),
+ static_cast<int>(i.code()),
+ i.note().get_value_or("<none>"),
+ i.file().get_value_or("<none>"),
+ i.line().get_value_or(0)
+ );
}
BOOST_REQUIRE_MESSAGE (notes == test_notes, message);
e.replace (from, to);
}
- auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
+ auto notes = dcp::verify({dir}, &stage, &progress, {}, xsd_test);
BOOST_REQUIRE_EQUAL (notes.size(), codes.size());
auto i = notes.begin();
{
stages.clear ();
auto dir = setup (1, "no_error");
- auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
+ auto notes = dcp::verify({dir}, &stage, &progress, {}, xsd_test);
path const cpl_file = dir / dcp_test1_cpl;
path const pkl_file = dir / dcp_test1_pkl;
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, dcp_test1_cpl_id, canonical(dir / dcp_test1_cpl) },
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_PICTURE_HASHES, canonical(dir / "video.mxf") },
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_HASHES, canonical(dir / "audio.mxf") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xKcJb7S2K5cNm8RG4kfQD5FTeS0A=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 26 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xKcJb7S2K5cNm8RG4kfQD5FTeS0A=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 28 },
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xtfX1mVIKJCVr1m7Y32Nzxf0+Rpw=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 12 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xwUmt8G+cFFKMGt0ueS9+F1S4uhc=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 19 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xwUmt8G+cFFKMGt0ueS9+F1S4uhc=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 20 },
});
}
{
stages.clear ();
auto dir = setup (3, "verify_invalid_standard");
- auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
+ auto notes = dcp::verify({dir}, &stage, &progress, {}, xsd_test);
path const cpl_file = dir / "cpl_cbfd2bc0-21cf-4a8f-95d8-9cddcbe51296.xml";
path const pkl_file = dir / "pkl_d87a950c-bd6f-41f6-90cc-56ccd673e131.xml";
}
+BOOST_AUTO_TEST_CASE(verify_interop_subtitle_asset_with_no_subtitles)
+{
+ path const dir("build/test/verify_interop_subtitle_asset_with_no_subtitles");
+ prepare_directory(dir);
+ copy_file("test/data/subs4.xml", dir / "subs.xml");
+ auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
+ auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
+ write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
+
+ check_verify_result (
+ { dir },
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get()) },
+ });
+
+}
+
+
BOOST_AUTO_TEST_CASE (verify_valid_smpte_subtitles)
{
path const dir("build/test/verify_valid_smpte_subtitles");
auto reel_asset = make_shared<dcp::ReelSMPTESubtitleAsset>(asset, dcp::Fraction(24, 1), 6046, 0);
auto cpl = write_dcp_with_single_asset (dir, reel_asset);
- check_verify_result ({dir}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-04-14T13:19:14.000+02:00"} }
+ });
}
},
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2020-05-09T00:29:21.000+02:00"} }
});
}
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-08-09T18:34:46.000+02:00"} }
});
}
check_verify_result (
{ dir },
{
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get()) },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT },
});
}
+path
+find_prefix(path dir, string prefix)
+{
+ auto iter = std::find_if(directory_iterator(dir), directory_iterator(), [prefix](path const& p) {
+ return boost::starts_with(p.filename().string(), prefix);
+ });
+
+ BOOST_REQUIRE(iter != directory_iterator());
+ return iter->path();
+}
+
+
path find_cpl (path dir)
{
- for (auto i: directory_iterator(dir)) {
- if (boost::starts_with(i.path().filename().string(), "cpl_")) {
- return i.path();
- }
- }
+ return find_prefix(dir, "cpl_");
+}
+
+
+path
+find_pkl(path dir)
+{
+ return find_prefix(dir, "pkl_");
+}
- BOOST_REQUIRE (false);
- return {};
+
+path
+find_asset_map(path dir)
+{
+ return find_prefix(dir, "ASSETMAP");
}
cpl->set_issue_date ("2012-07-17T04:45:18+00:00");
cpl->set_main_sound_configuration ("L,C,R,Lfe,-,-");
cpl->set_main_sound_sample_rate (48000);
- cpl->set_main_picture_stored_area (dcp::Size(1998, 1080));
- cpl->set_main_picture_active_area (dcp::Size(1998, 1080));
+ cpl->set_main_picture_stored_area(dcp::Size(width, height));
+ cpl->set_main_picture_active_area(dcp::Size(width, height));
cpl->set_version_number (1);
auto reel = make_shared<dcp::Reel>();
d->set_annotation_text("A Test DCP");
d->write_xml();
- return dcp::verify ({dcp_path}, &stage, &progress, xsd_test);
+ return dcp::verify({dcp_path}, &stage, &progress, {}, xsd_test);
}
{
dcp::VerificationNote::Type::BV21_ERROR,
dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
- string("419346"),
+ string("419336"),
canonical(dir / "subs.mxf")
},
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
check_verify_result (
{ dir },
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695542"), canonical(dir / "subs.mxf") },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695532"), canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
{ dir },
{
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
});
}
{dir},
{
{ dcp::VerificationNote::Type::BV21_ERROR, code, subs->id() },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
});
}
"<Id>urn:uuid:%1</Id>"
"<ContentTitleText>Content</ContentTitleText>"
"<AnnotationText>Annotation</AnnotationText>"
- "<IssueDate>2018-10-02T12:25:14+02:00</IssueDate>"
+ "<IssueDate>2018-10-02T12:25:14</IssueDate>"
"<ReelNumber>1</ReelNumber>"
"<Language>en-US</Language>"
"<EditRate>25 1</EditRate>"
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf) },
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID },
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2018-10-02T12:25:14+02:00"} }
});
}
});
}
+
+
+BOOST_AUTO_TEST_CASE(verify_invalid_main_picture_active_area_1)
+{
+ path dir = "build/test/verify_invalid_main_picture_active_area_1";
+ prepare_directory(dir);
+ auto dcp = make_simple(dir, 1, 24);
+ dcp->write_xml();
+
+ auto constexpr area = "<meta:MainPictureActiveArea>";
+
+ {
+ Editor e(find_cpl(dir));
+ e.delete_lines_after(area, 2);
+ e.insert(area, "<meta:Height>4080</meta:Height>");
+ e.insert(area, "<meta:Width>1997</meta:Width>");
+ }
+
+ dcp::PKL pkl(find_pkl(dir));
+ dcp::CPL cpl(find_cpl(dir));
+
+ check_verify_result(
+ { dir },
+ {
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir)) },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, pkl.id(), canonical(find_pkl(dir)), },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 1997 is not a multiple of 2", canonical(find_cpl(dir)) },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 4080 is bigger than the asset height 1080", canonical(find_cpl(dir)) },
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE(verify_invalid_main_picture_active_area_2)
+{
+ path dir = "build/test/verify_invalid_main_picture_active_area_2";
+ prepare_directory(dir);
+ auto dcp = make_simple(dir, 1, 24);
+ dcp->write_xml();
+
+ auto constexpr area = "<meta:MainPictureActiveArea>";
+
+ {
+ Editor e(find_cpl(dir));
+ e.delete_lines_after(area, 2);
+ e.insert(area, "<meta:Height>5125</meta:Height>");
+ e.insert(area, "<meta:Width>9900</meta:Width>");
+ }
+
+ dcp::PKL pkl(find_pkl(dir));
+ dcp::CPL cpl(find_cpl(dir));
+
+ check_verify_result(
+ { dir },
+ {
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir)) },
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, pkl.id(), canonical(find_pkl(dir)), },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is not a multiple of 2", canonical(find_cpl(dir)) },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 9900 is bigger than the asset width 1998", canonical(find_cpl(dir)) },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is bigger than the asset height 1080", canonical(find_cpl(dir)) },
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE(verify_duplicate_pkl_asset_ids)
+{
+ RNGFixer rg;
+
+ path dir = "build/test/verify_duplicate_pkl_asset_ids";
+ prepare_directory(dir);
+ auto dcp = make_simple(dir, 1, 24);
+ dcp->write_xml();
+
+ {
+ Editor e(find_pkl(dir));
+ e.replace("urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54", "urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab");
+ }
+
+ dcp::PKL pkl(find_pkl(dir));
+
+ check_verify_result(
+ { dir },
+ {
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl.id(), canonical(find_pkl(dir)) },
+ });
+}
+
+
+BOOST_AUTO_TEST_CASE(verify_duplicate_assetmap_asset_ids)
+{
+ RNGFixer rg;
+
+ path dir = "build/test/verify_duplicate_assetmap_asset_ids";
+ prepare_directory(dir);
+ auto dcp = make_simple(dir, 1, 24);
+ dcp->write_xml();
+
+ {
+ Editor e(find_asset_map(dir));
+ e.replace("urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54", "urn:uuid:97f0f352-5b77-48ee-a558-9df37717f4fa");
+ }
+
+ dcp::PKL pkl(find_pkl(dir));
+ dcp::AssetMap asset_map(find_asset_map(dir));
+
+ check_verify_result(
+ { dir },
+ {
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, pkl.id(), canonical(find_pkl(dir)), },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP, asset_map.id(), canonical(find_asset_map(dir)) },
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EXTERNAL_ASSET, string("5407b210-4441-4e97-8b16-8bdc7c12da54") },
+ });
+}
+