Cleanup: tidy enum names for verification codes.
[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::INVALID_STANDARD && i.code() != dcp::VerificationNote::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         BOOST_FOREACH (boost::filesystem::path i, inputs)
132         {
133                 dcp::DCP input_dcp (i);
134                 input_dcp.read ();
135
136                 BOOST_REQUIRE (input_dcp.cpls().size() == 1);
137                 shared_ptr<dcp::CPL> input_cpl = input_dcp.cpls().front();
138
139                 shared_ptr<dcp::CPL> output_cpl = pointer_to_id_in_vector (input_cpl, output_dcp.cpls());
140                 BOOST_REQUIRE (output_cpl);
141
142                 BOOST_FOREACH (shared_ptr<dcp::Asset> i, input_dcp.assets(true)) {
143                         shared_ptr<dcp::Asset> o = pointer_to_id_in_vector(i, output_dcp.assets());
144                         BOOST_REQUIRE_MESSAGE (o, "Could not find " << i->id() << " in combined DCP.");
145                         BOOST_CHECK (i->equals(o, options, note_handler));
146                 }
147         }
148 }
149
150
151 BOOST_AUTO_TEST_CASE (combine_single_dcp_test)
152 {
153         using namespace boost::algorithm;
154         using namespace boost::filesystem;
155         boost::filesystem::path const out = "build/test/combine_single_dcp_test";
156
157         remove_all (out);
158         vector<path> inputs;
159         inputs.push_back ("test/ref/DCP/dcp_test1");
160         dcp::combine (
161                 inputs,
162                 out,
163                 dcp::String::compose("libdcp %1", dcp::version),
164                 dcp::String::compose("libdcp %1", dcp::version),
165                 dcp::LocalTime().as_string(),
166                 "A Test DCP"
167                 );
168
169         check_no_errors (out);
170         check_combined (inputs, out);
171 }
172
173
174 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_same_asset_filenames_test)
175 {
176         using namespace boost::algorithm;
177         using namespace boost::filesystem;
178         boost::filesystem::path const out = "build/test/combine_two_dcps_with_same_asset_filenames_test";
179
180         shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2");
181         second->write_xml (dcp::SMPTE);
182
183         remove_all (out);
184         vector<path> inputs;
185         inputs.push_back ("test/ref/DCP/dcp_test1");
186         inputs.push_back ("build/test/combine_input2");
187         dcp::combine (inputs, out);
188
189         check_no_errors (out);
190         check_combined (inputs, out);
191 }
192
193
194 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_subs_test)
195 {
196         using namespace boost::algorithm;
197         using namespace boost::filesystem;
198         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_subs_test";
199
200         shared_ptr<dcp::DCP> first = make_simple_with_interop_subs ("build/test/combine_input1");
201         first->write_xml (dcp::INTEROP);
202
203         shared_ptr<dcp::DCP> second = make_simple_with_interop_subs ("build/test/combine_input2");
204         second->write_xml (dcp::INTEROP);
205
206         remove_all (out);
207         vector<path> inputs;
208         inputs.push_back ("build/test/combine_input1");
209         inputs.push_back ("build/test/combine_input2");
210         dcp::combine (inputs, out);
211
212         check_no_errors (out);
213         check_combined (inputs, out);
214 }
215
216
217 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_subs_test)
218 {
219         using namespace boost::algorithm;
220         using namespace boost::filesystem;
221         boost::filesystem::path const out = "build/test/combine_two_dcps_with_smpte_subs_test";
222
223         shared_ptr<dcp::DCP> first = make_simple_with_smpte_subs ("build/test/combine_input1");
224         first->write_xml (dcp::SMPTE);
225
226         shared_ptr<dcp::DCP> second = make_simple_with_smpte_subs ("build/test/combine_input2");
227         second->write_xml (dcp::SMPTE);
228
229         remove_all (out);
230         vector<path> inputs;
231         inputs.push_back ("build/test/combine_input1");
232         inputs.push_back ("build/test/combine_input2");
233         dcp::combine (inputs, out);
234
235         check_no_errors (out);
236         check_combined (inputs, out);
237 }
238
239
240 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_interop_ccaps_test)
241 {
242         using namespace boost::algorithm;
243         using namespace boost::filesystem;
244         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
245
246         shared_ptr<dcp::DCP> first = make_simple_with_interop_ccaps ("build/test/combine_input1");
247         first->write_xml (dcp::INTEROP);
248
249         shared_ptr<dcp::DCP> second = make_simple_with_interop_ccaps ("build/test/combine_input2");
250         second->write_xml (dcp::INTEROP);
251
252         remove_all (out);
253         vector<path> inputs;
254         inputs.push_back ("build/test/combine_input1");
255         inputs.push_back ("build/test/combine_input2");
256         dcp::combine (inputs, out);
257
258         check_no_errors (out);
259         check_combined (inputs, out);
260 }
261
262
263 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_smpte_ccaps_test)
264 {
265         using namespace boost::algorithm;
266         using namespace boost::filesystem;
267         boost::filesystem::path const out = "build/test/combine_two_dcps_with_interop_ccaps_test";
268
269         shared_ptr<dcp::DCP> first = make_simple_with_smpte_ccaps ("build/test/combine_input1");
270         first->write_xml (dcp::SMPTE);
271
272         shared_ptr<dcp::DCP> second = make_simple_with_smpte_ccaps ("build/test/combine_input2");
273         second->write_xml (dcp::SMPTE);
274
275         remove_all (out);
276         vector<path> inputs;
277         inputs.push_back ("build/test/combine_input1");
278         inputs.push_back ("build/test/combine_input2");
279         dcp::combine (inputs, out);
280
281         check_no_errors (out);
282         check_combined (inputs, out);
283 }
284
285
286 BOOST_AUTO_TEST_CASE (combine_two_multi_reel_dcps)
287 {
288         using namespace boost::algorithm;
289         using namespace boost::filesystem;
290         boost::filesystem::path const out = "build/test/combine_two_multi_reel_dcps";
291
292         shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 4);
293         first->write_xml (dcp::SMPTE);
294
295         shared_ptr<dcp::DCP> second = make_simple ("build/test/combine_input2", 4);
296         second->write_xml (dcp::SMPTE);
297
298         remove_all (out);
299         vector<path> inputs;
300         inputs.push_back ("build/test/combine_input1");
301         inputs.push_back ("build/test/combine_input2");
302         dcp::combine (inputs, out);
303
304         check_no_errors (out);
305         check_combined (inputs, out);
306 }
307
308
309 BOOST_AUTO_TEST_CASE (combine_two_dcps_with_shared_asset)
310 {
311         using namespace boost::filesystem;
312         boost::filesystem::path const out = "build/test/combine_two_dcps_with_shared_asset";
313
314         shared_ptr<dcp::DCP> first = make_simple ("build/test/combine_input1", 1);
315         first->write_xml (dcp::SMPTE);
316
317         remove_all ("build/test/combine_input2");
318         shared_ptr<dcp::DCP> second(new dcp::DCP("build/test/combine_input2"));
319
320         dcp::MXFMetadata mxf_meta;
321         mxf_meta.company_name = "OpenDCP";
322         mxf_meta.product_version = "0.0.25";
323
324         shared_ptr<dcp::CPL> cpl (new dcp::CPL("A Test DCP", dcp::TRAILER));
325         cpl->set_content_version (
326                 dcp::ContentVersion("urn:uuid:75ac29aa-42ac-1234-ecae-49251abefd11","content-version-label-text")
327                 );
328         cpl->set_main_sound_configuration ("L,C,R,Lfe,-,-");
329         cpl->set_main_sound_sample_rate (48000);
330         cpl->set_main_picture_stored_area (dcp::Size(1998, 1080));
331         cpl->set_main_picture_active_area (dcp::Size(1440, 1080));
332         cpl->set_version_number(1);
333
334         shared_ptr<dcp::ReelMonoPictureAsset> pic(new dcp::ReelMonoPictureAsset(simple_picture("build/test/combine_input2", ""), 0));
335         shared_ptr<dcp::ReelSoundAsset> sound(new dcp::ReelSoundAsset(first->cpls().front()->reels().front()->main_sound()->asset(), 0));
336         auto reel = make_shared<dcp::Reel>(pic, sound);
337         reel->add (simple_markers());
338         cpl->add (reel);
339         second->add (cpl);
340         second->write_xml (dcp::SMPTE);
341
342         remove_all (out);
343         vector<path> inputs;
344         inputs.push_back ("build/test/combine_input1");
345         inputs.push_back ("build/test/combine_input2");
346         dcp::combine (inputs, out);
347
348         check_no_errors (out);
349         check_combined (inputs, out);
350 }
351
352
353 /* XXX: same CPL names */
354 /* XXX: Interop PNG subs */