2 Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "subrip_reader.h"
24 #include <boost/test/unit_test.hpp>
25 #include <boost/filesystem.hpp>
35 /* Test reading of a Subrip file */
36 BOOST_AUTO_TEST_CASE (subrip_reader_test)
38 FILE* f = fopen ("test/data/test.srt", "r");
39 sub::SubripReader reader (f);
41 list<sub::Subtitle> subs = sub::collect<std::list<sub::Subtitle> > (reader.subtitles ());
43 list<sub::Subtitle>::iterator i = subs.begin ();
48 BOOST_CHECK (i != subs.end ());
49 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 0, 41, 90));
50 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 0, 42, 210));
52 list<sub::Line>::iterator j = i->lines.begin ();
53 BOOST_CHECK (j != i->lines.end ());
54 BOOST_CHECK_EQUAL (j->blocks.size(), 1);
55 sub::Block b = j->blocks.front ();
56 BOOST_CHECK_EQUAL (b.text, "This is a subtitle");
57 /* No font is specified by subrip, so none should be seen here */
58 BOOST_CHECK (!b.font);
59 BOOST_CHECK (!b.font_size.specified());
60 BOOST_CHECK_EQUAL (b.bold, false);
61 BOOST_CHECK_EQUAL (b.italic, false);
62 BOOST_CHECK_EQUAL (b.underline, false);
63 BOOST_CHECK_EQUAL (j->vertical_position.line.get(), 0);
64 BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
67 BOOST_CHECK (j != i->lines.end ());
68 BOOST_CHECK_EQUAL (j->blocks.size(), 1);
69 b = j->blocks.front ();
70 BOOST_CHECK_EQUAL (b.text, "and that's a line break");
71 /* No font is specified by subrip, so none should be seen here */
72 BOOST_CHECK (!b.font);
73 BOOST_CHECK (!b.font_size.specified());
74 BOOST_CHECK_EQUAL (b.bold, false);
75 BOOST_CHECK_EQUAL (b.italic, false);
76 BOOST_CHECK_EQUAL (b.underline, false);
77 BOOST_CHECK_EQUAL (j->vertical_position.line.get(), 1);
78 BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
84 BOOST_CHECK (i != subs.end ());
85 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 1, 10));
86 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 2, 100));
88 BOOST_CHECK_EQUAL (i->lines.size(), 1);
89 sub::Line l = i->lines.front ();
90 BOOST_CHECK_EQUAL (l.blocks.size(), 7);
91 BOOST_CHECK_EQUAL (l.vertical_position.line.get(), 0);
92 BOOST_CHECK_EQUAL (l.vertical_position.reference.get(), sub::TOP_OF_SUBTITLE);
94 list<sub::Block>::iterator k = l.blocks.begin ();
96 BOOST_CHECK (k != l.blocks.end ());
97 BOOST_CHECK_EQUAL (k->text, "This is some ");
98 /* No font is specified by subrip, so none should be seen here */
99 BOOST_CHECK (!b.font);
100 BOOST_CHECK (!b.font_size.specified());
101 BOOST_CHECK_EQUAL (k->bold, false);
102 BOOST_CHECK_EQUAL (k->italic, false);
103 BOOST_CHECK_EQUAL (k->underline, false);
106 BOOST_CHECK (k != l.blocks.end ());
107 BOOST_CHECK_EQUAL (k->text, "bold");
108 /* No font is specified by subrip, so none should be seen here */
109 BOOST_CHECK (!b.font);
110 BOOST_CHECK (!b.font_size.specified());
111 BOOST_CHECK_EQUAL (k->bold, true);
112 BOOST_CHECK_EQUAL (k->italic, false);
113 BOOST_CHECK_EQUAL (k->underline, false);
116 BOOST_CHECK (k != l.blocks.end ());
117 BOOST_CHECK_EQUAL (k->text, " and some ");
118 /* No font is specified by subrip, so none should be seen here */
119 BOOST_CHECK (!b.font);
120 BOOST_CHECK (!b.font_size.specified());
121 BOOST_CHECK_EQUAL (k->bold, false);
122 BOOST_CHECK_EQUAL (k->italic, false);
123 BOOST_CHECK_EQUAL (k->underline, false);
126 BOOST_CHECK (k != l.blocks.end ());
127 BOOST_CHECK_EQUAL (k->text, "bold italic");
128 /* No font is specified by subrip, so none should be seen here */
129 BOOST_CHECK (!b.font);
130 BOOST_CHECK (!b.font_size.specified());
131 BOOST_CHECK_EQUAL (k->bold, true);
132 BOOST_CHECK_EQUAL (k->italic, true);
133 BOOST_CHECK_EQUAL (k->underline, false);
136 BOOST_CHECK (k != l.blocks.end ());
137 BOOST_CHECK_EQUAL (k->text, " and some ");
138 /* No font is specified by subrip, so none should be seen here */
139 BOOST_CHECK (!b.font);
140 BOOST_CHECK (!b.font_size.specified());
141 BOOST_CHECK_EQUAL (k->bold, false);
142 BOOST_CHECK_EQUAL (k->italic, false);
143 BOOST_CHECK_EQUAL (k->underline, false);
146 BOOST_CHECK (k != l.blocks.end ());
147 BOOST_CHECK_EQUAL (k->text, "underlined");
148 /* No font is specified by subrip, so none should be seen here */
149 BOOST_CHECK (!b.font);
150 BOOST_CHECK (!b.font_size.specified());
151 BOOST_CHECK_EQUAL (k->bold, false);
152 BOOST_CHECK_EQUAL (k->italic, false);
153 BOOST_CHECK_EQUAL (k->underline, true);
156 BOOST_CHECK (k != l.blocks.end ());
157 BOOST_CHECK_EQUAL (k->text, ".");
158 /* No font is specified by subrip, so none should be seen here */
159 BOOST_CHECK (!b.font);
160 BOOST_CHECK (!b.font_size.specified());
161 BOOST_CHECK_EQUAL (k->bold, false);
162 BOOST_CHECK_EQUAL (k->italic, false);
163 BOOST_CHECK_EQUAL (k->underline, false);
166 BOOST_CHECK (k == l.blocks.end ());
169 /* Test reading of another Subrip file */
170 BOOST_AUTO_TEST_CASE (subrip_reader_test2)
172 FILE* f = fopen ("test/data/test2.srt", "r");
173 sub::SubripReader reader (f);
175 list<sub::Subtitle> subs = sub::collect<list<sub::Subtitle> > (reader.subtitles ());
177 list<sub::Subtitle>::const_iterator i = subs.begin();
179 BOOST_CHECK (i != subs.end ());
180 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 49, 200));
181 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 52, 351));
182 BOOST_CHECK_EQUAL (i->lines.size(), 2);
183 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "This is a subtitle, and it goes ");
184 BOOST_CHECK_EQUAL (i->lines.back().blocks.front().text, "over two lines.");
187 BOOST_CHECK (i != subs.end ());
188 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 52, 440));
189 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 54, 351));
190 BOOST_CHECK_EQUAL (i->lines.size(), 1);
191 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "We have emboldened this");
192 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().bold, true);
195 BOOST_CHECK (i != subs.end ());
196 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 54, 440));
197 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 56, 590));
198 BOOST_CHECK_EQUAL (i->lines.size(), 1);
199 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "And italicised this.");
200 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().italic, true);
203 BOOST_CHECK (i != subs.end ());
204 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 1, 56, 680));
205 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 1, 58, 955));
206 BOOST_CHECK_EQUAL (i->lines.size(), 1);
207 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Shall I compare thee to a summers' day?");
210 BOOST_CHECK (i != subs.end ());
211 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 2, 0, 840));
212 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 2, 3, 400));
213 BOOST_CHECK_EQUAL (i->lines.size(), 1);
214 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Is this a dagger I see before me?");
217 BOOST_CHECK (i != subs.end ());
218 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 3, 54, 560));
219 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 3, 56, 471));
220 BOOST_CHECK_EQUAL (i->lines.size(), 1);
221 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Hello world.");
224 BOOST_CHECK (i != subs.end ());
225 BOOST_CHECK_EQUAL (i->from, sub::Time::from_hms (0, 4, 50, 123));
226 BOOST_CHECK_EQUAL (i->to, sub::Time::from_hms (0, 4, 55, 23));
227 BOOST_CHECK_EQUAL (i->lines.size(), 2);
228 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().text, "Some italics over");
229 BOOST_CHECK_EQUAL (i->lines.front().blocks.front().italic, true);
230 BOOST_CHECK_EQUAL (i->lines.back().blocks.front().text, "multiple lines");
231 BOOST_CHECK_EQUAL (i->lines.back().blocks.front().italic, true);
234 BOOST_CHECK (i == subs.end ());
237 /** Test SubripReader::convert_line */
238 BOOST_AUTO_TEST_CASE (subrip_reader_convert_line_test)
243 r.convert_line ("Hello world", rs);
244 BOOST_CHECK_EQUAL (r._subs.size(), 1);
245 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
248 rs = sub::RawSubtitle();
249 r.convert_line ("<b>Hello world</b>", rs);
250 BOOST_CHECK_EQUAL (r._subs.size(), 1);
251 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
252 BOOST_CHECK_EQUAL (r._subs.front().bold, true);
255 rs = sub::RawSubtitle();
256 r.convert_line ("<i>Hello world</i>", rs);
257 BOOST_CHECK_EQUAL (r._subs.size(), 1);
258 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
259 BOOST_CHECK_EQUAL (r._subs.front().italic, true);
262 rs = sub::RawSubtitle();
263 r.convert_line ("<u>Hello world</u>", rs);
264 BOOST_CHECK_EQUAL (r._subs.size(), 1);
265 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
266 BOOST_CHECK_EQUAL (r._subs.front().underline, true);
269 rs = sub::RawSubtitle();
270 r.convert_line ("{b}Hello world{/b}", rs);
271 BOOST_CHECK_EQUAL (r._subs.size(), 1);
272 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
273 BOOST_CHECK_EQUAL (r._subs.front().bold, true);
276 rs = sub::RawSubtitle();
277 r.convert_line ("{i}Hello world{/i}", rs);
278 BOOST_CHECK_EQUAL (r._subs.size(), 1);
279 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
280 BOOST_CHECK_EQUAL (r._subs.front().italic, true);
283 rs = sub::RawSubtitle();
284 r.convert_line ("{u}Hello world{/u}", rs);
285 BOOST_CHECK_EQUAL (r._subs.size(), 1);
286 BOOST_CHECK_EQUAL (r._subs.front().text, "Hello world");
287 BOOST_CHECK_EQUAL (r._subs.front().underline, true);
290 rs = sub::RawSubtitle();
291 r.convert_line ("<b>This is <i>nesting</i> of subtitles</b>", rs);
292 BOOST_CHECK_EQUAL (r._subs.size(), 3);
293 list<sub::RawSubtitle>::iterator i = r._subs.begin ();
294 BOOST_CHECK_EQUAL (i->text, "This is ");
295 BOOST_CHECK_EQUAL (i->bold, true);
296 BOOST_CHECK_EQUAL (i->italic, false);
298 BOOST_CHECK_EQUAL (i->text, "nesting");
299 BOOST_CHECK_EQUAL (i->bold, true);
300 BOOST_CHECK_EQUAL (i->italic, true);
302 BOOST_CHECK_EQUAL (i->text, " of subtitles");
303 BOOST_CHECK_EQUAL (i->bold, true);
304 BOOST_CHECK_EQUAL (i->italic, false);
308 rs = sub::RawSubtitle();
309 r.convert_line ("<font color=\"#ff00ff\">simple color</font>", rs);
310 BOOST_CHECK_EQUAL (r._subs.size(), 1);
311 BOOST_CHECK_EQUAL (r._subs.front().text, "simple color");
312 BOOST_CHECK_EQUAL (r._subs.front().bold, false);
313 BOOST_CHECK_CLOSE (r._subs.front().colour.r, 1, 0.1);
314 BOOST_CHECK (fabs (r._subs.front().colour.g) < 0.01);
315 BOOST_CHECK_CLOSE (r._subs.front().colour.b, 1, 0.1);
318 rs = sub::RawSubtitle();
319 r.convert_line ("<font color=\"#ff0000\">some red text <b>in bold</b></font>", rs);
320 BOOST_CHECK_EQUAL (r._subs.size(), 2);
321 i = r._subs.begin ();
322 BOOST_CHECK_EQUAL (i->text, "some red text ");
323 BOOST_CHECK_EQUAL (i->bold, false);
324 BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
325 BOOST_CHECK (fabs (i->colour.g) < 0.01);
326 BOOST_CHECK (fabs (i->colour.b) < 0.01);
328 BOOST_CHECK_EQUAL (i->text, "in bold");
329 BOOST_CHECK_EQUAL (i->bold, true);
330 BOOST_CHECK_CLOSE (i->colour.r, 1, 0.1);
331 BOOST_CHECK (fabs (i->colour.g) < 0.01);
332 BOOST_CHECK (fabs (i->colour.b) < 0.01);
335 rs = sub::RawSubtitle();
336 r.convert_line ("<font color=\"#0000ff\">some blue text <b>in bold</b></font>", rs);
337 BOOST_CHECK_EQUAL (r._subs.size(), 2);
338 i = r._subs.begin ();
339 BOOST_CHECK_EQUAL (i->text, "some blue text ");
340 BOOST_CHECK_EQUAL (i->bold, false);
341 BOOST_CHECK (fabs (i->colour.r) < 0.01);
342 BOOST_CHECK (fabs (i->colour.g) < 0.01);
343 BOOST_CHECK_CLOSE (i->colour.b, 1, 0.1);
345 BOOST_CHECK_EQUAL (i->text, "in bold");
346 BOOST_CHECK_EQUAL (i->bold, true);
347 BOOST_CHECK (fabs (i->colour.r) < 0.01);
348 BOOST_CHECK (fabs (i->colour.g) < 0.01);
349 BOOST_CHECK_CLOSE (i->colour.b, 1, 0.1);
353 /** Test SubripReader::convert_time */
354 BOOST_AUTO_TEST_CASE (subrip_reader_convert_time_test)
356 sub::SubripReader reader;
357 BOOST_CHECK_EQUAL (reader.convert_time ("00:03:10,500"), sub::Time::from_hms (0, 3, 10, 500));
358 BOOST_CHECK_EQUAL (reader.convert_time ("04:19:51,782"), sub::Time::from_hms (4, 19, 51, 782));
362 test (boost::filesystem::path p)
364 p = private_test / p;
365 FILE* f = fopen (p.string().c_str(), "r");
368 cerr << p << " not found.\n";
371 sub::SubripReader r (f);
375 /** Test of reading some typical .srt files */
376 BOOST_AUTO_TEST_CASE (subrip_read_test)
378 test ("sintel_en.srt");
379 test ("sintel_fr.srt");
380 test ("Fight.Club.1999.720p.BRRip.x264-x0r.srt");
382 test ("Subtitulos_HURTO_eng.srt");
385 #define SUB_START(f, t) \
386 BOOST_REQUIRE (i != subs.end ()); \
387 BOOST_CHECK_EQUAL (i->from, f); \
388 BOOST_CHECK_EQUAL (i->to, t); \
389 j = i->lines.begin ();
392 BOOST_REQUIRE (j != i->lines.end ()); \
393 BOOST_CHECK (j->vertical_position.line); \
394 BOOST_CHECK_EQUAL (j->vertical_position.line.get(), p); \
395 BOOST_CHECK (j->vertical_position.reference); \
396 BOOST_CHECK_EQUAL (j->vertical_position.reference.get(), sub::TOP_OF_SUBTITLE); \
397 k = j->blocks.begin (); \
400 #define BLOCK(t, f, s, b, i, u) \
401 BOOST_REQUIRE (k != j->blocks.end ()); \
402 BOOST_CHECK_EQUAL (k->text, t); \
403 BOOST_CHECK_EQUAL (k->bold, b); \
404 BOOST_CHECK_EQUAL (k->italic, i); \
405 BOOST_CHECK_EQUAL (k->underline, u); \
411 /** Test reading of another .srt file */
412 BOOST_AUTO_TEST_CASE (subrip_reader_test3)
414 boost::filesystem::path p = private_test / "DCP-o-matic_test_subs_1.srt";
415 FILE* f = fopen (p.string().c_str(), "r");
416 sub::SubripReader reader (f);
418 list<sub::Subtitle> subs = sub::collect<std::list<sub::Subtitle> > (reader.subtitles ());
420 list<sub::Subtitle>::iterator i = subs.begin ();
421 list<sub::Line>::iterator j;
422 list<sub::Block>::iterator k;
424 BOOST_REQUIRE (i != subs.end ());
426 SUB_START (sub::Time::from_hms (0, 0, 0, 76), sub::Time::from_hms (0, 0, 1, 116));
428 BLOCK ("This line is normal", "Arial", 30, false, false, false);
430 BLOCK ("This line is bold", "Arial", 30, true, false, false);
433 SUB_START (sub::Time::from_hms (0, 0, 1, 206), sub::Time::from_hms (0, 0, 2, 246));
435 BLOCK ("This line is bold", "Arial", 30, true, false, false);
437 BLOCK ("This line is normal", "Arial", 30, false, false, false);
440 SUB_START (sub::Time::from_hms (0, 0, 2, 308), sub::Time::from_hms (0, 0, 3, 380));
442 BLOCK ("This line is bold", "Arial", 30, true, false, false);
444 BLOCK ("This line is italic", "Arial", 30, false, true, false);
447 SUB_START (sub::Time::from_hms (0, 0, 3, 404), sub::Time::from_hms (0, 0, 4, 484));
449 BLOCK ("This line is italic", "Arial", 30, false, true, false);
451 BLOCK ("This line is bold", "Arial", 30, true, false, false);
454 SUB_START (sub::Time::from_hms (0, 0, 4, 519), sub::Time::from_hms (0, 0, 5, 604));
456 BLOCK ("Last three words are ", "Arial", 30, false, false, false);
457 BLOCK ("bold AND italic", "Arial", 30, true, true, false);
459 BLOCK ("Last three words are ", "Arial", 30, false, false, false);
460 BLOCK ("italic AND bold", "Arial", 30, true, true, false);
463 SUB_START (sub::Time::from_hms (0, 0, 5, 628), sub::Time::from_hms (0, 0, 6, 712));
465 BLOCK ("Last three words are ", "Arial", 30, false, false, false);
466 BLOCK ("bold AND italic", "Arial", 30, true, true, false);
468 BLOCK ("First three words", "Arial", 30, true, true, false);
469 BLOCK (" are italic AND bold", "Arial", 30, false, false, false);
472 SUB_START (sub::Time::from_hms (0, 0, 6, 736), sub::Time::from_hms (0, 0, 8, 31));
474 BLOCK ("Last three words are ", "Arial", 30, false, false, false);
475 BLOCK ("bold AND italic", "Arial", 30, true, true, false);
477 BLOCK ("This line is normal", "Arial", 30, false, false, false);
480 SUB_START (sub::Time::from_hms (0, 0, 8, 94), sub::Time::from_hms (0, 0, 9, 211));
482 BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);
484 BLOCK ("Both lines are bold AND italic", "Arial", 30, true, true, false);