runt 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -37,7 +37,7 @@ module Runt
37
37
  end
38
38
 
39
39
  def empty?
40
- return @start_expr>@end_expr
40
+ return @start_expr >= @end_expr
41
41
  end
42
42
 
43
43
  def gap(obj)
data/lib/runt/pdate.rb CHANGED
@@ -80,7 +80,7 @@ module Runt
80
80
  else
81
81
  result = super(other)
82
82
  end
83
- puts "#{self.to_s}<=>#{other.to_s} => #{result}" if $DEBUG
83
+ #puts "#{self.to_s}<=>#{other.to_s} => #{result}" if $DEBUG
84
84
  result
85
85
  end
86
86
 
data/lib/runt/schedule.rb CHANGED
@@ -39,7 +39,7 @@ module Runt
39
39
  end
40
40
 
41
41
  #
42
- # Returns all Events whose Tempoarl Expression includes the given date/expression
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
- # Will return true if the supplied object is included in the range used to
226
- # create this instance
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
- def initialize(start_month, start_day=0, end_month=start_month, end_day=0)
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
- @start_day = start_day
431
- @end_month = end_month
432
- @end_day = end_day
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
- months_include?(date) ||
437
- start_month_include?(date) ||
438
- end_month_include?(date)
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 months_include?(date)
526
+ def is_between_months?(date)
452
527
  (date.mon > @start_month) && (date.mon < @end_month)
453
528
  end
454
529
 
455
- def end_month_include?(date)
530
+ def same_end_month_include_day?(date)
456
531
  return false unless (date.mon == @end_month)
457
- (@end_day == 0) || (date.day <= @end_day)
532
+ (@end_day == NO_DAY) || (date.day <= @end_day)
458
533
  end
459
534
 
460
- def start_month_include?(date)
535
+ def same_start_month_include_day?(date)
461
536
  return false unless (date.mon == @start_month)
462
- (@start_day == 0) || (date.day >= @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
- return end_hour <= start_hour
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
@@ -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