runt 0.5.0 → 0.6.0
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/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
|