test/test_edl.rb in edl-0.0.1 vs test/test_edl.rb in edl-0.0.2

- old
+ new

@@ -2,302 +2,522 @@ require File.dirname(__FILE__) + '/../lib/edl/cutter' require File.dirname(__FILE__) + '/../lib/edl/grabber' require 'rubygems' require 'test/unit' +require 'test/spec' require 'flexmock' require 'flexmock/test_unit' -TRAILER_EDL = File.dirname(__FILE__) + '/samples/TRAILER_EDL.edl' -SIMPLE_DISSOLVE = File.dirname(__FILE__) + '/samples/SIMPLE_DISSOLVE.EDL' -SPLICEME = File.dirname(__FILE__) + '/samples/SPLICEME.EDL' -SIMPLE_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP.EDL' -SLOMO_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP_HALF.EDL' -FORTY_FIVER = File.dirname(__FILE__) + '/samples/45S_SAMPLE.EDL' -REVERSE = File.dirname(__FILE__) + '/samples/REVERSE.EDL' +TRAILER_EDL = File.dirname(__FILE__) + '/samples/TRAILER_EDL.edl' +SIMPLE_DISSOLVE = File.dirname(__FILE__) + '/samples/SIMPLE_DISSOLVE.EDL' +SPLICEME = File.dirname(__FILE__) + '/samples/SPLICEME.EDL' +SIMPLE_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP.EDL' +SLOMO_TIMEWARP = File.dirname(__FILE__) + '/samples/TIMEWARP_HALF.EDL' +FORTY_FIVER = File.dirname(__FILE__) + '/samples/45S_SAMPLE.EDL' +AVID_REVERSE = File.dirname(__FILE__) + '/samples/REVERSE.EDL' +SPEEDUP_AND_FADEOUT = File.dirname(__FILE__) + '/samples/SPEEDUP_AND_FADEOUT.EDL' +SPEEDUP_REVERSE_AND_FADEOUT = File.dirname(__FILE__) + '/samples/SPEEDUP_REVERSE_AND_FADEOUT.EDL' +FCP_REVERSE = File.dirname(__FILE__) + '/samples/FCP_REVERSE.EDL' -class TestEvent < Test::Unit::TestCase - def test_attributes_defined +class String + def tc(fps = Timecode::DEFAULT_FPS) + Timecode.parse(self, fps) + end +end + +context "An Event should" do + specify "define the needed attributes" do evt = EDL::Event.new %w( num reel track src_start_tc src_end_tc rec_start_tc rec_end_tc ).each do | em | - assert_respond_to evt, em + evt.should.respond_to em end end -end + + specify "support hash initialization" do + evt = EDL::Event.new(:src_start_tc => "01:00:00:00".tc) + evt.src_start_tc.should.equal "01:00:00:00".tc + end -class Test::Unit::TestCase - def parse_evt(matcher_klass, line) - stack = [] - matcher_klass.new.apply(stack, line) - stack.pop + specify "support block initialization" do + evt = EDL::Event.new do | e | + e.src_start_tc = "01:00:00:04".tc + end + evt.src_start_tc.should.equal "01:00:00:04".tc end -end -class TestParser < Test::Unit::TestCase - def test_inst - assert_nothing_raised { EDL::Parser.new } + specify "respond to ends_with_transition? with false if outgoing_transition_duration is zero" do + evt = EDL::Event.new + evt.outgoing_transition_duration = 0 + evt.ends_with_transition?.should.equal false end + specify "respond to ends_with_transition? with true if outgoing_transition_duration set above zero" do + evt = EDL::Event.new + evt.outgoing_transition_duration = 24 + evt.ends_with_transition?.should.equal true + end - def test_inits_matchers_with_framerate + specify "respond to has_timewarp? with false if no timewarp assigned" do + evt = EDL::Event.new(:timewarp => nil) + evt.has_timewarp?.should.equal false + end + + specify "respond to has_timewarp? with true if a timewarp is assigned" do + evt = EDL::Event.new(:timewarp => true) + evt.has_timewarp?.should.equal true + end + + specify "report rec_length as a difference of record timecodes" do + evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc ) + evt.rec_length.should.equal "10s 2f".tc.to_i + end + + specify "report rec_length_with_transition as a difference of record timecodes if no transition set" do + evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc, :outgoing_transition_duration => 0) + evt.rec_length_with_transition.should.equal "10s 2f".tc.to_i + end + + specify "add transition length to rec_length_with_transition if a transition is set" do + evt = EDL::Event.new(:rec_start_tc => "1h".tc, :rec_end_tc => "1h 10s 2f".tc, :outgoing_transition_duration => 10) + evt.rec_length_with_transition.should.equal("10s 2f".tc.to_i + 10) + end + + specify "return a default array for comments" do + EDL::Event.new.comments.should.be.kind_of Enumerable + end + + specify "respond false to has_transition? if incoming transition is set" do + EDL::Event.new(:transition => nil).has_transition?.should.equal false + end + + specify "respond true to has_transition? if incoming transition is set" do + EDL::Event.new(:transition => true).has_transition?.should.equal true + end + + specify "respond true to black? if reel is BL" do + EDL::Event.new(:reel => "BL").should.black + EDL::Event.new(:reel => "001").should.not.black + end + + specify "respond true to generator? if reel is BL or AX" do + EDL::Event.new(:reel => "BL").should.generator + EDL::Event.new(:reel => "AX").should.generator + EDL::Event.new(:reel => "001").should.not.generator + end + + specify "report src_length as rec_length_with_transition" do + e = EDL::Event.new(:rec_start_tc => "2h".tc, :rec_end_tc => "2h 2s".tc) + e.src_length.should.equal "2s".tc.to_i + end + + specify "support capture_length as an alias to src_length" do + tw = flexmock + tw.should_receive(:actual_length_of_source).and_return(:something) + e = EDL::Event.new(:timewarp => tw) + e.src_length.should.equal e.capture_length + end + + specify "delegate src_length to the timewarp if it is there" do + tw = flexmock + tw.should_receive(:actual_length_of_source).and_return(:something).once + e = EDL::Event.new(:timewarp => tw) + e.src_length.should.equal :something + end + + specify "report reverse? and reversed? based on the timewarp" do + e = EDL::Event.new(:timewarp => nil) + e.should.not.be.reverse + e.should.not.be.reversed + + tw = flexmock + tw.should_receive(:reverse?).and_return(true) + + e = EDL::Event.new(:timewarp => tw) + e.should.be.reverse + e.should.be.reversed + end +end + +context "A Parser should" do + + specify "store the passed framerate" do + p = EDL::Parser.new(45) + p.should.respond_to :fps + p.fps.should.equal 45 + end + + specify "return matchers tuned with the passed framerate" do p = EDL::Parser.new(30) matchers = p.get_matchers event_matcher = matchers.find{|e| e.is_a?(EDL::EventMatcher) } - assert_equal 30, event_matcher.fps + event_matcher.fps.should.equal 30 end - def test_timecode_from_elements + specify "create a Timecode from stringified elements" do elems = ["08", "04", "24", "24"] - assert_nothing_raised { @tc = EDL::Parser.timecode_from_line_elements(elems, 30) } - assert_kind_of Timecode, @tc - assert_equal "08:04:24:24", @tc.to_s - assert_equal 30, @tc.fps - assert elems.empty?, "The elements used for timecode should have been removed from the array" + lambda{ @tc = EDL::Parser.timecode_from_line_elements(elems, 30) }.should.not.raise + + @tc.should.be.kind_of Timecode + @tc.should.equal "08:04:24:24".tc(30) + + elems.length.should.equal 0 end - def test_dissolve + specify "parse from a String" do p = EDL::Parser.new - assert_nothing_raised{ @edl = p.parse File.open(SIMPLE_DISSOLVE) } - assert_kind_of EDL::List, @edl - assert_equal 2, @edl.events.length + lambda{ @edl = p.parse File.read(SIMPLE_DISSOLVE) }.should.not.raise - first = @edl.events[0] - assert_kind_of EDL::Clip, first + @edl.should.be.kind_of EDL::List + @edl.length.should.equal 2 + end + + specify "parse from a File/IOish" do + p = EDL::Parser.new + lambda{ @edl = p.parse File.open(SIMPLE_DISSOLVE) }.should.not.raise - second = @edl.events[1] - assert_kind_of EDL::Clip, second - assert second.has_transition? + @edl.should.be.kind_of EDL::List + @edl.length.should.equal 2 + end + specify "properly parse a dissolve" do + # TODO: reformulate + p = EDL::Parser.new + lambda{ @edl = p.parse File.open(SIMPLE_DISSOLVE) }.should.not.raise + + @edl.should.be.kind_of EDL::List + @edl.length.should.equal 2 + + first, second = @edl + first.should.be.kind_of EDL::Event + second.should.be.kind_of EDL::Event + + second.has_transition?.should.equal true + first.ends_with_transition?.should.equal true + second.ends_with_transition?.should.equal false + no_trans = @edl.without_transitions - assert_equal 2, no_trans.events.length + assert_equal 2, no_trans.length target_tc = (Timecode.parse('01:00:00:00') + 43) - assert_equal target_tc, no_trans.events[0].rec_end_tc, + assert_equal target_tc, no_trans[0].rec_end_tc, "The incoming clip should have been extended by the length of the dissolve" target_tc = Timecode.parse('01:00:00:00') - assert_equal target_tc, no_trans.events[1].rec_start_tc + assert_equal target_tc, no_trans[1].rec_start_tc "The outgoing clip should have been left in place" end - def test_spliced - p = EDL::Parser.new - assert_nothing_raised{ @edl = p.parse(File.open(SPLICEME)) } - assert_equal 3, @edl.events.length - - spliced = @edl.spliced - assert_equal 1, spliced.events.length, "Should have been spliced to one event" + specify "return a spliced EDL if the sources allow" do + lambda{ @spliced = EDL::Parser.new.parse(File.open(SPLICEME)).spliced }.should.not.raise + + @spliced.length.should.equal 1 + @spliced[0].src_start_tc.should.equal '06:42:50:18'.tc + @spliced[0].src_end_tc.should.equal '06:42:52:16'.tc end end -class TimewarpMatcherTest < Test::Unit::TestCase - - def test_parses_as_one_event +context "A TimewarpMatcher should" do + + specify "not create any extra events when used within a Parser" do @edl = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP)) - assert_kind_of EDL::List, @edl - assert_equal 1, @edl.events.length + @edl.length.should.equal 1 end - def test_timewarp_attributes - @edl = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP)) - assert_kind_of EDL::List, @edl - assert_equal 1, @edl.events.length + specify "properly describe a speedup" do + clip = EDL::Parser.new.parse(File.open(SIMPLE_TIMEWARP)).pop - clip = @edl.events[0] - assert clip.has_timewarp?, "Should respond true to has_timewarp?" - assert_not_nil clip.timewarp - assert_kind_of EDL::Timewarp, clip.timewarp + tw = clip.timewarp + + tw.should.be.kind_of EDL::Timewarp + tw.source_used_upto.should.be > clip.src_end_tc - assert clip.timewarp.actual_src_end_tc > clip.src_end_tc - assert_equal "03:03:24:18", clip.timewarp.actual_src_end_tc.to_s - assert_equal 124, clip.timewarp.actual_length_of_source - assert !clip.timewarp.reverse? + tw.source_used_from.should.equal clip.src_start_tc + clip.timewarp.actual_length_of_source.should.equal 124 + tw.reverse?.should.be false end - def test_timwarp_slomo - @edl = EDL::Parser.new.parse(File.open(SLOMO_TIMEWARP)) - clip = @edl.events[0] - assert clip.has_timewarp?, "Should respond true to has_timewarp?" - assert_not_nil clip.timewarp - assert_kind_of EDL::Timewarp, clip.timewarp + specify "properly describe a slomo" do + clip = EDL::Parser.new.parse(File.open(SLOMO_TIMEWARP)).pop - assert clip.timewarp.actual_src_end_tc < clip.src_end_tc - assert_equal "03:03:19:24", clip.timewarp.actual_src_end_tc.to_s - assert_equal 10, clip.length - assert_equal 5, clip.timewarp.actual_length_of_source - assert_equal 50, clip.timewarp.speed_in_percent.to_i - assert !clip.timewarp.reverse? + clip.rec_length.should.equal 10 + clip.src_length.should.equal 5 + tw = clip.timewarp + tw.should.be.kind_of EDL::Timewarp + + tw.source_used_upto.should.be < clip.src_end_tc + tw.source_used_upto.should.equal "03:03:19:24".tc + tw.speed_in_percent.to_i.should.equal 50 + tw.actual_length_of_source.should.equal 5 + + tw.should.not.be.reverse end + end -class ReverseTimewarpTest < Test::Unit::TestCase - def test_parse - @edl = EDL::Parser.new.parse(File.open(REVERSE)) - assert_equal 1, @edl.events.length +context "A reverse timewarp EDL coming from Avid should" do + + specify "be parsed properly" do - clip = @edl.events[0] - assert_equal 52, clip.length + clip = EDL::Parser.new.parse(File.open(AVID_REVERSE)).pop - assert clip.has_timewarp?, "Should respond true to has_timewarp?" + clip.rec_length.should.equal 52 + tw = clip.timewarp + tw.actual_framerate.to_i.should.equal -25 - assert_equal( -25, tw.actual_framerate.to_i) - assert tw.reverse? - assert_equal clip.length, tw.actual_length_of_source - assert_equal clip.src_start_tc, tw.actual_src_end_tc - assert_equal clip.src_start_tc - 52, tw.actual_src_start_tc - assert_equal( -100, clip.timewarp.speed_in_percent.to_i) + tw.should.be.reverse + tw.actual_length_of_source.should.equal 52 + + assert_equal 52, clip.src_length, "The src length should be computed the same as its just a reverse" + assert_equal -100.0, clip.timewarp.speed end end -class EventMatcherTest < Test::Unit::TestCase +context "A Final Cut Pro originating reverse should" do + specify "be interpreted properly" do + e = EDL::Parser.new.parse(File.open(FCP_REVERSE)).pop + + e.rec_length.should.equal 1000 + e.src_length.should.equal 1000 + e.rec_start_tc.should.equal "1h".tc + e.rec_end_tc.should.equal "1h 40s".tc + + e.should.be.reverse + e.timewarp.should.not.be nil + + tw = e.timewarp + tw.source_used_from.should.equal "1h".tc + tw.source_used_upto.should.equal "1h 40s".tc + end +end + +context "EventMatcher should" do + EVT_PATTERNS = [ '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17', '021 009 V C 00:39:04:21 00:39:05:09 01:00:26:17 01:00:27:05', '022 008C V C 08:08:01:23 08:08:02:18 01:00:27:05 01:00:28:00', '023 008C V C 08:07:30:02 08:07:30:21 01:00:28:00 01:00:28:19', '024 AX V C 00:00:00:00 00:00:01:00 01:00:28:19 01:00:29:19', '025 BL V C 00:00:00:00 00:00:00:00 01:00:29:19 01:00:29:19', '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20', ] - def test_clip_generation_from_line + specify "produce an Event" do m = EDL::EventMatcher.new(25) clip = m.apply([], '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17' ) - assert_not_nil clip - assert_kind_of EDL::Clip, clip - assert_equal '020', clip.num - assert_equal '008C', clip.reel - assert_equal 'V', clip.track - assert_equal '08:04:24:24', clip.src_start_tc.to_s - assert_equal '08:04:25:19', clip.src_end_tc.to_s - assert_equal '01:00:25:22', clip.rec_start_tc.to_s - assert_equal '01:00:26:17', clip.rec_end_tc.to_s - assert_equal '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17', clip.original_line + clip.should.be.kind_of EDL::Event + + clip.num.should.equal "020" + clip.reel.should.equal "008C" + clip.track.should.equal "V" + + clip.src_start_tc.should.equal '08:04:24:24'.tc + + clip.src_end_tc.should.equal '08:04:25:19'.tc + clip.rec_start_tc.should.equal '01:00:25:22'.tc + clip.rec_end_tc.should.equal '01:00:26:17'.tc + + clip.transition.should.be nil + clip.timewarp.should.be nil + clip.outgoing_transition_duration.should.be.zero + end - def test_dissolve_generation_from_line + specify "produce an Event with dissolve" do m = EDL::EventMatcher.new(25) + dissolve = m.apply([], '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20' ) - assert_not_nil dissolve - assert_kind_of EDL::Clip, dissolve - assert_equal '025', dissolve.num - assert_equal 'GEN', dissolve.reel - assert_equal 'V', dissolve.track + dissolve.should.be.kind_of EDL::Event - assert dissolve.has_transition? - assert_not_nil dissolve.transition - assert_kind_of EDL::Dissolve, dissolve.transition - assert_equal '025', dissolve.transition.duration + dissolve.num.should.equal "025" + dissolve.reel.should.equal "GEN" + dissolve.track.should.equal "V" + + dissolve.should.be.has_transition + + tr = dissolve.transition + + tr.should.be.kind_of EDL::Dissolve + tr.duration.should.equal 25 end + + specify "set flag on the previous event in the stack when a dissolve is encountered" do + m = EDL::EventMatcher.new(25) + previous_evt = flexmock + previous_evt.should_receive(:outgoing_transition_duration=).with(25).once + + m.apply([previous_evt], + '025 GEN V D 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20' + ) + end - def test_wipe_generation_from_line + specify "generate a Wipe" do m = EDL::EventMatcher.new(25) wipe = m.apply([], '025 GEN V W001 025 00:00:55:10 00:00:58:11 01:00:29:19 01:00:32:20' ) - assert_not_nil wipe - assert_kind_of EDL::Clip, wipe - assert wipe.generator? - assert_equal '025', wipe.num - assert_equal 'GEN', wipe.reel - assert_equal 'V', wipe.track - assert wipe.has_transition? - - assert_not_nil wipe.transition - assert_kind_of EDL::Wipe, wipe.transition - assert_equal '025', wipe.transition.duration - assert_equal '001', wipe.transition.smpte_wipe_index + tr = wipe.transition + tr.should.be.kind_of EDL::Wipe + tr.duration.should.equal 25 + tr.smpte_wipe_index.should.equal '001' end - def test_black_generation_from_line - m = EDL::EventMatcher.new(25) - black = m.apply([], - '025 BL V C 00:00:00:00 00:00:00:00 01:00:29:19 01:00:29:19' - ) - - assert_not_nil black - - assert black.black?, "Black should be black?" - assert black.slug?, "Black should be slug?" - - assert black.generator?, "Should be generator?" - assert_equal '025', black.num - assert_equal 'BL', black.reel - assert_equal 'V', black.track - assert_equal '025 BL V C 00:00:00:00 00:00:00:00 01:00:29:19 01:00:29:19', black.original_line - end - - def test_matches_all_patterns + specify "match the widest range of patterns" do EVT_PATTERNS.each do | pat | assert EDL::EventMatcher.new(25).matches?(pat), "EventMatcher should match #{pat}" end end + + specify "pass the framerate that it received upon instantiation to the Timecodes being created" do + + m = EDL::EventMatcher.new(30) + clip = m.apply([], + '020 008C V C 08:04:24:24 08:04:25:19 01:00:25:22 01:00:26:17' + ) + clip.rec_start_tc.fps.should.equal 30 + clip.rec_end_tc.fps.should.equal 30 + clip.src_start_tc.fps.should.equal 30 + clip.src_end_tc.fps.should.equal 30 + end end -class ClipNameMatcherTest < Test::Unit::TestCase - def test_matches +context "CommentMatcher should" do + specify "match a comment" do + line = "* COMMENT: PURE BULLSHIT" + assert EDL::CommentMatcher.new.matches?(line) + end + + specify "apply the comment to the last clip on the stack" do + line = "* COMMENT: PURE BULLSHIT" + + comments = [] + mok_evt = flexmock + + 2.times { mok_evt.should_receive(:comments).and_return(comments) } + 2.times { EDL::CommentMatcher.new.apply([mok_evt], line) } + + mok_evt.comments.should.equal ["COMMENT: PURE BULLSHIT", "COMMENT: PURE BULLSHIT"] + end +end + +context "ClipNameMatcher should" do + specify "match a clip name" do line = "* FROM CLIP NAME: TAPE_6-10.MOV" - assert EDL::NameMatcher.new.matches?(line) + EDL::NameMatcher.new.matches?(line).should.equal true end - def test_apply + specify "not match a simple comment" do + line = "* CRAP" + EDL::NameMatcher.new.matches?(line).should.equal false + end + + specify "apply the name to the last event on the stack" do line = "* FROM CLIP NAME: TAPE_6-10.MOV" + mok_evt = flexmock + comments = [] mok_evt.should_receive(:clip_name=).with('TAPE_6-10.MOV').once + mok_evt.should_receive(:comments).and_return(comments).once + EDL::NameMatcher.new.apply([mok_evt], line) + comments.should.equal ["FROM CLIP NAME: TAPE_6-10.MOV"] end + end -class EffectMatcherTest < Test::Unit::TestCase - def test_matches +context "EffectMatcher should" do + specify "not match a simple comment" do + line = "* STUFF" + EDL::EffectMatcher.new.matches?(line).should.equal false + end + + specify "match a dissolve name" do line = "* EFFECT NAME: CROSS DISSOLVE" - assert EDL::EffectMatcher.new.matches?(line) + EDL::EffectMatcher.new.matches?(line).should.equal true end - - def test_apply + + specify "apply the effect name to the transition of the last event on the stack" do line = "* EFFECT NAME: CROSS DISSOLVE" mok_evt, mok_transition = flexmock, flexmock + cmt = [] mok_evt.should_receive(:transition).once.and_return(mok_transition) + mok_evt.should_receive(:comments).once.and_return(cmt) + mok_transition.should_receive(:effect=).with("CROSS DISSOLVE").once EDL::EffectMatcher.new.apply([mok_evt], line) + + cmt.should.equal ["EFFECT NAME: CROSS DISSOLVE"] end + end -class ComplexTest < Test::Unit::TestCase - def test_parses_cleanly +context "A complex EDL passed via Parser should" do + specify "parse without errors" do assert_nothing_raised { EDL::Parser.new.parse(File.open(FORTY_FIVER)) } end - def test_from_zero + # TODO: this does not belong here + specify "be properly rewritten from zero" do complex = EDL::Parser.new.parse(File.open(FORTY_FIVER)) - from_zero = complex.from_zero - assert_equal '00:00:00:00', from_zero.events[0].rec_start_tc.to_s, - "The starting timecode of the first event should have been shifted to zero" - assert_equal '00:00:42:16', from_zero.events[-1].rec_end_tc.to_s, - "The ending timecode of the last event should have been shifted 10 hours back" + + # Should have the same number of events + from_zero.length.should.equal complex.length + + from_zero[0].rec_start_tc.should.be.zero + from_zero[-1].rec_end_tc.should.equal '00:00:42:16'.tc end end -# class GrabberTest < Test::Unit::TestCase -# FILM = '/Users/julik/Downloads/HC_CORRECT-TCS_VIDEO1.edl.txt' -# def test_cutter -# complex = EDL::Parser.new.parse(File.open(FILM)) -# cutter = EDL::Grabber.new("/Users/julik/Desktop/Cutto/HC_CORRECT-TCS.mov") -# cutter.ffmpeg_bin = '/opt/local/bin/ffmpeg' -# cutter.grab(complex) -# end -# end +context "A FinalCutPro speedup with fade at the end should" do + specify "be parsed cleanly" do + list = EDL::Parser.new.parse(File.open(SPEEDUP_AND_FADEOUT)) + + list.length.should.equal 2 + + first_evt = list[0] + + tw = first_evt.timewarp + tw.should.be.kind_of EDL::Timewarp + + first_evt.rec_length.should.equal 689 + first_evt.rec_length_with_transition.should.equal 714 + + tw.actual_length_of_source.should.equal 1000 + tw.speed.should.equal 140 + + assert_equal 1000, first_evt.src_length + + assert_equal "01:00:00:00", first_evt.capture_from_tc.to_s + assert_equal "01:00:40:00", first_evt.capture_to_tc.to_s + end +end + +context "A FinalCutPro speedup and reverse with fade at the end should" do + specify "parse cleanly" do + first_evt = EDL::Parser.new.parse(File.open(SPEEDUP_REVERSE_AND_FADEOUT)).shift + + first_evt.should.be.reverse + + first_evt.rec_length.should.equal 689 + first_evt.rec_length_with_transition.should.equal 714 + + tw = first_evt.timewarp + tw.source_used_from.should.equal "1h 1f".tc + tw.source_used_upto.should.equal "1h 40s".tc + end +end \ No newline at end of file