6277: add Manifest::valid? method in ruby sdk.
authorradhika <radhika@curoverse.com>
Thu, 11 Jun 2015 18:33:48 +0000 (14:33 -0400)
committerradhika <radhika@curoverse.com>
Thu, 11 Jun 2015 18:33:48 +0000 (14:33 -0400)
sdk/ruby/lib/arvados/keep.rb
sdk/ruby/test/test_keep_manifest.rb

index 739ff014262560630bc7fe0ca80497f4ad0af9b5..393266fb113160a4410f3e8aac1f479f51b68940 100644 (file)
@@ -97,6 +97,9 @@ module Keep
   end
 
   class Manifest
+    STREAM_REGEXP = /(\.)(\/+.*)*$/
+    FILE_REGEXP = /^[[:digit:]]+:[[:digit:]]+:/
+
     # Class to parse a manifest text and provide common views of that data.
     def initialize(manifest_text)
       @text = manifest_text
@@ -224,5 +227,39 @@ module Keep
       end
       false
     end
+
+    # Verify that a given manifest is valid as per the manifest format definition.
+    # Valid format: stream name + one or more locators + one or more files for each stream in manifest.
+    # https://arvados.org/projects/arvados/wiki/Keep_manifest_format
+    def self.valid?(manifest)
+      line_count = 0
+      manifest.each_line do |line|
+        line_count += 1
+
+        words = line.split
+
+        count = 0
+        word = words.shift
+        count += 1 if word =~ STREAM_REGEXP
+        raise ArgumentError.new "Manifest invalid for stream #{line_count}. Missing or invalid stream name #{word}" if count != 1
+
+        count = 0
+        word = words.shift
+        while word =~ Locator::LOCATOR_REGEXP
+          word = words.shift
+          count += 1
+        end
+        raise ArgumentError.new "Manifest invalid for stream #{line_count}. Missing or invalid locator #{word}" if count == 0
+
+        count = 0
+        while word =~ FILE_REGEXP
+          word = words.shift
+          count += 1
+        end
+        if(count == 0) or (word and word !~ FILE_REGEXP)
+          raise ArgumentError.new "Manifest invalid for stream #{line_count}. Missing or invalid file name #{word}"
+        end
+      end
+    end
   end
 end
index 7689d5016fcb9abe18bf975005199e2f717841cd..c49bd941d50c816f5cd101c84fc810e4fcfbaa6d 100644 (file)
@@ -279,4 +279,37 @@ class ManifestTest < Minitest::Test
       end
     end
   end
+
+  [
+   [false, 'abc d41d8cd98f00b204e9800998ecf8427e 0:0:abc.txt', 'invalid stream name abc'],
+   [false, 'd41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt', 'invalid stream name d41d8cd98f00b204e9800998ecf8427e'],
+   [false, '. d41d8cd98f00b204e9800998ecf8427 0:0:abc.txt', 'invalid locator d41d8cd98f00b204e9800998ecf8427'],
+   [true, '. d41d8cd98f00b204e9800998ecf8427e 0:0:abc.txt'],
+   [true, '. d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt'],
+   [true, '. d41d8cd98f00b204e9800998ecf8427e a41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt'], # 2 locators
+   [false, ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt\n/dir1 d41d8cd98f00b204e9800998ecf842 0:0:abc.txt",
+    'Manifest invalid for stream 2. Missing or invalid stream name /dir1'],
+   [false, ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt\n./dir1 d41d8cd98f00b204e9800998ecf842 0:0:abc.txt",
+    'Manifest invalid for stream 2. Missing or invalid locator d41d8cd98f00b204e9800998ecf842'],
+   [false, ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt\n./dir1 a41d8cd98f00b204e9800998ecf8427e+0 abc.txt",
+    'Manifest invalid for stream 2. Missing or invalid file name abc.txt'],
+   [false, ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt\n./dir1 a41d8cd98f00b204e9800998ecf8427e+0 0:abc.txt",
+    'Manifest invalid for stream 2. Missing or invalid file name 0:abc.txt'],
+   [false, ". d41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt\n./dir1 a41d8cd98f00b204e9800998ecf8427e+0 0:0:abc.txt xyz.txt",
+    'Manifest invalid for stream 2. Missing or invalid file name xyz.txt'],
+  ].each do |ok, manifest, expected_error=nil|
+    define_method "test_manifest_valid_#{ok}_#{manifest}_and_expect_error_#{expected_error}" do
+      if ok
+        assert Keep::Manifest.valid? manifest
+      else
+        begin
+          Keep::Manifest.valid? manifest
+        rescue ArgumentError => e
+          msg = e.message
+        end
+        refute_nil msg, "Expected ArgumentError"
+        assert msg.include?(expected_error), "Did not find error message #{expected_error} in #{msg}"
+      end
+    end
+  end
 end