blob: 71a877e5c57f403792d9b8eaafdf5fd22ac39457 [file] [log] [blame]
R David Murrayc137f7c2013-04-08 08:48:03 -04001import getpass
2import os
3import termios
4import unittest
5from io import StringIO
6from unittest import mock
7from test import support
8
9@mock.patch('os.environ')
10class GetpassGetuserTest(unittest.TestCase):
11
12 def test_username_takes_username_from_env(self, environ):
13 expected_name = 'some_name'
14 environ.get.return_value = expected_name
15 self.assertEqual(expected_name, getpass.getuser())
16
17 def test_username_priorities_of_env_values(self, environ):
18 environ.get.return_value = None
19 getpass.getuser()
20 self.assertEqual(
21 environ.get.call_args_list,
22 [mock.call(x) for x in ('LOGNAME', 'USER', 'LNAME', 'USERNAME')])
23
24 def test_username_falls_back_to_pwd(self, environ):
25 expected_name = 'some_name'
26 environ.get.return_value = None
27 with mock.patch('os.getuid') as uid, \
28 mock.patch('pwd.getpwuid') as getpw:
29 uid.return_value = 42
30 getpw.return_value = [expected_name]
31 self.assertEqual(expected_name,
32 getpass.getuser())
33 getpw.assert_called_once_with(42)
34
35
36class GetpassRawinputTest(unittest.TestCase):
37
38 def test_flushes_stream_after_prompt(self):
39 # see issue 1703
40 stream = mock.Mock(spec=StringIO)
41 input = StringIO('input_string')
42 getpass._raw_input('some_prompt', stream, input=input)
43 stream.flush.assert_called_once_with()
44
45 def test_uses_stderr_as_default(self):
46 input = StringIO('input_string')
47 prompt = 'some_prompt'
48 with mock.patch('sys.stderr') as stderr:
49 getpass._raw_input(prompt, input=input)
50 stderr.write.assert_called_once_with(prompt)
51
52 @mock.patch('sys.stdin')
53 def test_uses_stdin_as_default_input(self, mock_input):
54 mock_input.readline.return_value = 'input_string'
55 getpass._raw_input(stream=StringIO())
56 mock_input.readline.assert_called_once_with()
57
58 def test_raises_on_empty_input(self):
59 input = StringIO('')
60 self.assertRaises(EOFError, getpass._raw_input, input=input)
61
62 def test_trims_trailing_newline(self):
63 input = StringIO('test\n')
64 self.assertEqual('test', getpass._raw_input(input=input))
65
66
67# Some of these tests are a bit white-box. The functional requirement is that
68# the password input be taken directly from the tty, and that it not be echoed
69# on the screen, unless we are falling back to stderr/stdin.
70
71# Some of these might run on other platforms, but play it safe.
72@unittest.skipUnless(os.name == 'posix',
73 'tests are for the unix version of getpass')
74class UnixGetpassTest(unittest.TestCase):
75
76 def test_uses_tty_directly(self):
77 with mock.patch('os.open') as open, \
78 mock.patch('os.fdopen'):
79 # By setting open's return value to None the implementation will
80 # skip code we don't care about in this test. We can mock this out
81 # fully if an alternate implementation works differently.
82 open.return_value = None
83 getpass.unix_getpass()
84 open.assert_called_once_with('/dev/tty',
85 os.O_RDWR | os.O_NOCTTY)
86
87 def test_resets_termios(self):
88 with mock.patch('os.open') as open, \
89 mock.patch('os.fdopen'), \
90 mock.patch('termios.tcgetattr') as tcgetattr, \
91 mock.patch('termios.tcsetattr') as tcsetattr:
92 open.return_value = 3
93 fake_attrs = [255, 255, 255, 255, 255]
94 tcgetattr.return_value = list(fake_attrs)
95 getpass.unix_getpass()
96 tcsetattr.assert_called_with(3, mock.ANY, fake_attrs)
97
98 def test_falls_back_to_fallback_if_termios_raises(self):
99 with mock.patch('os.open') as open, \
100 mock.patch('os.fdopen') as fdopen, \
101 mock.patch('termios.tcgetattr'), \
102 mock.patch('termios.tcsetattr') as tcsetattr, \
103 mock.patch('getpass.fallback_getpass') as fallback:
104 open.return_value = 3
105 fdopen.return_value = StringIO()
106 tcsetattr.side_effect = termios.error
107 getpass.unix_getpass()
108 fallback.assert_called_once_with('Password: ',
109 fdopen.return_value)
110
111 def test_flushes_stream_after_input(self):
112 # issue 7208
113 with mock.patch('os.open') as open, \
114 mock.patch('os.fdopen'), \
115 mock.patch('termios.tcgetattr'), \
116 mock.patch('termios.tcsetattr'):
117 open.return_value = 3
118 mock_stream = mock.Mock(spec=StringIO)
119 getpass.unix_getpass(stream=mock_stream)
120 mock_stream.flush.assert_called_with()
121
122 def test_falls_back_to_stdin(self):
123 with mock.patch('os.open') as os_open, \
124 mock.patch('sys.stdin', spec=StringIO) as stdin:
125 os_open.side_effect = IOError
126 stdin.fileno.side_effect = AttributeError
127 with support.captured_stderr() as stderr:
128 with self.assertWarns(getpass.GetPassWarning):
129 getpass.unix_getpass()
130 stdin.readline.assert_called_once_with()
131 self.assertIn('Warning', stderr.getvalue())
132 self.assertIn('Password:', stderr.getvalue())
133
134
135if __name__ == "__main__":
136 unittest.main()