integration/support/match_manifest.rb
# encoding: utf-8
# Matches the contents of a TarFile (or PerformedJob.package)
# against the given manifest.
#
# Usage:
#
# performed_job = backup_perform :trigger
#
# expect(performed_job.package).to match_manifest(<<-EOS)
# 51200 my_backup/archives/my_archive.tar
# 8099 my_backup/databases/MySQL/backup_test_01.sql
# EOS
#
# File sizes may also be tested against a range, using `min..max`.
#
# expect(performed_job.package).to match_manifest(%q[
# 51200..51250 my_backup/archives/my_archive.tar
# 8099 my_backup/databases/MySQL/backup_test_01.sql
# ])
#
# Or simply checked for existance, using `-`:
#
# expect(performed_job.package).to match_manifest(%q[
# - my_backup/archives/my_archive.tar
# 8099 my_backup/databases/MySQL/backup_test_01.sql
# ])
#
# Extra spaces and blank lines are ok.
#
# If the given files with the given sizes do not match all the files
# in the archive"s manifest, the error message will include the entire
# manifest as output by `tar -tvf`.
RSpec::Matchers.define :match_manifest do |expected|
match do |actual|
expected_contents = expected.split("\n").map(&:strip).reject(&:empty?)
expected_contents.map! { |line| line.split(" ") }
expected_contents = Hash[
expected_contents.map { |fields| [fields[1], fields[0]] }
]
files_match = expected_contents.keys.sort == actual.contents.keys.sort
if files_match
sizes_ok = true
expected_contents.each do |path, size|
actual_size = actual.contents[path]
sizes_ok =
case size
when "-" then true
when /\d+(\.\.)\d+/
a, b = size.split("..").map(&:to_i)
(a..b).cover? actual_size
else
size.to_i == actual_size
end
break unless sizes_ok
end
end
files_match && sizes_ok
end
failure_message do |actual|
"expected that:\n\n#{actual.manifest}\n" \
"would match:\n#{expected}"
end
end