예제 #1
0
 def test_cli_quiet(self):
     """Test copying of a password without echoing the entry's text."""
     # Generate a password and some additional text for a dummy password store entry.
     a_password = random_string()
     additional_text = random_string()
     raw_entry = a_password + "\n\n" + additional_text
     # Prepare a mock method to test that the password is copied,
     # but without actually invoking the `pass' program.
     copy_password_method = MagicMock()
     # Some voodoo to mock methods in classes that
     # have yet to be instantiated follows :-).
     mocked_class = type("TestPasswordEntry", (PasswordEntry, ),
                         dict(text=raw_entry))
     setattr(mocked_class, "copy_password", copy_password_method)
     with PatchedAttribute(qpass, "PasswordEntry", mocked_class):
         with PatchedAttribute(cli, "is_clipboard_supported", lambda: True):
             with TemporaryDirectory() as directory:
                 touch(os.path.join(directory, "foo.gpg"))
                 returncode, output = run_cli(
                     main, "--password-store=%s" % directory, "--quiet",
                     "foo")
                 # Make sure the command succeeded.
                 assert returncode == 0
                 # Make sure the password was copied to the clipboard.
                 assert copy_password_method.called
                 # Make sure no output was generated.
                 assert not output.strip()
예제 #2
0
 def test_dynamic_stderr_lookup(self):
     """Make sure coloredlogs.install() uses StandardErrorHandler when possible."""
     coloredlogs.install()
     # Redirect sys.stderr to a temporary buffer.
     initial_stream = StringIO()
     initial_text = "Which stream will receive this text?"
     with PatchedAttribute(sys, 'stderr', initial_stream):
         logging.info(initial_text)
     assert initial_text in initial_stream.getvalue()
     # Redirect sys.stderr again, to a different destination.
     subsequent_stream = StringIO()
     subsequent_text = "And which stream will receive this other text?"
     with PatchedAttribute(sys, 'stderr', subsequent_stream):
         logging.info(subsequent_text)
     assert subsequent_text in subsequent_stream.getvalue()
예제 #3
0
    def test_show_entry(self):
        """Test showing of an entry on the terminal."""
        password = random_string()
        # Some voodoo to mock methods in classes that
        # have yet to be instantiated follows :-).
        mocked_class = type(
            'TestPasswordEntry',
            (PasswordEntry, ),
            dict(text=password),
        )
        with PatchedAttribute(qpass, 'PasswordEntry', mocked_class):
            with TemporaryDirectory() as directory:
                name = 'some/random/password'
                touch(os.path.join(directory, '%s.gpg' % name))
                returncode, output = run_cli(
                    main,
                    '--password-store=%s' % directory,
                    '--no-clipboard',
                    name,
                )
                assert returncode == 0
                assert dedent(output) == dedent(
                    """
                    {title}

                    Password: {password}
                    """,
                    title=name.replace('/', ' / '),
                    password=password,
                )
예제 #4
0
 def test_version_comparison(self):
     """Test the comparison of version objects (under both implementations)."""
     self.version_comparison_helper()
     if version.have_python_apt:
         with PatchedAttribute(version, 'have_python_apt', False):
             self.version_comparison_helper()
             self.assertRaises(NotImplementedError, version.compare_versions_with_python_apt, '0.1', '<<', '0.2')
예제 #5
0
 def test_prompt_for_input(self):
     """Test :func:`humanfriendly.prompts.prompt_for_input()`."""
     with open(os.devnull) as handle:
         with PatchedAttribute(sys, 'stdin', handle):
             # If standard input isn't connected to a terminal the default value should be returned.
             default_value = "To seek the holy grail!"
             assert prompt_for_input("What is your quest?", default=default_value) == default_value
             # If standard input isn't connected to a terminal and no default value
             # is given the EOFError exception should be propagated to the caller.
             self.assertRaises(EOFError, prompt_for_input, "What is your favorite color?")
예제 #6
0
 def test_patch_attribute(self):
     """Test :class:`humanfriendly.testing.PatchedAttribute`."""
     class Subject(object):
         my_attribute = 42
     instance = Subject()
     assert instance.my_attribute == 42
     with PatchedAttribute(instance, 'my_attribute', 13) as return_value:
         assert return_value is instance
         assert instance.my_attribute == 13
     assert instance.my_attribute == 42
예제 #7
0
 def test_prompt_for_confirmation(self):
     """Test :func:`humanfriendly.prompts.prompt_for_confirmation()`."""
     # Test some (more or less) reasonable replies that indicate agreement.
     for reply in 'yes', 'Yes', 'YES', 'y', 'Y':
         with PatchedAttribute(prompts, 'interactive_prompt', lambda p: reply):
             assert prompt_for_confirmation("Are you sure?") is True
     # Test some (more or less) reasonable replies that indicate disagreement.
     for reply in 'no', 'No', 'NO', 'n', 'N':
         with PatchedAttribute(prompts, 'interactive_prompt', lambda p: reply):
             assert prompt_for_confirmation("Are you sure?") is False
     # Test that empty replies select the default choice.
     for default_choice in True, False:
         with PatchedAttribute(prompts, 'interactive_prompt', lambda p: ''):
             assert prompt_for_confirmation("Are you sure?", default=default_choice) is default_choice
     # Test that a warning is shown when no input nor a default is given.
     replies = ['', 'y']
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: replies.pop(0)):
         with CaptureOutput() as capturer:
             assert prompt_for_confirmation("Are you sure?") is True
             assert "there's no default choice" in capturer.get_text()
     # Test that the default reply is shown in uppercase.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: 'y'):
         for default_value, expected_text in (True, 'Y/n'), (False, 'y/N'), (None, 'y/n'):
             with CaptureOutput() as capturer:
                 assert prompt_for_confirmation("Are you sure?", default=default_value) is True
                 assert expected_text in capturer.get_text()
     # Test that interactive prompts eventually give up on invalid replies.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: ''):
         self.assertRaises(TooManyInvalidReplies, prompt_for_confirmation, "Are you sure?")
예제 #8
0
 def test_clipboard_enabled(self):
     """Test the detection whether the clipboard should be used."""
     # Make sure the clipboard is enabled by default on macOS.
     if platform.system().lower() == 'darwin':
         assert is_clipboard_supported() is True
     else:
         # Make sure the clipboard is used when $DISPLAY is set.
         with PatchedItem(os.environ, 'DISPLAY', ':0'):
             assert is_clipboard_supported() is True
         # Make sure the clipboard is not used when $DISPLAY isn't set.
         environment = os.environ.copy()
         environment.pop('DISPLAY', None)
         with PatchedAttribute(os, 'environ', environment):
             assert is_clipboard_supported() is False
예제 #9
0
 def test_prompt_for_choice(self):
     """Test :func:`humanfriendly.prompts.prompt_for_choice()`."""
     # Choice selection without any options should raise an exception.
     self.assertRaises(ValueError, prompt_for_choice, [])
     # If there's only one option no prompt should be rendered so we expect
     # the following code to not raise an EOFError exception (despite
     # connecting standard input to /dev/null).
     with open(os.devnull) as handle:
         with PatchedAttribute(sys, 'stdin', handle):
             only_option = 'only one option (shortcut)'
             assert prompt_for_choice([only_option]) == only_option
     # Choice selection by full string match.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: 'foo'):
         assert prompt_for_choice(['foo', 'bar']) == 'foo'
     # Choice selection by substring input.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: 'f'):
         assert prompt_for_choice(['foo', 'bar']) == 'foo'
     # Choice selection by number.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: '2'):
         assert prompt_for_choice(['foo', 'bar']) == 'bar'
     # Choice selection by going with the default.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: ''):
         assert prompt_for_choice(['foo', 'bar'], default='bar') == 'bar'
     # Invalid substrings are refused.
     replies = ['', 'q', 'z']
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: replies.pop(0)):
         assert prompt_for_choice(['foo', 'bar', 'baz']) == 'baz'
     # Choice selection by substring input requires an unambiguous substring match.
     replies = ['a', 'q']
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: replies.pop(0)):
         assert prompt_for_choice(['foo', 'bar', 'baz', 'qux']) == 'qux'
     # Invalid numbers are refused.
     replies = ['42', '2']
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: replies.pop(0)):
         assert prompt_for_choice(['foo', 'bar', 'baz']) == 'bar'
     # Test that interactive prompts eventually give up on invalid replies.
     with PatchedAttribute(prompts, 'interactive_prompt', lambda p: ''):
         self.assertRaises(TooManyInvalidReplies, prompt_for_choice, ['a', 'b', 'c'])
예제 #10
0
 def test_cli_filter(self):
     """Test filtering of entry text."""
     # Generate a password and some additional text for a dummy password store entry.
     a_password = random_string()
     additional_text = random_string()
     sensitive_detail = "password: %s" % random_string()
     raw_entry = a_password + "\n\n" + additional_text + "\n" + sensitive_detail
     # Some voodoo to mock methods in classes that
     # have yet to be instantiated follows :-).
     mocked_class = type("TestPasswordEntry", (PasswordEntry, ),
                         dict(copy_password=MagicMock(), text=raw_entry))
     with PatchedAttribute(qpass, "PasswordEntry", mocked_class):
         with TemporaryDirectory() as directory:
             touch(os.path.join(directory, "foo.gpg"))
             returncode, output = run_cli(main,
                                          "--password-store=%s" % directory,
                                          "--filter=^password:"******"foo")
             # Make sure the command succeeded.
             assert returncode == 0
             # Make sure the expected output was generated.
             assert additional_text in output
             assert sensitive_detail not in output
예제 #11
0
 def test_repository_activation(self):
     """Test the activation of trivial repositories."""
     if SKIP_SLOW_TESTS:
         return self.skipTest("skipping slow tests")
     elif os.getuid() != 0:
         return self.skipTest("need superuser privileges")
     repository = self.test_repository_creation(preserve=True)
     returncode, output = run_cli(main, '--activate-repo=%s' % repository)
     assert returncode == 0
     try:
         handle = os.popen('apt-cache show %s' % TEST_PACKAGE_NAME)
         fields = Deb822(handle)
         assert fields['Package'] == TEST_PACKAGE_NAME
     finally:
         returncode, output = run_cli(main, '--deactivate-repo=%s' % repository)
         assert returncode == 0
     # XXX If we skipped the GPG key handling because apt supports the
     # [trusted=yes] option, re-run the test *including* GPG key
     # handling (we want this to be tested...).
     from deb_pkg_tools import repo
     if repo.apt_supports_trusted_option():
         with PatchedAttribute(repo, 'trusted_option_supported', False):
             self.test_repository_activation()
예제 #12
0
    def test_custom_record_factory(self):
        """
        Test that custom LogRecord factories are supported.

        This test is a bit convoluted because the logging module suppresses
        exceptions. We monkey patch the method suspected of encountering
        exceptions so that we can tell after it was called whether any
        exceptions occurred (despite the exceptions not propagating).
        """
        if not hasattr(logging, 'getLogRecordFactory'):
            return self.skipTest("this test requires Python >= 3.2")

        exceptions = []
        original_method = ColoredFormatter.format
        original_factory = logging.getLogRecordFactory()

        def custom_factory(*args, **kwargs):
            record = original_factory(*args, **kwargs)
            record.custom_attribute = 0xdecafbad
            return record

        def custom_method(*args, **kw):
            try:
                return original_method(*args, **kw)
            except Exception as e:
                exceptions.append(e)
                raise

        with PatchedAttribute(ColoredFormatter, 'format', custom_method):
            logging.setLogRecordFactory(custom_factory)
            try:
                demonstrate_colored_logging()
            finally:
                logging.setLogRecordFactory(original_factory)

        # Ensure that no exceptions were triggered.
        assert not exceptions