21739d1850490cb9bef1c1f8fafd77f59fe7c951
[dcpomatic.git] / test / dcpomatic_time_test.cc
1 /*
2     Copyright (C) 2015-2017 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 /** @file  test/dcpomatic_time_test.cc
23  *  @brief Test dcpomatic::Time and dcpomatic::TimePeriod classes.
24  *  @ingroup selfcontained
25  */
26
27
28 #include "lib/dcpomatic_time.h"
29 #include "lib/dcpomatic_time_coalesce.h"
30 #include <boost/test/unit_test.hpp>
31 #include <iostream>
32 #include <list>
33
34
35 using std::cout;
36 using std::list;
37 using namespace dcpomatic;
38
39
40 BOOST_AUTO_TEST_CASE (dcpomatic_time_test)
41 {
42         FrameRateChange frc (24, 48);
43         int j = 0;
44         int k = 0;
45         for (int64_t i = 0; i < 62000; i += 2000) {
46                 DCPTime d (i);
47                 ContentTime c (d, frc);
48                 BOOST_CHECK_EQUAL (c.frames_floor (24.0), j);
49                 ++k;
50                 if (k == 2) {
51                         ++j;
52                         k = 0;
53                 }
54         }
55 }
56
57
58 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_overlaps_test)
59 {
60         /* Taking times as the start of a sampling interval
61
62            |--|--|--|--|--|--|--|--|--|--|
63            0  1  2  3  4  5  6  7  8  9  |
64            |--|--|--|--|--|--|--|--|--|--|
65
66            <------a----><----b----->
67
68            and saying `from' is the start of the first sampling
69            interval and `to' is the start of the interval after
70            the period... a and b do not overlap.
71         */
72
73         TimePeriod<DCPTime> a (DCPTime(0), DCPTime(4));
74         TimePeriod<DCPTime> b (DCPTime (4), DCPTime (8));
75         BOOST_CHECK (!a.overlap (b));
76
77         /* Some more obvious non-overlaps */
78         a = TimePeriod<DCPTime> (DCPTime (0), DCPTime (4));
79         b = TimePeriod<DCPTime> (DCPTime (5), DCPTime (8));
80         BOOST_CHECK (!a.overlap (b));
81
82         /* Some overlaps */
83         a = TimePeriod<DCPTime> (DCPTime (0), DCPTime (4));
84         b = TimePeriod<DCPTime> (DCPTime (3), DCPTime (8));
85         BOOST_CHECK (a.overlap(b));
86         BOOST_CHECK (a.overlap(b).get() == DCPTimePeriod(DCPTime(3), DCPTime(4)));
87         a = TimePeriod<DCPTime> (DCPTime (1), DCPTime (9));
88         b = TimePeriod<DCPTime> (DCPTime (0), DCPTime (10));
89         BOOST_CHECK (a.overlap(b));
90         BOOST_CHECK (a.overlap(b).get() == DCPTimePeriod(DCPTime(1), DCPTime(9)));
91 }
92
93
94 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test1)
95 {
96         DCPTimePeriod A (DCPTime (0), DCPTime (106));
97         list<DCPTimePeriod> B = {
98                 DCPTimePeriod(DCPTime(0), DCPTime(42)),
99                 DCPTimePeriod(DCPTime(52), DCPTime(91)),
100                 DCPTimePeriod(DCPTime(94), DCPTime(106))
101         };
102         auto r = subtract ({A}, B);
103         auto i = r.begin ();
104         BOOST_REQUIRE (i != r.end ());
105         BOOST_CHECK (i->from == DCPTime (42));
106         BOOST_CHECK (i->to == DCPTime (52));
107         ++i;
108         BOOST_REQUIRE (i != r.end ());
109         BOOST_CHECK (i->from == DCPTime (91));
110         BOOST_CHECK (i->to == DCPTime (94));
111         ++i;
112         BOOST_REQUIRE (i == r.end ());
113 }
114
115
116 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test2)
117 {
118         DCPTimePeriod A (DCPTime (0), DCPTime (106));
119         list<DCPTimePeriod> B = {
120                 DCPTimePeriod(DCPTime(14), DCPTime(42)),
121                 DCPTimePeriod(DCPTime(52), DCPTime(91)),
122                 DCPTimePeriod(DCPTime(94), DCPTime(106))
123         };
124         auto r = subtract ({A}, B);
125         auto i = r.begin ();
126         BOOST_REQUIRE (i != r.end ());
127         BOOST_CHECK (i->from == DCPTime (0));
128         BOOST_CHECK (i->to == DCPTime (14));
129         ++i;
130         BOOST_REQUIRE (i != r.end ());
131         BOOST_CHECK (i->from == DCPTime (42));
132         BOOST_CHECK (i->to == DCPTime (52));
133         ++i;
134         BOOST_REQUIRE (i != r.end ());
135         BOOST_CHECK (i->from == DCPTime (91));
136         BOOST_CHECK (i->to == DCPTime (94));
137         ++i;
138         BOOST_REQUIRE (i == r.end ());
139 }
140
141
142 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test3)
143 {
144         DCPTimePeriod A (DCPTime (0), DCPTime (106));
145         list<DCPTimePeriod> B = {
146                 DCPTimePeriod(DCPTime(14), DCPTime(42)),
147                 DCPTimePeriod(DCPTime(52), DCPTime(91)),
148                 DCPTimePeriod(DCPTime(94), DCPTime(99))
149         };
150         auto r = subtract ({A}, B);
151         auto i = r.begin ();
152         BOOST_REQUIRE (i != r.end ());
153         BOOST_CHECK (i->from == DCPTime (0));
154         BOOST_CHECK (i->to == DCPTime (14));
155         ++i;
156         BOOST_REQUIRE (i != r.end ());
157         BOOST_CHECK (i->from == DCPTime (42));
158         BOOST_CHECK (i->to == DCPTime (52));
159         ++i;
160         BOOST_REQUIRE (i != r.end ());
161         BOOST_CHECK (i->from == DCPTime (91));
162         BOOST_CHECK (i->to == DCPTime (94));
163         ++i;
164         BOOST_REQUIRE (i != r.end ());
165         BOOST_CHECK (i->from == DCPTime (99));
166         BOOST_CHECK (i->to == DCPTime (106));
167         ++i;
168         BOOST_REQUIRE (i == r.end ());
169 }
170
171
172 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test4)
173 {
174         DCPTimePeriod A (DCPTime (0), DCPTime (106));
175         list<DCPTimePeriod> B;
176         auto r = subtract ({A}, B);
177         auto i = r.begin ();
178         BOOST_REQUIRE (i != r.end ());
179         BOOST_CHECK (i->from == DCPTime (0));
180         BOOST_CHECK (i->to == DCPTime (106));
181         ++i;
182         BOOST_REQUIRE (i == r.end ());
183 }
184
185
186 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test5)
187 {
188         DCPTimePeriod A (DCPTime (0), DCPTime (106));
189         list<DCPTimePeriod> B = {
190                 DCPTimePeriod(DCPTime(14), DCPTime(42)),
191                 DCPTimePeriod(DCPTime(42), DCPTime(91)),
192                 DCPTimePeriod(DCPTime(94), DCPTime(99))
193         };
194         auto r = subtract ({A}, B);
195         auto i = r.begin ();
196         BOOST_REQUIRE (i != r.end ());
197         BOOST_CHECK (i->from == DCPTime (0));
198         BOOST_CHECK (i->to == DCPTime (14));
199         ++i;
200         BOOST_REQUIRE (i != r.end ());
201         BOOST_CHECK (i->from ==DCPTime (91));
202         BOOST_CHECK (i->to == DCPTime (94));
203         ++i;
204         BOOST_REQUIRE (i != r.end ());
205         BOOST_CHECK (i->from == DCPTime (99));
206         BOOST_CHECK (i->to == DCPTime (106));
207         ++i;
208         BOOST_REQUIRE (i == r.end ());
209 }
210
211
212 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test6)
213 {
214         DCPTimePeriod A (DCPTime (0), DCPTime (106));
215         list<DCPTimePeriod> B = {
216                 DCPTimePeriod(DCPTime(0), DCPTime(42)),
217                 DCPTimePeriod(DCPTime(42), DCPTime(91)),
218                 DCPTimePeriod(DCPTime(91), DCPTime(106))
219         };
220         auto r = subtract ({A}, B);
221         BOOST_CHECK (r.empty());
222 }
223
224
225 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test7)
226 {
227         DCPTimePeriod A (DCPTime (228), DCPTime (356));
228         list<DCPTimePeriod> B = {
229                 DCPTimePeriod(DCPTime(34), DCPTime(162))
230         };
231         auto r = subtract ({A}, B);
232         auto i = r.begin ();
233         BOOST_REQUIRE (i != r.end ());
234         BOOST_CHECK (i->from == DCPTime (228));
235         BOOST_CHECK (i->to == DCPTime (356));
236         ++i;
237         BOOST_REQUIRE (i == r.end ());
238 }
239
240
241 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_test8)
242 {
243         DCPTimePeriod A (DCPTime(0), DCPTime(32000));
244         list<DCPTimePeriod> B = {
245                 DCPTimePeriod(DCPTime(8000), DCPTime(20000)),
246                 DCPTimePeriod(DCPTime(28000), DCPTime(32000))
247         };
248         auto r = subtract ({A}, B);
249         auto i = r.begin ();
250         BOOST_REQUIRE (i != r.end ());
251         BOOST_CHECK (*i == DCPTimePeriod(DCPTime(0), DCPTime(8000)));
252         ++i;
253         BOOST_REQUIRE (i != r.end ());
254         BOOST_CHECK (*i == DCPTimePeriod(DCPTime(20000), DCPTime(28000)));
255         ++i;
256         BOOST_REQUIRE (i == r.end ());
257 }
258
259
260 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_list_from_list_test1)
261 {
262         list<DCPTimePeriod> A = {
263                 DCPTimePeriod(DCPTime(0),    DCPTime(2000)),
264                 DCPTimePeriod(DCPTime(4000), DCPTime(6000))
265         };
266
267         list<DCPTimePeriod> B = {
268                 DCPTimePeriod(DCPTime(1000), DCPTime(3000)),
269                 DCPTimePeriod(DCPTime(5000), DCPTime(7000))
270         };
271
272         auto result = subtract(A, B);
273         list<DCPTimePeriod> reference = {
274                 DCPTimePeriod(DCPTime(0),    DCPTime(1000)),
275                 DCPTimePeriod(DCPTime(4000), DCPTime(5000))
276         };
277
278         BOOST_CHECK (result == reference);
279 }
280
281
282 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_list_from_list_test2)
283 {
284         list<DCPTimePeriod> A = {
285                 DCPTimePeriod(DCPTime(0),    DCPTime(2000)),
286                 DCPTimePeriod(DCPTime(4000), DCPTime(6000))
287         };
288
289         list<DCPTimePeriod> B = {
290                 DCPTimePeriod(DCPTime(500),  DCPTime(1500)),
291                 DCPTimePeriod(DCPTime(4500), DCPTime(5500))
292         };
293
294         auto result = subtract(A, B);
295         list<DCPTimePeriod> reference = {
296                 DCPTimePeriod(DCPTime(0),    DCPTime(500)),
297                 DCPTimePeriod(DCPTime(1500), DCPTime(2000)),
298                 DCPTimePeriod(DCPTime(4000), DCPTime(4500)),
299                 DCPTimePeriod(DCPTime(5500), DCPTime(6000)),
300         };
301
302         BOOST_CHECK (result == reference);
303 }
304
305
306 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_subtract_list_from_list_test3)
307 {
308         list<DCPTimePeriod> A = {
309                 DCPTimePeriod(DCPTime(500),  DCPTime(1500)),
310                 DCPTimePeriod(DCPTime(4500), DCPTime(5500))
311         };
312
313         list<DCPTimePeriod> B = {
314                 DCPTimePeriod(DCPTime(0),    DCPTime(2000)),
315                 DCPTimePeriod(DCPTime(4000), DCPTime(6000))
316         };
317
318         auto result = subtract(A, B);
319         BOOST_CHECK (result.empty());
320 }
321
322
323 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_coalesce_test1)
324 {
325         DCPTimePeriod A (DCPTime(14), DCPTime(29));
326         DCPTimePeriod B (DCPTime(45), DCPTime(91));
327         list<DCPTimePeriod> p = { A, B };
328         auto q = coalesce (p);
329         BOOST_REQUIRE_EQUAL (q.size(), 2U);
330         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(14), DCPTime(29)));
331         BOOST_CHECK (q.back () == DCPTimePeriod(DCPTime(45), DCPTime(91)));
332 }
333
334
335 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_coalesce_test2)
336 {
337         DCPTimePeriod A (DCPTime(14), DCPTime(29));
338         DCPTimePeriod B (DCPTime(26), DCPTime(91));
339         list<DCPTimePeriod> p = { A, B };
340         auto q = coalesce (p);
341         BOOST_REQUIRE_EQUAL (q.size(), 1U);
342         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(14), DCPTime(91)));
343 }
344
345
346 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_coalesce_test3)
347 {
348         DCPTimePeriod A (DCPTime(14), DCPTime(29));
349         DCPTimePeriod B (DCPTime(29), DCPTime(91));
350         list<DCPTimePeriod> p = { A, B };
351         auto q = coalesce (p);
352         BOOST_REQUIRE_EQUAL (q.size(), 1U);
353         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(14), DCPTime(91)));
354 }
355
356
357 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_coalesce_test4)
358 {
359         DCPTimePeriod A (DCPTime(14), DCPTime(29));
360         DCPTimePeriod B (DCPTime(20), DCPTime(91));
361         DCPTimePeriod C (DCPTime(35), DCPTime(106));
362         list<DCPTimePeriod> p = { A, B, C };
363         auto q = coalesce (p);
364         BOOST_REQUIRE_EQUAL (q.size(), 1U);
365         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(14), DCPTime(106)));
366 }
367
368
369 BOOST_AUTO_TEST_CASE (dcpomatic_time_period_coalesce_test5)
370 {
371         DCPTimePeriod A (DCPTime(14), DCPTime(29));
372         DCPTimePeriod B (DCPTime(20), DCPTime(91));
373         DCPTimePeriod C (DCPTime(100), DCPTime(106));
374         list<DCPTimePeriod> p = { A, B, C };
375         auto q = coalesce (p);
376         BOOST_REQUIRE_EQUAL (q.size(), 2U);
377         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(14), DCPTime(91)));
378         BOOST_CHECK (q.back()  == DCPTimePeriod(DCPTime(100), DCPTime(106)));
379 }
380
381
382 BOOST_AUTO_TEST_CASE (test_coalesce_with_overlapping_periods)
383 {
384         DCPTimePeriod A (DCPTime(0), DCPTime(10));
385         DCPTimePeriod B (DCPTime(2), DCPTime(8));
386         list<DCPTimePeriod> p = { A, B };
387         auto q = coalesce(p);
388         BOOST_REQUIRE_EQUAL (q.size(), 1U);
389         BOOST_CHECK (q.front() == DCPTimePeriod(DCPTime(0), DCPTime(10)));
390 }
391
392
393 /* Straightforward test of DCPTime::ceil */
394 BOOST_AUTO_TEST_CASE (dcpomatic_time_ceil_test)
395 {
396         BOOST_CHECK_EQUAL (DCPTime(0).ceil(DCPTime::HZ / 2).get(), 0);
397         BOOST_CHECK_EQUAL (DCPTime(1).ceil(DCPTime::HZ / 2).get(), 2);
398         BOOST_CHECK_EQUAL (DCPTime(2).ceil(DCPTime::HZ / 2).get(), 2);
399         BOOST_CHECK_EQUAL (DCPTime(3).ceil(DCPTime::HZ / 2).get(), 4);
400
401         BOOST_CHECK_EQUAL (DCPTime(0).ceil(DCPTime::HZ / 42).get(), 0);
402         BOOST_CHECK_EQUAL (DCPTime(1).ceil(DCPTime::HZ / 42).get(), 42);
403         BOOST_CHECK_EQUAL (DCPTime(42).ceil(DCPTime::HZ / 42).get(), 42);
404         BOOST_CHECK_EQUAL (DCPTime(43).ceil(DCPTime::HZ / 42).get(), 84);
405
406         /* Check that rounding up to non-integer frame rates works */
407         BOOST_CHECK_EQUAL (DCPTime(45312).ceil(29.976).get(), 48038);
408
409         /* Check another tricky case that used to fail */
410         BOOST_CHECK_EQUAL (DCPTime(212256039).ceil(23.976).get(), 212256256);
411 }
412
413
414 /* Straightforward test of DCPTime::floor */
415 BOOST_AUTO_TEST_CASE (dcpomatic_time_floor_test)
416 {
417         BOOST_CHECK_EQUAL (DCPTime(0).floor(DCPTime::HZ / 2).get(), 0);
418         BOOST_CHECK_EQUAL (DCPTime(1).floor(DCPTime::HZ / 2).get(), 0);
419         BOOST_CHECK_EQUAL (DCPTime(2).floor(DCPTime::HZ / 2).get(), 2);
420         BOOST_CHECK_EQUAL (DCPTime(3).floor(DCPTime::HZ / 2).get(), 2);
421
422         BOOST_CHECK_EQUAL (DCPTime(0).floor(DCPTime::HZ / 42).get(), 0);
423         BOOST_CHECK_EQUAL (DCPTime(1).floor(DCPTime::HZ / 42).get(), 0);
424         BOOST_CHECK_EQUAL (DCPTime(42).floor(DCPTime::HZ / 42.0).get(), 42);
425         BOOST_CHECK_EQUAL (DCPTime(43).floor(DCPTime::HZ / 42.0).get(), 42);
426
427         /* Check that rounding down to non-integer frame rates works */
428         BOOST_CHECK_EQUAL (DCPTime(45312).floor(29.976).get(), 44836);
429 }