18574: Adds strict checking on conversion methods. Adds/updates tests.
[arvados.git] / sdk / python / tests / test_vocabulary.py
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 import arvados
6 import unittest
7 import mock
8
9 from arvados import api, vocabulary
10
11 class VocabularyTest(unittest.TestCase):
12     EXAMPLE_VOC = {
13         'tags': {
14             'IDTAGANIMALS': {
15                 'strict': False,
16                 'labels': [
17                     {'label': 'Animal'},
18                     {'label': 'Creature'},
19                 ],
20                 'values': {
21                     'IDVALANIMAL1': {
22                         'labels': [
23                             {'label': 'Human'},
24                             {'label': 'Homo sapiens'},
25                         ],
26                     },
27                     'IDVALANIMAL2': {
28                         'labels': [
29                             {'label': 'Elephant'},
30                             {'label': 'Loxodonta'},
31                         ],
32                     },
33                 },
34             },
35             'IDTAGIMPORTANCES': {
36                 'strict': True,
37                 'labels': [
38                     {'label': 'Importance'},
39                     {'label': 'Priority'},
40                 ],
41                 'values': {
42                     'IDVALIMPORTANCE1': {
43                         'labels': [
44                             {'label': 'High'},
45                             {'label': 'High priority'},
46                         ],
47                     },
48                     'IDVALIMPORTANCE2': {
49                         'labels': [
50                             {'label': 'Medium'},
51                             {'label': 'Medium priority'},
52                         ],
53                     },
54                     'IDVALIMPORTANCE3': {
55                         'labels': [
56                             {'label': 'Low'},
57                             {'label': 'Low priority'},
58                         ],
59                     },
60                 },
61             },
62         },
63     }
64
65     def setUp(self):
66         self.api = arvados.api('v1')
67         self.voc = vocabulary.Vocabulary(self.EXAMPLE_VOC)
68         self.api.vocabulary = mock.MagicMock(return_value=self.EXAMPLE_VOC)
69
70     def test_vocabulary_keys(self):
71         self.assertEqual(self.voc.strict_keys, False)
72         self.assertEqual(
73             self.voc.key_aliases.keys(),
74             set(['idtaganimals', 'creature', 'animal',
75                 'idtagimportances', 'importance', 'priority'])
76         )
77
78         vk = self.voc.key_aliases['creature']
79         self.assertEqual(vk.strict, False)
80         self.assertEqual(vk.identifier, 'IDTAGANIMALS')
81         self.assertEqual(vk.aliases, ['Animal', 'Creature'])
82         self.assertEqual(vk.preferred_label, 'Animal')
83         self.assertEqual(
84             vk.value_aliases.keys(),
85             set(['idvalanimal1', 'human', 'homo sapiens',
86                 'idvalanimal2', 'elephant', 'loxodonta'])
87         )
88
89     def test_vocabulary_values(self):
90         vk = self.voc.key_aliases['creature']
91         vv = vk.value_aliases['human']
92         self.assertEqual(vv.identifier, 'IDVALANIMAL1')
93         self.assertEqual(vv.aliases, ['Human', 'Homo sapiens'])
94         self.assertEqual(vv.preferred_label, 'Human')
95
96     def test_vocabulary_indexing(self):
97         self.assertEqual(self.voc['creature']['human'].identifier, 'IDVALANIMAL1')
98         self.assertEqual(self.voc['Creature']['Human'].identifier, 'IDVALANIMAL1')
99         self.assertEqual(self.voc['CREATURE']['HUMAN'].identifier, 'IDVALANIMAL1')
100         with self.assertRaises(KeyError):
101             inexistant = self.voc['foo']
102
103     def test_empty_vocabulary(self):
104         voc = vocabulary.Vocabulary({})
105         self.assertEqual(voc.strict_keys, False)
106         self.assertEqual(voc.key_aliases, {})
107
108     def test_load_vocabulary_with_api(self):
109         voc = vocabulary.load_vocabulary(self.api)
110         self.assertEqual(voc['creature']['human'].identifier, 'IDVALANIMAL1')
111         self.assertEqual(voc['Creature']['Human'].identifier, 'IDVALANIMAL1')
112         self.assertEqual(voc['CREATURE']['HUMAN'].identifier, 'IDVALANIMAL1')
113
114     def test_convert_to_identifiers(self):
115         cases = [
116             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
117             {'IDTAGIMPORTANCES': 'High'},
118             {'importance': 'IDVALIMPORTANCE1'},
119             {'priority': 'high priority'},
120         ]
121         for case in cases:
122             self.assertEqual(
123                 self.voc.convert_to_identifiers(case),
124                 {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
125                 "failing test case: {}".format(case)
126             )
127
128     def test_convert_to_identifiers_multiple_pairs(self):
129         cases = [
130             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1'},
131             {'IDTAGIMPORTANCES': 'High', 'IDTAGANIMALS': 'IDVALANIMAL1'},
132             {'importance': 'IDVALIMPORTANCE1', 'animal': 'IDVALANIMAL1'},
133             {'priority': 'high priority', 'animal': 'IDVALANIMAL1'},
134         ]
135         for case in cases:
136             self.assertEqual(
137                 self.voc.convert_to_identifiers(case),
138                 {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1'},
139                 "failing test case: {}".format(case)
140             )
141
142     def test_convert_to_identifiers_unknown_key(self):
143         # Non-strict vocabulary
144         self.assertEqual(self.voc.strict_keys, False)
145         self.assertEqual(self.voc.convert_to_identifiers({'foo': 'bar'}), {'foo': 'bar'})
146         # Strict vocabulary
147         strict_voc = arvados.vocabulary.Vocabulary(self.EXAMPLE_VOC)
148         strict_voc.strict_keys = True
149         with self.assertRaises(KeyError):
150             strict_voc.convert_to_identifiers({'foo': 'bar'})
151
152     def test_convert_to_identifiers_unknown_value(self):
153         # Non-strict key
154         self.assertEqual(self.voc['animal'].strict, False)
155         self.assertEqual(self.voc.convert_to_identifiers({'Animal': 'foo'}), {'IDTAGANIMALS': 'foo'})
156         # Strict key
157         self.assertEqual(self.voc['priority'].strict, True)
158         with self.assertRaises(ValueError):
159             self.voc.convert_to_identifiers({'Priority': 'foo'})
160
161     def test_convert_to_labels(self):
162         cases = [
163             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1'},
164             {'IDTAGIMPORTANCES': 'High'},
165             {'importance': 'IDVALIMPORTANCE1'},
166             {'priority': 'high priority'},
167         ]
168         for case in cases:
169             self.assertEqual(
170                 self.voc.convert_to_labels(case),
171                 {'Importance': 'High'},
172                 "failing test case: {}".format(case)
173             )
174
175     def test_convert_to_labels_multiple_pairs(self):
176         cases = [
177             {'IDTAGIMPORTANCES': 'IDVALIMPORTANCE1', 'IDTAGANIMALS': 'IDVALANIMAL1'},
178             {'IDTAGIMPORTANCES': 'High', 'IDTAGANIMALS': 'IDVALANIMAL1'},
179             {'importance': 'IDVALIMPORTANCE1', 'animal': 'IDVALANIMAL1'},
180             {'priority': 'high priority', 'animal': 'IDVALANIMAL1'},
181         ]
182         for case in cases:
183             self.assertEqual(
184                 self.voc.convert_to_labels(case),
185                 {'Importance': 'High', 'Animal': 'Human'},
186                 "failing test case: {}".format(case)
187             )
188
189     def test_convert_to_labels_unknown_key(self):
190         # Non-strict vocabulary
191         self.assertEqual(self.voc.strict_keys, False)
192         self.assertEqual(self.voc.convert_to_labels({'foo': 'bar'}), {'foo': 'bar'})
193         # Strict vocabulary
194         strict_voc = arvados.vocabulary.Vocabulary(self.EXAMPLE_VOC)
195         strict_voc.strict_keys = True
196         with self.assertRaises(KeyError):
197             strict_voc.convert_to_labels({'foo': 'bar'})
198
199     def test_convert_to_labels_unknown_value(self):
200         # Non-strict key
201         self.assertEqual(self.voc['animal'].strict, False)
202         self.assertEqual(self.voc.convert_to_labels({'IDTAGANIMALS': 'foo'}), {'Animal': 'foo'})
203         # Strict key
204         self.assertEqual(self.voc['priority'].strict, True)
205         with self.assertRaises(ValueError):
206             self.voc.convert_to_labels({'IDTAGIMPORTANCES': 'foo'})