runt 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +18 -0
- data/Rakefile +7 -4
- data/TODO +4 -2
- data/doc/tutorial_schedule.rdoc +355 -46
- data/doc/tutorial_te.rdoc +3 -3
- data/examples/reminder.rb +63 -0
- data/examples/schedule_tutorial.rb +59 -0
- data/examples/schedule_tutorialtest.rb +52 -0
- data/lib/runt/daterange.rb +1 -1
- data/lib/runt/pdate.rb +1 -1
- data/lib/runt/schedule.rb +1 -1
- data/lib/runt/temporalexpression.rb +109 -27
- data/test/baseexpressiontest.rb +110 -0
- data/test/collectiontest.rb +63 -0
- data/test/combinedexpressionstest.rb +158 -0
- data/test/daterangetest.rb +2 -0
- data/test/dayintervaltetest.rb +37 -0
- data/test/difftest.rb +37 -0
- data/test/dimonthtest.rb +59 -0
- data/test/diweektest.rb +32 -0
- data/test/everytetest.rb +36 -0
- data/test/intersecttest.rb +34 -0
- data/test/redaytest.rb +30 -0
- data/test/remonthtest.rb +37 -0
- data/test/reweektest.rb +51 -0
- data/test/reyeartest.rb +98 -0
- data/test/rspectest.rb +25 -0
- data/test/spectest.rb +36 -0
- data/test/temporalexpressiontest.rb +49 -585
- data/test/uniontest.rb +36 -0
- data/test/wimonthtest.rb +54 -0
- data/test/yeartetest.rb +22 -0
- metadata +54 -6
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'runt'
|
5
|
+
require 'schedule_tutorial'
|
6
|
+
|
7
|
+
class ReminderTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
include Runt
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@schedule = Schedule.new
|
13
|
+
@north_event = Event.new("north side of the street will be ticketed")
|
14
|
+
north_expr = (DIWeek.new(Mon) | DIWeek.new(Wed) | DIWeek.new(Fri)) & REDay.new(8,00,11,00)
|
15
|
+
@schedule.add(@north_event, north_expr)
|
16
|
+
@south_event = Event.new("south side of the street will be ticketed")
|
17
|
+
south_expr = (DIWeek.new(Tue) | DIWeek.new(Thu)) & REDay.new(11,30,14,00)
|
18
|
+
@schedule.add(@south_event, south_expr)
|
19
|
+
@mail_server = MailServer.new
|
20
|
+
@reminder = Reminder.new(@schedule, @mail_server)
|
21
|
+
@saturday_at_10 = PDate.min(2007,11,24,10,0,0)
|
22
|
+
@monday_at_10 = PDate.min(2007,11,26,10,0,0)
|
23
|
+
@tuesday_at_noon = PDate.min(2007,11,27,12,0,0)
|
24
|
+
end
|
25
|
+
def test_initalize
|
26
|
+
assert_same @schedule, @reminder.schedule, "Expected #{@schedule} instead was #{@reminder.schedule}"
|
27
|
+
assert_same @mail_server, @reminder.mail_server, "Expected #{@mail_server} instead was #{@reminder.mail_server}"
|
28
|
+
end
|
29
|
+
def test_send
|
30
|
+
params = [@north_event, @south_event]
|
31
|
+
result = @reminder.send(params)
|
32
|
+
assert_email result, Reminder::TEXT + params.join(', ')
|
33
|
+
end
|
34
|
+
def test_check
|
35
|
+
assert_equal 1, @reminder.check(@monday_at_10).size, "Unexpected size #{@reminder.check(@monday_at_10).size} returned"
|
36
|
+
assert_same @north_event, @reminder.check(@monday_at_10)[0], "Expected Event #{@north_event}. Got #{@reminder.check(@monday_at_10)[0]}."
|
37
|
+
assert_equal 1, @reminder.check(@tuesday_at_noon).size, "Unexpected size #{@reminder.check(@tuesday_at_noon).size} returned"
|
38
|
+
assert_same @south_event, @reminder.check(@tuesday_at_noon)[0], "Expected Event #{@south_event}. Got #{@reminder.check(@tuesday_at_noon)[0]}."
|
39
|
+
assert @reminder.check(@saturday_at_10).empty?, "Expected empty Array. Got #{@reminder.check(@saturday_at_10)}"
|
40
|
+
end
|
41
|
+
def test_run
|
42
|
+
result = @reminder.run(@monday_at_10)
|
43
|
+
assert_email result, Reminder::TEXT + @north_event.to_s
|
44
|
+
end
|
45
|
+
def assert_email(result, text)
|
46
|
+
assert_equal Reminder::TO, result.to, "Unexpected value for 'to' field of Email Struct: #{result.to}"
|
47
|
+
assert_equal Reminder::FROM, result.from, "Unexpected value for 'from' field of Email Struct: #{result.from}"
|
48
|
+
assert_equal Reminder::SUBJECT, result.subject, "Unexpected value for 'subject' field of Email Struct: #{result.subject}"
|
49
|
+
assert_equal text, result.text, "Unexpected value for 'text' field of Email Struct: #{result.text}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/lib/runt/daterange.rb
CHANGED
data/lib/runt/pdate.rb
CHANGED
data/lib/runt/schedule.rb
CHANGED
@@ -39,7 +39,7 @@ module Runt
|
|
39
39
|
end
|
40
40
|
|
41
41
|
#
|
42
|
-
# Returns all Events whose
|
42
|
+
# Returns all Events whose Temporal Expression includes the given date/expression
|
43
43
|
#
|
44
44
|
def events(date)
|
45
45
|
self.select{|ev,xpr| xpr.include?(date);}
|
@@ -86,7 +86,6 @@ class Collection
|
|
86
86
|
include TExpr
|
87
87
|
|
88
88
|
attr_reader :expressions
|
89
|
-
#protected :expressions
|
90
89
|
|
91
90
|
def initialize
|
92
91
|
@expressions = Array.new
|
@@ -172,6 +171,8 @@ class Diff
|
|
172
171
|
|
173
172
|
include TExpr
|
174
173
|
|
174
|
+
attr_reader :expr1, :expr2
|
175
|
+
|
175
176
|
def initialize(expr1, expr2)
|
176
177
|
@expr1 = expr1
|
177
178
|
@expr2 = expr2
|
@@ -191,6 +192,8 @@ end
|
|
191
192
|
class Spec
|
192
193
|
|
193
194
|
include TExpr
|
195
|
+
|
196
|
+
attr_reader :date_expr
|
194
197
|
|
195
198
|
def initialize(date_expr)
|
196
199
|
@date_expr = date_expr
|
@@ -214,16 +217,10 @@ end
|
|
214
217
|
# facilitating inclusion of an arbitrary range in a temporal expression.
|
215
218
|
#
|
216
219
|
# See also: Range
|
217
|
-
class RSpec
|
218
|
-
|
219
|
-
include TExpr
|
220
|
-
|
221
|
-
def initialize(date_expr)
|
222
|
-
@date_expr = date_expr
|
223
|
-
end
|
220
|
+
class RSpec < Spec
|
224
221
|
|
225
|
-
|
226
|
-
|
222
|
+
## Will return true if the supplied object is included in the range used to
|
223
|
+
## create this instance
|
227
224
|
def include?(date_expr)
|
228
225
|
return @date_expr.include?(date_expr)
|
229
226
|
end
|
@@ -237,9 +234,6 @@ class RSpec
|
|
237
234
|
false
|
238
235
|
end
|
239
236
|
|
240
|
-
def to_s
|
241
|
-
@date_expr.to_s
|
242
|
-
end
|
243
237
|
end
|
244
238
|
|
245
239
|
#######################################################################
|
@@ -421,21 +415,102 @@ class REWeek
|
|
421
415
|
end
|
422
416
|
end
|
423
417
|
|
418
|
+
#
|
419
|
+
# TExpr that matches date ranges within a single year. Assumes that the start
|
420
|
+
# and end parameters occur within the same year.
|
421
|
+
#
|
422
|
+
#
|
424
423
|
class REYear
|
425
424
|
|
425
|
+
# Sentinel value used to denote that no specific day was given to create
|
426
|
+
# the expression.
|
427
|
+
NO_DAY = 0
|
428
|
+
|
426
429
|
include TExpr
|
430
|
+
|
431
|
+
attr_accessor :start_month, :start_day, :end_month, :end_day
|
427
432
|
|
428
|
-
|
433
|
+
#
|
434
|
+
# == Synopsis
|
435
|
+
#
|
436
|
+
# REYear.new(start_month [, (start_day | end_month), ...]
|
437
|
+
#
|
438
|
+
# == Args
|
439
|
+
#
|
440
|
+
# One or two arguments given::
|
441
|
+
#
|
442
|
+
# +start_month+::
|
443
|
+
# Start month. Valid values are 1..12. When no other parameters are given
|
444
|
+
# this value will be used for the end month as well. Matches the entire
|
445
|
+
# month through the ending month.
|
446
|
+
# +end_month+::
|
447
|
+
# End month. Valid values are 1..12. When given in two argument form
|
448
|
+
# will match through the entire month.
|
449
|
+
#
|
450
|
+
# Three or four arguments given::
|
451
|
+
#
|
452
|
+
# +start_month+::
|
453
|
+
# Start month. Valid values are 1..12.
|
454
|
+
# +start_day+::
|
455
|
+
# Start day. Valid values are 1..31, depending on the month.
|
456
|
+
# +end_month+::
|
457
|
+
# End month. Valid values are 1..12. If a fourth argument is not given,
|
458
|
+
# this value will cover through the entire month.
|
459
|
+
# +end_day+::
|
460
|
+
# End day. Valid values are 1..31, depending on the month.
|
461
|
+
#
|
462
|
+
# == Description
|
463
|
+
#
|
464
|
+
# Create a new REYear expression expressing a range of months or days
|
465
|
+
# within months within a year.
|
466
|
+
#
|
467
|
+
# == Usage
|
468
|
+
#
|
469
|
+
# # Creates the range March 12th through May 23rd
|
470
|
+
# expr = REYear.new(3,12,5,23)
|
471
|
+
#
|
472
|
+
# # Creates the range March 1st through May 31st
|
473
|
+
# expr = REYear.new(3,5)
|
474
|
+
#
|
475
|
+
# # Creates the range March 12th through May 31st
|
476
|
+
# expr = REYear.new(3,12,5)
|
477
|
+
#
|
478
|
+
# # Creates the range March 1st through March 30th
|
479
|
+
# expr = REYear.new(3)
|
480
|
+
#
|
481
|
+
def initialize(start_month, *args)
|
429
482
|
@start_month = start_month
|
430
|
-
|
431
|
-
|
432
|
-
|
483
|
+
if (args.nil? || args.size == NO_DAY) then
|
484
|
+
# One argument given
|
485
|
+
@end_month = start_month
|
486
|
+
@start_day = NO_DAY
|
487
|
+
@end_day = NO_DAY
|
488
|
+
else
|
489
|
+
case args.size
|
490
|
+
when 1
|
491
|
+
@end_month = args[0]
|
492
|
+
@start_day = NO_DAY
|
493
|
+
@end_day = NO_DAY
|
494
|
+
when 2
|
495
|
+
@start_day = args[0]
|
496
|
+
@end_month = args[1]
|
497
|
+
@end_day = NO_DAY
|
498
|
+
when 3
|
499
|
+
@start_day = args[0]
|
500
|
+
@end_month = args[1]
|
501
|
+
@end_day = args[2]
|
502
|
+
else
|
503
|
+
raise "Invalid number of var args: 1 or 3 expected, #{args.size} given"
|
504
|
+
end
|
505
|
+
end
|
506
|
+
@same_month_dates_provided = (@start_month == @end_month) && (@start_day!=NO_DAY && @end_day != NO_DAY)
|
433
507
|
end
|
434
508
|
|
435
509
|
def include?(date)
|
436
|
-
|
437
|
-
|
438
|
-
|
510
|
+
return ((@start_day <= date.day) && (@end_day >= date.day)) if @same_month_dates_provided
|
511
|
+
is_between_months?(date) ||
|
512
|
+
(same_start_month_include_day?(date) ||
|
513
|
+
same_end_month_include_day?(date))
|
439
514
|
end
|
440
515
|
|
441
516
|
def save
|
@@ -448,19 +523,20 @@ class REYear
|
|
448
523
|
end
|
449
524
|
|
450
525
|
private
|
451
|
-
def
|
526
|
+
def is_between_months?(date)
|
452
527
|
(date.mon > @start_month) && (date.mon < @end_month)
|
453
528
|
end
|
454
529
|
|
455
|
-
def
|
530
|
+
def same_end_month_include_day?(date)
|
456
531
|
return false unless (date.mon == @end_month)
|
457
|
-
(@end_day ==
|
532
|
+
(@end_day == NO_DAY) || (date.day <= @end_day)
|
458
533
|
end
|
459
534
|
|
460
|
-
def
|
535
|
+
def same_start_month_include_day?(date)
|
461
536
|
return false unless (date.mon == @start_month)
|
462
|
-
(@start_day ==
|
537
|
+
(@start_day == NO_DAY) || (date.day >= @start_day)
|
463
538
|
end
|
539
|
+
|
464
540
|
end
|
465
541
|
|
466
542
|
# TExpr that matches periods of the day with minute
|
@@ -491,8 +567,11 @@ class REDay
|
|
491
567
|
end
|
492
568
|
|
493
569
|
def include?(date)
|
570
|
+
# 2007-11-9: Not completely sure of the implications of commenting this
|
571
|
+
# out but...
|
572
|
+
#
|
494
573
|
# If precision is day or greater, then the result is always true
|
495
|
-
return true if date.date_precision <= DPrecision::DAY
|
574
|
+
#return true if date.date_precision <= DPrecision::DAY
|
496
575
|
|
497
576
|
if(@spans_midnight&&date.hour<12) then
|
498
577
|
#Assume next day
|
@@ -509,7 +588,9 @@ class REDay
|
|
509
588
|
|
510
589
|
private
|
511
590
|
def spans_midnight?(start_hour, end_hour)
|
512
|
-
|
591
|
+
#puts "spans midnight? #{end_hour < start_hour} (end==#{end_hour} <= start==#{start_hour})"
|
592
|
+
#return end_hour <= start_hour
|
593
|
+
return end_hour < start_hour
|
513
594
|
end
|
514
595
|
|
515
596
|
def get_current(hour,minute)
|
@@ -527,6 +608,7 @@ end
|
|
527
608
|
# WIMonth.new(1)
|
528
609
|
#
|
529
610
|
# See also: Date
|
611
|
+
# FIXME .dates mixin seems functionally broken
|
530
612
|
class WIMonth
|
531
613
|
|
532
614
|
include TExpr
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'runt'
|
5
|
+
require 'date'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
$DEBUG=false
|
9
|
+
|
10
|
+
# Base test case for refactored temporal expression unit tests
|
11
|
+
# Author:: Matthew Lipper
|
12
|
+
|
13
|
+
class BaseExpressionTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
include Runt
|
16
|
+
include DPrecision
|
17
|
+
|
18
|
+
def setup
|
19
|
+
@stub1 = StubExpression.new(false, "stub 1", false)
|
20
|
+
@stub2 = StubExpression.new(false, "stub 2", false)
|
21
|
+
@pdate_198606 = PDate.month(1986,6) # June, 1986
|
22
|
+
@pdate_20040531 = PDate.day(2004,5,31) # Monday, May 31st, 2004
|
23
|
+
@pdate_20040704 = PDate.day(2004,7,4) # Sunday, July 4th, 2004
|
24
|
+
@pdate_20060914 = PDate.day(2006,9,14) # Thursday, September 14th, 2006
|
25
|
+
@pdate_20060921 = PDate.day(2006,9,21) # Thursday, September 21st, 2006
|
26
|
+
@pdate_20071008 = PDate.day(2007,10,8) # Monday, October 8th, 2007
|
27
|
+
@pdate_20071024 = PDate.day(2007,10,24) # Wednesday, October 24th, 2007
|
28
|
+
@pdate_20071028 = PDate.day(2007,10,28) # Sunday, October 28th, 2007
|
29
|
+
@pdate_20071030 = PDate.day(2007,10,30) # Tuesday, October 30th, 2007
|
30
|
+
@pdate_20071114 = PDate.day(2007,11,14) # Wednesday, November 14th, 2007
|
31
|
+
@pdate_1922041816 = PDate.hour(1922,4,18,16) # 4pm, Tuesday, April 18th, 1922
|
32
|
+
@pdate_1975060512 = PDate.hour(1975,6,5,12) # 12pm, Thursday, June 5th, 1975
|
33
|
+
@pdate_2004090600 = PDate.hour(2004,9,6,0) # 12am, Monday, September 6th, 2004
|
34
|
+
@pdate_2012050803 = PDate.hour(2012,5,8,3) # 3am, Tuesday, May 8th, 2012
|
35
|
+
@pdate_2012050815 = PDate.hour(2012,5,8,15) # 3pm, Tuesday, May 8th, 2012
|
36
|
+
@pdate_200401282100 = PDate.min(2004,1,28,21,0) # 9:00pm, Wednesday, January 28th, 2004
|
37
|
+
@pdate_200401280000 = PDate.min(2004,1,28,0,0) # 12:00am, Wednesday, January 28th, 2004
|
38
|
+
@pdate_200401280001 = PDate.min(2004,1,28,0,1) # 12:01am, Wednesday, January 28th, 2004
|
39
|
+
@pdate_200405010806 = PDate.min(2004,5,1,8,6) # 8:06am, Saturday, May 1st, 2004
|
40
|
+
@pdate_200405030906 = PDate.min(2004,5,3,9,6) # 9:06am, Monday, May 3rd, 2004
|
41
|
+
@pdate_200405040806 = PDate.min(2004,5,4,8,6) # 8:06am, Tuesday, May 4th, 2004
|
42
|
+
@pdate_200605291012 = PDate.min(2006,5,29,10,12)
|
43
|
+
@pdate_200605301400 = PDate.min(2006,5,30,14,00)
|
44
|
+
@pdate_200609211001 = PDate.min(2006,9,21,10,1)
|
45
|
+
@pdate_200609211002 = PDate.min(2006,9,21,10,2)
|
46
|
+
@pdate_20071116100030 = PDate.sec(2007,11,16,10,0,30)
|
47
|
+
@date_19611101 = Date.civil(1961,11,1)
|
48
|
+
@date_20040109 = Date.civil(2004,1,9) # Friday, January 9th 2004
|
49
|
+
@date_20040116 = Date.civil(2004,1,16) # Friday, January 16th 2004
|
50
|
+
@date_20040125 = Date.civil(2004,1,25) # Sunday, January 25th 2004
|
51
|
+
@date_20040501 = Date.civil(2004,5,1)
|
52
|
+
@date_20040806 = Date.civil(2004,8,6)
|
53
|
+
@date_20050101 = Date.civil(2005,1,1)
|
54
|
+
@date_20050102 = Date.civil(2005,1,2)
|
55
|
+
@date_20050109 = Date.civil(2005,1,9)
|
56
|
+
@date_20050116 = Date.civil(2005,1,16)
|
57
|
+
@date_20050123 = Date.civil(2005,1,23)
|
58
|
+
@date_20050130 = Date.civil(2005,1,30)
|
59
|
+
@date_20050131 = Date.civil(2005,1,31)
|
60
|
+
@date_20050228 = Date.civil(2005,2,28)
|
61
|
+
@date_20051231 = Date.civil(2005,12,31)
|
62
|
+
@date_20060504 = Date.civil(2006,5,4)
|
63
|
+
@datetime_200403081200 = DateTime.new(2004,3,8,12,0) # 12:00pm, Monday, March 8th, 2004
|
64
|
+
@datetime_200403100800 = DateTime.new(2004,3,10,8,00)
|
65
|
+
@datetime_200403100915 = DateTime.new(2004,3,10,9,15)
|
66
|
+
@datetime_200403101915 = DateTime.new(2004,3,10,19,15) # 7:15pm, Wednesday, March 10th, 2004
|
67
|
+
@datetime_200403110000 = DateTime.new(2004,3,11,0,0) # 12:00am, Thursday, March 11th, 2004
|
68
|
+
@datetime_200403110115 = DateTime.new(2004,3,11,1,15)
|
69
|
+
@datetime_200403111215 = DateTime.new(2004,3,11,12,15)
|
70
|
+
@datetime_200403140900 = DateTime.new(2004,3,14,9,00) # 9:00am, Sunday, March 14th, 2004
|
71
|
+
@datetime_200709161007 = DateTime.new(2007,9,16,10,7)
|
72
|
+
@time_20070925115959 = Time.mktime(2007,9,25,11,59,59) # 11:59:59am, Tuesday, September 25th, 2007
|
73
|
+
@time_20070926000000 = Time.mktime(2007,9,26,0,0,0) # 12:00:00am, Wednesday, September 26th, 2007
|
74
|
+
@time_20070927065959 = Time.mktime(2007,9,27,6,59,59) # 6:59:59am, Thursday, September 27th, 2007
|
75
|
+
@time_20070927115900 = Time.mktime(2007,9,27,11,59,0) # 11:59:00am, Thursday, September 27th, 2007
|
76
|
+
@time_20070928000000 = Time.mktime(2007,9,28,0,0,0) # 12:00:00am, Friday, September 28th, 2007
|
77
|
+
@time_20070929110000 = Time.mktime(2007,9,29,11,0,0) # 11:00:00am, Saturday, September 29th, 2007
|
78
|
+
@time_20070929000000 = Time.mktime(2007,9,29,0,0,0) # 12:00:00am, Saturday, September 29th, 2007
|
79
|
+
@time_20070929235959 = Time.mktime(2007,9,29,23,59,59) # 11:59:59pm, Saturday, September 29th, 2007
|
80
|
+
@time_20070930235959 = Time.mktime(2007,9,30,23,59,59) # 11:59:59am, Sunday, September 30th, 2007
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_nothing
|
84
|
+
# Sigh...I should figure out how to tell TestUnit that this is an "abstract" class
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
class StubExpression
|
90
|
+
include Runt
|
91
|
+
include TExpr
|
92
|
+
attr_accessor :match, :string, :overlap, :args
|
93
|
+
def initialize(match=false, string="StubExpression",overlap=false)
|
94
|
+
@match=match
|
95
|
+
@string=string
|
96
|
+
@overlap=overlap
|
97
|
+
@args=[]
|
98
|
+
end
|
99
|
+
def include?(arg)
|
100
|
+
@args << arg
|
101
|
+
@match
|
102
|
+
end
|
103
|
+
def overlap?(arg)
|
104
|
+
@args << arg
|
105
|
+
@overlap
|
106
|
+
end
|
107
|
+
def to_s
|
108
|
+
@string
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'baseexpressiontest'
|
4
|
+
|
5
|
+
# Unit tests for Collection class
|
6
|
+
# Author:: Matthew Lipper
|
7
|
+
|
8
|
+
class CollectionTest < BaseExpressionTest
|
9
|
+
|
10
|
+
def setup
|
11
|
+
super
|
12
|
+
@expr = Collection.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_initialize
|
16
|
+
assert !@expr.expressions.nil?, "Newly created Collection should have a non-nil @expressions attribute"
|
17
|
+
assert @expr.expressions.empty?, "Newly created Collection should have an empty @expressions attribute"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_include
|
21
|
+
#base class that should always return false
|
22
|
+
assert !@expr.include?(StubExpression.new(true)), "Collection#include? should always return false"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def test_to_s
|
27
|
+
assert_equal 'empty', @expr.to_s
|
28
|
+
assert_equal 'empty', @expr.to_s{['b','oo']}
|
29
|
+
dim = StubExpression.new(false,"Mock1")
|
30
|
+
@expr.expressions << dim
|
31
|
+
assert_equal 'ff' + dim.to_s, @expr.to_s{['ff','nn']}
|
32
|
+
red = StubExpression.new(false, "Mock2")
|
33
|
+
@expr.expressions << red
|
34
|
+
assert_equal 'ff' + dim.to_s + 'nn' + red.to_s, @expr.to_s{['ff','nn']}
|
35
|
+
wim = StubExpression.new(false, "Mock3")
|
36
|
+
@expr.expressions << wim
|
37
|
+
assert_equal 'ff' + dim.to_s + 'nn' + red.to_s + 'nn' + wim.to_s, @expr.to_s{['ff','nn']}
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_add
|
41
|
+
e1 = StubExpression.new
|
42
|
+
e2 = StubExpression.new
|
43
|
+
assert @expr.expressions.empty?, "Empty Collection should not include any expressions"
|
44
|
+
result = @expr.add(e1)
|
45
|
+
assert_same @expr, result, "Collection#add method should return self instance"
|
46
|
+
assert @expr.expressions.include?(e1), "Collection should include added expression"
|
47
|
+
@expr.add(e2)
|
48
|
+
assert @expr.expressions.include?(e2), "Collection should include added expression"
|
49
|
+
assert_same e2, @expr.expressions.pop, "Collection should keep added expressions in stack order"
|
50
|
+
assert_same e1, @expr.expressions.pop, "Collection should keep added expressions in stack order"
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_overlap
|
54
|
+
stub = StubExpression.new(false, "stubby", true) # start with "always overlap?" stub
|
55
|
+
assert !@expr.overlap?(stub), "Empty Collection should never overlap"
|
56
|
+
@expr.add StubExpression.new
|
57
|
+
assert @expr.overlap?(stub), "Collection should overlap with given stub argument"
|
58
|
+
assert_same stub.args[0], @expr.expressions.first, "First expression should be given to stub in the first call to overlap?"
|
59
|
+
stub.overlap = false
|
60
|
+
assert !@expr.overlap?(stub), "Collection should not overlap with given stub argument"
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
|
2
|
+
#!/usr/bin/env ruby
|
3
|
+
|
4
|
+
require 'baseexpressiontest'
|
5
|
+
|
6
|
+
# Unit tests for composite temporal expressions
|
7
|
+
# Author:: Matthew Lipper
|
8
|
+
|
9
|
+
class CombinedExpressionTest < BaseExpressionTest
|
10
|
+
|
11
|
+
def test_dates_on_last_fri_or_first_tues
|
12
|
+
date_range = @date_20050101..@date_20051231
|
13
|
+
expr = DIMonth.new(Last, Friday) | DIMonth.new(First, Tuesday)
|
14
|
+
dates = expr.dates(date_range)
|
15
|
+
assert_equal 24, dates.size, "Expected 24 dates in 2005 which were either on the last Friday or first Tuesday of the month"
|
16
|
+
month_days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
|
17
|
+
dates.each do |d|
|
18
|
+
unless (d.wday == 2 and d.day < 8) or \
|
19
|
+
(d.wday == 5 and d.day > month_days[d.month-1] - 8)
|
20
|
+
# Fail
|
21
|
+
assert false, d.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_january_except_from_7th_to_15th
|
27
|
+
date_range = @date_20050101..@date_20050131
|
28
|
+
dates = (REYear.new(1, 1, 1, 31) - REMonth.new(7, 15)).dates(date_range)
|
29
|
+
assert_equal 22, dates.size, "Expected 22 dates: 1/1-1/6, 1/16-1/31"
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_work_day
|
33
|
+
# Should match for 9am to 5pm except for 12pm to 1pm
|
34
|
+
expr = REDay.new(9,0,17,0) - REDay.new(12,0,13,0)
|
35
|
+
assert expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should include #{@pdate_200405030906.to_s}"
|
36
|
+
assert !expr.include?(@pdate_1975060512), "Expression #{expr.to_s} should not include #{@pdate_1975060512.to_s}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_monday_tuesday_8am_to_9am
|
40
|
+
expr = REWeek.new(Mon,Fri) & REDay.new(8,0,9,0)
|
41
|
+
assert expr.include?(@pdate_200405040806), "Expression #{expr.to_s} should include #{@pdate_200405040806.to_s}"
|
42
|
+
assert !expr.include?(@pdate_200405010806), "Expression #{expr.to_s} should not include #{@pdate_200405010806.to_s}"
|
43
|
+
assert !expr.include?(@pdate_200405030906), "Expression #{expr.to_s} should not include #{@pdate_200405030906.to_s}"
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
def test_midnight_to_9am_or_tuesday
|
48
|
+
expr = REDay.new(0,0,9,0) | DIWeek.new(Tuesday)
|
49
|
+
assert expr.include?(@pdate_20071030), "Expression #{expr.to_s} should include #{@pdate_20071030.to_s}"
|
50
|
+
assert expr.include?(@pdate_2012050803), "Expression #{expr.to_s} should include #{@pdate_2012050803.to_s}"
|
51
|
+
assert !expr.include?(@pdate_20071116100030), "Expression #{expr.to_s} should not include #{@pdate_20071116100030.to_s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_wednesday_thru_saturday_6_to_12am
|
55
|
+
expr = REWeek.new(Wed, Sat) & REDay.new(6,0,12,00)
|
56
|
+
assert !expr.include?(@time_20070926000000), "Expression #{expr.to_s} should include #{@time_20070926000000.to_s}"
|
57
|
+
assert expr.include?(@time_20070927065959), "Expression #{expr.to_s} should include #{@time_20070927065959.to_s}"
|
58
|
+
assert !expr.include?(@time_20070928000000), "Expression #{expr.to_s} should include #{@time_20070928000000.to_s}"
|
59
|
+
assert expr.include?(@time_20070929110000), "Expression #{expr.to_s} should include #{@time_20070929110000.to_s}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_memorial_day
|
63
|
+
# Monday through Friday, from 9am to 5pm
|
64
|
+
job = REWeek.new(Mon,Fri) & REDay.new(9,00,17,00)
|
65
|
+
# Memorial Day (U.S.)
|
66
|
+
memorial_day = REYear.new(5) & DIMonth.new(Last,Monday)
|
67
|
+
# May 29th, 2006
|
68
|
+
last_monday_in_may = @pdate_200605291012
|
69
|
+
# Before
|
70
|
+
assert job.include?(last_monday_in_may), "Expression #{job.to_s} should include #{last_monday_in_may.to_s}"
|
71
|
+
assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
|
72
|
+
# Add Diff expression
|
73
|
+
job_with_holiday = job - last_monday_in_may
|
74
|
+
assert !job_with_holiday.include?(last_monday_in_may), "Expression #{job_with_holiday.to_s} should not include #{last_monday_in_may.to_s}"
|
75
|
+
# Still have to work on Tuesday
|
76
|
+
assert job.include?(@pdate_200605301400), "Expression #{job.to_s} should include #{@pdate_200605301400.to_s}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_summertime
|
80
|
+
#This is a hack.....
|
81
|
+
#In the U.S., Memorial Day begins the last Monday of May
|
82
|
+
#
|
83
|
+
#The month of May
|
84
|
+
may=REYear.new(5)
|
85
|
+
#Monday through Saturday
|
86
|
+
monday_to_saturday = REWeek.new(1,6)
|
87
|
+
#Last week of (any) month
|
88
|
+
last_week_in = WIMonth.new(Last_of)
|
89
|
+
#So, to say 'starting from the last Monday in May',
|
90
|
+
#we need to select just that last week of May begining with
|
91
|
+
#the Monday of that week
|
92
|
+
last_week_of_may = may & monday_to_saturday & last_week_in
|
93
|
+
|
94
|
+
#This is another hack similar to the above, except instead of selecting a range
|
95
|
+
#starting at the begining of the month, we need to select only the time period in
|
96
|
+
#September up until Labor Day.
|
97
|
+
#
|
98
|
+
#In the U.S., Labor Day is the first Monday in September
|
99
|
+
#
|
100
|
+
#The month of September
|
101
|
+
september=REYear.new(9)
|
102
|
+
#First week of (any) month
|
103
|
+
first_week_in = WIMonth.new(First)
|
104
|
+
entire_first_week_of_september = september & first_week_in
|
105
|
+
#To exclude everything in the first week which occurs on or after Monday.
|
106
|
+
first_week_of_september=entire_first_week_of_september - monday_to_saturday
|
107
|
+
#June through August
|
108
|
+
june_through_august=REYear.new(6, 1, 8)
|
109
|
+
assert june_through_august.include?(@pdate_20040704), "Expression #{june_through_august.to_s} should include #{@pdate_20040704.to_s}"
|
110
|
+
#Finally!
|
111
|
+
summer_time = last_week_of_may | first_week_of_september | june_through_august
|
112
|
+
|
113
|
+
#Will work, but will be incredibly slow:
|
114
|
+
# assert(summer_time.include?(PDate.min(2004,5,31,0,0)))
|
115
|
+
assert summer_time.include?(@pdate_20040531), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
|
116
|
+
assert summer_time.include?(@pdate_20040704), "Expression #{summer_time.to_s} should include #{@pdate_20040704.to_s}"
|
117
|
+
#also works...also slow:
|
118
|
+
# assert(!summer_time.include?(PDate.min(2004,9,6,0,0)))
|
119
|
+
assert !summer_time.include?(@pdate_2004090600), "Expression #{summer_time.to_s} should not include #{@pdate_2004090600.to_s}"
|
120
|
+
|
121
|
+
end
|
122
|
+
def test_nyc_parking_te
|
123
|
+
|
124
|
+
#Monday, Wednesday, Friday
|
125
|
+
mon_wed_fri = DIWeek.new(Mon) | \
|
126
|
+
DIWeek.new(Wed) | \
|
127
|
+
DIWeek.new(Fri)
|
128
|
+
|
129
|
+
assert mon_wed_fri.include?(@datetime_200403101915), "Expression #{mon_wed_fri.to_s} should include #{@datetime_200403101915.to_s}"
|
130
|
+
assert !mon_wed_fri.include?(@datetime_200403140900), "Expression #{mon_wed_fri.to_s} should not include #{@datetime_200403140900.to_s}"
|
131
|
+
# 8am to 11am
|
132
|
+
eight_to_eleven = REDay.new(8,00,11,00)
|
133
|
+
# => Mon,Wed,Fri - 8am to 11am
|
134
|
+
expr1 = mon_wed_fri & eight_to_eleven
|
135
|
+
# Tuesdays, Thursdays
|
136
|
+
tues_thurs = DIWeek.new(Tue) | DIWeek.new(Thu)
|
137
|
+
# 11:30am to 2pm
|
138
|
+
eleven_thirty_to_two = REDay.new(11,30,14,00)
|
139
|
+
assert eleven_thirty_to_two.include?(@datetime_200403081200), "Expression #{eleven_thirty_to_two.to_s} should include #{@datetime_200403081200.to_s}"
|
140
|
+
assert !eleven_thirty_to_two.include?(@datetime_200403110000), "Expression #{eleven_thirty_to_two.to_s} should not include #{@datetime_200403110000.to_s}"
|
141
|
+
# => Tues,Thurs - 11:30am to 2pm
|
142
|
+
expr2 = tues_thurs & eleven_thirty_to_two
|
143
|
+
#
|
144
|
+
# No parking: Mon Wed Fri, 8am - 11am
|
145
|
+
# Tu Thu, 11:30am - 2pm
|
146
|
+
parking_ticket = expr1 | expr2
|
147
|
+
assert parking_ticket.include?(@datetime_200403111215), "Expression #{parking_ticket.to_s} should include #{@datetime_200403111215.to_s}"
|
148
|
+
assert parking_ticket.include?(@datetime_200403100915), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100915.to_s}"
|
149
|
+
assert parking_ticket.include?(@datetime_200403100800), "Expression #{parking_ticket.to_s} should include #{@datetime_200403100800.to_s}"
|
150
|
+
assert !parking_ticket.include?(@datetime_200403110115), "Expression #{parking_ticket.to_s} should not include #{@datetime_200403110115.to_s}"
|
151
|
+
|
152
|
+
# The preceeding example can be condensed to:
|
153
|
+
# e1 = (DIWeek.new(Mon) | DIWeek.new(Wed) | DIWeek.new(Fri)) & REDay.new(8,00,11,00)
|
154
|
+
# e2 = (DIWeek.new(Tue) | DIWeek.new(Thu)) & REDay.new(11,30,14,00)
|
155
|
+
# ticket = e1 | e2
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
data/test/daterangetest.rb
CHANGED
@@ -70,6 +70,8 @@ class DateRangeTest < Test::Unit::TestCase
|
|
70
70
|
empty_range = DateRange.new(r_start,r_end)
|
71
71
|
assert(empty_range.empty?)
|
72
72
|
assert(DateRange::EMPTY.empty?)
|
73
|
+
# start == end should be empty
|
74
|
+
assert DateRange.new(r_start,r_start).empty?, "Range should be empty when start == end"
|
73
75
|
end
|
74
76
|
|
75
77
|
def test_gap
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'baseexpressiontest'
|
4
|
+
|
5
|
+
# Unit tests for DayIntervalTE class
|
6
|
+
# Author:: Matthew Lipper
|
7
|
+
|
8
|
+
class DayIntervalTETest < BaseExpressionTest
|
9
|
+
|
10
|
+
|
11
|
+
def test_every_8_days
|
12
|
+
date = @date_20040116
|
13
|
+
# Match every 8 days
|
14
|
+
expr = DayIntervalTE.new(date, 8)
|
15
|
+
assert expr.include?(date + 8), "Expression #{expr.to_s} should include #{(date + 8).to_s}"
|
16
|
+
assert expr.include?(date + 16), "Expression #{expr.to_s} should include #{(date + 16).to_s}"
|
17
|
+
assert expr.include?(date + 64), "Expression #{expr.to_s} should include #{(date + 64).to_s}"
|
18
|
+
assert !expr.include?(date + 4), "Expression #{expr.to_s} should not include #{(date + 4).to_s}"
|
19
|
+
# FIXME This test fails
|
20
|
+
#assert !expr.include?(date - 8), "Expression #{expr.to_s} should not include #{(date - 8).to_s}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_every_2_days
|
24
|
+
date = @datetime_200709161007
|
25
|
+
expr = DayIntervalTE.new(date, 2)
|
26
|
+
assert expr.include?(date + 2), "Expression #{expr.to_s} should include #{(date + 2).to_s}"
|
27
|
+
assert expr.include?(date + 4), "Expression #{expr.to_s} should include #{(date + 4).to_s}"
|
28
|
+
assert !expr.include?(date + 3), "Expression #{expr.to_s} should not include #{(date + 3).to_s}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_to_s
|
32
|
+
every_four_days = DayIntervalTE.new(Date.new(2006,2,26), 4)
|
33
|
+
assert_equal "every 4th day after #{Runt.format_date(Date.new(2006,2,26))}", every_four_days.to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|