/* TimeParsing(Test) - handling textual time(code) specifications Copyright (C) 2011, Hermann Vosseler   **Lumiera** is free software; you can redistribute it and/or modify it   under the terms of the GNU General Public License as published by the   Free Software Foundation; either version 2 of the License, or (at your   option) any later version. See the file COPYING for further details. * *****************************************************************/ /** @file time-parsing-test.cpp ** unit test \ref TimeParsing_test */ #include "lib/test/run.hpp" #include "lib/test/test-helper.hpp" #include "steam/asset/meta/time-grid.hpp" #include "lib/time/quantiser.hpp" #include "lib/time/timecode.hpp" #include "lib/symbol.hpp" #include "lib/util.hpp" using lib::Symbol; namespace lib { namespace time{ namespace test{ using steam::asset::meta::TimeGrid; using LERR_(INVALID_TIMECODE); namespace { // Helper for writing test cases Symbol DEFAULT_GRID = "pal0"; Symbol OFFSET_GRID = "pal10"; /** * Expression builder * for writing time value parsing tests */ template class Parsing { string const& timeSpec_; PQuant grid_; public: Parsing (string const& toParse, Symbol gridID =DEFAULT_GRID) : timeSpec_(toParse) , grid_(Quantiser::retrieve(gridID)) { } void should_yield (TimeValue const& expected) { TimeValue parsed = FMT::parse (timeSpec_, *grid_); CHECK (parsed == expected, "parsing '%s' resulted in %s instead of %s" , timeSpec_.c_str() , string{Time(parsed)}.c_str() , string{Time(expected)}.c_str()); } void should_yield (FSecs const& expectedSecs) { should_yield (Time (expectedSecs)); } void should_fail () { VERIFY_ERROR (INVALID_TIMECODE, FMT::parse (timeSpec_, *grid_)); } }; }//(End)Test case helper /****************************************************//** * @test parse textual time specifications given * in the supported timecode formats */ class TimeParsing_test : public Test { virtual void run (Arg) { defineTestTimeGrids(); parseFrames(); parseFractionalSeconds(); /////////////////////////////////////////////TODO // parseHms(); // parseSmpte(); // parseDropFrame(); } void defineTestTimeGrids() { TimeGrid::build(DEFAULT_GRID, FrameRate::PAL); TimeGrid::build(OFFSET_GRID, FrameRate::PAL, Time(0,10)); } void parseFrames () { Parsing ("0#") .should_yield (0); Parsing ("1#") .should_yield (FSecs(1,25) ); Parsing ("-1#") .should_yield (FSecs(-1,25) ); Parsing ("-0#") .should_yield (0); Parsing ("25#") .should_yield (1 ); Parsing ("26#") .should_yield (Time(40,1) ); Parsing ("25#", OFFSET_GRID).should_yield (1+10 ); Parsing ("-1#", OFFSET_GRID).should_yield (10 - FSecs(1,25)); Parsing ("23") .should_fail(); Parsing ("23 #") .should_fail(); Parsing ("23.#") .should_fail(); Parsing ("23x#") .should_fail(); Parsing ("xxx25#xxx") .should_yield (1); Parsing ("12 25#") .should_yield (1); Parsing ("12 25# 33#") .should_yield (1); // note pitfall: the first valid number is used Parsing ("12 25# \n 33#") .should_yield (1); Parsing ("12\n 25# \n 33#") .should_yield (1); Parsing ("12.25#") .should_fail(); // rejected because of leading dot (ambiguity) } void parseFractionalSeconds () { Parsing ("0sec") .should_yield (0); Parsing ("1sec") .should_yield (1); Parsing ("10sec") .should_yield (10); Parsing ("100sec") .should_yield (100); Parsing ("-10sec") .should_yield (-10); Parsing ("-0sec") .should_yield (0); Parsing ("1/2sec") .should_yield (Time(500,0) ); Parsing ("1/25sec") .should_yield (Time( 40,0) ); Parsing ("1/250sec") .should_yield (Time( 4,0) ); // no quantisation involved in parsing Parsing ("1/250sec", OFFSET_GRID).should_yield (Time(4,10)); // ...but the origin of the grid is used Parsing ("10/2sec") .should_yield (5); Parsing ("1000/200sec") .should_yield (5); Parsing ("-10/2sec") .should_yield (-5); Parsing ("10/-2sec") .should_fail(); // only leading sign allowed (ambiguity) Parsing ("1+1/2sec") .should_yield (Time(500,1) ); Parsing ("1-1/2sec") .should_yield (Time(500,0) ); Parsing ("-1-1/2sec") .should_yield (-Time(500,1) ); Parsing ("-1+1/2sec") .should_yield (-Time(500,0) ); Parsing ("-1+1/-2sec") .should_fail(); Parsing ("-12+24690/12345sec", OFFSET_GRID).should_yield(0); // origin=+10sec -12sec + 2/1sec == 0 Parsing ("1") .should_fail(); Parsing ("1 sec") .should_fail(); Parsing ("--1sec") .should_fail(); Parsing ("/-1sec") .should_fail(); Parsing ("1.2sec") .should_fail(); Parsing ("1/.2sec") .should_fail(); Parsing ("1 + 2 / 4 sec") .should_fail(); Parsing ("1 + 2 / 4sec") .should_yield(4); // note pitfall: leading garbage not considered Parsing ("xxx4secxxxx") .should_yield(4); Parsing ("x1# 8/2sec 2sec").should_yield(4); // note pitfall: first valid number used } void parseHms () { UNIMPLEMENTED ("verify reading hour-minutes-seconds-millis time specs"); } void parseSmpte () { } void parseDropFrame () { UNIMPLEMENTED ("verify especially SMPTE-drop-frame timecode"); } }; /** Register this test class... */ LAUNCHER (TimeParsing_test, "unit common"); }}} // namespace lib::time::test