Some more use of enum class.
[libdcp.git] / test / combine_test.cc
1 /*
2     Copyright (C) 2020 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp 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     libdcp 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 libdcp.  If not, see <http://www.gnu.org/licenses/>.
18
19     In addition, as a special exception, the copyright holders give
20     permission to link the code of portions of this program with the
21     OpenSSL library under certain conditions as described in each
22     individual source file, and distribute linked combinations
23     including the two.
24
25     You must obey the GNU General Public License in all respects
26     for all of the code used other than OpenSSL.  If you modify
27     file(s) with this exception, you may extend this exception to your
28     version of the file(s), but you are not obligated to do so.  If you
29     do not wish to do so, delete this exception statement from your
30     version.  If you delete this exception statement from all source
31     files in the program, then also delete it here.
32 */
33
34
35 #include "combine.h"
36 #include "cpl.h"
37 #include "dcp.h"
38 #include "interop_subtitle_asset.h"
39 #include "reel_subtitle_asset.h"
40 #include "reel_mono_picture_asset.h"
41 #include "reel_sound_asset.h"
42 #include "test.h"
43 #include "types.h"
44 #include "verify.h"
45 #include "reel_markers_asset.h"
46 #include <boost/algorithm/string.hpp>
47 #include <boost/foreach.hpp>
48 #include <boost/optional.hpp>
49 #include <boost/test/unit_test.hpp>
50 #include <iostream>
51
52
53 using std::list;
54 using std::string;
55 using std::make_shared;
56 using std::vector;
57 using std::shared_ptr;
58 using boost::optional;
59
60
61 static void
62 stage (string, optional<boost::filesystem::path>)
63 {
64 }
65
66
67 static void
68 progress (float)
69 {
70 }
71
72
73 static
74 void
75 dump_notes (vector<dcp::VerificationNote> const & notes)
76 {
77         BOOST_FOREACH (dcp::VerificationNote i, notes) {
78                 std::cout << dcp::note_to_string(i) << "\n";
79         }
80 }
81
82
83 static
84 void
85 check_no_errors (boost::filesystem::path path)
86 {
87         vector<boost::filesystem::path> directories;
88         directories.push_back (path);
89         auto notes = dcp::verify (directories, &stage, &progress, xsd_test);
90         vector<dcp::VerificationNote> filtered_notes;
91         std::copy_if (notes.begin(), notes.end(), std::back_inserter(filtered_notes), [](dcp::VerificationNote const& i) {
92                 return i.code() != dcp::VerificationNote::Code::INVALID_STANDARD && i.code() != dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION;
93         });
94         dump_notes (filtered_notes);
95         BOOST_CHECK (filtered_notes.empty());
96 }
97
98
99 template <class T>
100 shared_ptr<T>
101 pointer_to_id_in_vector (shared_ptr<T> needle, vector<shared_ptr<T> > haystack)
102 {
103         BOOST_FOREACH (shared_ptr<T> i, haystack) {
104                 if (i->id() == needle->id()) {
105                         return i;
106                 }
107         }
108
109         return shared_ptr<T>();
110 }
111
112
113 static
114 void
115 note_handler (dcp::NoteType, std::string)
116 {
117         // std::cout << "> " << n << "\n";
118 }
119
120
121 static
122 void
123 check_combined (vector<boost::filesystem::path> inputs, boost::filesystem::path output)
124 {
125         dcp::DCP output_dcp (output);
126         output_dcp.read ();
127
128         dcp::EqualityOptions options;
129         options.load_font_nodes_can_differ = true;
130
131         for (auto i: inputs) {
132                 dcp::DCP input_dcp (i);
133                 input_dcp.read ();
134
135                 BOOST_REQUIRE (input_dcp.cpls().size() == 1);
136                 auto input_cpl = input_dcp.cpls().front();
137
138                 auto output_cpl = pointer_to_id_in_vector (input_cpl, output_dcp.cpls());
139                 BOOST_REQUIRE (output_cpl);
140
141                 for (auto i: input_dcp.assets(true)) {
142                         auto o = pointer_to_id_in_vector(i, output_dcp.assets());
143                         BOOST_REQUIRE_MESSAGE (o, "Could not find " << i->id() << " in combined DCP.");
144                         BOOST_CHECK (i->equals(o, options, note_handler));
145                 }
146         }
147 }
148
149
150 BOOST_AUTO_TEST_CASE (combine_single_dcp_test)
151 {
152         using namespace boost::algorithm;
153         using namespace boost::filesystem;
154         boost::filesystem::path const out = "build/test/combine_single_dcp_test";
155
156         remove_all (out);
157         vector<path> inputs;
158         inputs.push_back ("test/ref/DCP/dcp_test1");
159         dcp::combine (
160                 inputs,
161                 out,
162                 dcp::String::compose("libdcp %1", dcp::version),
163                 dcp::String::compose("libdcp %1", dcp::version),
164                 dcp::LocalTime().as_string(),
165                 "A Test DCP"
166                 );
167
168         check_no_errors (out);
169         check_combined (inputs, out);
170 }
171
172
173 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
174 {
175         using namespace boost::algorithm;
176         using namespace boost::filesystem;
177         boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
178
179         shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
180         second->write_xml (dcp::Standard::SMPTE);
181
182         remove_all (out);
183         vector<path> inputs;
184         inputs.push_back ("test/ref/DCP/dcp_test1");
185         inputs.push_back ("build/test/combine_input2");
186         dcp::combine (inputs, out);
187
188         check_no_errors (out);
189         check_combined (inputs, out);
190 }
191
192
193 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
194 {
195         using namespace boost::algorithm;
196         using namespace boost::filesystem;
197         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
198
199         shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
200         first->write_xml (dcp::Standard::INTEROP);
201
202         shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
203         second->write_xml (dcp::Standard::INTEROP);
204
205         remove_all (out);
206         vector<path> inputs;
207         inputs.push_back ("build/test/combine_input1");
208         inputs.push_back ("build/test/combine_input2");
209         dcp::combine (inputs, out);
210
211         check_no_errors (out);
212         check_combined (inputs, out);
213 }
214
215
216 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
217 {
218         using namespace boost::algorithm;
219         using namespace boost::filesystem;
220         boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
221
222         shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
223         first->write_xml (dcp::Standard::SMPTE);
224
225         shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
226         second->write_xml (dcp::Standard::SMPTE);
227
228         remove_all (out);
229         vector<path> inputs;
230         inputs.push_back ("build/test/combine_input1");
231         inputs.push_back ("build/test/combine_input2");
232         dcp::combine (inputs, out);
233
234         check_no_errors (out);
235         check_combined (inputs, out);
236 }
237
238
239 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
240 {
241         using namespace boost::algorithm;
242         using namespace boost::filesystem;
243         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
244
245         shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
246         first->write_xml (dcp::Standard::INTEROP);
247
248         shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
249         second->write_xml (dcp::Standard::INTEROP);
250
251         remove_all (out);
252         vector<path> inputs;
253         inputs.push_back ("build/test/combine_input1");
254         inputs.push_back ("build/test/combine_input2");
255         dcp::combine (inputs, out);
256
257         check_no_errors (out);
258         check_combined (inputs, out);
259 }
260
261
262 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
263 {
264         using namespace boost::algorithm;
265         using namespace boost::filesystem;
266         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
267
268         shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
269         first->write_xml (dcp::Standard::SMPTE);
270
271         shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
272         second->write_xml (dcp::Standard::SMPTE);
273
274         remove_all (out);
275         vector<path> inputs;
276         inputs.push_back ("build/test/combine_input1");
277         inputs.push_back ("build/test/combine_input2");
278         dcp::combine (inputs, out);
279
280         check_no_errors (out);
281         check_combined (inputs, out);
282 }
283
284
285 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
286 {
287         using namespace boost::algorithm;
288         using namespace boost::filesystem;
289         boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
290
291         shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
292         first->write_xml (dcp::Standard::SMPTE);
293
294         shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
295         second->write_xml (dcp::Standard::SMPTE);
296
297         remove_all (out);
298         vector<path> inputs;
299         inputs.push_back ("build/test/combine_input1");
300         inputs.push_back ("build/test/combine_input2");
301         dcp::combine (inputs, out);
302
303         check_no_errors (out);
304         check_combined (inputs, out);
305 }
306
307
308 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
309 {
310         using namespace boost::filesystem;
311         boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
312
313         shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
314         first->write_xml (dcp::Standard::SMPTE);
315
316         remove_all ("build/test/combine_input2");
317         shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
318
319         dcp::MXFMetadata mxf_meta;
320         mxf_meta.company_name = "OpenDCP";
321         mxf_meta.product_version = "0.0.25";
322
323         auto cpl = make_shared<dcp::CPL>("A Test DCP", dcp::ContentKind::TRAILER);
324         cpl->set_content_version (
325                 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
326                 );
327         cpl->set_main_sound_configuration ("L,C,R,Lfe,-,-");
328         cpl->set_main_sound_sample_rate (48000);
329         cpl->set_main_picture_stored_area (dcp::Size(1998, 1080));
330         cpl->set_main_picture_active_area (dcp::Size(1440, 1080));
331         cpl->set_version_number(1);
332
333         auto pic = make_shared<dcp::ReelMonoPictureAsset>(simple_picture("build/test/combine_input2", ""), 0);
334         auto sound = make_shared<dcp::ReelSoundAsset>(first->cpls().front()->reels().front()->main_sound()->asset(), 0);
335         auto reel = make_shared<dcp::Reel>(pic, sound);
336         reel->add (simple_markers());
337         cpl->add (reel);
338         second->add (cpl);
339         second->write_xml (dcp::Standard::SMPTE);
340
341         remove_all (out);
342         vector<path> inputs;
343         inputs.push_back ("build/test/combine_input1");
344         inputs.push_back ("build/test/combine_input2");
345         dcp::combine (inputs, out);
346
347         check_no_errors (out);
348         check_combined (inputs, out);
349 }
350
351
352 /* XXX: same CPL names */
353 /* XXX: Interop PNG subs */