f704fc9a148a2077320b185c39c003f46b933259
[libdcp.git] / test / cpl_metadata_test.cc
1 /*
2     Copyright (C) 2020-2021 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 "certificate_chain.h"
36 #include "compose.hpp"
37 #include "cpl.h"
38 #include "exceptions.h"
39 #include "language_tag.h"
40 #include "reel.h"
41 #include "reel_mono_picture_asset.h"
42 #include "reel_smpte_subtitle_asset.h"
43 #include "reel_sound_asset.h"
44 #include "stream_operators.h"
45 #include "test.h"
46 #include <memory>
47 #include <boost/test/unit_test.hpp>
48
49
50 using std::list;
51 using std::make_shared;
52 using std::shared_ptr;
53 using std::string;
54 using std::vector;
55
56
57 BOOST_AUTO_TEST_CASE (cpl_metadata_bad_values_test)
58 {
59         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
60         BOOST_CHECK_THROW (cpl.set_version_number(-1), dcp::BadSettingError);
61
62         vector<dcp::ContentVersion> cv = {
63                 dcp::ContentVersion("same-id", "version 1"),
64                 dcp::ContentVersion("same-id", "version 2")
65         };
66         BOOST_CHECK_THROW (cpl.set_content_versions(cv), dcp::DuplicateIdError);
67 }
68
69
70 BOOST_AUTO_TEST_CASE (main_sound_configuration_test1)
71 {
72         dcp::MainSoundConfiguration msc("51/L,R,C,LFE,-,-");
73         BOOST_CHECK_EQUAL (msc.to_string(), "51/L,R,C,LFE,-,-");
74         BOOST_CHECK_EQUAL (msc.channels(), 6);
75         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::FIVE_POINT_ONE);
76         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
77         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
78         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
79         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
80         BOOST_CHECK (!msc.mapping(4));
81         BOOST_CHECK (!msc.mapping(5));
82 }
83
84
85 BOOST_AUTO_TEST_CASE (main_sound_configuration_test2)
86 {
87         dcp::MainSoundConfiguration msc("71/L,R,C,LFE,-,-");
88         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,R,C,LFE,-,-");
89         BOOST_CHECK_EQUAL (msc.channels(), 6);
90         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
91         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
92         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
93         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
94         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
95         BOOST_CHECK (!msc.mapping(4));
96         BOOST_CHECK (!msc.mapping(5));
97 }
98
99
100 BOOST_AUTO_TEST_CASE (main_sound_configuration_test3)
101 {
102         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss");
103         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss");
104         BOOST_CHECK_EQUAL (msc.channels(), 6);
105         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
106         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
107         BOOST_CHECK (!msc.mapping(1));
108         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
109         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
110         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
111         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
112 }
113
114
115 BOOST_AUTO_TEST_CASE (main_sound_configuration_test4)
116 {
117         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss,-,-,-,-,-,-,-,-,-");
118         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss,-,-,-,-,-,-,-,-,-");
119         BOOST_CHECK_EQUAL (msc.channels(), 15);
120         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
121         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
122         BOOST_CHECK (!msc.mapping(1));
123         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
124         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
125         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
126         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
127         for (int i = 6; i < 15; ++i) {
128                 BOOST_CHECK (!msc.mapping(i));
129         }
130 }
131
132
133 BOOST_AUTO_TEST_CASE (main_sound_configuration_test5)
134 {
135         dcp::MainSoundConfiguration msc("71/L,-,C,LFE,Lss,Rss,HI,VIN,-,-,Lrs,Rrs,DBOX,FSKSync,SLVS");
136         BOOST_CHECK_EQUAL (msc.to_string(), "71/L,-,C,LFE,Lss,Rss,HI,VIN,-,-,Lrs,Rrs,DBOX,FSKSync,SLVS");
137         BOOST_CHECK_EQUAL (msc.channels(), 15);
138         BOOST_CHECK_EQUAL (msc.field(), dcp::MCASoundField::SEVEN_POINT_ONE);
139         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
140         BOOST_CHECK (!msc.mapping(1));
141         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
142         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
143         BOOST_CHECK_EQUAL (msc.mapping(4).get(), dcp::Channel::LS);
144         BOOST_CHECK_EQUAL (msc.mapping(5).get(), dcp::Channel::RS);
145         BOOST_CHECK_EQUAL (msc.mapping(6).get(), dcp::Channel::HI);
146         BOOST_CHECK_EQUAL (msc.mapping(7).get(), dcp::Channel::VI);
147         BOOST_CHECK (!msc.mapping(8));
148         BOOST_CHECK (!msc.mapping(9));
149         BOOST_CHECK_EQUAL (msc.mapping(10).get(), dcp::Channel::BSL);
150         BOOST_CHECK_EQUAL (msc.mapping(11).get(), dcp::Channel::BSR);
151         BOOST_CHECK_EQUAL (msc.mapping(12).get(), dcp::Channel::MOTION_DATA);
152         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
153         BOOST_CHECK_EQUAL (msc.mapping(14).get(), dcp::Channel::SIGN_LANGUAGE);
154 }
155
156
157 /* 482-12 says that implementations may use case-insensitive comparisons for the channel identifiers,
158  * and there is one DCP in the private test suite (made by Disney) that uses LS for left surround.
159  */
160 BOOST_AUTO_TEST_CASE(main_sound_configuration_test_case_insensitive)
161 {
162         dcp::MainSoundConfiguration msc("51/L,-,C,LFE,LS,RS,HI,VIN");
163         BOOST_CHECK_EQUAL(msc.to_string(), "51/L,-,C,LFE,Ls,Rs,HI,VIN");
164         BOOST_CHECK_EQUAL(msc.channels(), 8);
165         BOOST_CHECK_EQUAL(msc.field(), dcp::MCASoundField::FIVE_POINT_ONE);
166         BOOST_CHECK_EQUAL(msc.mapping(0).get(), dcp::Channel::LEFT);
167         BOOST_CHECK(!msc.mapping(1));
168         BOOST_CHECK_EQUAL(msc.mapping(2).get(), dcp::Channel::CENTRE);
169         BOOST_CHECK_EQUAL(msc.mapping(3).get(), dcp::Channel::LFE);
170         BOOST_CHECK_EQUAL(msc.mapping(4).get(), dcp::Channel::LS);
171         BOOST_CHECK_EQUAL(msc.mapping(5).get(), dcp::Channel::RS);
172         BOOST_CHECK_EQUAL(msc.mapping(6).get(), dcp::Channel::HI);
173         BOOST_CHECK_EQUAL(msc.mapping(7).get(), dcp::Channel::VI);
174 }
175
176
177 BOOST_AUTO_TEST_CASE (luminance_test1)
178 {
179         BOOST_CHECK_NO_THROW (dcp::Luminance(4, dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE));
180         BOOST_CHECK_THROW (dcp::Luminance(-4, dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE), dcp::MiscError);
181 }
182
183
184 BOOST_AUTO_TEST_CASE (luminance_test2)
185 {
186         auto doc = make_shared<cxml::Document>("Luminance");
187
188         doc->read_string (
189                 "<Luminance units=\"candela-per-square-metre\">4.5</Luminance>"
190                 );
191
192         dcp::Luminance lum (doc);
193         BOOST_CHECK (lum.unit() == dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE);
194         BOOST_CHECK_CLOSE (lum.value(), 4.5, 0.1);
195 }
196
197
198 BOOST_AUTO_TEST_CASE (luminance_test3)
199 {
200         auto doc = make_shared<cxml::Document>("Luminance");
201
202         doc->read_string (
203                 "<Luminance units=\"candela-per-square-motre\">4.5</Luminance>"
204                 );
205
206         BOOST_CHECK_THROW (new dcp::Luminance(doc), dcp::XMLError);
207 }
208
209
210 BOOST_AUTO_TEST_CASE (luminance_test4)
211 {
212         auto doc = make_shared<cxml::Document>("Luminance");
213
214         doc->read_string (
215                 "<Luminance units=\"candela-per-square-metre\">-4.5</Luminance>"
216                 );
217
218         /* We tolerate out-of-range values when reading from XML */
219         dcp::Luminance lum (doc);
220         BOOST_CHECK (lum.unit() == dcp::Luminance::Unit::CANDELA_PER_SQUARE_METRE);
221         BOOST_CHECK_CLOSE (lum.value(), -4.5, 0.1);
222 }
223
224
225 /** A test where most CPL metadata is present */
226 BOOST_AUTO_TEST_CASE (cpl_metadata_read_test1)
227 {
228         dcp::CPL cpl("test/ref/cpl_metadata_test1.xml");
229
230         BOOST_CHECK_EQUAL (cpl.full_content_title_text().get(), "full-content-title");
231         BOOST_CHECK (cpl.full_content_title_text_language().get() == "de");
232         BOOST_CHECK (cpl.release_territory().get() == "ES");
233         BOOST_CHECK_EQUAL (cpl.version_number().get(), 2);
234         BOOST_CHECK_EQUAL (cpl.status().get(), dcp::Status::FINAL);
235         BOOST_CHECK_EQUAL (cpl.chain().get(), "the-chain");
236         BOOST_CHECK_EQUAL (cpl.distributor().get(), "the-distributor");
237         BOOST_CHECK_EQUAL (cpl.facility().get(), "the-facility");
238         BOOST_CHECK (cpl.luminance() == dcp::Luminance(4.5, dcp::Luminance::Unit::FOOT_LAMBERT));
239
240         dcp::MainSoundConfiguration msc(cpl.main_sound_configuration().get());
241         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
242         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
243         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
244         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
245         BOOST_CHECK (!msc.mapping(4));
246         BOOST_CHECK (!msc.mapping(5));
247         BOOST_CHECK (!msc.mapping(6));
248         BOOST_CHECK (!msc.mapping(7));
249         BOOST_CHECK (!msc.mapping(8));
250         BOOST_CHECK (!msc.mapping(9));
251         BOOST_CHECK (!msc.mapping(10));
252         BOOST_CHECK (!msc.mapping(11));
253         BOOST_CHECK (!msc.mapping(12));
254         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
255
256         BOOST_CHECK_EQUAL (cpl.main_sound_sample_rate().get(), 48000);
257         BOOST_CHECK (cpl.main_picture_stored_area().get() == dcp::Size(1998, 1080));
258         BOOST_CHECK (cpl.main_picture_active_area().get() == dcp::Size(1440, 1080));
259
260         auto reels = cpl.reels ();
261         BOOST_REQUIRE_EQUAL (reels.size(), 1U);
262         BOOST_REQUIRE (reels.front()->main_subtitle()->language());
263         BOOST_CHECK_EQUAL (reels.front()->main_subtitle()->language().get(), "de-DE");
264
265         auto asl = cpl.additional_subtitle_languages();
266         BOOST_REQUIRE_EQUAL (asl.size(), 2U);
267         BOOST_CHECK_EQUAL (asl[0], "en-US");
268         BOOST_CHECK_EQUAL (asl[1], "fr-ZA");
269
270         BOOST_CHECK (cpl.additional_subtitle_languages() == asl);
271 }
272
273
274 /** A test where most CPL metadata is present */
275 BOOST_AUTO_TEST_CASE (cpl_metadata_write_test1)
276 {
277         RNGFixer fix;
278
279         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
280         cpl.set_issue_date ("2020-08-28T13:35:06+02:00");
281
282         vector<dcp::ContentVersion> cv = {
283                 dcp::ContentVersion("some-id", "version 1"),
284                 dcp::ContentVersion("another-id", "version 2")
285         };;
286         cpl.set_content_versions (cv);
287
288         cpl.set_full_content_title_text ("full-content-title");
289         cpl.set_full_content_title_text_language (dcp::LanguageTag("de"));
290         cpl.set_release_territory (dcp::LanguageTag::RegionSubtag("ES"));
291         cpl.set_version_number (2);
292         cpl.set_status (dcp::Status::FINAL);
293         cpl.set_chain ("the-chain");
294         cpl.set_distributor ("the-distributor");
295         cpl.set_facility ("the-facility");
296         cpl.set_luminance (dcp::Luminance(4.5, dcp::Luminance::Unit::FOOT_LAMBERT));
297         cpl.set_issuer ("libdcp1.6.4devel");
298         cpl.set_creator ("libdcp1.6.4devel");
299
300         dcp::MainSoundConfiguration msc(dcp::MCASoundField::SEVEN_POINT_ONE, 16);
301         msc.set_mapping (0, dcp::Channel::LEFT);
302         msc.set_mapping (1, dcp::Channel::RIGHT);
303         msc.set_mapping (2, dcp::Channel::CENTRE);
304         msc.set_mapping (3, dcp::Channel::LFE);
305         msc.set_mapping (13, dcp::Channel::SYNC_SIGNAL);
306         cpl.set_main_sound_configuration(msc);
307
308         cpl.set_main_sound_sample_rate (48000);
309         cpl.set_main_picture_stored_area (dcp::Size(1998, 1080));
310         cpl.set_main_picture_active_area (dcp::Size(1440, 1080));
311
312         auto doc = make_shared<cxml::Document>("MainSubtitle");
313
314         doc->read_string (
315                 "<MainSubtitle>"
316                 "<Id>urn:uuid:8bca1489-aab1-9259-a4fd-8150abc1de12</Id>"
317                 "<AnnotationText>Goodbye world!</AnnotationText>"
318                 "<EditRate>25 1</EditRate>"
319                 "<IntrinsicDuration>1870</IntrinsicDuration>"
320                 "<EntryPoint>0</EntryPoint>"
321                 "<Duration>525</Duration>"
322                 "<KeyId>urn:uuid:540cbf10-ab14-0233-ab1f-fb31501cabfa</KeyId>"
323                 "<Hash>3EABjX9BB1CAWhLUtHhrGSyLgOY=</Hash>"
324                 "<Language>de-DE</Language>"
325                 "</MainSubtitle>"
326                 );
327
328         auto reel = make_shared<dcp::Reel>();
329         reel->add (black_picture_asset("build/test/cpl_metadata_write_test1"));
330         reel->add (make_shared<dcp::ReelSMPTESubtitleAsset>(doc));
331         cpl.add (reel);
332
333         auto lt = { dcp::LanguageTag("en-US"), dcp::LanguageTag("fr-ZA") };
334         cpl.set_additional_subtitle_languages (lt);
335
336         cpl.set_sign_language_video_language (dcp::LanguageTag("bzs"));
337
338         cpl.write_xml ("build/test/cpl_metadata_write_test1.xml", {});
339         check_xml (
340                 dcp::file_to_string("test/ref/cpl_metadata_test1.xml"),
341                 dcp::file_to_string("build/test/cpl_metadata_write_test1.xml"),
342                 {"Id", "Hash"}
343                 );
344 }
345
346
347 /** A test where most CPL metadata is present */
348 BOOST_AUTO_TEST_CASE (cpl_metadata_roundtrip_test_1)
349 {
350         dcp::CPL cpl ("test/ref/cpl_metadata_test1.xml");
351         cpl.write_xml ("build/test/cpl_metadata_roundtrip_test1.xml", shared_ptr<dcp::CertificateChain>());
352         check_xml (
353                 dcp::file_to_string("test/ref/cpl_metadata_test1.xml"),
354                 dcp::file_to_string("build/test/cpl_metadata_roundtrip_test1.xml"),
355                 {"Id"}
356                 );
357 }
358
359
360 /** A test where only a bare minimum of CPL metadata is present */
361 BOOST_AUTO_TEST_CASE (cpl_metadata_write_test2)
362 {
363         RNGFixer fix;
364
365         dcp::CPL cpl("", dcp::ContentKind::FEATURE, dcp::Standard::SMPTE);
366         cpl.set_issue_date ("2020-08-28T13:35:06+02:00");
367         cpl.set_content_version (dcp::ContentVersion("id", "version"));
368         cpl.set_issuer ("libdcp1.6.4devel");
369         cpl.set_creator ("libdcp1.6.4devel");
370
371         dcp::MainSoundConfiguration msc(dcp::MCASoundField::SEVEN_POINT_ONE, 16);
372         msc.set_mapping (0, dcp::Channel::LEFT);
373         msc.set_mapping (1, dcp::Channel::RIGHT);
374         msc.set_mapping (2, dcp::Channel::CENTRE);
375         msc.set_mapping (3, dcp::Channel::LFE);
376         msc.set_mapping (13, dcp::Channel::SYNC_SIGNAL);
377         cpl.set_main_sound_configuration(msc);
378
379         cpl.set_main_sound_sample_rate (48000);
380         cpl.set_main_picture_stored_area (dcp::Size(1998, 1080));
381         cpl.set_main_picture_active_area (dcp::Size(1440, 1080));
382
383         auto reel = make_shared<dcp::Reel>();
384         reel->add (black_picture_asset("build/test/cpl_metadata_write_test1"));
385         cpl.add (reel);
386
387         cpl.write_xml ("build/test/cpl_metadata_write_test2.xml", {});
388         check_xml (
389                 dcp::file_to_string("test/ref/cpl_metadata_test2.xml"),
390                 dcp::file_to_string("build/test/cpl_metadata_write_test2.xml"),
391                 {"Id", "Hash"}
392                 );
393 }
394
395
396 /** A test where only a bare minimum of CPL metadata is present */
397 BOOST_AUTO_TEST_CASE (cpl_metadata_read_test2)
398 {
399         dcp::CPL cpl("test/ref/cpl_metadata_test2.xml");
400
401         BOOST_CHECK_EQUAL (cpl.full_content_title_text().get(), "");
402         BOOST_CHECK (!cpl.full_content_title_text_language());
403         BOOST_CHECK (!cpl.release_territory());
404         BOOST_CHECK (!cpl.version_number());
405         BOOST_CHECK (!cpl.status());
406         BOOST_CHECK (!cpl.chain());
407         BOOST_CHECK (!cpl.distributor());
408         BOOST_CHECK (!cpl.facility());
409         BOOST_CHECK (!cpl.luminance());
410
411         dcp::MainSoundConfiguration msc(cpl.main_sound_configuration().get());
412         BOOST_CHECK_EQUAL (msc.mapping(0).get(), dcp::Channel::LEFT);
413         BOOST_CHECK_EQUAL (msc.mapping(1).get(), dcp::Channel::RIGHT);
414         BOOST_CHECK_EQUAL (msc.mapping(2).get(), dcp::Channel::CENTRE);
415         BOOST_CHECK_EQUAL (msc.mapping(3).get(), dcp::Channel::LFE);
416         BOOST_CHECK (!msc.mapping(4));
417         BOOST_CHECK (!msc.mapping(5));
418         BOOST_CHECK (!msc.mapping(6));
419         BOOST_CHECK (!msc.mapping(7));
420         BOOST_CHECK (!msc.mapping(8));
421         BOOST_CHECK (!msc.mapping(9));
422         BOOST_CHECK (!msc.mapping(10));
423         BOOST_CHECK (!msc.mapping(11));
424         BOOST_CHECK (!msc.mapping(12));
425         BOOST_CHECK_EQUAL (msc.mapping(13).get(), dcp::Channel::SYNC_SIGNAL);
426
427         BOOST_CHECK_EQUAL (cpl.main_sound_sample_rate().get(), 48000);
428         BOOST_CHECK (cpl.main_picture_stored_area().get() == dcp::Size(1998, 1080));
429         BOOST_CHECK (cpl.main_picture_active_area().get() == dcp::Size(1440, 1080));
430
431         auto reels = cpl.reels ();
432         BOOST_REQUIRE_EQUAL (reels.size(), 1U);
433 }
434
435
436 /** A test where only a bare minimum of CPL metadata is present */
437 BOOST_AUTO_TEST_CASE (cpl_metadata_roundtrip_test_2)
438 {
439         dcp::CPL cpl ("test/ref/cpl_metadata_test2.xml");
440         cpl.write_xml ("build/test/cpl_metadata_roundtrip_test2.xml", shared_ptr<dcp::CertificateChain>());
441         check_xml (
442                 dcp::file_to_string("test/ref/cpl_metadata_test2.xml"),
443                 dcp::file_to_string("build/test/cpl_metadata_roundtrip_test2.xml"),
444                 {"Id"}
445                 );
446 }
447
448
449 BOOST_AUTO_TEST_CASE(check_that_missing_full_content_title_text_is_tolerated)
450 {
451         dcp::CPL cpl("test/ref/cpl_metadata_test3.xml");
452 }
453
454
455 BOOST_AUTO_TEST_CASE(check_sign_language_video_language)
456 {
457         dcp::CPL cpl("test/ref/cpl_metadata_test3.xml");
458         cpl.set_sign_language_video_language(dcp::LanguageTag("es-PT"));
459         cpl.write_xml("build/test/check_sign_language_video_language.xml", {});
460         check_xml(
461                 dcp::file_to_string("test/ref/cpl_metadata_test4.xml"),
462                 dcp::file_to_string("build/test/check_sign_language_video_language.xml"),
463                 {"Id"}
464                 );
465
466         dcp::CPL check("build/test/check_sign_language_video_language.xml");
467         BOOST_CHECK_EQUAL(check.sign_language_video_language().get_value_or(""), "es-PT");
468
469 }