Coverage for tests/admin/test_adm_ledger.py: 100%

118 statements  

« 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. 

22 

23import sys 

24from argparse import Namespace 

25from unittest import TestCase 

26from unittest.mock import call, patch 

27from adm_ledger import main, DEFAULT_ATT_UD_SOURCE 

28import logging 

29 

30logging.disable(logging.CRITICAL) 

31 

32 

33class TestAdmLedger(TestCase): 

34 def setUp(self): 

35 self.old_stderr = sys.stderr 

36 # sys.stderr = Mock() 

37 self.old_stdout = sys.stdout 

38 # sys.stdout = Mock() 

39 self.DEFAULT_OPTIONS = { 

40 "any_pin": False, 

41 "attestation_certificate_file_path": None, 

42 "attestation_ud_source": DEFAULT_ATT_UD_SOURCE, 

43 "new_pin": None, 

44 "no_exec": False, 

45 "no_unlock": False, 

46 "operation": None, 

47 "output_file_path": None, 

48 "pin": None, 

49 "pubkeys_file_path": None, 

50 "root_authority": None, 

51 "signer_authorization_file_path": None, 

52 "verbose": False, 

53 } 

54 

55 def tearDown(self): 

56 sys.stderr = self.old_stderr 

57 sys.stdout = self.old_stdout 

58 

59 @patch("adm_ledger.do_unlock") 

60 def test_unlock(self, do_unlock): 

61 expected_options = { 

62 **self.DEFAULT_OPTIONS, 

63 'operation': 'unlock', 

64 'pin': 'a-pin', 

65 } 

66 expected_call_args_list = [ 

67 call(Namespace(**expected_options)), 

68 call(Namespace(**expected_options)) 

69 ] 

70 

71 with patch('sys.argv', ['adm_ledger.py', '-p', 'a-pin', 'unlock']): 

72 with self.assertRaises(SystemExit) as e: 

73 main() 

74 self.assertEqual(e.exception.code, 0) 

75 

76 with patch('sys.argv', ['adm_ledger.py', '--pin', 'a-pin', 'unlock']): 

77 with self.assertRaises(SystemExit) as e: 

78 main() 

79 self.assertEqual(e.exception.code, 0) 

80 

81 self.assertTrue(do_unlock.called) 

82 self.assertEqual(do_unlock.call_count, 2) 

83 self.assertEqual(expected_call_args_list, do_unlock.call_args_list) 

84 

85 @patch("adm_ledger.do_onboard") 

86 def test_onboard(self, do_onboard): 

87 expected_options = { 

88 **self.DEFAULT_OPTIONS, 

89 'operation': 'onboard', 

90 'output_file_path': 'a-path', 

91 'pin': 'a-pin', 

92 } 

93 

94 expected_call_args_list = [ 

95 call(Namespace(**expected_options)), 

96 call(Namespace(**expected_options)) 

97 ] 

98 

99 with patch('sys.argv', 

100 ['adm_ledger.py', '-p', 'a-pin', '-o', 'a-path', 'onboard']): 

101 with self.assertRaises(SystemExit) as e: 

102 main() 

103 self.assertEqual(e.exception.code, 0) 

104 

105 with patch('sys.argv', 

106 ['adm_ledger.py', '--pin', 'a-pin', '--output', 'a-path', 'onboard']): 

107 with self.assertRaises(SystemExit) as e: 

108 main() 

109 self.assertEqual(e.exception.code, 0) 

110 

111 self.assertTrue(do_onboard.called) 

112 self.assertEqual(expected_call_args_list, do_onboard.call_args_list) 

113 

114 @patch("adm_ledger.do_get_pubkeys") 

115 def test_pubkeys(self, do_get_pubkeys): 

116 expected_options = { 

117 **self.DEFAULT_OPTIONS, 

118 'no_unlock': True, 

119 'operation': 'pubkeys', 

120 'output_file_path': 'a-path', 

121 'pin': 'a-pin', 

122 } 

123 

124 expected_call_args_list = [ 

125 call(Namespace(**expected_options)), 

126 call(Namespace(**expected_options)) 

127 ] 

128 

129 with patch('sys.argv', ['adm_ledger.py', '-p', 'a-pin', '-o', 'a-path', '-u', 

130 'pubkeys']): 

131 with self.assertRaises(SystemExit) as e: 

132 main() 

133 self.assertEqual(e.exception.code, 0) 

134 

135 with patch('sys.argv', 

136 ['adm_ledger.py', 

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) 

144 

145 self.assertTrue(do_get_pubkeys.called) 

146 self.assertEqual(expected_call_args_list, do_get_pubkeys.call_args_list) 

147 

148 @patch("adm_ledger.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 } 

157 expected_call_args_list = [ 

158 call(Namespace(**expected_options)), 

159 call(Namespace(**expected_options)) 

160 ] 

161 

162 with patch('sys.argv', ['adm_ledger.py', '-p', 'old-pin', '-n', 'new-pin', 

163 '-a', 'changepin']): 

164 with self.assertRaises(SystemExit) as e: 

165 main() 

166 self.assertEqual(e.exception.code, 0) 

167 

168 with patch('sys.argv', ['adm_ledger.py', 

169 '--newpin', 'new-pin', '--anypin', 'changepin', 

170 '--pin', 'old-pin']): 

171 with self.assertRaises(SystemExit) as e: 

172 main() 

173 self.assertEqual(e.exception.code, 0) 

174 

175 self.assertTrue(do_changepin.called) 

176 self.assertEqual(do_changepin.call_count, 2) 

177 self.assertEqual(expected_call_args_list, do_changepin.call_args_list) 

178 

179 @patch("adm_ledger.do_attestation") 

180 def test_attestation(self, do_attestation): 

181 expected_options = { 

182 **self.DEFAULT_OPTIONS, 

183 'attestation_certificate_file_path': 'certification-path', 

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)) 

192 ] 

193 

194 with patch('sys.argv', ['adm_ledger.py', 

195 '-p', 'a-pin', 

196 '-o', 'out-path', 

197 '-t', 'certification-path', 

198 '--attudsource', 'user-defined-source', 

199 'attestation']): 

200 with self.assertRaises(SystemExit) as e: 

201 main() 

202 self.assertEqual(e.exception.code, 0) 

203 

204 with patch('sys.argv', ['adm_ledger.py', 

205 '--pin', 'a-pin', 

206 '--output', 'out-path', 

207 '--attcert', 'certification-path', 

208 '--attudsource', 'user-defined-source', 

209 'attestation']): 

210 with self.assertRaises(SystemExit) as e: 

211 main() 

212 self.assertEqual(e.exception.code, 0) 

213 

214 self.assertTrue(do_attestation.called) 

215 self.assertEqual(do_attestation.call_count, 2) 

216 self.assertEqual(expected_call_args_list, do_attestation.call_args_list) 

217 

218 @patch("adm_ledger.do_verify_attestation") 

219 def test_verify_attestation(self, do_verify_attestation): 

220 expected_options = { 

221 **self.DEFAULT_OPTIONS, 

222 'attestation_certificate_file_path': 'certification-path', 

223 'operation': 'verify_attestation', 

224 'pin': 'a-pin', 

225 'pubkeys_file_path': 'pubkeys-path', 

226 'root_authority': 'root-authority', 

227 } 

228 expected_call_args_list = [ 

229 call(Namespace(**expected_options)), 

230 call(Namespace(**expected_options)) 

231 ] 

232 

233 with patch('sys.argv', ['adm_ledger.py', 

234 '-p', 'a-pin', 

235 '-t', 'certification-path', 

236 '-r', 'root-authority', 

237 '-b', 'pubkeys-path', 

238 'verify_attestation']): 

239 with self.assertRaises(SystemExit) as e: 

240 main() 

241 self.assertEqual(e.exception.code, 0) 

242 

243 with patch('sys.argv', ['adm_ledger.py', 

244 '--pin', 'a-pin', 

245 '--attcert', 'certification-path', 

246 '--root', 'root-authority', 

247 '--pubkeys', 'pubkeys-path', 

248 'verify_attestation']): 

249 with self.assertRaises(SystemExit) as e: 

250 main() 

251 self.assertEqual(e.exception.code, 0) 

252 

253 self.assertTrue(do_verify_attestation.called) 

254 self.assertEqual(do_verify_attestation.call_count, 2) 

255 self.assertEqual(expected_call_args_list, do_verify_attestation.call_args_list) 

256 

257 @patch("adm_ledger.do_authorize_signer") 

258 def test_authorize_signer(self, do_authorize_signer): 

259 expected_options = { 

260 **self.DEFAULT_OPTIONS, 

261 'operation': 'authorize_signer', 

262 'pin': 'a-pin', 

263 'signer_authorization_file_path': 'a-file-path', 

264 } 

265 expected_call_args_list = [ 

266 call(Namespace(**expected_options)), 

267 call(Namespace(**expected_options)) 

268 ] 

269 

270 with patch('sys.argv', ['adm_ledger.py', 

271 '-p', 'a-pin', 

272 '-z', 'a-file-path', 

273 'authorize_signer']): 

274 with self.assertRaises(SystemExit) as e: 

275 main() 

276 self.assertEqual(e.exception.code, 0) 

277 

278 with patch('sys.argv', ['adm_ledger.py', 

279 '--pin', 'a-pin', 

280 '--signauth', 'a-file-path', 

281 'authorize_signer']): 

282 with self.assertRaises(SystemExit) as e: 

283 main() 

284 self.assertEqual(e.exception.code, 0) 

285 

286 self.assertTrue(do_authorize_signer.called) 

287 self.assertEqual(do_authorize_signer.call_count, 2) 

288 self.assertEqual(expected_call_args_list, do_authorize_signer.call_args_list)