file_scheduler 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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