Skip to content

Commit

Permalink
Fix initialization of DOSTime when given a nil
Browse files Browse the repository at this point in the history
* Add validation for given time structure
* Add tests for validation
* Closes #17
  • Loading branch information
javanthropus committed Dec 18, 2016
1 parent 15904a1 commit c0797b9
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 1 deletion.
31 changes: 30 additions & 1 deletion lib/archive/support/time.rb
Expand Up @@ -45,7 +45,7 @@ class DOSTime
def initialize(dos_time = nil)
case dos_time
when nil
@dos_time = Time.now.to_dos_time.dos_time
@dos_time = Time.now.to_dos_time.to_i
when Integer
@dos_time = dos_time
else
Expand All @@ -54,6 +54,8 @@ def initialize(dos_time = nil)
end
@dos_time = dos_time.unpack('V')[0]
end

validate
end

# Returns -1 if _other_ is a time earlier than this one, 0 if _other_ is the
Expand Down Expand Up @@ -86,5 +88,32 @@ def to_time
year = ((0b1111111 << 25 & @dos_time) >> 25) + 1980
return Time.local(year, month, day, hour, minute, second)
end

private

def validate
second = (0b11111 & @dos_time)
minute = (0b111111 << 5 & @dos_time) >> 5
hour = (0b11111 << 11 & @dos_time) >> 11
day = (0b11111 << 16 & @dos_time) >> 16
month = (0b1111 << 21 & @dos_time) >> 21
year = (0b1111111 << 25 & @dos_time) >> 25

if second > 29
raise ArgumentError, 'second must not be greater than 29'
elsif minute > 59
raise ArgumentError, 'minute must not be greater than 59'
elsif hour > 24
raise ArgumentError, 'hour must not be greater than 24'
elsif day < 1
raise ArgumentError, 'day must not be less than 1'
elsif month < 1
raise ArgumentError, 'month must not be less than 1'
elsif month > 12
raise ArgumentError, 'month must not be greater than 12'
elsif year > 119
raise ArgumentError, 'year must not be greater than 119'
end
end
end
end
113 changes: 113 additions & 0 deletions spec/archive/dos_time_spec.rb
@@ -0,0 +1,113 @@
# encoding: UTF-8

require 'minitest/autorun'

require 'archive/support/time'

describe 'Archive::DOSTime.new' do
let(:epoc) { 0b0000000_0001_00001_00000_000000_00000 }
let(:end_times) { 0b1110111_1100_11111_11000_111011_11101 }

it 'uses the current time when no structure is given' do
now = Time.now.localtime
dos_time = Archive::DOSTime.new.to_time

now.year.must_be_close_to(dos_time.year, 1)
now.month.must_be_close_to(dos_time.month, 1)
now.day.must_be_close_to(dos_time.day, 1)
now.hour.must_be_close_to(dos_time.hour, 1)
now.min.must_be_close_to(dos_time.min, 1)
now.sec.must_be_close_to(dos_time.sec, 3)
end

it 'accepts valid Integer structures' do
Archive::DOSTime.new(epoc)
Archive::DOSTime.new(end_times)
end

it 'accepts valid String structures' do
Archive::DOSTime.new([epoc].pack('V'))
Archive::DOSTime.new([end_times].pack('V'))
end

it 'rejects invalid Integer structures' do
# Second must not be greater than 29.
proc {
Archive::DOSTime.new(epoc | 0b0000000_0000_00000_00000_000000_11110)
}.must_raise(ArgumentError)

# Minute must not be greater than 59.
proc {
Archive::DOSTime.new(epoc | 0b0000000_0000_00000_00000_111100_00000)
}.must_raise(ArgumentError)

# Hour must not be greater than 24.
proc {
Archive::DOSTime.new(epoc | 0b0000000_0000_00000_11001_000000_00000)
}.must_raise(ArgumentError)

# Day must not be zero.
proc {
Archive::DOSTime.new(epoc & 0b1111111_1111_00000_11111_111111_11111)
}.must_raise(ArgumentError)

# Month must not be zero.
proc {
Archive::DOSTime.new(epoc & 0b1111111_0000_11111_11111_111111_11111)
}.must_raise(ArgumentError)

# Month must not be greater than 12.
proc {
Archive::DOSTime.new(epoc | 0b0000000_1101_00000_00000_000000_00000)
}.must_raise(ArgumentError)

# Year must not be greater than 119.
proc {
Archive::DOSTime.new(epoc | 0b1111000_0000_00000_00000_000000_00000)
}.must_raise(ArgumentError)
end

it 'rejects invalid String structures' do
# Second must not be greater than 29.
proc {
packed = [epoc | 0b0000000_0000_00000_00000_000000_11110].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Minute must not be greater than 59.
proc {
packed = [epoc | 0b0000000_0000_00000_00000_111100_00000].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Hour must not be greater than 24.
proc {
packed = [epoc | 0b0000000_0000_00000_11001_000000_00000].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Day must not be zero.
proc {
packed = [epoc & 0b1111111_1111_00000_11111_111111_11111].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Month must not be zero.
proc {
packed = [epoc & 0b1111111_0000_11111_11111_111111_11111].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Month must not be greater than 12.
proc {
packed = [epoc | 0b0000000_1101_00000_00000_000000_00000].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)

# Year must not be greater than 119.
proc {
packed = [epoc | 0b1111000_0000_00000_00000_000000_00000].pack('V')
Archive::DOSTime.new(packed)
}.must_raise(ArgumentError)
end
end

0 comments on commit c0797b9

Please sign in to comment.