Skip to content

Instantly share code, notes, and snippets.

@sshaw
Last active December 20, 2021 13:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sshaw/df14f6f89860b2dbcfd2 to your computer and use it in GitHub Desktop.
Save sshaw/df14f6f89860b2dbcfd2 to your computer and use it in GitHub Desktop.
RSpec::Checksum::Matchers: Check if a String looks like a digest produced a the given hash algorithm. Also see https://github.com/sshaw/has_checksum
# RSpec::Checksum::Matchers Check if a String looks like a checksum produced by the given algorithm.
# https://gist.github.com/sshaw/df14f6f89860b2dbcfd2
#
# Copyright (c) 2016 Skye Shaw. Released under the MIT License (https://opensource.org/licenses/MIT)
#
require "rspec/expectations"
RSpec::Matchers.define :be_a_checksum do
regex = /\A[0-9a-f]{32,128}\z/i
chars = {
:md2 => 32,
:md4 => 32,
:md5 => 32,
:sha1 => 40,
:sha224 => 56,
:sha256 => 64,
:sha384 => 96,
:sha512 => 128
}
match do |checksum|
checksum = String(checksum)
return checksum.bytesize == chars[@function] / 2 if @use_bytes # 2 hex chars = 1 byte
matched = !!(checksum =~ regex)
return matched unless @function && matched
checksum.size == chars[@function]
end
chain :produced_by do |name|
@function = name.to_s.downcase.to_sym
raise ArgumentError, "unknown algorithm given to be_a_checksum.produced_by: #@function" unless chars.include?(@function)
end
chain :of_bytes do
@use_bytes = true
end
end
if File.basename($0) == "rspec"
require "digest"
RSpec.describe "Checksum expectations" do
describe "#be_a_checksum" do
it "matches a checksum" do
expect(Digest::MD5.hexdigest("a")).to be_a_checksum
expect("a").to_not be_a_checksum
end
end
describe "#produced_by" do
it "matches a MD5" do
expect(Digest::MD5.hexdigest("a")).to be_a_checksum.produced_by(:md5)
end
it "matches SHA1" do
expect(Digest::SHA1.hexdigest("a")).to be_a_checksum.produced_by(:sha1)
end
it "matches SHA256" do
expect(Digest::SHA256.hexdigest("a")).to be_a_checksum.produced_by(:sha256)
end
it "raises an exception when the algorithm is not known" do
expect { expect("a").to be_a_checksum.produced_by(:foo) }.to raise_exception(/unknown algorithm/)
end
it "does not match when the wrong algorithm is given" do
expect(Digest::SHA256.hexdigest("a")).to_not be_a_checksum.produced_by(:md5)
end
end
describe "#of_bytes" do
it "matches a bytes string" do
md5 = Digest::MD5.new
md5 << "a"
expect(md5.digest).to be_a_checksum.produced_by(:md5).of_bytes
end
end
end
end
@kleinjm
Copy link

kleinjm commented Sep 4, 2018

Just what I was looking for, thank you!

@shawn42
Copy link

shawn42 commented Oct 25, 2018

@sshaw Love this! There's no license on this, is this MIT like the rest of your github repos? Can you add one so I can use this?

@sshaw
Copy link
Author

sshaw commented Oct 31, 2018

@shawn42, yes it's MIT. I added this to the top of the file.

@davidteren
Copy link

@sshaw thanks so much for this. Came in handy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment