Move UTC offset for KDMs from the cinema to the point of KDM creation (#2300).
[dcpomatic.git] / test / kdm_naming_test.cc
1 /*
2     Copyright (C) 2020-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 #include "lib/cinema.h"
23 #include "lib/config.h"
24 #include "lib/content_factory.h"
25 #include "lib/film.h"
26 #include "lib/kdm_with_metadata.h"
27 #include "lib/screen.h"
28 #include "test.h"
29 #include <boost/test/unit_test.hpp>
30
31
32 using std::dynamic_pointer_cast;
33 using std::list;
34 using std::make_shared;
35 using std::shared_ptr;
36 using std::string;
37 using std::vector;
38 using boost::optional;
39
40
41 static
42 bool
43 confirm_overwrite (boost::filesystem::path)
44 {
45         return true;
46 }
47
48
49 static shared_ptr<dcpomatic::Screen> cinema_a_screen_1;
50 static shared_ptr<dcpomatic::Screen> cinema_a_screen_2;
51 static shared_ptr<dcpomatic::Screen> cinema_b_screen_x;
52 static shared_ptr<dcpomatic::Screen> cinema_b_screen_y;
53 static shared_ptr<dcpomatic::Screen> cinema_b_screen_z;
54
55
56 BOOST_AUTO_TEST_CASE (single_kdm_naming_test)
57 {
58         auto c = Config::instance();
59
60         auto crypt_cert = c->decryption_chain()->leaf();
61
62         auto cinema_a = make_shared<Cinema>("Cinema A", list<string>(), "");
63         cinema_a_screen_1 = std::make_shared<dcpomatic::Screen>("Screen 1", "", crypt_cert, boost::none, vector<TrustedDevice>());
64         cinema_a->add_screen (cinema_a_screen_1);
65         cinema_a_screen_2 = std::make_shared<dcpomatic::Screen>("Screen 2", "", crypt_cert, boost::none, vector<TrustedDevice>());
66         cinema_a->add_screen (cinema_a_screen_2);
67         c->add_cinema (cinema_a);
68
69         auto cinema_b = make_shared<Cinema>("Cinema B", list<string>(), "");
70         cinema_b_screen_x = std::make_shared<dcpomatic::Screen>("Screen X", "", crypt_cert, boost::none, vector<TrustedDevice>());
71         cinema_b->add_screen (cinema_b_screen_x);
72         cinema_b_screen_y = std::make_shared<dcpomatic::Screen>("Screen Y", "", crypt_cert, boost::none, vector<TrustedDevice>());
73         cinema_b->add_screen (cinema_b_screen_y);
74         cinema_b_screen_z = std::make_shared<dcpomatic::Screen>("Screen Z", "", crypt_cert, boost::none, vector<TrustedDevice>());
75         cinema_b->add_screen (cinema_b_screen_z);
76         c->add_cinema (cinema_a);
77
78         /* Film */
79         boost::filesystem::remove_all ("build/test/single_kdm_naming_test");
80         auto film = new_test_film2 ("single_kdm_naming_test");
81         film->set_name ("my_great_film");
82         film->examine_and_add_content (content_factory("test/data/flat_black.png")[0]);
83         BOOST_REQUIRE (!wait_for_jobs());
84         film->set_encrypted (true);
85         make_and_verify_dcp (film);
86         auto cpls = film->cpls ();
87         BOOST_REQUIRE(cpls.size() == 1);
88
89         auto sign_cert = c->signer_chain()->leaf();
90
91         dcp::LocalTime from = sign_cert.not_before();
92         from.set_offset({ 4, 30 });
93         from.add_months (2);
94         dcp::LocalTime until = sign_cert.not_after();
95         until.set_offset({ 4, 30 });
96         until.add_months (-2);
97
98         std::vector<KDMCertificatePeriod> period_checks;
99
100         auto cpl = cpls.front().cpl_file;
101         std::function<dcp::DecryptedKDM (dcp::LocalTime, dcp::LocalTime)> make_kdm = [film, cpl](dcp::LocalTime begin, dcp::LocalTime end) {
102                 return film->make_kdm(cpl, begin, end);
103         };
104         auto kdm = kdm_for_screen (
105                         make_kdm,
106                         cinema_a_screen_1,
107                         from,
108                         until,
109                         dcp::Formulation::MODIFIED_TRANSITIONAL_1,
110                         false,
111                         optional<int>(),
112                         period_checks
113                         );
114
115         write_files (
116                 { kdm },
117                 boost::filesystem::path("build/test/single_kdm_naming_test"),
118                 dcp::NameFormat("KDM %c - %s - %f - %b - %e"),
119                 &confirm_overwrite
120                 );
121
122         auto from_time = from.time_of_day (true, false);
123         boost::algorithm::replace_all (from_time, ":", "-");
124         auto until_time = until.time_of_day (true, false);
125         boost::algorithm::replace_all (until_time, ":", "-");
126
127         auto const dcp_date = boost::gregorian::to_iso_string(film->isdcf_date());
128         auto const ref = String::compose("KDM_Cinema_A_-_Screen_1_-_MyGreatFilm_TST-1_F_XX-XX_MOS_2K_%1_SMPTE_OV_-_%2_%3_-_%4_%5.xml", dcp_date, from.date(), from_time, until.date(), until_time);
129         BOOST_CHECK_MESSAGE (boost::filesystem::exists("build/test/single_kdm_naming_test/" + ref), "File " << ref << " not found");
130 }
131
132
133 BOOST_AUTO_TEST_CASE (directory_kdm_naming_test, * boost::unit_test::depends_on("single_kdm_naming_test"))
134 {
135         using boost::filesystem::path;
136
137         /* Film */
138         boost::filesystem::remove_all ("build/test/directory_kdm_naming_test");
139         auto film = new_test_film2 (
140                 "directory_kdm_naming_test",
141                 { content_factory("test/data/flat_black.png")[0] }
142                 );
143
144         film->set_name ("my_great_film");
145         film->set_encrypted (true);
146         make_and_verify_dcp (film);
147         auto cpls = film->cpls ();
148         BOOST_REQUIRE(cpls.size() == 1);
149
150         auto sign_cert = Config::instance()->signer_chain()->leaf();
151
152         dcp::LocalTime from (sign_cert.not_before());
153         from.add_months (2);
154         dcp::LocalTime until (sign_cert.not_after());
155         until.add_months (-2);
156
157         list<shared_ptr<dcpomatic::Screen>> screens = {
158                 cinema_a_screen_2, cinema_b_screen_x, cinema_a_screen_1, (cinema_b_screen_z)
159         };
160
161         auto const cpl = cpls.front().cpl_file;
162         auto const cpl_id = cpls.front().cpl_id;
163
164         std::vector<KDMCertificatePeriod> period_checks;
165         list<KDMWithMetadataPtr> kdms;
166
167         std::function<dcp::DecryptedKDM (dcp::LocalTime, dcp::LocalTime)> make_kdm = [film, cpls](dcp::LocalTime begin, dcp::LocalTime end) {
168                 return film->make_kdm(cpls.front().cpl_file, begin, end);
169         };
170
171         for (auto i: screens) {
172                 auto kdm = kdm_for_screen (
173                                 make_kdm,
174                                 i,
175                                 from,
176                                 until,
177                                 dcp::Formulation::MODIFIED_TRANSITIONAL_1,
178                                 false,
179                                 optional<int>(),
180                                 period_checks
181                                 );
182
183                 kdms.push_back (kdm);
184         }
185
186         write_directories (
187                 collect(kdms),
188                 path("build/test/directory_kdm_naming_test"),
189                 dcp::NameFormat("%c - %s - %f - %b - %e"),
190 #ifdef DCPOMATIC_WINDOWS
191                 /* Use a shorter name on Windows so that the paths aren't too long */
192                 dcp::NameFormat("KDM %f"),
193 #else
194                 dcp::NameFormat("KDM %c - %s - %f - %b - %e - %i"),
195 #endif
196                 &confirm_overwrite
197                 );
198
199         auto from_time = from.time_of_day (true, false);
200         boost::algorithm::replace_all (from_time, ":", "-");
201         auto until_time = until.time_of_day (true, false);
202         boost::algorithm::replace_all (until_time, ":", "-");
203
204         auto const dcp_date = boost::gregorian::to_iso_string(film->isdcf_date());
205         auto const dcp_name = String::compose("MyGreatFilm_TST-1_F_XX-XX_MOS_2K_%1_SMPTE_OV", dcp_date);
206         auto const common = String::compose("%1_-_%2_%3_-_%4_%5", dcp_name, from.date(), from_time, until.date(), until_time);
207
208         path const base = "build/test/directory_kdm_naming_test";
209
210         path dir_a = String::compose("Cinema_A_-_%s_-_%1", common);
211         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a), "Directory " << dir_a << " not found");
212         path dir_b = String::compose("Cinema_B_-_%s_-_%1", common);
213         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b), "Directory " << dir_b << " not found");
214
215 #ifdef DCPOMATIC_WINDOWS
216         path ref = String::compose("KDM_%1.xml", dcp_name);
217 #else
218         path ref = String::compose("KDM_Cinema_A_-_Screen_2_-_%1_-_%2.xml", common, cpl_id);
219 #endif
220         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a / ref), "File " << ref << " not found");
221
222 #ifdef DCPOMATIC_WINDOWS
223         ref = String::compose("KDM_%1.xml", dcp_name);
224 #else
225         ref = String::compose("KDM_Cinema_B_-_Screen_X_-_%1_-_%2.xml", common, cpl_id);
226 #endif
227         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b / ref), "File " << ref << " not found");
228
229 #ifdef DCPOMATIC_WINDOWS
230         ref = String::compose("KDM_%1.xml", dcp_name);
231 #else
232         ref = String::compose("KDM_Cinema_A_-_Screen_1_-_%1_-_%2.xml", common, cpl_id);
233 #endif
234         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_a / ref), "File " << ref << " not found");
235
236 #ifdef DCPOMATIC_WINDOWS
237         ref = String::compose("KDM_%1.xml", dcp_name);
238 #else
239         ref = String::compose("KDM_Cinema_B_-_Screen_Z_-_%1_-_%2.xml", common, cpl_id);
240 #endif
241         BOOST_CHECK_MESSAGE (boost::filesystem::exists(base / dir_b / ref), "File " << ref << " not found");
242 }
243