Fix a load of stuff that wasn't being freed on close.
[dcpomatic.git] / test / test.cc
index 6c811221d9a3de55d7ef03017cf602f9d0e7739c..7136b038d99bbb9c28bc1a8569cdb0f6b226e72f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 */
 
+
+
 /** @file  test/test.cc
  *  @brief Overall test stuff and useful methods for tests.
  */
 
+
 #include "lib/compose.hpp"
 #include "lib/config.h"
 #include "lib/cross.h"
@@ -35,6 +38,7 @@
 #include "lib/job.h"
 #include "lib/job_manager.h"
 #include "lib/log_entry.h"
+#include "lib/make_dcp.h"
 #include "lib/ratio.h"
 #include "lib/signal_manager.h"
 #include "lib/util.h"
@@ -61,6 +65,7 @@ extern "C" {
 #include <list>
 #include <vector>
 
+
 using std::abs;
 using std::cerr;
 using std::cout;
@@ -95,13 +100,12 @@ boost::filesystem::path TestPaths::xsd ()
 }
 
 
-void
+static void
 setup_test_config ()
 {
-       Config::instance()->set_master_encoding_threads (boost::thread::hardware_concurrency());
+       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_isdcf_metadata (ISDCFMetadata ());
        Config::instance()->set_default_container (Ratio::from_id ("185"));
        Config::instance()->set_default_dcp_content_type (static_cast<DCPContentType*> (0));
        Config::instance()->set_default_audio_delay (0);
@@ -110,18 +114,23 @@ setup_test_config ()
        Config::instance()->set_default_still_length (10);
        Config::instance()->set_log_types (
                LogEntry::TYPE_GENERAL | LogEntry::TYPE_WARNING |
-               LogEntry::TYPE_ERROR | LogEntry::TYPE_DEBUG_THREE_D |
-               LogEntry::TYPE_DEBUG_ENCODE | LogEntry::TYPE_DEBUG_PLAYER |
-               LogEntry::TYPE_DISK
+               LogEntry::TYPE_ERROR | LogEntry::TYPE_DISK
                );
        Config::instance()->set_automatic_audio_analysis (false);
+       auto signer = make_shared<dcp::CertificateChain>(dcp::file_to_string("test/data/signer_chain"));
+       signer->set_key(dcp::file_to_string("test/data/signer_key"));
+       Config::instance()->set_signer_chain (signer);
+       auto decryption = make_shared<dcp::CertificateChain>(dcp::file_to_string("test/data/decryption_chain"));
+       decryption->set_key(dcp::file_to_string("test/data/decryption_key"));
+       Config::instance()->set_decryption_chain (decryption);
 }
 
+
 class TestSignalManager : public SignalManager
 {
 public:
        /* No wakes in tests: we call ui_idle ourselves */
-       void wake_ui ()
+       void wake_ui () override
        {
 
        }
@@ -150,8 +159,10 @@ struct TestConfig
        }
 };
 
+
 BOOST_GLOBAL_FIXTURE (TestConfig);
 
+
 boost::filesystem::path
 test_film_dir (string name)
 {
@@ -162,6 +173,7 @@ test_film_dir (string name)
        return p;
 }
 
+
 shared_ptr<Film>
 new_test_film (string name)
 {
@@ -175,21 +187,32 @@ new_test_film (string name)
        return film;
 }
 
+
 shared_ptr<Film>
-new_test_film2 (string name)
+new_test_film2 (string name, vector<shared_ptr<Content>> content, Cleanup* cleanup)
 {
        auto p = test_film_dir (name);
        if (boost::filesystem::exists (p)) {
                boost::filesystem::remove_all (p);
        }
+       if (cleanup) {
+               cleanup->add (p);
+       }
 
        auto film = make_shared<Film>(p);
        film->set_dcp_content_type (DCPContentType::from_isdcf_name ("TST"));
        film->set_container (Ratio::from_id ("185"));
        film->write_metadata ();
+
+       for (auto i: content) {
+               film->examine_and_add_content (i);
+               BOOST_REQUIRE (!wait_for_jobs());
+       }
+
        return film;
 }
 
+
 void
 check_wav_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
@@ -233,6 +256,7 @@ check_wav_file (boost::filesystem::path ref, boost::filesystem::path check)
        }
 }
 
+
 void
 check_mxf_audio_file (boost::filesystem::path ref, boost::filesystem::path check)
 {
@@ -340,13 +364,15 @@ static
 double
 rms_error (boost::filesystem::path ref, boost::filesystem::path check)
 {
-       FFmpegImageProxy ref_proxy (ref, VideoRange::FULL);
-       auto ref_image = ref_proxy.image().image;
-       FFmpegImageProxy check_proxy (check, VideoRange::FULL);
-       auto check_image = check_proxy.image().image;
+       FFmpegImageProxy ref_proxy (ref);
+       auto ref_image = ref_proxy.image(Image::Alignment::COMPACT).image;
+       FFmpegImageProxy check_proxy (check);
+       auto check_image = check_proxy.image(Image::Alignment::COMPACT).image;
+
+       BOOST_REQUIRE_EQUAL (ref_image->planes(), check_image->planes());
 
        BOOST_REQUIRE_EQUAL (ref_image->pixel_format(), check_image->pixel_format());
-       AVPixelFormat const format = ref_image->pixel_format();
+       auto const format = ref_image->pixel_format();
 
        BOOST_REQUIRE (ref_image->size() == check_image->size());
        int const width = ref_image->size().width;
@@ -393,6 +419,19 @@ rms_error (boost::filesystem::path ref, boost::filesystem::path check)
                        }
                        break;
                }
+               case AV_PIX_FMT_YUVJ420P:
+               {
+                       for (int c = 0; c < ref_image->planes(); ++c) {
+                               for (int y = 0; y < height / ref_image->vertical_factor(c); ++y) {
+                                       auto p = ref_image->data()[c] + y * ref_image->stride()[c];
+                                       auto q = check_image->data()[c] + y * check_image->stride()[c];
+                                       for (int x = 0; x < ref_image->line_size()[c]; ++x) {
+                                               sum_square += pow((*p++ - *q++), 2);
+                                       }
+                               }
+                       }
+                       break;
+               }
                default:
                        BOOST_REQUIRE_MESSAGE (false, "unrecognised pixel format " << format);
        }
@@ -456,6 +495,39 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
        fclose (check_file);
 }
 
+
+void
+check_text_file (boost::filesystem::path ref, boost::filesystem::path check)
+{
+       auto ref_file = fopen_boost (ref, "r");
+       BOOST_CHECK (ref_file);
+       auto check_file = fopen_boost (check, "r");
+       BOOST_CHECK (check_file);
+
+       int const buffer_size = std::max(
+               boost::filesystem::file_size(ref),
+               boost::filesystem::file_size(check)
+               );
+
+       DCPOMATIC_ASSERT (buffer_size < 1024 * 1024);
+
+       auto ref_buffer = new uint8_t[buffer_size];
+       auto ref_read = fread(ref_buffer, 1, buffer_size, ref_file);
+       auto check_buffer = new uint8_t[buffer_size];
+       auto check_read = fread(check_buffer, 1, buffer_size, check_file);
+       BOOST_CHECK_EQUAL (ref_read, check_read);
+
+       string const error = "File " + check.string() + " differs from reference " + ref.string();
+       BOOST_CHECK_MESSAGE(memcmp(ref_buffer, check_buffer, ref_read) == 0, error);
+
+       delete[] ref_buffer;
+       delete[] check_buffer;
+
+       fclose (ref_file);
+       fclose (check_file);
+}
+
+
 static void
 note (dcp::NoteType t, string n)
 {
@@ -642,9 +714,9 @@ png_flush (png_structp)
 
 
 static void
-png_error_fn (png_structp png_ptr, char const * message)
+png_error_fn (png_structp, char const * message)
 {
-       reinterpret_cast<Image*>(png_get_error_ptr(png_ptr))->png_error (message);
+       throw EncodeError (String::compose("Error during PNG write: %1", message));
 }
 
 
@@ -811,3 +883,63 @@ operator<< (std::ostream&s, VideoFrameType f)
        return s;
 }
 
+
+void
+Cleanup::add (boost::filesystem::path path)
+{
+       _paths.push_back (path);
+}
+
+
+void
+Cleanup::run ()
+{
+       boost::system::error_code ec;
+       for (auto i: _paths) {
+               boost::filesystem::remove_all (i, ec);
+       }
+}
+
+
+void stage (string, boost::optional<boost::filesystem::path>) {}
+void progress (float) {}
+
+
+void
+make_and_verify_dcp (shared_ptr<Film> film, vector<dcp::VerificationNote::Code> ignore)
+{
+       film->write_metadata ();
+       make_dcp (film, TranscodeJob::ChangedBehaviour::IGNORE);
+       BOOST_REQUIRE (!wait_for_jobs());
+       auto notes = dcp::verify ({film->dir(film->dcp_name())}, &stage, &progress, TestPaths::xsd());
+       bool ok = true;
+       for (auto i: notes) {
+               if (find(ignore.begin(), ignore.end(), i.code()) == ignore.end()) {
+                       std::cout << "\t" << dcp::note_to_string(i) << "\n";
+                       ok = false;
+               }
+       }
+       BOOST_CHECK(ok);
+}
+
+
+void
+check_int_close (int a, int b, int d)
+{
+       BOOST_CHECK_MESSAGE (std::abs(a - b) < d, a << " differs from " << b << " by more than " << d);
+}
+
+
+void
+check_int_close (std::pair<int, int> a, std::pair<int, int> b, int d)
+{
+       check_int_close (a.first, b.first, d);
+       check_int_close (a.second, b.second, d);
+}
+
+
+ConfigRestorer::~ConfigRestorer()
+{
+       setup_test_config();
+}
+