Fix tests after change to working directories.
[dcpomatic.git] / test / test.cc
index 9b08dfb4e8619c8fe00cc70a16ae5e3b81fd69a6..acbc97ea13557ad398aa1883ed361025ec57ed16 100644 (file)
 #include <dcp/dcp.h>
 #include <dcp/equality_options.h>
 #include <dcp/filesystem.h>
-#include <dcp/mono_picture_asset.h>
-#include <dcp/mono_picture_frame.h>
+#include <dcp/mono_j2k_picture_asset.h>
+#include <dcp/mono_j2k_picture_frame.h>
 #include <dcp/openjpeg_image.h>
 #include <dcp/reel.h>
 #include <dcp/reel_picture_asset.h>
+#include <dcp/scope_guard.h>
 #include <dcp/warnings.h>
 #include <asdcp/AS_DCP.h>
 #include <png.h>
@@ -81,6 +82,7 @@ using std::min;
 using std::shared_ptr;
 using std::string;
 using std::vector;
+using boost::optional;
 using boost::scoped_array;
 using std::dynamic_pointer_cast;
 #if BOOST_VERSION >= 106100
@@ -118,12 +120,8 @@ setup_test_config ()
        Config::instance()->set_master_encoding_threads (boost::thread::hardware_concurrency() / 2);
        Config::instance()->set_server_encoding_threads (1);
        Config::instance()->set_server_port_base (61921);
-       Config::instance()->set_default_dcp_content_type (static_cast<DCPContentType*> (0));
        Config::instance()->set_default_audio_delay (0);
-       Config::instance()->set_default_j2k_bandwidth (100000000);
-       Config::instance()->set_default_interop (false);
        Config::instance()->set_default_still_length (10);
-       Config::instance()->set_default_dcp_audio_channels(8);
        Config::instance()->set_log_types (
                LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING |
                LogEntry::TYPE_ERROR | LogEntry::TYPE_DISK
@@ -136,7 +134,8 @@ setup_test_config ()
        decryption->set_key(dcp::file_to_string("test/data/decryption_key"));
        Config::instance()->set_decryption_chain (decryption);
        Config::instance()->set_dcp_asset_filename_format(dcp::NameFormat("%t"));
-       Config::instance()->set_cinemas_file("test/data/empty_cinemas.xml");
+       Config::instance()->set_cinemas_file("build/test/cinemas.sqlite3");
+       Config::instance()->set_dkdm_recipients_file("build/test/dkdm_recipients.sqlite3");
 }
 
 
@@ -161,11 +160,21 @@ struct TestConfig
                setup_test_config ();
                capture_ffmpeg_logs();
 
-               EncodeServerFinder::instance()->stop ();
+               EncodeServerFinder::drop();
 
                signal_manager = new TestSignalManager ();
 
                dcpomatic_log.reset (new FileLog("build/test/log"));
+
+               auto const& suite = boost::unit_test::framework::master_test_suite();
+               int types = LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING | LogEntry::TYPE_ERROR;
+               for (int i = 1; i < suite.argc; ++i) {
+                       if (string(suite.argv[i]) == "--log=debug-player") {
+                               types |= LogEntry::TYPE_DEBUG_PLAYER;
+                       }
+               }
+
+               dcpomatic_log->set_types(types);
        }
 
        ~TestConfig ()
@@ -190,21 +199,7 @@ test_film_dir (string name)
 
 
 shared_ptr<Film>
-new_test_film (string name)
-{
-       auto p = test_film_dir (name);
-       if (boost::filesystem::exists (p)) {
-               boost::filesystem::remove_all (p);
-       }
-
-       auto film = make_shared<Film>(p);
-       film->write_metadata ();
-       return film;
-}
-
-
-shared_ptr<Film>
-new_test_film2 (string name, vector<shared_ptr<Content>> content, Cleanup* cleanup)
+new_test_film(string name, vector<shared_ptr<Content>> content, Cleanup* cleanup)
 {
        auto p = test_film_dir (name);
        if (boost::filesystem::exists (p)) {
@@ -215,6 +210,7 @@ new_test_film2 (string name, vector<shared_ptr<Content>> content, Cleanup* clean
        }
 
        auto film = make_shared<Film>(p);
+       film->use_template({});
        film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
        film->set_container (Ratio::from_id ("185"));
        film->write_metadata ();
@@ -275,13 +271,14 @@ check_wav_file (boost::filesystem::path ref, boost::filesystem::path check)
 void
 check_mxf_audio_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
-       ASDCP::PCM::MXFReader ref_reader;
+       Kumu::FileReaderFactory factory;
+       ASDCP::PCM::MXFReader ref_reader(factory);
        BOOST_REQUIRE (!ASDCP_FAILURE (ref_reader.OpenRead (ref.string().c_str())));
 
        ASDCP::PCM::AudioDescriptor ref_desc;
        BOOST_REQUIRE (!ASDCP_FAILURE (ref_reader.FillAudioDescriptor (ref_desc)));
 
-       ASDCP::PCM::MXFReader check_reader;
+       ASDCP::PCM::MXFReader check_reader(factory);
        BOOST_REQUIRE (!ASDCP_FAILURE (check_reader.OpenRead (check.string().c_str())));
 
        ASDCP::PCM::AudioDescriptor check_desc;
@@ -304,13 +301,14 @@ check_mxf_audio_file (boost::filesystem::path ref, boost::filesystem::path check
 bool
 mxf_atmos_files_same (boost::filesystem::path ref, boost::filesystem::path check, bool verbose)
 {
-       ASDCP::ATMOS::MXFReader ref_reader;
+       Kumu::FileReaderFactory factory;
+       ASDCP::ATMOS::MXFReader ref_reader(factory);
        BOOST_REQUIRE (!ASDCP_FAILURE(ref_reader.OpenRead(ref.string().c_str())));
 
        ASDCP::ATMOS::AtmosDescriptor ref_desc;
        BOOST_REQUIRE (!ASDCP_FAILURE(ref_reader.FillAtmosDescriptor(ref_desc)));
 
-       ASDCP::ATMOS::MXFReader check_reader;
+       ASDCP::ATMOS::MXFReader check_reader(factory);
        BOOST_REQUIRE (!ASDCP_FAILURE(check_reader.OpenRead(check.string().c_str())));
 
        ASDCP::ATMOS::AtmosDescriptor check_desc;
@@ -572,7 +570,13 @@ check_dcp(boost::filesystem::path ref, boost::filesystem::path check, bool sound
 }
 
 void
-check_xml (xmlpp::Element* ref, xmlpp::Element* test, list<string> ignore)
+check_xml(
+       xmlpp::Element* ref,
+       xmlpp::Element* test,
+       list<Glib::ustring> ignore,
+       optional<boost::filesystem::path> ref_file,
+       optional<boost::filesystem::path> test_file
+       )
 {
        BOOST_CHECK_EQUAL (ref->get_name (), test->get_name ());
        BOOST_CHECK_EQUAL (ref->get_namespace_prefix (), test->get_namespace_prefix ());
@@ -583,9 +587,13 @@ check_xml (xmlpp::Element* ref, xmlpp::Element* test, list<string> ignore)
 
        auto ref_children = ref->get_children ();
        auto test_children = test->get_children ();
+       string context;
+       if (ref_file && test_file) {
+               context = String::compose(" comparing %1 and %2", ref_file->string(), test_file->string());
+       }
        BOOST_REQUIRE_MESSAGE (
                ref_children.size() == test_children.size(),
-               ref->get_name() << " has " << ref_children.size() << " or " << test_children.size() << " children"
+               ref->get_name() << " has " << ref_children.size() << " or " << test_children.size() << " children" << context
                );
 
        auto k = ref_children.begin ();
@@ -598,7 +606,7 @@ check_xml (xmlpp::Element* ref, xmlpp::Element* test, list<string> ignore)
                auto test_el = dynamic_cast<xmlpp::Element*>(*l);
                BOOST_CHECK ((ref_el && test_el) || (!ref_el && !test_el));
                if (ref_el && test_el) {
-                       check_xml (ref_el, test_el, ignore);
+                       check_xml(ref_el, test_el, ignore, ref_file, test_file);
                }
 
                auto ref_cn = dynamic_cast<xmlpp::ContentNode*>(*k);
@@ -628,14 +636,14 @@ check_xml (xmlpp::Element* ref, xmlpp::Element* test, list<string> ignore)
 }
 
 void
-check_xml (boost::filesystem::path ref, boost::filesystem::path test, list<string> ignore)
+check_xml(boost::filesystem::path ref, boost::filesystem::path test, list<Glib::ustring> ignore)
 {
        auto ref_parser = new xmlpp::DomParser(ref.string());
        auto ref_root = ref_parser->get_document()->get_root_node();
        auto test_parser = new xmlpp::DomParser(test.string());
        auto test_root = test_parser->get_document()->get_root_node();
 
-       check_xml (ref_root, test_root, ignore);
+       check_xml(ref_root, test_root, ignore, ref, test);
 }
 
 bool
@@ -815,22 +823,25 @@ check_one_frame (boost::filesystem::path dcp_dir, int64_t index, boost::filesyst
 {
        dcp::DCP dcp (dcp_dir);
        dcp.read ();
-       auto asset = dynamic_pointer_cast<dcp::MonoPictureAsset> (dcp.cpls().front()->reels().front()->main_picture()->asset());
+       auto asset = dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(dcp.cpls().front()->reels().front()->main_picture()->asset());
        BOOST_REQUIRE (asset);
        auto frame = asset->start_read()->get_frame(index);
-       auto ref_frame (new dcp::MonoPictureFrame (ref));
+       dcp::MonoJ2KPictureFrame ref_frame(ref);
 
        auto image = frame->xyz_image ();
-       auto ref_image = ref_frame->xyz_image ();
+       auto ref_image = ref_frame.xyz_image();
 
        BOOST_REQUIRE (image->size() == ref_image->size());
 
        int off = 0;
        for (int y = 0; y < ref_image->size().height; ++y) {
                for (int x = 0; x < ref_image->size().width; ++x) {
-                       BOOST_REQUIRE_EQUAL (ref_image->data(0)[off], image->data(0)[off]);
-                       BOOST_REQUIRE_EQUAL (ref_image->data(1)[off], image->data(1)[off]);
-                       BOOST_REQUIRE_EQUAL (ref_image->data(2)[off], image->data(2)[off]);
+                       auto x_error = std::abs(ref_image->data(0)[off] - image->data(0)[off]);
+                       BOOST_REQUIRE_MESSAGE(x_error == 0, "x component at " << x << "," << y << " differs by " << x_error);
+                       auto y_error = std::abs(ref_image->data(1)[off] - image->data(1)[off]);
+                       BOOST_REQUIRE_MESSAGE(y_error == 0, "y component at " << x << "," << y << " differs by " << y_error);
+                       auto z_error = std::abs(ref_image->data(2)[off] - image->data(2)[off]);
+                       BOOST_REQUIRE_MESSAGE(z_error == 0, "z component at " << x << "," << y << " differs by " << z_error);
                        ++off;
                }
        }
@@ -843,7 +854,7 @@ dcp_file (shared_ptr<const Film> film, string prefix)
 
        vector<directory_entry> matches;
        std::copy_if(recursive_directory_iterator(film->dir(film->dcp_name())), recursive_directory_iterator(), std::back_inserter(matches), [&prefix](directory_entry const& entry) {
-               return boost::algorithm::starts_with(entry.path().leaf().string(), prefix);
+               return boost::algorithm::starts_with(entry.path().filename().string(), prefix);
        });
 
        BOOST_REQUIRE_MESSAGE(matches.size() == 1, "Found " << matches.size() << " files with prefix " << prefix);
@@ -854,7 +865,7 @@ boost::filesystem::path
 subtitle_file (shared_ptr<Film> film)
 {
        for (auto i: boost::filesystem::recursive_directory_iterator(film->directory().get() / film->dcp_name(false))) {
-               if (boost::algorithm::starts_with(i.path().leaf().string(), "sub_")) {
+               if (boost::algorithm::starts_with(i.path().filename().string(), "sub_")) {
                        return i.path();
                }
        }
@@ -948,10 +959,10 @@ void progress (float) {}
 void
 verify_dcp(boost::filesystem::path dir, vector<dcp::VerificationNote::Code> ignore)
 {
-       auto notes = dcp::verify({dir}, &stage, &progress, {}, TestPaths::xsd());
+       auto result = dcp::verify({dir}, {}, &stage, &progress, {}, TestPaths::xsd());
        bool ok = true;
-       for (auto i: notes) {
-               if (find(ignore.begin(), ignore.end(), i.code()) == ignore.end()) {
+       for (auto i: result.notes) {
+               if (i.type() != dcp::VerificationNote::Type::OK && find(ignore.begin(), ignore.end(), i.code()) == ignore.end()) {
                        std::cout << "\t" << dcp::note_to_string(i) << "\n";
                        ok = false;
                }
@@ -961,12 +972,52 @@ verify_dcp(boost::filesystem::path dir, vector<dcp::VerificationNote::Code> igno
 
 
 void
-make_and_verify_dcp (shared_ptr<Film> film, vector<dcp::VerificationNote::Code> ignore)
+#ifdef  DCPOMATIC_LINUX
+make_and_verify_dcp(shared_ptr<Film> film, vector<dcp::VerificationNote::Code> ignore, bool dcp_inspect, bool clairmeta)
+#else
+make_and_verify_dcp(shared_ptr<Film> film, vector<dcp::VerificationNote::Code> ignore, bool, bool)
+#endif
 {
        film->write_metadata ();
        make_dcp (film, TranscodeJob::ChangedBehaviour::IGNORE);
        BOOST_REQUIRE (!wait_for_jobs());
        verify_dcp({film->dir(film->dcp_name())}, ignore);
+
+#ifdef DCPOMATIC_LINUX
+       auto test_tools_path_env = getenv("DCPOMATIC_TEST_TOOLS_PATH");
+       string test_tools_path;
+       if (test_tools_path_env) {
+               test_tools_path = test_tools_path_env;
+       }
+
+       auto old_path_env = getenv("PATH");
+       string old_path;
+       if (old_path_env) {
+               old_path = old_path_env;
+       }
+
+       dcp::ScopeGuard sg = [old_path]() { setenv("PATH", old_path.c_str(), 1); };
+       string new_path = old_path;
+       if (!new_path.empty()) {
+               new_path += ":";
+       }
+       new_path += test_tools_path;
+       setenv("PATH", new_path.c_str(), 1);
+
+       auto dcp_inspect_env = getenv("DCPOMATIC_DCP_INSPECT");
+       if (dcp_inspect && dcp_inspect_env) {
+               boost::filesystem::path dcp_inspect(dcp_inspect_env);
+               auto cmd = String::compose("%1 %2 > %3 2>&1", dcp_inspect, film->dir(film->dcp_name()), film->file("dcp_inspect.log"));
+               auto result = system(cmd.c_str());
+               BOOST_CHECK_EQUAL(WEXITSTATUS(result), 0);
+       }
+
+       if (clairmeta && getenv("DCPOMATIC_CLAIRMETA")) {
+               auto cmd = String::compose("python3 -m clairmeta.cli check -type dcp %1 > %2 2>&1", film->dir(film->dcp_name()), film->file("clairmeta.log"));
+               auto result = system(cmd.c_str());
+               BOOST_CHECK_EQUAL(WEXITSTATUS(result), 0);
+       }
+#endif
 }
 
 
@@ -985,8 +1036,16 @@ check_int_close (std::pair<int, int> a, std::pair<int, int> b, int d)
 }
 
 
+ConfigRestorer::ConfigRestorer(boost::filesystem::path override_path)
+{
+       Config::override_path = override_path;
+       Config::drop();
+}
+
+
 ConfigRestorer::~ConfigRestorer()
 {
+       Config::override_path = boost::none;
        setup_test_config();
 }