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

59 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-05 20:41 +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 

23from types import SimpleNamespace 

24from unittest import TestCase 

25from unittest.mock import Mock, call, patch 

26from admin.misc import AdminError 

27from admin.unlock import do_unlock 

28from ledger.hsm2dongle import HSM2Dongle 

29from parameterized import parameterized 

30 

31import logging 

32 

33logging.disable(logging.CRITICAL) 

34 

35 

36@patch("sys.stdout.write") 

37@patch("admin.unlock.get_hsm") 

38class TestUnlock(TestCase): 

39 def setUp(self): 

40 self.valid_pin = '1234ABCD' 

41 self.invalid_pin = '123456789' 

42 

43 options = { 

44 'pin': self.valid_pin, 

45 'any_pin': False, 

46 'no_exec': None, 

47 'verbose': False 

48 } 

49 self.default_options = SimpleNamespace(**options) 

50 self.dongle = Mock() 

51 

52 @patch("admin.unlock.info") 

53 def test_unlock(self, info_mock, get_hsm, _): 

54 get_hsm.return_value = self.dongle 

55 self.dongle.get_current_mode = Mock(return_value=HSM2Dongle.MODE.BOOTLOADER) 

56 self.dongle.is_onboarded = Mock(return_value=True) 

57 

58 do_unlock(self.default_options) 

59 self.assertEqual(call('PIN accepted'), info_mock.call_args_list[7]) 

60 

61 def test_unlock_invalid_pin(self, get_hsm, _): 

62 get_hsm.return_value = self.dongle 

63 self.dongle.get_current_mode = Mock(return_value=HSM2Dongle.MODE.BOOTLOADER) 

64 self.dongle.is_onboarded = Mock(return_value=True) 

65 

66 options = self.default_options 

67 options.pin = self.invalid_pin 

68 with self.assertRaises(AdminError) as e: 

69 do_unlock(options) 

70 self.assertTrue(str(e.exception).startswith('Invalid pin given.')) 

71 

72 def test_unlock_not_onboarded(self, get_hsm, _): 

73 get_hsm.return_value = self.dongle 

74 self.dongle.get_current_mode = Mock(return_value=HSM2Dongle.MODE.BOOTLOADER) 

75 self.dongle.is_onboarded = Mock(return_value=False) 

76 

77 with self.assertRaises(AdminError) as e: 

78 do_unlock(self.default_options) 

79 self.assertEqual('Device not onboarded', str(e.exception)) 

80 

81 @parameterized.expand([ 

82 (HSM2Dongle.MODE.SIGNER, ), 

83 (HSM2Dongle.MODE.UI_HEARTBEAT, ), 

84 ]) 

85 def test_unlock_invalid_mode(self, get_hsm, _, mode): 

86 get_hsm.return_value = self.dongle 

87 self.dongle.get_current_mode = Mock(return_value=mode) 

88 self.dongle.is_onboarded = Mock(return_value=True) 

89 

90 with self.assertRaises(AdminError) as e: 

91 do_unlock(self.default_options) 

92 self.assertEqual('Device already unlocked', str(e.exception)) 

93 

94 self.dongle.get_current_mode = Mock(return_value=HSM2Dongle.MODE.UNKNOWN) 

95 with self.assertRaises(AdminError) as e: 

96 do_unlock(self.default_options) 

97 

98 self.assertTrue(str(e.exception).startswith('Device mode unknown.')) 

99 

100 def test_unlock_wrong_pin(self, get_hsm, _): 

101 get_hsm.return_value = self.dongle 

102 self.dongle.get_current_mode = Mock(return_value=HSM2Dongle.MODE.BOOTLOADER) 

103 self.dongle.is_onboarded = Mock(return_value=True) 

104 self.dongle.unlock = Mock(return_value=False) 

105 

106 with self.assertRaises(AdminError) as e: 

107 do_unlock(self.default_options) 

108 self.assertEqual('Unable to unlock: PIN mismatch', str(e.exception))