Coverage for test / idm_orcid_test.py: 99%
164 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 18:06 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 18:06 +0000
1# SPDX-FileCopyrightText: 2023 Marta Soricetti <marta.soricetti@unibo.it>
2# SPDX-FileCopyrightText: 2023-2024 Arianna Moretti <arianna.moretti4@unibo.it>
3# SPDX-FileCopyrightText: 2024-2026 Arcangelo Massari <arcangelo.massari@unibo.it>
4#
5# SPDX-License-Identifier: ISC
7import json
8import re
9import unittest
10from os import makedirs
11from os.path import exists, join
13from oc_ds_converter.oc_idmanager.orcid import ORCIDManager
16class orcidIdentifierManagerTest(unittest.TestCase):
17 """This class aim at testing identifiers manager."""
19 def setUp(self):
20 if not exists("tmp"):
21 makedirs("tmp")
23 self.test_dir = join("test", "data")
24 self.test_json_path = join(self.test_dir, "glob.json")
25 with open(self.test_json_path, encoding="utf-8") as fp:
26 self.data = json.load(fp)
28 self.valid_orcid_1 = "0000-0003-0530-4305"
29 self.valid_orcid_2 = "0000-0001-5506-523X"
30 self.invalid_orcid_1 = "0000-0003-0530-430C"
31 self.invalid_orcid_2 = "0000-0001-5506-5232"
32 self.invalid_orcid_3 = "0000-0001-5506-523"
33 self.invalid_orcid_4 = "1-5506-5232"
34 self.invalid_orcid_5 = "0000-0001-2345-6789"
37 def test_orcid_normalise(self):
38 om = ORCIDManager()
39 self.assertEqual(
40 self.valid_orcid_1, om.normalise(self.valid_orcid_1.replace("-", " "))
41 )
42 self.assertEqual(
43 self.valid_orcid_1, om.normalise("https://orcid.org/" + self.valid_orcid_1)
44 )
45 self.assertEqual(
46 self.valid_orcid_2, om.normalise(self.valid_orcid_2.replace("-", " "))
47 )
48 self.assertEqual(
49 self.invalid_orcid_3, om.normalise(self.invalid_orcid_3.replace("-", " "))
50 )
52 def test_orcid_is_valid(self):
53 om = ORCIDManager()
54 self.assertTrue(om.is_valid(self.valid_orcid_1))
55 self.assertTrue(om.is_valid(self.valid_orcid_2))
56 self.assertFalse(om.is_valid(self.invalid_orcid_1))
57 self.assertFalse(om.is_valid(self.invalid_orcid_2))
58 self.assertFalse(om.is_valid(self.invalid_orcid_3))
59 self.assertFalse(om.is_valid(self.invalid_orcid_4))
61 om_file = ORCIDManager(testing=True, use_api_service=False)
62 self.assertTrue(om_file.normalise(self.valid_orcid_1, include_prefix=True) in self.data)
63 self.assertTrue(om_file.normalise(self.valid_orcid_2, include_prefix=True) in self.data)
64 self.assertTrue(om_file.is_valid(om_file.normalise(self.valid_orcid_1, include_prefix=True)))
65 self.assertTrue(om_file.is_valid(om_file.normalise(self.valid_orcid_2, include_prefix=True)))
67 om_nofile_noapi = ORCIDManager(use_api_service=False)
68 self.assertTrue(om_nofile_noapi.is_valid(self.valid_orcid_1))
69 self.assertTrue(om_nofile_noapi.is_valid(self.valid_orcid_2))
71 def test_exists(self):
72 with self.subTest(msg="get_extra_info=True, allow_extra_api=None"):
73 orcid_manager = ORCIDManager()
74 output = orcid_manager.exists(self.valid_orcid_2, get_extra_info=True, allow_extra_api=None)
75 self.assertTrue(output[0]) # Check if exists
76 info = output[1]
77 self.assertEqual(info['id'], '0000-0001-5506-523X')
78 self.assertTrue(info['valid'])
79 self.assertEqual(info['family_name'], 'Shotton')
80 self.assertEqual(info['given_name'], 'David')
81 self.assertEqual(info['email'], "")
82 self.assertEqual(info['external_identifiers'], {})
83 self.assertEqual(info['submission_date'], '2012-10-31')
84 # Check if update_date is a valid date string and not earlier than submission_date
85 self.assertTrue(re.match(r'\d{4}-\d{2}-\d{2}', info['update_date']))
86 self.assertGreaterEqual(info['update_date'], info['submission_date'])
87 with self.subTest(msg="get_extra_info=False, allow_extra_api=None"):
88 orcid_manager = ORCIDManager()
89 output = orcid_manager.exists(orcid_manager.normalise(self.valid_orcid_1), get_extra_info=False, allow_extra_api=None)
90 expected_output = True
91 self.assertEqual(output, expected_output)
92 with self.subTest(msg="get_extra_info=False, allow_extra_api='None'"):
93 orcid_manager = ORCIDManager()
94 output = orcid_manager.exists(self.invalid_orcid_5, get_extra_info=False, allow_extra_api='None')
95 expected_output = False
96 self.assertEqual(output, expected_output)
98 def test_orcid_default(self):
99 am_nofile = ORCIDManager(testing=True)
100 # Uses RedisStorageManager with testing=True (fakeredis)
101 # uses API
102 self.assertTrue(am_nofile.is_valid(self.valid_orcid_1))
103 self.assertTrue(am_nofile.is_valid(self.valid_orcid_2))
104 self.assertFalse(am_nofile.is_valid(self.invalid_orcid_2))
105 self.assertFalse(am_nofile.is_valid(self.invalid_orcid_1))
106 validated_ids = [self.valid_orcid_1, self.valid_orcid_2, self.invalid_orcid_1, self.invalid_orcid_2]
107 # check that all the validated ids are stored in redis
108 all_ids_stored = am_nofile.storage_manager.get_all_keys()
109 self.assertTrue(all(am_nofile.normalise(x, include_prefix=True) in all_ids_stored for x in validated_ids))
110 am_nofile.storage_manager.delete_storage()
111 # check that the storage was correctly deleted
112 self.assertEqual(am_nofile.storage_manager.get_all_keys(), set())
114 def test_orcid_memory_file_noapi(self):
115 # Uses support file (without updating it)
116 # Uses RedisStorageManager storage manager
117 # does not use API (so a syntactically correct id is considered to be valid)
118 am_file = ORCIDManager(testing=True, use_api_service=False)
119 self.assertTrue(am_file.normalise(self.valid_orcid_1, include_prefix=True) in self.data)
120 self.assertTrue(am_file.normalise(self.invalid_orcid_2, include_prefix=True) in self.data)
121 self.assertFalse(am_file.is_valid(self.invalid_orcid_2)) # is stored in support file as invalid
122 self.assertTrue(am_file.is_valid(am_file.normalise(self.invalid_orcid_5, include_prefix=True))) # is not stored in support file as invalid, does not exist but has correct syntax
124 def test_orcid_memory_file_api(self):
125 # Uses support file (without updating it)
126 # Uses RedisStorageManager storage manager
127 # uses API (so a syntactically correct id which is not valid is considered to be invalid)
128 am_file = ORCIDManager(testing=True, use_api_service=True)
129 self.assertFalse(am_file.is_valid(self.invalid_orcid_1))
131 def test_orcid_memory_nofile_noapi(self):
132 # Does not use support file
133 # Uses RedisStorageManager storage manager
134 # Does not API (so a syntactically correct id which is not valid is considered to be valid)
135 am_nofile_noapi = ORCIDManager(testing=True, use_api_service=False)
136 self.assertTrue(am_nofile_noapi.is_valid(self.valid_orcid_1))
137 self.assertTrue(am_nofile_noapi.is_valid(self.invalid_orcid_5))
138 am_nofile_noapi.storage_manager.delete_storage()
142 def test_orcid_sqlite_nofile_api(self):
143 # No pre-existing data
144 # storage manager : RedisStorageManager
145 # uses API
146 sql_am_nofile = ORCIDManager(testing=True)
147 self.assertTrue(sql_am_nofile.is_valid(self.valid_orcid_1))
148 self.assertTrue(sql_am_nofile.is_valid(self.valid_orcid_2))
149 self.assertFalse(sql_am_nofile.is_valid(self.invalid_orcid_1))
150 self.assertFalse(sql_am_nofile.is_valid(self.invalid_orcid_2))
151 # check that the redis storage contains all the validated ids
152 validated_ids = [self.valid_orcid_1, self.valid_orcid_2, self.invalid_orcid_1, self.invalid_orcid_2]
153 all_ids_stored = sql_am_nofile.storage_manager.get_all_keys()
154 # check that all the validated ids are stored
155 self.assertTrue(all(sql_am_nofile.normalise(x, include_prefix=True) in all_ids_stored for x in validated_ids))
156 sql_am_nofile.storage_manager.delete_storage()
157 # check that the storage was correctly deleted
158 self.assertEqual(sql_am_nofile.storage_manager.get_all_keys(), set())
160 def test_orcid_sqlite_file_api(self):
161 # Uses pre-existing data in Redis
162 # Uses RedisStorageManager storage manager
163 # tests validation behavior with pre-seeded data
164 to_insert = [self.invalid_orcid_1, self.valid_orcid_1]
165 sql_file = ORCIDManager(testing=True, use_api_service=True)
166 for id in to_insert:
167 norm_id = sql_file.normalise(id, include_prefix=True)
168 is_valid = sql_file.is_valid(norm_id)
169 sql_file.storage_manager.set_value(norm_id, is_valid)
171 sql_no_api = ORCIDManager(testing=True, use_api_service=False)
172 # Copy values from the first manager to the second for testing
173 for id in to_insert:
174 norm_id = sql_no_api.normalise(id, include_prefix=True)
175 value = sql_file.storage_manager.get_value(norm_id)
176 if value is not None:
177 sql_no_api.storage_manager.set_value(norm_id, value)
178 all_db_keys = sql_no_api.storage_manager.get_all_keys()
179 # check that all the normalised ids in the list were correctly inserted
180 self.assertTrue(all(sql_no_api.normalise(x, include_prefix=True) in all_db_keys for x in to_insert))
181 self.assertTrue(sql_no_api.is_valid(self.valid_orcid_1)) # is stored as valid
182 self.assertFalse(sql_no_api.is_valid(self.invalid_orcid_1)) # is stored as invalid
183 self.assertTrue(sql_no_api.is_valid(sql_no_api.normalise(self.invalid_orcid_5, include_prefix=True))) # not stored as invalid, has correct syntax
184 sql_no_api.storage_manager.delete_storage()
186 def test_orcid_sqlite_nofile_noapi(self):
187 # Does not use support file
188 # Uses RedisStorageManager storage manager
189 # Does not use API (so a syntactically correct id which is not valid is considered to be valid)
190 am_nofile_noapi = ORCIDManager(testing=True, use_api_service=False)
191 self.assertTrue(am_nofile_noapi.is_valid(self.valid_orcid_1))
192 self.assertTrue(am_nofile_noapi.is_valid(self.invalid_orcid_5))
193 am_nofile_noapi.storage_manager.delete_storage()
197 #### REDIS STORAGE MANAGER
198 def test_orcid_redis_nofile_api(self):
199 # No available data in redis db
200 # Storage manager : RedisStorageManager
201 # uses API
202 sql_am_nofile = ORCIDManager(testing=True)
203 self.assertTrue(sql_am_nofile.is_valid(self.valid_orcid_1))
204 self.assertTrue(sql_am_nofile.is_valid(self.valid_orcid_2))
205 self.assertFalse(sql_am_nofile.is_valid(self.invalid_orcid_1))
206 self.assertFalse(sql_am_nofile.is_valid(self.invalid_orcid_2))
207 # check that the redis db was correctly filled and that it contains all the validated ids
209 validated_ids = {self.valid_orcid_1, self.valid_orcid_2, self.invalid_orcid_1, self.invalid_orcid_2}
210 validated_ids = {sql_am_nofile.normalise(x, include_prefix=True) for x in validated_ids}
211 all_ids_stored = sql_am_nofile.storage_manager.get_all_keys()
212 # check that all the validated ids are stored in the json file
213 self.assertEqual(validated_ids, all_ids_stored)
214 sql_am_nofile.storage_manager.delete_storage()
215 # check that the support file was correctly deleted
216 self.assertEqual(sql_am_nofile.storage_manager.get_all_keys(), set())
218 def test_orcid_redis_file_api(self):
219 # Uses data in redis db
220 # Uses RedisStorageManager
221 # does not use API (so a syntactically correct id is considered to be valid)
222 # fills db
224 to_insert = [self.invalid_orcid_1, self.valid_orcid_1]
225 sql_file = ORCIDManager(testing=True, use_api_service=True)
226 for id in to_insert:
227 norm_id = sql_file.normalise(id, include_prefix=True)
228 is_valid = sql_file.is_valid(norm_id)
229 sql_file.storage_manager.set_value(norm_id,is_valid)
231 sql_no_api = ORCIDManager(testing=True, use_api_service=False)
232 # Copy values from the first manager to the second for testing
233 for id in to_insert:
234 norm_id = sql_no_api.normalise(id, include_prefix=True)
235 value = sql_file.storage_manager.get_value(norm_id)
236 if value is not None:
237 sql_no_api.storage_manager.set_value(norm_id, value)
238 all_db_keys = sql_no_api.storage_manager.get_all_keys()
239 #check that all the normalised ids in the list were correctly inserted in the db
240 self.assertTrue(all(sql_no_api.normalise(x,include_prefix=True) in all_db_keys for x in to_insert))
242 self.assertTrue(sql_no_api.is_valid(self.valid_orcid_1)) # is stored in support file as valid
243 self.assertFalse(sql_no_api.is_valid(self.invalid_orcid_1)) # is stored in support file as invalid
244 self.assertTrue(sql_no_api.is_valid(sql_no_api.normalise(self.invalid_orcid_5, include_prefix=True))) # is not stored in support file as invalid, does not exist but has correct syntax
245 sql_no_api.storage_manager.delete_storage()
247 def test_orcid_redis_nofile_noapi(self):
248 # No data in redis db
249 # Uses RedisStorageManager
250 # Does not API (so a syntactically correct id which is not valid is considered to be valid)
251 am_nofile_noapi = ORCIDManager(testing=True, use_api_service=False)
252 self.assertTrue(am_nofile_noapi.is_valid(self.valid_orcid_1))
253 self.assertTrue(am_nofile_noapi.is_valid(self.invalid_orcid_5))
254 am_nofile_noapi.storage_manager.delete_storage()