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.
@@ -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