Merge branch '8784-dir-listings'
[arvados.git] / sdk / cli / test / test_arv-get.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 require 'minitest/autorun'
6 require 'json'
7 require 'yaml'
8
9 # Black box tests for 'arv get' command.
10 class TestArvGet < Minitest::Test
11   # UUID for an Arvados object that does not exist
12   NON_EXISTENT_OBJECT_UUID = "zzzzz-zzzzz-zzzzzzzzzzzzzzz"
13   # Name of field of Arvados object that can store any (textual) value
14   STORED_VALUE_FIELD_NAME = "name"
15   # Name of UUID field of Arvados object
16   UUID_FIELD_NAME = "uuid"
17   # Name of an invalid field of Arvados object
18   INVALID_FIELD_NAME = "invalid"
19
20   # Tests that a valid Arvados object can be retrieved in a supported format
21   # using: `arv get [uuid]`. Given all other `arv foo` commands return JSON
22   # when no format is specified, JSON should be expected in this case.
23   def test_get_valid_object_no_format_specified
24     stored_value = __method__.to_s
25     uuid = create_arv_object_with_value(stored_value)
26     out, err = capture_subprocess_io do
27       assert(arv_get_default(uuid))
28     end
29     assert_empty(err, "Error text not expected: '#{err}'")
30     arv_object = parse_json_arv_object(out)
31     assert(has_field_with_value(arv_object, STORED_VALUE_FIELD_NAME, stored_value))
32   end
33
34   # Tests that a valid Arvados object can be retrieved in JSON format using:
35   # `arv get [uuid] --format json`.
36   def test_get_valid_object_json_format_specified
37     stored_value = __method__.to_s
38     uuid = create_arv_object_with_value(stored_value)
39     out, err = capture_subprocess_io do
40       assert(arv_get_json(uuid))
41     end
42     assert_empty(err, "Error text not expected: '#{err}'")
43     arv_object = parse_json_arv_object(out)
44     assert(has_field_with_value(arv_object, STORED_VALUE_FIELD_NAME, stored_value))
45   end
46
47   # Tests that a valid Arvados object can be retrieved in YAML format using:
48   # `arv get [uuid] --format yaml`.
49   def test_get_valid_object_yaml_format_specified
50     stored_value = __method__.to_s
51     uuid = create_arv_object_with_value(stored_value)
52     out, err = capture_subprocess_io do
53       assert(arv_get_yaml(uuid))
54     end
55     assert_empty(err, "Error text not expected: '#{err}'")
56     arv_object = parse_yaml_arv_object(out)
57     assert(has_field_with_value(arv_object, STORED_VALUE_FIELD_NAME, stored_value))
58   end
59
60   # Tests that a subset of all fields of a valid Arvados object can be retrieved
61   # using: `arv get [uuid] [fields...]`.
62   def test_get_valid_object_with_valid_fields
63     stored_value = __method__.to_s
64     uuid = create_arv_object_with_value(stored_value)
65     out, err = capture_subprocess_io do
66       assert(arv_get_json(uuid, STORED_VALUE_FIELD_NAME, UUID_FIELD_NAME))
67     end
68     assert_empty(err, "Error text not expected: '#{err}'")
69     arv_object = parse_json_arv_object(out)
70     assert(has_field_with_value(arv_object, STORED_VALUE_FIELD_NAME, stored_value))
71     assert(has_field_with_value(arv_object, UUID_FIELD_NAME, uuid))
72   end
73
74   # Tests that the valid field is retrieved when both a valid and invalid field
75   # are requested from a valid Arvados object, using:
76   # `arv get [uuid] [fields...]`.
77   def test_get_valid_object_with_both_valid_and_invalid_fields
78     stored_value = __method__.to_s
79     uuid = create_arv_object_with_value(stored_value)
80     out, err = capture_subprocess_io do
81       assert(arv_get_json(uuid, STORED_VALUE_FIELD_NAME, INVALID_FIELD_NAME))
82     end
83     assert_empty(err, "Error text not expected: '#{err}'")
84     arv_object = parse_json_arv_object(out)
85     assert(has_field_with_value(arv_object, STORED_VALUE_FIELD_NAME, stored_value))
86     refute(has_field_with_value(arv_object, INVALID_FIELD_NAME, stored_value))
87   end
88
89   # Tests that no fields are retreived when no valid fields are requested from
90   # a valid Arvados object, using: `arv get [uuid] [fields...]`.
91   def test_get_valid_object_with_no_valid_fields
92     stored_value = __method__.to_s
93     uuid = create_arv_object_with_value(stored_value)
94     out, err = capture_subprocess_io do
95       assert(arv_get_json(uuid, INVALID_FIELD_NAME))
96     end
97     assert_empty(err, "Error text not expected: '#{err}'")
98     arv_object = parse_json_arv_object(out)
99     assert_equal(0, arv_object.length)
100   end
101
102   # Tests that an invalid (non-existent) Arvados object is not retrieved using:
103   # using: `arv get [non-existent-uuid]`.
104   def test_get_invalid_object
105     out, err = capture_subprocess_io do
106       refute(arv_get_json(NON_EXISTENT_OBJECT_UUID))
107     end
108     refute_empty(err, "Expected error feedback on request for invalid object")
109     assert_empty(out)
110   end
111
112   # Tests that help text exists using: `arv get --help`.
113   def test_help_exists
114     out, err = capture_subprocess_io do
115 #      assert(arv_get_default("--help"), "Expected exit code 0: #{$?}")
116        #XXX: Exit code given is 255. It probably should be 0, which seems to be
117        #     standard elsewhere. However, 255 is in line with other `arv`
118        #     commands (e.g. see `arv edit`) so ignoring the problem here.
119        arv_get_default("--help")
120     end
121     assert_empty(err, "Error text not expected: '#{err}'")
122     refute_empty(out, "Help text should be given")
123   end
124
125   protected
126   # Runs 'arv get <varargs>' with given arguments. Returns whether the exit
127   # status was 0 (i.e. success). Use $? to attain more details on failure.
128   def arv_get_default(*args)
129     return system("arv", "get", *args)
130   end
131
132   # Runs 'arv --format json get <varargs>' with given arguments. Returns whether
133   # the exit status was 0 (i.e. success). Use $? to attain more details on
134   # failure.
135   def arv_get_json(*args)
136     return system("arv", "--format", "json", "get", *args)
137   end
138
139   # Runs 'arv --format yaml get <varargs>' with given arguments. Returns whether
140   # the exit status was 0 (i.e. success). Use $? to attain more details on
141   # failure.
142   def arv_get_yaml(*args)
143     return system("arv", "--format", "yaml", "get", *args)
144   end
145
146   # Creates an Arvados object that stores a given value. Returns the uuid of the
147   # created object.
148   def create_arv_object_with_value(value)
149     out, err = capture_subprocess_io do
150       system("arv", "tag", "add", value, "--object", "testing")
151       assert $?.success?, "Command failure running `arv tag`: #{$?}"
152     end
153     assert_equal '', err
154     assert_operator 0, :<, out.strip.length
155     out.strip
156   end
157
158   # Parses the given JSON representation of an Arvados object, returning
159   # an equivalent Ruby representation (a hash map).
160   def parse_json_arv_object(arvObjectAsJson)
161     begin
162       parsed = JSON.parse(arvObjectAsJson)
163       assert(parsed.instance_of?(Hash))
164       return parsed
165     rescue JSON::ParserError => e
166       raise "Invalid JSON representation of Arvados object.\n" \
167             "Parse error: '#{e}'\n" \
168             "JSON: '#{arvObjectAsJson}'\n"
169     end
170   end
171
172   # Parses the given JSON representation of an Arvados object, returning
173   # an equivalent Ruby representation (a hash map).
174   def parse_yaml_arv_object(arvObjectAsYaml)
175     begin
176       parsed = YAML.load(arvObjectAsYaml)
177       assert(parsed.instance_of?(Hash))
178       return parsed
179     rescue
180       raise "Invalid YAML representation of Arvados object.\n" \
181             "YAML: '#{arvObjectAsYaml}'\n"
182     end
183   end
184
185   # Checks whether the given Arvados object has the given expected value for the
186   # specified field.
187   def has_field_with_value(arvObjectAsHash, fieldName, expectedValue)
188     if !arvObjectAsHash.has_key?(fieldName)
189       return false
190     end
191     return (arvObjectAsHash[fieldName] == expectedValue)
192   end
193 end