summaryrefslogtreecommitdiffstats
path: root/spec/unit/util/checksums_spec.rb
blob: f8800b512af0101ee6f1b2fcbdeb13543c50ab4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/env rspec
require 'spec_helper'

require 'puppet/util/checksums'

describe Puppet::Util::Checksums do
  before do
    @summer = Object.new
    @summer.extend(Puppet::Util::Checksums)
  end

  content_sums = [:md5, :md5lite, :sha1, :sha1lite]
  file_only = [:ctime, :mtime, :none]

  content_sums.each do |sumtype|
    it "should be able to calculate #{sumtype} sums from strings" do
      @summer.should be_respond_to(sumtype)
    end
  end

  [content_sums, file_only].flatten.each do |sumtype|
    it "should be able to calculate #{sumtype} sums from files" do
      @summer.should be_respond_to(sumtype.to_s + "_file")
    end
  end

  [content_sums, file_only].flatten.each do |sumtype|
    it "should be able to calculate #{sumtype} sums from stream" do
      @summer.should be_respond_to(sumtype.to_s + "_stream")
    end
  end

  it "should have a method for determining whether a given string is a checksum" do
    @summer.should respond_to(:checksum?)
  end

  %w{{md5}asdfasdf {sha1}asdfasdf {ctime}asdasdf {mtime}asdfasdf}.each do |sum|
    it "should consider #{sum} to be a checksum" do
      @summer.should be_checksum(sum)
    end
  end

  %w{{nosuchsum}asdfasdf {a}asdfasdf {ctime}}.each do |sum|
    it "should not consider #{sum} to be a checksum" do
      @summer.should_not be_checksum(sum)
    end
  end

  it "should have a method for stripping a sum type from an existing checksum" do
    @summer.sumtype("{md5}asdfasdfa").should == "md5"
  end

  it "should have a method for stripping the data from a checksum" do
    @summer.sumdata("{md5}asdfasdfa").should == "asdfasdfa"
  end

  it "should return a nil sumtype if the checksum does not mention a checksum type" do
    @summer.sumtype("asdfasdfa").should be_nil
  end

  {:md5 => Digest::MD5, :sha1 => Digest::SHA1}.each do |sum, klass|
    describe("when using #{sum}") do
      it "should use #{klass} to calculate string checksums" do
        klass.expects(:hexdigest).with("mycontent").returns "whatever"
        @summer.send(sum, "mycontent").should == "whatever"
      end

      it "should use incremental #{klass} sums to calculate file checksums" do
        digest = mock 'digest'
        klass.expects(:new).returns digest

        file = "/path/to/my/file"

        fh = mock 'filehandle'
        fh.expects(:read).with(4096).times(3).returns("firstline").then.returns("secondline").then.returns(nil)
        #fh.expects(:read).with(512).returns("secondline")
        #fh.expects(:read).with(512).returns(nil)

        File.expects(:open).with(file, "r").yields(fh)

        digest.expects(:<<).with "firstline"
        digest.expects(:<<).with "secondline"
        digest.expects(:hexdigest).returns :mydigest

        @summer.send(sum.to_s + "_file", file).should == :mydigest
      end

      it "should yield #{klass} to the given block to calculate stream checksums" do
        digest = mock 'digest'
        klass.expects(:new).returns digest
        digest.expects(:hexdigest).returns :mydigest

        @summer.send(sum.to_s + "_stream") do |sum|
          sum.should == digest
        end.should == :mydigest
      end
    end
  end

  {:md5lite => Digest::MD5, :sha1lite => Digest::SHA1}.each do |sum, klass|
    describe("when using #{sum}") do
      it "should use #{klass} to calculate string checksums from the first 512 characters of the string" do
        content = "this is a test" * 100
        klass.expects(:hexdigest).with(content[0..511]).returns "whatever"
        @summer.send(sum, content).should == "whatever"
      end

      it "should use #{klass} to calculate a sum from the first 512 characters in the file" do
        digest = mock 'digest'
        klass.expects(:new).returns digest

        file = "/path/to/my/file"

        fh = mock 'filehandle'
        fh.expects(:read).with(512).returns('my content')

        File.expects(:open).with(file, "r").yields(fh)

        digest.expects(:<<).with "my content"
        digest.expects(:hexdigest).returns :mydigest

        @summer.send(sum.to_s + "_file", file).should == :mydigest
      end
    end
  end

  [:ctime, :mtime].each do |sum|
    describe("when using #{sum}") do
      it "should use the '#{sum}' on the file to determine the ctime" do
        file = "/my/file"
        stat = mock 'stat', sum => "mysum"

        File.expects(:stat).with(file).returns(stat)

        @summer.send(sum.to_s + "_file", file).should == "mysum"
      end

      it "should return nil for streams" do
        expectation = stub "expectation"
        expectation.expects(:do_something!).at_least_once
        @summer.send(sum.to_s + "_stream"){ |checksum| checksum << "anything" ; expectation.do_something!  }.should be_nil
      end
    end
  end

  describe "when using the none checksum" do
    it "should return an empty string" do
      @summer.none_file("/my/file").should == ""
    end

    it "should return an empty string for streams" do
      expectation = stub "expectation"
      expectation.expects(:do_something!).at_least_once
      @summer.none_stream{ |checksum| checksum << "anything" ; expectation.do_something!  }.should == ""
    end
  end
end