Skip to content

Commit

Permalink
Merge pull request #518 from nanoc/bounded-recursive-checksumming
Browse files Browse the repository at this point in the history
Bound recursive checksumming
  • Loading branch information
denisdefreyne committed Jan 11, 2015
2 parents 3bf0cf7 + 2bcf98b commit e3b0740
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
15 changes: 10 additions & 5 deletions lib/nanoc/base/checksummer.rb
Expand Up @@ -18,23 +18,28 @@ def calc(obj)

private

def update(obj, digest)
def update(obj, digest, visited = Set.new)
digest.update(obj.class.to_s)

if visited.include?(obj)
digest.update('recur')
return
end

case obj
when String
digest.update(obj)
when Array
obj.each do |el|
digest.update('elem')
update(el, digest)
update(el, digest, visited + [obj])
end
when Hash
obj.each do |key, value|
digest.update('key')
update(key, digest)
update(key, digest, visited + [obj])
digest.update('value')
update(value, digest)
update(value, digest, visited + [obj])
end
when Pathname
filename = obj.to_s
Expand All @@ -59,7 +64,7 @@ def update(obj, digest)
digest.update('attributes')
attributes = obj.attributes.dup
attributes.delete(:file)
update(attributes, digest)
update(attributes, digest, visited + [obj])
else
data = begin
Marshal.dump(obj)
Expand Down
26 changes: 26 additions & 0 deletions test/base/checksummer_spec.rb
Expand Up @@ -25,6 +25,12 @@
it 'should checksum non-serializable arrays' do
subject.calc([-> {}]).must_match(CHECKSUM_REGEX)
end

it 'should checksum recursive arrays' do
array = [:a]
array << array
subject.calc(array).must_equal('mR3c98xA5ecazxx+M3h0Ss4/J20=')
end
end

describe 'for Hash' do
Expand All @@ -39,6 +45,18 @@
it 'should checksum non-serializable hashes' do
subject.calc({ a: -> {} }).must_match(CHECKSUM_REGEX)
end

it 'should checksum recursive hash keys' do
hash = {}
hash[hash] = 123
subject.calc(hash).must_equal('mKucWMhRtR/FHWNqR/EErF4qgTk=')
end

it 'should checksum recursive hash values' do
hash = {}
hash[123] = hash
subject.calc(hash).must_equal('PBiDX0nWnV+DAYB+w+xM0Kf21ZM=')
end
end

describe 'for Pathname' do
Expand Down Expand Up @@ -195,6 +213,14 @@
subject.calc(item).must_equal(normal_checksum)
end

describe 'with recursive attributes' do
it 'should checksum' do
item.attributes[:a] = item
subject.calc(item).must_match(CHECKSUM_REGEX)
subject.calc(item).wont_equal(normal_checksum)
end
end

describe 'with changed attributes' do
let(:attributes) { { x: 4, y: 5 } }

Expand Down

0 comments on commit e3b0740

Please sign in to comment.