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.
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +9 -0
- data/Guardfile +8 -0
- data/Rakefile +10 -0
- data/bin/file-scheduler +19 -0
- data/file_scheduler.gemspec +24 -0
- data/lib/file_scheduler.rb +21 -0
- data/lib/file_scheduler/attributes_parser.rb +40 -0
- data/lib/file_scheduler/base.rb +62 -0
- data/lib/file_scheduler/content.rb +19 -0
- data/lib/file_scheduler/core_ext.rb +37 -0
- data/lib/file_scheduler/file.rb +80 -0
- data/lib/file_scheduler/log.rb +53 -0
- data/lib/file_scheduler/playlist.rb +36 -0
- data/lib/file_scheduler/scheduling.rb +59 -0
- data/lib/file_scheduler/time_chain.rb +19 -0
- data/lib/file_scheduler/time_interval.rb +38 -0
- data/lib/file_scheduler/time_mark.rb +66 -0
- data/lib/file_scheduler/time_parser.rb +37 -0
- data/lib/file_scheduler/url.rb +56 -0
- data/lib/file_scheduler/version.rb +3 -0
- data/spec/lib/file_scheduler/attributes_parser_spec.rb +33 -0
- data/spec/lib/file_scheduler/base_spec.rb +75 -0
- data/spec/lib/file_scheduler/content_shared_examples.rb +12 -0
- data/spec/lib/file_scheduler/file_spec.rb +104 -0
- data/spec/lib/file_scheduler/log_spec.rb +50 -0
- data/spec/lib/file_scheduler/playlist_spec.rb +17 -0
- data/spec/lib/file_scheduler/scheduling_spec.rb +114 -0
- data/spec/lib/file_scheduler/time_interval_spec.rb +46 -0
- data/spec/lib/file_scheduler/time_mark_spec.rb +51 -0
- data/spec/lib/file_scheduler/time_parser_spec.rb +33 -0
- data/spec/lib/file_scheduler/url_spec.rb +33 -0
- data/spec/lib/file_scheduler_spec.rb +117 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/pathname.rb +23 -0
- data/spec/support/time.rb +19 -0
- data/spec/support/tmpdir.rb +1 -0
- 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
|