diff --git a/.rubocop.yml b/.rubocop.yml index cb1f7332..20c591d0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -27,6 +27,11 @@ Metrics/LineLength: - 'lib/moab/file_manifestation.rb' - 'spec/unit_tests/moab/bagger_spec.rb' # remove after PR #52 merged - 'spec/unit_tests/moab/file_group_difference_spec.rb' # remove after PR #50 merged + - 'spec/unit_tests/moab/storage_object_validator_spec.rb' + +# Code was readable with allowing higher perceived complexity +Metrics/PerceivedComplexity: + Max: 9 # --- Naming --- @@ -41,6 +46,14 @@ Naming/FileName: # --- Style --- +# Pointless change +Style/FormatStringToken: + Enabled: false + +# Loops were easier to understand without using 'next' statement +Style/Next: + Enabled: false + # because ' vs " isn't a big deal for readability or maintainability or execution time Style/StringLiterals: Enabled: false diff --git a/lib/moab.rb b/lib/moab.rb index cf4a8043..b5e413b4 100644 --- a/lib/moab.rb +++ b/lib/moab.rb @@ -56,3 +56,4 @@ module Moab require 'moab/storage_services' require 'moab/exceptions' require 'moab/verification_result' +require 'moab/storage_object_validator' diff --git a/lib/moab/storage_object_validator.rb b/lib/moab/storage_object_validator.rb new file mode 100644 index 00000000..73f383cd --- /dev/null +++ b/lib/moab/storage_object_validator.rb @@ -0,0 +1,180 @@ +require 'moab' + +module Moab + # Given a druid path, are the contents actually a well-formed Moab? + # Shameless green: repetitious code included. + class StorageObjectValidator + + EXPECTED_DATA_SUB_DIRS = ["content", "metadata"].freeze + IMPLICIT_DIRS = ['.', '..'].freeze # unlike Find.find, Dir.entries returns these + DATA_DIR_NAME = "data".freeze + EXPECTED_VERSION_SUB_DIRS = [DATA_DIR_NAME, "manifests"].freeze + MANIFEST_INVENTORY_PATH = 'manifests/manifestInventory.xml'.freeze + SIGNATURE_CATALOG_PATH = 'manifests/signatureCatalog.xml'.freeze + + # error codes + INCORRECT_DIR = 0 + MISSING_DIR = 1 + EXTRA_CHILD_DETECTED = 2 + VERSION_DIR_BAD_FORMAT = 3 + NO_SIGNATURE_CATALOG = 4 + NO_MANIFEST_INVENTORY = 5 + NO_XML_FILES = 6 + VERSIONS_NOT_IN_ORDER = 7 + FILES_IN_VERSION_DIR = 8 + + ERROR_CODE_TO_MESSAGES = { + INCORRECT_DIR=> "Incorrect items in path", + MISSING_DIR => "Missing directory: %{addl}", + EXTRA_CHILD_DETECTED => "Unexpected item in path: %{addl}", + VERSION_DIR_BAD_FORMAT => "Version directory name not in 'v00xx' format", + FILES_IN_VERSION_DIR => "Top level should contain only sequential version directories. Also contains files: %{addl}", + NO_SIGNATURE_CATALOG => "Version: %{addl} Missing signatureCatalog.xml", + NO_MANIFEST_INVENTORY => "Version: %{addl} Missing manifestInventory.xml", + NO_XML_FILES => "Version: %{addl} Missing all required metadata files", + VERSIONS_NOT_IN_ORDER => "Should contain only sequential version directories. Current directories: %{addl}" + }.freeze + + attr_reader :storage_obj_path + + def initialize(storage_object) + @storage_obj_path = storage_object.object_pathname + @directory_entries_hash = {} + end + + def validation_errors + errors = [] + errors.concat check_correctly_named_version_dirs + errors.concat check_sequential_version_dirs if errors.empty? + errors.concat check_correctly_formed_moabs if errors.empty? + errors + end + + # TODO: Figure out which methods should be public + + private + + def version_directories + @vdirs ||= sub_dirs(storage_obj_path) + end + + def check_correctly_named_version_dirs + errors = [] + version_directories.each do |version_dir| + errors << result_hash(VERSION_DIR_BAD_FORMAT) unless version_dir =~ /^[v]\d{4}$/ + end + errors + end + + # This method will be called only if the version directories are correctly named + def check_sequential_version_dirs + errors = [] + version_directories.each_with_index do |dir_name, index| + expected_vers_num = index + 1 # version numbering starts at 1, array indexing starts at 0 + if dir_name[1..-1].to_i != expected_vers_num + errors << result_hash(VERSIONS_NOT_IN_ORDER, version_directories) + break + end + end + + errors + end + + def check_correctly_formed_moabs + errors = [] + version_directories.each do |version_dir| + version_path = "#{storage_obj_path}/#{version_dir}" + version_sub_dirs = sub_dirs(version_path) + before_result_size = errors.size + errors.concat check_sub_dirs(version_sub_dirs, version_dir, EXPECTED_VERSION_SUB_DIRS) + after_result_size = errors.size + # run the following checks if this version dir passes check_sub_dirs, even if some prior version dirs didn't + if before_result_size == after_result_size + data_dir_path = "#{version_path}/#{DATA_DIR_NAME}" + data_sub_dirs = sub_dirs(data_dir_path) + errors.concat check_sub_dirs(data_sub_dirs, version_dir, EXPECTED_DATA_SUB_DIRS) + errors.concat check_required_manifest_files(version_path, version_dir) + end + end + + errors + end + + def check_sub_dirs(sub_dirs, version, required_sub_dirs) + errors = [] + sub_dir_count = sub_dirs.size + if sub_dir_count == required_sub_dirs.size + errors.concat expected_dirs(sub_dirs, version, required_sub_dirs) + elsif sub_dir_count > required_sub_dirs.size + errors.concat found_unexpected(sub_dirs, version, required_sub_dirs) + elsif sub_dir_count < required_sub_dirs.size + errors.concat missing_dir(sub_dirs, version, required_sub_dirs) + end + errors + end + + # This method removes the implicit '.' and '..' directories. + # Returns an array of strings. + def directory_entries(path) + @directory_entries_hash[path] ||= + begin + dirs = [] + (Dir.entries(path).sort - IMPLICIT_DIRS).each do |child| + dirs << child + end + dirs + end + end + + def sub_dirs(path) + directory_entries(path) + end + + def found_unexpected(array, version, required_sub_dirs) + errors = [] + unexpected = (array - required_sub_dirs) + unexpected = "#{unexpected} Version: #{version}" + errors << result_hash(EXTRA_CHILD_DETECTED, unexpected) + errors + end + + def missing_dir(array, version, required_sub_dirs) + errors = [] + missing = (required_sub_dirs - array) + missing ="#{missing} Version: #{version}" + errors << result_hash(MISSING_DIR, missing) + errors + end + + def expected_dirs(array, _version, required_sub_dirs) + errors = [] + errors << result_hash(INCORRECT_DIR) unless array == required_sub_dirs + errors + end + + def result_hash(response_code, addl=nil) + { response_code => error_code_msg(response_code, addl) } + end + + def error_code_msg(response_code, addl=nil) + format(ERROR_CODE_TO_MESSAGES[response_code], addl: addl) + end + + def check_required_manifest_files(dir, version) + errors = [] + has_manifest_inventory = File.exist?("#{dir}/#{MANIFEST_INVENTORY_PATH}") + has_signature_catalog = File.exist?("#{dir}/#{SIGNATURE_CATALOG_PATH}") + result = if has_manifest_inventory && has_signature_catalog + nil + elsif has_manifest_inventory && !has_signature_catalog + result_hash(NO_SIGNATURE_CATALOG, version) + elsif !has_manifest_inventory && has_signature_catalog + result_hash(NO_MANIFEST_INVENTORY, version) + else + result_hash(NO_XML_FILES, version) + end + errors << result if result + errors + end + end +end diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0001/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0001/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/data/metadata/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/data/metadata/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/extra_dir/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/extra_dir/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0002/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/content/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/content/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/extra_dir/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/extra_dir/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/metadata/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/data/metadata/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/extra_file.txt b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/extra_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0003/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0004/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0004/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/content/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/content/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/extra_file.txt b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/extra_file.txt new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/metadata/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/data/metadata/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0005/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0006/data/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0006/data/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0006/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0006/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/data/content/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/data/content/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/data/metadata/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/data/metadata/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/manifests/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000/v0007/manifests/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0001/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0001/.keep new file mode 100644 index 00000000..5e401192 --- /dev/null +++ b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0001/.keep @@ -0,0 +1 @@ +.keep diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0003/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0003/.keep new file mode 100644 index 00000000..5e401192 --- /dev/null +++ b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0003/.keep @@ -0,0 +1 @@ +.keep diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0004/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0004/.keep new file mode 100644 index 00000000..4f07f1ca --- /dev/null +++ b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0004/.keep @@ -0,0 +1 @@ +.keep \ No newline at end of file diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0006/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000/v0006/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/v0002/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/v0002/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/v0003/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/v0003/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/x0001/.keep b/spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000/x0001/.keep new file mode 100644 index 00000000..e69de29b diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation-augmented.pdf b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation-augmented.pdf new file mode 100644 index 00000000..0e017f7e Binary files /dev/null and b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation-augmented.pdf differ diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation.pdf b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation.pdf new file mode 100644 index 00000000..ca38fbd7 Binary files /dev/null and b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/content/eric-smith-dissertation.pdf differ diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/contentMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/contentMetadata.xml new file mode 100644 index 00000000..5470c3b7 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/contentMetadata.xml @@ -0,0 +1,20 @@ + + + + Body of dissertation (as submitted) + + aead2f6f734355c59af2d5b2689e4fb3 + 22dc6464e25dc9a7d600b1de6e3848bf63970595 + e49957d53fb2a46e3652f4d399bd14d019600cf496b98d11ebcdf2d10a8ffd2f + + + + Body of dissertation + + https://stacks.stanford.edu/file/druid:bj102hs9687/eric-smith-dissertation-augmented.pdf + 93802f1a639bc9215c6336ff5575ee22 + 32f7129a81830004f0360424525f066972865221 + a67276820853ddd839ba614133f1acd7330ece13f1082315d40219bed10009de + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/descMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/descMetadata.xml new file mode 100644 index 00000000..a7e83260 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/descMetadata.xml @@ -0,0 +1,74 @@ + + + + Axe, an automated formal equivalence checking tool for programs + + + Smith, Eric Whitman. + + creator + + + + Dill, David + + primary advisor. + + + ths + + + + Engler, Dawson R. + + advisor. + + + ths + + + + Mitchell, John + + advisor. + + + ths + + + + Stanford University + Computer Science Dept. + + text + theses + + + xx + + 2011 + 2011 + monographic + + + eng + + +
electronic
+
electronic resource
+ 1 online resource. +
+ This dissertation describes Axe, an automated formal verification tool for proving equivalence of programs. Axe has been used to verify real-world Java implementations of cryptographic operations, including block ciphers, stream ciphers, and cryptographic hash functions. Axe proves the bit-for-bit equivalence of the outputs of two programs, one of which may be a formal, mathematical specification. To do so, Axe relies on a novel combination of techniques from combinational equivalence checking and inductive theorem proving. First, the loops in some programs can be completely unrolled, creating large loop-free terms. Axe proves the equivalence of such terms using a phased approach, including aggressive word-level simplifications, bit-blasting, test-case-based identification of internal equivalences, and ``sweeping and merging.'' For loops that cannot be unrolled, Axe uses execution traces to detect loop properties, including loop invariants for single loops and connection relationships between corresponding loops. Axe proves such properties inductively. In many cases, synchronizing transformations must be performed to align the loop structures of the programs being compared; Axe can perform and verify a variety of these transformations. + Eric Whitman Smith. + Submitted to the Department of Computer Science. + Thesis (Ph.D.)--Stanford University, 2011. + http://purl.stanford.edu/bj102hs9687 + + http://purl.stanford.edu/bj102hs9687 + + + CSt + 110721 + a9238371 + +
diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/identityMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/identityMetadata.xml new file mode 100644 index 00000000..3c43ccbf --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/identityMetadata.xml @@ -0,0 +1,15 @@ + + + druid:bj102hs9687 + item + + DOR + Axe: An Automated Formal Equivalence Checking Tool for Programs + Smith, Eric Whitman + 0000001024 + 9238371 + + druid:ct692vv3660 + ETDs + ETD : Dissertation + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/provenanceMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/provenanceMetadata.xml new file mode 100644 index 00000000..6ecc16db --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/provenanceMetadata.xml @@ -0,0 +1,8 @@ + + + + + DOR Common Accessioning completed + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/relationshipMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/relationshipMetadata.xml new file mode 100644 index 00000000..97b24e8d --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/relationshipMetadata.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/rightsMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/rightsMetadata.xml new file mode 100644 index 00000000..024535f7 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/rightsMetadata.xml @@ -0,0 +1,21 @@ + + + + (c) Copyright 2011 by Eric Whitman Smith + + + + + + + + + stanford + 2013-06-02 + + + + none + no Creative Commons (CC) license + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/technicalMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/technicalMetadata.xml new file mode 100644 index 00000000..f22a3069 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/technicalMetadata.xml @@ -0,0 +1,25 @@ + + + 2011-10-28T01:15:16-07:00 + + PDF-hul + PDF + 1.4 + Well-Formed and valid + + PDF-hul + + application/pdf + + + + PDF-hul + PDF + Not well-formed + + PDF-hul + + application/pdf + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/versionMetadata.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/versionMetadata.xml new file mode 100644 index 00000000..93c96640 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/data/metadata/versionMetadata.xml @@ -0,0 +1,5 @@ + + + Initial Version + + \ No newline at end of file diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/fileInventoryDifference.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/fileInventoryDifference.xml new file mode 100644 index 00000000..bf21d532 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/fileInventoryDifference.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/manifestInventory.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/manifestInventory.xml new file mode 100644 index 00000000..8806a292 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/manifestInventory.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/signatureCatalog.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/signatureCatalog.xml new file mode 100644 index 00000000..5c943489 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/signatureCatalog.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionAdditions.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionAdditions.xml new file mode 100644 index 00000000..83dd392d --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionAdditions.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionInventory.xml b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionInventory.xml new file mode 100644 index 00000000..e3f20f62 --- /dev/null +++ b/spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687/v0001/manifests/versionInventory.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec/unit_tests/moab/storage_object_validator_spec.rb b/spec/unit_tests/moab/storage_object_validator_spec.rb new file mode 100644 index 00000000..2ee1857a --- /dev/null +++ b/spec/unit_tests/moab/storage_object_validator_spec.rb @@ -0,0 +1,87 @@ +require 'spec_helper' +RSpec.describe Moab::StorageObjectValidator do + let(:druid1) { 'xx000xx0000'} + let(:druid_path1) { 'spec/fixtures/bad_root01/bad_moab_storage_trunk/xx/000/xx/0000/xx000xx0000' } + let(:storage_obj1) { Moab::StorageObject.new(druid1, druid_path1) } + let(:storage_obj_validator1) { described_class.new(storage_obj1) } + + describe '#initialize' do + it "sets storage_obj_path" do + storage_obj_validator = described_class.new(storage_obj1) + expect(storage_obj_validator.storage_obj_path.to_s).to eq druid_path1 + end + end + context '#validation_errors' do + let(:verification_array) { storage_obj_validator1.validation_errors } + + it 'returns correct data structure' do + expect(storage_obj_validator1.validation_errors).to be_kind_of Array + end + + it 'has item in the array that is the expected structure' do + expect(verification_array[0]).to be_kind_of Hash + end + context 'under version directory' do + it 'has missing items' do + # v0001 + expect(verification_array[0]).to eq(Moab::StorageObjectValidator::MISSING_DIR => "Missing directory: [\"data\", \"manifests\"] Version: v0001") + end + it 'has unexpected directory' do + # v0002 + expect(verification_array[1]).to eq(Moab::StorageObjectValidator::EXTRA_CHILD_DETECTED =>"Unexpected item in path: [\"extra_dir\"] Version: v0002") + end + it 'has unexpected file' do + # v0003 + expect(verification_array[2]).to eq(Moab::StorageObjectValidator::EXTRA_CHILD_DETECTED =>"Unexpected item in path: [\"extra_file.txt\"] Version: v0003") + end + it 'has missing data directory' do + # v0004 + expect(verification_array[3]).to eq(Moab::StorageObjectValidator::MISSING_DIR =>"Missing directory: [\"data\"] Version: v0004") + end + end + + context 'under data directory' do + it 'has unexpected file' do + # v0005 + expect(verification_array[4]).to eq(Moab::StorageObjectValidator::EXTRA_CHILD_DETECTED =>"Unexpected item in path: [\"extra_file.txt\"] Version: v0005") + expect(verification_array[8]).to eq(Moab::StorageObjectValidator::NO_XML_FILES =>"Version: v0007 Missing all required metadata files") + end + it 'has missing manifest files' do + # v0005 + expect(verification_array[5]).to eq(Moab::StorageObjectValidator::NO_XML_FILES =>"Version: v0005 Missing all required metadata files") + end + it 'has missing content directory' do + # v0006 + expect(verification_array[6]).to eq(Moab::StorageObjectValidator::MISSING_DIR =>"Missing directory: [\"content\", \"metadata\"] Version: v0006") + end + it 'has no required items' do + # v0006 + expect(verification_array[7]).to eq(Moab::StorageObjectValidator::NO_XML_FILES =>"Version: v0006 Missing all required metadata files") + end + end + it "has non contiguous version directories" do + druid = 'yy000yy0000' + druid_path = 'spec/fixtures/bad_root01/bad_moab_storage_trunk/yy/000/yy/0000/yy000yy0000' + storage_obj = Moab::StorageObject.new(druid, druid_path) + storage_obj_validator = described_class.new(storage_obj) + verification_array = storage_obj_validator.validation_errors + expect(verification_array).to eq([{ Moab::StorageObjectValidator::VERSIONS_NOT_IN_ORDER =>"Should contain only sequential version directories. Current directories: [\"v0001\", \"v0003\", \"v0004\", \"v0006\"]" }]) + end + it "has incorrect version directory name" do + druid = 'zz000zz0000' + druid_path = 'spec/fixtures/bad_root01/bad_moab_storage_trunk/zz/000/zz/0000/zz000zz0000' + storage_obj = Moab::StorageObject.new(druid, druid_path) + storage_obj_validator = described_class.new(storage_obj) + verification_array = storage_obj_validator.validation_errors + expect(verification_array).to eq [Moab::StorageObjectValidator::VERSION_DIR_BAD_FORMAT =>"Version directory name not in 'v00xx' format"] + end + it "returns true when moab is in correct format" do + druid = 'bj103hs9687' + druid_path = 'spec/fixtures/good_root01/moab_storage_trunk/bj/103/hs/9687/bj103hs9687' + storage_obj = Moab::StorageObject.new(druid, druid_path) + storage_obj_validator = described_class.new(storage_obj) + verification_array = storage_obj_validator.validation_errors + expect(verification_array.empty?).to eq true + end + end +end