Cleanup: replace some list with vector.
[dcpomatic.git] / test / config_test.cc
index d22e635c826a93713b0fb067158f11217a992370..103a6a58555ac0f181353afac8f6f257c14f495d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 */
 
+
+#include "lib/cinema.h"
 #include "lib/config.h"
 #include "test.h"
 #include <boost/test/unit_test.hpp>
 #include <fstream>
 
+
+using std::make_shared;
 using std::ofstream;
+using std::string;
+using std::vector;
+using boost::optional;
 
-static void
-rewrite_bad_config ()
+
+static string
+rewrite_bad_config (string filename, string extra_line)
 {
+       using namespace boost::filesystem;
+
+       auto base = path("build/test/bad_config/2.16");
+       auto file = base / filename;
+
        boost::system::error_code ec;
-       boost::filesystem::remove ("build/test/bad_config/config.xml", ec);
+       remove (file, ec);
 
-       Config::override_path = "build/test/bad_config";
-       boost::filesystem::create_directories ("build/test/bad_config");
-       ofstream f ("build/test/bad_config/config.xml");
+       boost::filesystem::create_directories (base);
+       std::ofstream f (file.string().c_str());
        f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
          << "<Config>\n"
          << "<Foo></Foo>\n"
+         << extra_line << "\n"
          << "</Config>\n";
        f.close ();
+
+       return dcp::file_to_string (file);
 }
 
 
 BOOST_AUTO_TEST_CASE (config_backup_test)
 {
-       Config::override_path = "build/test/bad_config";
+       ConfigRestorer cr;
 
+       Config::override_path = "build/test/bad_config";
        Config::drop();
-
        boost::filesystem::remove_all ("build/test/bad_config");
 
-       rewrite_bad_config();
+       /* Write an invalid config file to config.xml */
+       auto const first_write_xml = rewrite_bad_config("config.xml", "first write");
 
+       /* Load the config; this should fail, causing the bad config to be copied to config.xml.1
+        * and a new config.xml created in its place.
+        */
        Config::instance();
 
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.1") == first_write_xml);
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
 
        Config::drop();
-       rewrite_bad_config();
+       auto const second_write_xml = rewrite_bad_config("config.xml", "second write");
        Config::instance();
 
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.1") == first_write_xml);
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.2") == second_write_xml);
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
 
        Config::drop();
-       rewrite_bad_config();
+       auto const third_write_xml = rewrite_bad_config("config.xml", "third write");
        Config::instance();
 
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
-       BOOST_CHECK ( boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
-       BOOST_CHECK (!boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.1") == first_write_xml);
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.2") == second_write_xml);
+       BOOST_CHECK ( boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.3") == third_write_xml);
+       BOOST_CHECK (!boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
 
        Config::drop();
-       rewrite_bad_config();
+       auto const fourth_write_xml = rewrite_bad_config("config.xml", "fourth write");
        Config::instance();
 
-       BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.1"));
-       BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.2"));
-       BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.3"));
-       BOOST_CHECK (boost::filesystem::exists ("build/test/bad_config/config.xml.4"));
+       BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.1"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.1") == first_write_xml);
+       BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.2"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.2") == second_write_xml);
+       BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.3"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.3") == third_write_xml);
+       BOOST_CHECK (boost::filesystem::exists("build/test/bad_config/2.16/config.xml.4"));
+       BOOST_CHECK (dcp::file_to_string("build/test/bad_config/2.16/config.xml.4") == fourth_write_xml);
+}
+
+
+BOOST_AUTO_TEST_CASE (config_backup_with_link_test)
+{
+       using namespace boost::filesystem;
+
+       ConfigRestorer cr;
+
+       auto base = path("build/test/bad_config");
+       auto version = base / "2.16";
 
-       /* This test has called Config::set_defaults(), so take us back
-          to the config that we want for our tests.
-       */
-       setup_test_config ();
+       Config::override_path = base;
+       Config::drop();
+
+       boost::filesystem::remove_all (base);
+
+       boost::filesystem::create_directories (version);
+       std::ofstream f (path(version / "config.xml").string().c_str());
+       f << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+         << "<Config>\n"
+         << "<Link>" << path(version / "actual.xml").string() << "</Link>\n"
+         << "</Config>\n";
+       f.close ();
+
+       Config::drop ();
+       /* Cause actual.xml to be backed up */
+       rewrite_bad_config ("actual.xml", "first write");
+       Config::instance ();
+
+       /* Make sure actual.xml was backed up to the right place */
+       BOOST_CHECK (boost::filesystem::exists(version / "actual.xml.1"));
 }
 
 
 BOOST_AUTO_TEST_CASE (config_write_utf8_test)
 {
+       ConfigRestorer cr;
+
        boost::filesystem::remove_all ("build/test/config.xml");
        boost::filesystem::copy_file ("test/data/utf8_config.xml", "build/test/config.xml");
        Config::override_path = "build/test";
        Config::drop ();
        Config::instance()->write();
 
-       check_file ("test/data/utf8_config.xml", "build/test/config.xml", false);
+       check_text_file ("test/data/utf8_config.xml", "build/test/config.xml");
+}
+
+
+BOOST_AUTO_TEST_CASE (config_upgrade_test)
+{
+       ConfigRestorer cr;
+
+       boost::filesystem::path dir = "build/test/config_upgrade_test";
+       Config::override_path = dir;
+       Config::drop ();
+       boost::filesystem::remove_all (dir);
+       boost::filesystem::create_directories (dir);
+
+       boost::filesystem::copy_file ("test/data/2.14.config.xml", dir / "config.xml");
+       boost::filesystem::copy_file ("test/data/2.14.cinemas.xml", dir / "cinemas.xml");
+       Config::instance();
+       try {
+               /* This will fail to write cinemas.xml since the link is to a non-existent directory */
+               Config::instance()->write();
+       } catch (...) {}
+
+       check_xml (dir / "config.xml", "test/data/2.14.config.xml", {});
+       check_xml (dir / "cinemas.xml", "test/data/2.14.cinemas.xml", {});
+#ifdef DCPOMATIC_WINDOWS
+       /* This file has the windows path for dkdm_recipients.xml (with backslashes) */
+       check_xml (dir / "2.16" / "config.xml", "test/data/2.16.config.windows.xml", {});
+#else
+       check_xml (dir / "2.16" / "config.xml", "test/data/2.16.config.xml", {});
+#endif
+       /* cinemas.xml is not copied into 2.16 as its format has not changed */
+       BOOST_REQUIRE (!boost::filesystem::exists(dir / "2.16" / "cinemas.xml"));
+}
+
+
+BOOST_AUTO_TEST_CASE (config_keep_cinemas_if_making_new_config)
+{
+       ConfigRestorer cr;
+
+       boost::filesystem::path dir = "build/test/config_keep_cinemas_if_making_new_config";
+       Config::override_path = dir;
+       Config::drop ();
+       boost::filesystem::remove_all (dir);
+       boost::filesystem::create_directories (dir);
+
+       Config::instance()->write();
+
+       Config::instance()->add_cinema(make_shared<Cinema>("My Great Cinema", vector<string>(), "", 0, 0));
+       Config::instance()->write();
+
+       boost::filesystem::copy_file (dir / "cinemas.xml", dir / "backup_for_test.xml");
+
+       Config::drop ();
+       boost::filesystem::remove (dir / "2.16" / "config.xml");
+       Config::instance();
+
+       check_text_file(dir / "backup_for_test.xml", dir / "cinemas.xml");
+}
+
+
+BOOST_AUTO_TEST_CASE(keep_config_if_cinemas_fail_to_load)
+{
+       ConfigRestorer cr;
+
+       /* Make a new config */
+       boost::filesystem::path dir = "build/test/keep_config_if_cinemas_fail_to_load";
+       Config::override_path = dir;
+       Config::drop();
+       boost::filesystem::remove_all(dir);
+       boost::filesystem::create_directories(dir);
+       Config::instance()->write();
+
+       auto const cinemas = dir / "cinemas.xml";
+
+       /* Back things up */
+       boost::filesystem::copy_file(dir / "2.16" / "config.xml", dir / "config_backup_for_test.xml");
+       boost::filesystem::copy_file(cinemas, dir / "cinemas_backup_for_test.xml");
+
+       /* Corrupt the cinemas */
+       Config::drop();
+       std::ofstream corrupt(cinemas.string().c_str());
+       corrupt << "foo\n";
+       corrupt.close();
+       Config::instance();
 
-       /* This test has called Config::set_defaults(), so take us back
-          to the config that we want for our tests.
-       */
-       setup_test_config ();
+       /* We should have a new cinemas.xml and the old config.xml */
+       check_text_file(dir / "2.16" / "config.xml", dir / "config_backup_for_test.xml");
+       check_text_file(cinemas, dir / "cinemas_backup_for_test.xml");
 }