file_scheduler 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +9 -0
  4. data/Guardfile +8 -0
  5. data/Rakefile +10 -0
  6. data/bin/file-scheduler +19 -0
  7. data/file_scheduler.gemspec +24 -0
  8. data/lib/file_scheduler.rb +21 -0
  9. data/lib/file_scheduler/attributes_parser.rb +40 -0
  10. data/lib/file_scheduler/base.rb +62 -0
  11. data/lib/file_scheduler/content.rb +19 -0
  12. data/lib/file_scheduler/core_ext.rb +37 -0
  13. data/lib/file_scheduler/file.rb +80 -0
  14. data/lib/file_scheduler/log.rb +53 -0
  15. data/lib/file_scheduler/playlist.rb +36 -0
  16. data/lib/file_scheduler/scheduling.rb +59 -0
  17. data/lib/file_scheduler/time_chain.rb +19 -0
  18. data/lib/file_scheduler/time_interval.rb +38 -0
  19. data/lib/file_scheduler/time_mark.rb +66 -0
  20. data/lib/file_scheduler/time_parser.rb +37 -0
  21. data/lib/file_scheduler/url.rb +56 -0
  22. data/lib/file_scheduler/version.rb +3 -0
  23. data/spec/lib/file_scheduler/attributes_parser_spec.rb +33 -0
  24. data/spec/lib/file_scheduler/base_spec.rb +75 -0
  25. data/spec/lib/file_scheduler/content_shared_examples.rb +12 -0
  26. data/spec/lib/file_scheduler/file_spec.rb +104 -0
  27. data/spec/lib/file_scheduler/log_spec.rb +50 -0
  28. data/spec/lib/file_scheduler/playlist_spec.rb +17 -0
  29. data/spec/lib/file_scheduler/scheduling_spec.rb +114 -0
  30. data/spec/lib/file_scheduler/time_interval_spec.rb +46 -0
  31. data/spec/lib/file_scheduler/time_mark_spec.rb +51 -0
  32. data/spec/lib/file_scheduler/time_parser_spec.rb +33 -0
  33. data/spec/lib/file_scheduler/url_spec.rb +33 -0
  34. data/spec/lib/file_scheduler_spec.rb +117 -0
  35. data/spec/spec_helper.rb +12 -0
  36. data/spec/support/pathname.rb +23 -0
  37. data/spec/support/time.rb +19 -0
  38. data/spec/support/tmpdir.rb +1 -0
  39. metadata +118 -0
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::Log do
4
+
5
+ let(:content) { mock }
6
+
7
+ def another_content
8
+ mock
9
+ end
10
+
11
+ describe "#distance" do
12
+
13
+ it "should be nil when content is unknown" do
14
+ subject.distance(mock).should be_nil
15
+ end
16
+
17
+ it "should be zero when content has been logged just before" do
18
+ subject.log(content)
19
+ subject.distance(content).should be_zero
20
+ end
21
+
22
+ it "should be increase each time another content is logged" do
23
+ subject.log(content)
24
+ 5.times { subject.log another_content }
25
+ subject.distance(content).should == 5
26
+ end
27
+
28
+ end
29
+
30
+ describe "#log" do
31
+
32
+ it "should returh the logged content" do
33
+ subject.log(content).should == content
34
+ end
35
+
36
+ end
37
+
38
+ describe "#max_size" do
39
+
40
+ it "should limit the number of reminded contents" do
41
+ subject.max_size = 10
42
+ subject.log(content)
43
+ 10.times { subject.log another_content }
44
+ subject.distance(content).should be_nil
45
+ end
46
+
47
+ end
48
+
49
+
50
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::Playlist do
4
+
5
+ def url(definition)
6
+ FileScheduler::URL.new definition
7
+ end
8
+
9
+ describe "contents" do
10
+
11
+ it "should return contents described by URLs" do
12
+ FileScheduler::Playlist.new(:content => "dummy").contents.should include(url("dummy"))
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::Scheduling do
4
+
5
+ let(:content) { mock }
6
+ let(:root) { mock :contents => [] }
7
+
8
+ subject { FileScheduler::Scheduling.new root, Time.now }
9
+
10
+ it "should logged each next content" do
11
+ subject.stub :next_without_log => content
12
+ subject.log.should_receive(:log).with(content)
13
+ subject.next
14
+ end
15
+
16
+ describe "schedulable?" do
17
+
18
+ it "should not accept a content not schedulable_by_time" do
19
+ subject.stub :schedulable_by_repeat? => true
20
+ subject.should_receive(:schedulable_by_time?).with(content).and_return(false)
21
+ subject.schedulable?(content).should be_false
22
+ end
23
+
24
+ it "should not accept a content not schedulable_by_repeat" do
25
+ subject.stub :schedulable_by_time? => true
26
+ subject.should_receive(:schedulable_by_repeat?).with(content).and_return(false)
27
+ subject.schedulable?(content).should be_false
28
+ end
29
+
30
+ it "should accept a content schedulable by time and repeat" do
31
+ subject.stub :schedulable_by_time? => true
32
+ subject.stub :schedulable_by_repeat? => true
33
+
34
+ subject.schedulable?(content).should be_true
35
+ end
36
+
37
+ end
38
+
39
+ describe "schedulable_by_time?" do
40
+
41
+ context "when context time_constraints matches time" do
42
+ before(:each) do
43
+ content.stub :time_constraints => mock(:matches? => true)
44
+ end
45
+
46
+ it { subject.schedulable_by_time?(content).should be_true }
47
+ end
48
+
49
+ context "when content has no time_constraints" do
50
+ before(:each) do
51
+ content.stub :time_constraints => nil
52
+ end
53
+
54
+ it { subject.schedulable_by_time?(content).should be_true }
55
+ end
56
+
57
+ context "when content time_constraints doesn't match time" do
58
+ before(:each) do
59
+ content.stub :time_constraints => mock(:matches? => false)
60
+ end
61
+
62
+ it { subject.schedulable_by_time?(content).should be_false }
63
+ end
64
+
65
+ end
66
+
67
+ describe "schedulable_by_repeat?" do
68
+
69
+ context "when content has no repeat_constraints" do
70
+
71
+ before(:each) do
72
+ content.stub :repeat_constraints => nil
73
+ end
74
+
75
+ it { subject.schedulable_by_repeat?(content).should be_true }
76
+
77
+ end
78
+
79
+ context "when content has never been scheduled" do
80
+
81
+ before(:each) do
82
+ content.stub :repeat_constraints => 10
83
+ subject.log.stub :distance => nil
84
+ end
85
+
86
+ it { subject.schedulable_by_repeat?(content).should be_true }
87
+
88
+ end
89
+
90
+ context "when content has been scheduled longer than the repeat constraints" do
91
+
92
+ before(:each) do
93
+ content.stub :repeat_constraints => 5
94
+ subject.log.stub :distance => 10
95
+ end
96
+
97
+ it { subject.schedulable_by_repeat?(content).should be_true }
98
+
99
+ end
100
+
101
+ context "when content has been scheduled less than the repeat constraints" do
102
+
103
+ before(:each) do
104
+ content.stub :repeat_constraints => 10
105
+ subject.log.stub :distance => 5
106
+ end
107
+
108
+ it { subject.schedulable_by_repeat?(content).should be_false }
109
+
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::TimeInterval do
4
+
5
+ let(:time) { Time.now }
6
+
7
+ def mark(attributes = {})
8
+ FileScheduler::TimeMark.new attributes
9
+ end
10
+
11
+ def interval(from, to)
12
+ from = mark(from) if Hash === from
13
+ to = mark(to) if Hash === to
14
+
15
+ FileScheduler::TimeInterval.new from, to
16
+ end
17
+
18
+ describe "#includes?" do
19
+
20
+ it "should include 13h55 in 12h30m-15h45m" do
21
+ interval({:hour => 12, :minute => 30}, {:hour => 15, :minute => 45}).should include(Time.parse("13:55"))
22
+ end
23
+
24
+ it "should include 00h15 in 22h30-06h45" do
25
+ interval({:hour => 22, :minute => 30}, {:hour => 06, :minute => 45}).should include(Time.parse("00:15"))
26
+ end
27
+
28
+ it "should include 23h45 in 22h30-06h45" do
29
+ interval({:hour => 22, :minute => 30}, {:hour => 06, :minute => 45}).should include(Time.parse("23:45"))
30
+ end
31
+
32
+ it "should not include 00h15 in 22h30-2009Y06h45" do
33
+ interval({:hour => 22, :minute => 30}, {:year => 2009, :hour => 06, :minute => 45}).should_not include(Time.parse("00:15"))
34
+ end
35
+
36
+ it "should include Sun Dec 18 2011 in 6w-1w" do
37
+ interval({:week_day => 6}, {:week_day => 1}).should include(Time.parse("Sun Dec 18 2011"))
38
+ end
39
+
40
+ it "should include Sun Dec 18 2011 in 3w-4w" do
41
+ interval({:week_day => 3}, {:week_day => 4}).should_not include(Time.parse("Sun Dec 18 2011"))
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::TimeMark do
4
+
5
+ let(:time) { Time.now }
6
+
7
+ def mark(attributes = {})
8
+ attributes = attributes.attributes if attributes.respond_to?(:attributes)
9
+ FileScheduler::TimeMark.new attributes
10
+ end
11
+
12
+ describe "#matches?" do
13
+
14
+ RSpec::Matchers.define :match do |time|
15
+ match do |mark|
16
+ mark.matches? time
17
+ end
18
+ end
19
+
20
+ it "should match a Time when all defined attributes are equal" do
21
+ mark(time).should match(time)
22
+ end
23
+
24
+ it "should not match a Time when an attribute is diffirent" do
25
+ mark(time.attributes.merge(:month => time.month + 1)).should_not match(time)
26
+ end
27
+
28
+ it "should match week day" do
29
+ mark(time.attributes(:week_day)).should match(time)
30
+ end
31
+
32
+ end
33
+
34
+ describe "#<=>" do
35
+
36
+ it "should be smaller when all attributes are equal or smaller" do
37
+ mark(time).should < time + 60
38
+ end
39
+
40
+ it "should be equal when all attributes are equal" do
41
+ mark(time).should == time
42
+ end
43
+
44
+ it "should be higher when all attributes are equal or higher" do
45
+ mark(time).should > time - 60
46
+ end
47
+
48
+ end
49
+
50
+
51
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::TimeParser do
4
+
5
+ describe "#parse" do
6
+
7
+ it "should return nil for dummy" do
8
+ subject.parse("dummy").should be_nil
9
+ end
10
+
11
+ it "should parse 12h30m-dummy" do
12
+ subject.parse("12h30m-dummy").should == FileScheduler::TimeMark.new(:hour => 12, :minute => 30)
13
+ end
14
+
15
+ it "should parse 1w12h30m-dummy" do
16
+ subject.parse("1w12h30m-dummy").should == FileScheduler::TimeMark.new(:week_day => 1, :hour => 12, :minute => 30)
17
+ end
18
+
19
+ it "should parse 2011y11M24d12h30m-dummy" do
20
+ subject.parse("1w12h30m-dummy").should == FileScheduler::TimeMark.new(:week_day => 1, :hour => 12, :minute => 30)
21
+ end
22
+
23
+ it "should parse 12h30m-15h45m-dummy" do
24
+ subject.parse("12h30m-15h45m-dummy").should == FileScheduler::TimeInterval.new(FileScheduler::TimeMark.new(:hour => 12, :minute => 30), FileScheduler::TimeMark.new(:hour => 15, :minute => 45))
25
+ end
26
+
27
+ it "should parse T12h30m-dummy" do
28
+ subject.parse("T12h30m-dummy").should == FileScheduler::TimeMark.new(:hour => 12, :minute => 30)
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe FileScheduler::URL do
4
+
5
+ def url(definition)
6
+ FileScheduler::URL.new definition
7
+ end
8
+
9
+ describe "#time_constraints" do
10
+
11
+ it "should parse 12h30m-dummy" do
12
+ url("12h30m-dummy").time_constraints.should == FileScheduler::TimeMark.new(:hour => 12, :minute => 30)
13
+ end
14
+
15
+ it "should parse 1w/12h30m-dummy" do
16
+ url("1w/12h30m-dummy").time_constraints.should == FileScheduler::TimeChain.new(FileScheduler::TimeMark.new(:week_day => 1), FileScheduler::TimeMark.new(:hour => 12, :minute => 30))
17
+ end
18
+
19
+ end
20
+
21
+ describe "#attributes" do
22
+
23
+ it "should merge the parts attributes" do
24
+ url("parent{key1=parent_value,key2=value2}/dummy{key1=value1}.wav").attributes.should == { :key1 => "value1", :key2 => "value2" }
25
+ end
26
+
27
+ end
28
+
29
+ require File.expand_path("../content_shared_examples", __FILE__)
30
+
31
+ it_behaves_like "a content"
32
+
33
+ end
@@ -0,0 +1,117 @@
1
+ require 'spec_helper'
2
+
3
+ require 'time'
4
+
5
+ class TestDir < Pathname
6
+
7
+ def self.open
8
+ Dir.mktmpdir do |directory|
9
+ yield TestDir.new(directory)
10
+ end
11
+ end
12
+
13
+ def file(name)
14
+ (self + name).tap do |file|
15
+ file.dirname.mkpath
16
+ FileUtils.touch file
17
+ end
18
+ end
19
+
20
+ def scheduler
21
+ @scheduler ||= FileScheduler::Base.new self
22
+ end
23
+
24
+ def next(time = nil)
25
+ time = time ? Time::parse(time) : Time.now
26
+ next_content = scheduler.next(time)
27
+ next_content.to_s.gsub("#{self}/", "") if next_content
28
+ end
29
+
30
+ end
31
+
32
+ class TestPlaylist
33
+
34
+ attr_reader :definition
35
+
36
+ def initialize
37
+ @definition = ""
38
+ end
39
+
40
+ def url(definition)
41
+ @definition << "#{definition}\n"
42
+ end
43
+
44
+ def scheduler
45
+ @scheduler ||= FileScheduler::Base.new :playlist => definition
46
+ end
47
+
48
+ def next(time)
49
+ scheduler.next(Time::parse(time)).to_s.gsub("#{self}/", "")
50
+ end
51
+
52
+ end
53
+
54
+ describe FileScheduler do
55
+
56
+ def at(time)
57
+ Time::parse time
58
+ end
59
+
60
+ it "should support time intervals in files" do
61
+ TestDir.open do |directory|
62
+ directory.file "13h-15h-test.wav"
63
+ directory.file "15h-17h-test.wav"
64
+
65
+ directory.next("13:30").should == "13h-15h-test.wav"
66
+ directory.next("16:00").should == "15h-17h-test.wav"
67
+ end
68
+ end
69
+
70
+ it "should support time intervals in directories" do
71
+ TestDir.open do |directory|
72
+ directory.file "13h-15h/test1.wav"
73
+ directory.file "15h-17h/test2.wav"
74
+
75
+ directory.next("13:30").should == "13h-15h/test1.wav"
76
+ directory.next("16:00").should == "15h-17h/test2.wav"
77
+ end
78
+ end
79
+
80
+ it "should support week day intervals" do
81
+ TestDir.open do |directory|
82
+ directory.file "3w-4w-music.wav"
83
+
84
+ directory.next("Sun Dec 18 2011").should be_nil
85
+ end
86
+ end
87
+
88
+ it "should support fixed time" do
89
+ TestDir.open do |directory|
90
+ directory.file "test.wav"
91
+ directory.file "T13h-test.wav"
92
+
93
+ directory.next("13:00").should == "T13h-test.wav"
94
+ end
95
+ end
96
+
97
+ it "should support repeat constraint" do
98
+ TestDir.open do |directory|
99
+ directory.file "test{repeat=+5}.wav"
100
+
101
+ directory.next.should == "test{repeat=+5}.wav"
102
+ directory.next.should be_nil
103
+ end
104
+ end
105
+
106
+ context "with playlist" do
107
+ it "should support time intervals in files" do
108
+ TestPlaylist.new.tap do |playlist|
109
+ playlist.url "13h-15h-test.wav"
110
+ playlist.url "15h-17h-test.wav"
111
+
112
+ playlist.next("16:00").should == "15h-17h-test.wav"
113
+ end
114
+ end
115
+ end
116
+
117
+ end