Coverage for tests/admin/test_adm_sgx.py: 100%
102 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
1# The MIT License (MIT)
2#
3# Copyright (c) 2021 RSK Labs Ltd
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy of
6# this software and associated documentation files (the "Software"), to deal in
7# the Software without restriction, including without limitation the rights to
8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9# of the Software, and to permit persons to whom the Software is furnished to do
10# so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
23import sys
24from argparse import Namespace
25from unittest import TestCase
26from unittest.mock import call, patch
27from adm_sgx import main
28import logging
30logging.disable(logging.CRITICAL)
33class TestAdmSgx(TestCase):
34 def setUp(self):
35 self.old_stdout = sys.stdout
36 self.DEFAULT_OPTIONS = {
37 "sgx_host": "localhost",
38 "sgx_port": 7777,
39 "any_pin": False,
40 "new_pin": None,
41 "no_unlock": False,
42 "attestation_ud_source": "https://public-node.rsk.co",
43 "attestation_certificate_file_path": None,
44 "root_authority": None,
45 "pubkeys_file_path": None,
46 "operation": None,
47 "output_file_path": None,
48 "pin": None,
49 "destination_sgx_port": 3333,
50 "destination_sgx_host": "localhost",
51 "migration_authorization_file_path": None,
52 "verbose": False,
53 }
55 def tearDown(self):
56 sys.stdout = self.old_stdout
58 @patch("adm_sgx.do_unlock")
59 def test_unlock(self, do_unlock):
60 expected_options = {
61 **self.DEFAULT_OPTIONS,
62 'operation': 'unlock',
63 'pin': 'a-pin',
64 }
65 expected_call_args_list = [
66 call(Namespace(**expected_options)),
67 call(Namespace(**expected_options))
68 ]
70 with patch('sys.argv', ['adm_sgx.py', '-P', 'a-pin', 'unlock']):
71 with self.assertRaises(SystemExit) as e:
72 main()
73 self.assertEqual(e.exception.code, 0)
75 with patch('sys.argv', ['adm_sgx.py', '--pin', 'a-pin', 'unlock']):
76 with self.assertRaises(SystemExit) as e:
77 main()
78 self.assertEqual(e.exception.code, 0)
80 self.assertTrue(do_unlock.called)
81 self.assertEqual(do_unlock.call_count, 2)
82 self.assertEqual(expected_call_args_list, do_unlock.call_args_list)
84 @patch("adm_sgx.do_onboard")
85 def test_onboard(self, do_onboard):
86 expected_options = {
87 **self.DEFAULT_OPTIONS,
88 'operation': 'onboard',
89 'pin': 'a-pin',
90 }
92 expected_call_args_list = [
93 call(Namespace(**expected_options)),
94 call(Namespace(**expected_options))
95 ]
97 with patch('sys.argv',
98 ['adm_sgx.py', '-P', 'a-pin', 'onboard']):
99 with self.assertRaises(SystemExit) as e:
100 main()
101 self.assertEqual(e.exception.code, 0)
103 with patch('sys.argv',
104 ['adm_sgx.py', '--pin', 'a-pin', 'onboard']):
105 with self.assertRaises(SystemExit) as e:
106 main()
107 self.assertEqual(e.exception.code, 0)
109 self.assertTrue(do_onboard.called)
110 self.assertEqual(expected_call_args_list, do_onboard.call_args_list)
112 @patch("adm_sgx.do_get_pubkeys")
113 def test_pubkeys(self, do_get_pubkeys):
114 expected_options = {
115 **self.DEFAULT_OPTIONS,
116 'no_unlock': True,
117 'operation': 'pubkeys',
118 'output_file_path': 'a-path',
119 'pin': 'a-pin',
120 'sgx_host': '1.2.3.4',
121 }
123 expected_call_args_list = [
124 call(Namespace(**expected_options)),
125 call(Namespace(**expected_options))
126 ]
128 with patch('sys.argv', ['adm_sgx.py', '-P', 'a-pin', '-o', 'a-path', '-u',
129 '-s', '1.2.3.4', 'pubkeys']):
130 with self.assertRaises(SystemExit) as e:
131 main()
132 self.assertEqual(e.exception.code, 0)
134 with patch('sys.argv',
135 ['adm_sgx.py',
136 '--host', '1.2.3.4',
137 '--pin', 'a-pin',
138 '--output', 'a-path',
139 '--nounlock',
140 'pubkeys']):
141 with self.assertRaises(SystemExit) as e:
142 main()
143 self.assertEqual(e.exception.code, 0)
145 self.assertTrue(do_get_pubkeys.called)
146 self.assertEqual(expected_call_args_list, do_get_pubkeys.call_args_list)
148 @patch("adm_sgx.do_changepin")
149 def test_changepin(self, do_changepin):
150 expected_options = {
151 **self.DEFAULT_OPTIONS,
152 'any_pin': True,
153 'new_pin': 'new-pin',
154 'operation': 'changepin',
155 'pin': 'old-pin',
156 'sgx_port': 4567,
157 }
158 expected_call_args_list = [
159 call(Namespace(**expected_options)),
160 call(Namespace(**expected_options))
161 ]
163 with patch('sys.argv', ['adm_sgx.py', '-P', 'old-pin', '-n', 'new-pin',
164 '-p', '4567', '-a', 'changepin']):
165 with self.assertRaises(SystemExit) as e:
166 main()
167 self.assertEqual(e.exception.code, 0)
169 with patch('sys.argv', ['adm_sgx.py',
170 '--newpin', 'new-pin', '--anypin', 'changepin',
171 '--port', '4567', '--pin', 'old-pin']):
172 with self.assertRaises(SystemExit) as e:
173 main()
174 self.assertEqual(e.exception.code, 0)
176 self.assertTrue(do_changepin.called)
177 self.assertEqual(do_changepin.call_count, 2)
178 self.assertEqual(expected_call_args_list, do_changepin.call_args_list)
180 @patch("adm_sgx.do_attestation")
181 def test_attestation(self, do_attestation):
182 expected_options = {
183 **self.DEFAULT_OPTIONS,
184 'attestation_ud_source': 'user-defined-source',
185 'operation': 'attestation',
186 'output_file_path': 'out-path',
187 'pin': 'a-pin',
188 }
189 expected_call_args_list = [
190 call(Namespace(**expected_options)),
191 call(Namespace(**{**expected_options, "no_unlock": True}))
192 ]
194 with patch('sys.argv', ['adm_sgx.py',
195 '-P', 'a-pin',
196 '-o', 'out-path',
197 '--attudsource', 'user-defined-source',
198 'attestation']):
199 with self.assertRaises(SystemExit) as e:
200 main()
201 self.assertEqual(e.exception.code, 0)
203 with patch('sys.argv', ['adm_sgx.py',
204 '--pin', 'a-pin',
205 '--output', 'out-path',
206 '--attudsource', 'user-defined-source',
207 '--nounlock',
208 'attestation']):
209 with self.assertRaises(SystemExit) as e:
210 main()
211 self.assertEqual(e.exception.code, 0)
213 self.assertTrue(do_attestation.called)
214 self.assertEqual(do_attestation.call_count, 2)
215 self.assertEqual(expected_call_args_list, do_attestation.call_args_list)
217 @patch("adm_sgx.do_migrate_db")
218 def test_migrate_db(self, do_migrate_db):
219 expected_options = {
220 **self.DEFAULT_OPTIONS,
221 "operation": "migrate_db",
222 "migration_authorization_file_path": "a-file-path",
223 }
224 expected_call_args_list = [
225 call(Namespace(**expected_options)),
226 call(Namespace(**{
227 **expected_options,
228 "destination_sgx_port": 4444,
229 "destination_sgx_host": "another.host.com"}))
230 ]
232 with patch("sys.argv", ["adm_sgx.py",
233 "migrate_db",
234 "--migauth", "a-file-path"]):
235 with self.assertRaises(SystemExit) as e:
236 main()
237 self.assertEqual(e.exception.code, 0)
239 with patch("sys.argv", ["adm_sgx.py",
240 "migrate_db",
241 "-z", "a-file-path",
242 "--dest-port", "4444",
243 "--dest-host", "another.host.com"]):
244 with self.assertRaises(SystemExit) as e:
245 main()
246 self.assertEqual(e.exception.code, 0)
248 self.assertTrue(do_migrate_db.called)
249 self.assertEqual(do_migrate_db.call_count, 2)
250 for i, call_args in enumerate(expected_call_args_list):
251 self.assertEqual(call_args, do_migrate_db.call_args_list[i], f"Call #{i}")