Пример #1
0
 def test_export(self):
     """Test exporting of revisions."""
     with TemporaryDirectory() as directory:
         # Change the current working directory to our temporary directory
         # so that we can give a relative pathname to export(). This is a
         # regression test for a bug that was fixed in vcs-repo-mgr 4.1.3.
         os.chdir(directory)
         # Initialize a repository object of the parametrized type.
         repository = self.get_instance(bare=False, local=os.path.join(directory, 'repo'))
         repository.create()
         # Commit a file to the repository.
         versioned_filename = random_string(10)
         versioned_contents = random_string(250)
         self.commit_file(
             repository=repository,
             filename=versioned_filename,
             contents=versioned_contents,
             message="Initial commit",
         )
         # Export the initial revision.
         export_directory_relative = 'export'
         export_directory_absolute = os.path.join(directory, export_directory_relative)
         returncode, output = run_cli(
             main, '--repository=%s' % repository.local,
             '--export=%s' % export_directory_relative,
         )
         self.assertEquals(returncode, 0)
         # Check that the file we committed was exported.
         exported_file = os.path.join(export_directory_absolute, versioned_filename)
         self.assertTrue(os.path.isfile(exported_file))
         with codecs.open(exported_file, 'r', 'UTF-8') as handle:
             self.assertEquals(handle.read(), versioned_contents)
         # Reset the working directory.
         os.chdir(tempfile.gettempdir())
Пример #2
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()
Пример #3
0
 def test_unmerged_capture(self):
     """Test that standard output and error can be captured separately."""
     expected_stdout = random_string()
     expected_stderr = random_string()
     with CaptureOutput(merged=False) as capturer:
         sys.stdout.write(expected_stdout + "\n")
         sys.stderr.write(expected_stderr + "\n")
         assert expected_stdout in capturer.stdout.get_lines()
         assert expected_stderr in capturer.stderr.get_lines()
Пример #4
0
 def test_combined_capture_same_process(self):
     """Test combined standard output and error capturing from the same process."""
     expected_stdout = random_string()
     expected_stderr = random_string()
     with CaptureOutput() as capturer:
         sys.stdout.write(expected_stdout + "\n")
         sys.stderr.write(expected_stderr + "\n")
         assert expected_stdout in capturer.get_lines()
         assert expected_stderr in capturer.get_lines()
Пример #5
0
 def commit_file(self, repository, filename=None, contents=None, message=None):
     """Commit a file to the given repository."""
     filename = filename or random_string(15)
     contents = contents or random_string(1024)
     exists = repository.context.exists(filename)
     repository.context.write_file(filename, contents)
     repository.add_files(filename)
     repository.commit(message=message or ("Committing %s file '%s'" % (
         "changed" if exists else "new", filename,
     )))
Пример #6
0
 def test_partial_read(self):
     """Test that partial reading works as expected."""
     # This test method uses retry logic because `partial=True' makes these
     # tests prone to race conditions (this is the whole reason why
     # `partial=False' by default :-).
     initial_part = random_string()
     later_part = random_string()
     with CaptureOutput() as capturer:
         sys.stderr.write("%s\n" % initial_part)
         retry(lambda: initial_part in capturer.get_lines(partial=True))
         sys.stderr.write("%s\n" % later_part)
         retry(lambda: later_part in capturer.get_lines(partial=True))
Пример #7
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,
                )
Пример #8
0
 def test_combined_capture_subprocess(self):
     """Test combined standard output and error capturing from subprocesses."""
     expected_stdout = random_string()
     expected_stderr = random_string()
     with CaptureOutput() as capturer:
         subprocess.call([
             sys.executable,
             '-c',
             ';'.join([
                 'import sys',
                 'sys.stdout.write(%r)' % (expected_stdout + '\n'),
                 'sys.stderr.write(%r)' % (expected_stderr + '\n'),
             ]),
         ])
         assert expected_stdout in capturer.get_lines()
         assert expected_stderr in capturer.get_lines()
Пример #9
0
 def test_tags(self):
     """Test that tags can be created and introspected."""
     with TemporaryDirectory() as directory:
         repository = self.get_instance(bare=False, local=directory)
         # Create an initial commit and give it a tag.
         self.create_initial_commit(repository)
         initial_tag = random_string(10)
         assert initial_tag not in repository.tags
         repository.create_tag(initial_tag)
         assert initial_tag in repository.tags
         # Create a follow up commit and give it a tag.
         self.create_followup_commit(repository)
         followup_tag = random_string(10)
         assert followup_tag not in repository.tags
         repository.create_tag(followup_tag)
         assert followup_tag in repository.tags
Пример #10
0
 def test_get_password(self):
     """Test getting a password from an entry."""
     random_password = random_string()
     entry = PasswordEntry(name='some/random/password', store=object())
     set_property(
         entry, 'text',
         '\n'.join([random_password, '', 'This is the description']))
     self.assertEquals(random_password, entry.password)
Пример #11
0
 def test_get_password(self):
     """Test getting a password from an entry."""
     random_password = random_string()
     entry = PasswordEntry(name="some/random/password", store=object())
     set_property(
         entry, "text",
         "\n".join([random_password, "", "This is the description"]))
     self.assertEquals(random_password, entry.password)
def generate_screenshots():
    """Generate screenshots from shell scripts."""
    this_script = os.path.abspath(__file__)
    this_directory = os.path.dirname(this_script)
    repository = os.path.join(this_directory, os.pardir)
    examples_directory = os.path.join(repository, 'docs', 'examples')
    images_directory = os.path.join(repository, 'docs', 'images')
    for shell_script in sorted(glob.glob(os.path.join(examples_directory, '*.sh'))):
        basename, extension = os.path.splitext(os.path.basename(shell_script))
        image_file = os.path.join(images_directory, '%s.png' % basename)
        logger.info("Generating %s by running %s ..",
                    format_path(image_file),
                    format_path(shell_script))
        command_line = [sys.executable, __file__, shell_script]
        random_title = random_string(25)
        # Generate the urxvt command line.
        urxvt_command = [
            'urxvt',
            # Enforce a default geometry.
            '-geometry', '98x30',
            # Set the text and background color.
            '-fg', TEXT_COLOR,
            '-bg', BACKGROUND_COLOR,
            # Set the font name and pixel size.
            '-fn', 'xft:%s:pixelsize=%i' % (FONT_NAME, FONT_SIZE),
            # Set the window title.
            '-title', random_title,
            # Hide scrollbars.
            '+sb',
        ]
        if which('qtile-run'):
            # I've been using tiling window managers for years now, at the
            # moment 'qtile' is my window manager of choice. It requires the
            # following special handling to enable the 'urxvt' window to float,
            # which in turn enables it to respect the '--geometry' option.
            urxvt_command.insert(0, 'qtile-run')
            urxvt_command.insert(1, '-f')
        # Apply the Ubuntu color scheme to urxvt.
        for index, css_color in enumerate(EIGHT_COLOR_PALETTE):
            urxvt_command.extend(('--color%i' % index, css_color))
        # Add the command that should run inside the terminal.
        urxvt_command.extend(('-e', 'sh', '-c', 'setterm -cursor off; %s' % quote(command_line)))
        # Launch urxvt.
        execute(*urxvt_command, asynchronous=True)
        # Make sure we close the urxvt window.
        try:
            # Wait for urxvt to start up. If I were to improve this I could
            # instead wait for the creation of a file by interpret_script().
            time.sleep(10)
            # Take a screen shot of the window using ImageMagick.
            execute('import', '-window', random_title, image_file)
            # Auto-trim the screen shot, then give it a 5px border.
            execute('convert', image_file, '-trim',
                    '-bordercolor', BACKGROUND_COLOR,
                    '-border', '5', image_file)
        finally:
            execute('wmctrl', '-c', random_title)
Пример #13
0
 def test_save_to_path(self):
     """Test that captured output can be stored in a file."""
     expected_output = random_string()
     with CaptureOutput() as capturer:
         print(expected_output)
         fd, temporary_file = tempfile.mkstemp()
         try:
             capturer.save_to_path(temporary_file)
             with open(temporary_file, 'r') as handle:
                 assert expected_output in handle.read()
         finally:
             os.unlink(temporary_file)
Пример #14
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
Пример #15
0
 def test_merge_conflicts(self):
     """Test handling of merge conflicts."""
     with TemporaryDirectory() as directory:
         # Initialize a repository object of the parametrized type.
         repository = self.get_instance(bare=False, local=directory)
         # Create the local repository.
         repository.create()
         # Create an initial commit in the repository.
         versioned_filename = random_string(10)
         versioned_contents = random_string(250)
         self.commit_file(
             repository=repository,
             filename=versioned_filename,
             contents=versioned_contents,
             message="Initial commit",
         )
         # Create a new branch in which we'll modify
         # the file that the initial commit created.
         repository.create_branch('dev')
         self.commit_file(
             repository=repository,
             filename=versioned_filename,
             message="Commit on 'dev' branch",
         )
         # Now modify the same file in the default branch.
         repository.checkout()
         self.commit_file(
             repository=repository,
             filename=versioned_filename,
             message="Commit on default branch",
         )
         # Now try to merge the 'dev' branch into the default branch
         # (triggering the merge conflict) and make sure that the intended
         # exception type is raised.
         self.assertRaises(MergeConflictError, repository.merge, 'dev')
         # Make sure the filename of the file with merge conflicts is
         # available to callers.
         assert repository.merge_conflicts == [versioned_filename]
Пример #16
0
    def test_format_text(self):
        """Test human friendly formatting of password store entries."""
        entry = PasswordEntry(name='some/random/password', store=object())
        set_property(entry, 'text', random_string())
        self.assertEquals(
            # We enable ANSI escape sequences but strip them before we
            # compare the generated string. This may seem rather pointless
            # but it ensures that the relevant code paths are covered :-).
            dedent(
                ansi_strip(
                    entry.format_text(include_password=True,
                                      use_colors=True))),
            dedent('''
                some / random / password

                Password: {value}
            ''',
                   value=entry.text))
Пример #17
0
 def test_merge_up(self):
     """Test merging up through release branches."""
     initial_release_branches = ['v1', 'v2', 'v3', 'v4']
     intermediate_release_branch = 'v3.1'
     final_release_branches = ['v1', 'v2', 'v3', intermediate_release_branch, 'v4']
     with MockedHomeDirectory() as home:
         self.configure_author(home, AUTHOR_NAME, AUTHOR_EMAIL)
         # Initialize a repository object of the parametrized type.
         repository = self.get_instance(
             bare=False,
             local=os.path.join(home, 'repo'),
             release_filter=r'^v(\d+(?:\.\d+)*)$',
             release_scheme='branches',
         )
         # Add the repository to ~/.vcs-repo-mgr.ini.
         prepare_config({
             'merge-up-test': {
                 'local': repository.local,
                 'release-filter': r'^v(\d+(?:\.\d+)*)$',
                 'release-scheme': 'branches',
                 'type': repository.ALIASES[0],
             },
         })
         # Make sure the repository contains an initial commit on the
         # default branch, otherwise the merge process will try to
         # checkout() the default branch which can fail when that branch
         # "doesn't have any contents yet".
         self.create_initial_commit(repository)
         # Create the release branches.
         previous_branch = repository.current_branch
         for branch_name in initial_release_branches:
             repository.checkout(revision=previous_branch)
             repository.create_branch(branch_name)
             self.commit_file(
                 repository=repository,
                 filename=branch_name,
                 contents="This is release branch '%s'\n" % branch_name,
                 message="Create release branch '%s'" % branch_name,
             )
             previous_branch = branch_name
         # Create a feature branch based on the initial release branch.
         feature_branch = 'feature-%s' % random_string(10)
         repository.checkout('v3')
         repository.create_branch(feature_branch)
         self.commit_file(
             repository=repository,
             filename=intermediate_release_branch,
             contents="This will be release branch '%s'\n" % intermediate_release_branch,
             message="Fixed a bug in version 3!",
         )
         assert feature_branch in repository.branches
         # Merge the change up into the release branches using the command line interface.
         returncode, output = run_cli(
             main, '--repository=merge-up-test',
             '--revision=v3.1', '--merge-up',
             feature_branch, merged=True,
         )
         self.assertEquals(returncode, 0)
         # Make sure the feature branch was closed.
         assert feature_branch not in repository.branches
         # Validate the contents of the default branch.
         repository.checkout()
         # Check that all of the release branches have been merged into the
         # default branch by checking the `v1', `v2', etc. filenames.
         entries = repository.context.list_entries('.')
         assert all(fn in entries for fn in final_release_branches)
         # Make sure the contents of the bug fix were merged up.
         assert repository.context.read_file('v1') == b"This is release branch 'v1'\n"
         assert repository.context.read_file('v2') == b"This is release branch 'v2'\n"
         assert repository.context.read_file('v3') == b"This is release branch 'v3'\n"
         assert repository.context.read_file('v3.1') == b"This will be release branch 'v3.1'\n"
         assert repository.context.read_file('v4') == b"This is release branch 'v4'\n"
Пример #18
0
 def test_non_interpreted_lines_capture(self):
     """Test that interpretation of special characters can be disabled."""
     expected_output = random_string()
     with CaptureOutput() as capturer:
         print(expected_output)
         assert expected_output in capturer.get_lines(interpreted=False)
Пример #19
0
 def test_text_capture(self):
     """Test that capturing of all output as a single string is supported."""
     expected_output = random_string()
     with CaptureOutput() as capturer:
         print(expected_output)
         assert expected_output in capturer.get_text()
Пример #20
0
 def test_stdout_capture_same_process(self):
     """Test standard output capturing from the same process."""
     expected_stdout = random_string()
     with CaptureOutput() as capturer:
         print(expected_stdout)
         assert expected_stdout in capturer.get_lines()