Exemplo n.º 1
0
def test_controller_continues_after_oserror(sftp, monkeypatch, capsys):
    """This test verifies that the controller prints an OSError message
    when it receives it and then continues execution (rather than quitting).
    """

    oserror_message = "THIS IS A TEST"

    def mock_put(s, f):
        """A mock put action that simply raises a known exception."""

        raise OSError(1, oserror_message)

    # Patch in our mocked put function.
    monkeypatch.setattr(put_file_onto_remote_server, "put", mock_put)

    # Our strategy here is to invoke two actions: our mock put, then an
    # invalid command. This will allow us to test for correct behavior, because
    # the controller will print its error message for unrecognized commands
    # if and only if it continues execution after handling the OSError.

    inputs = """
             put file
             hooligan town banana republic
             """
    with mock_input(inputs):
        main_loop(sftp)
        output = capsys.readouterr().out
        assert oserror_message in output

        # Now, we want to ensure that the error for unrecognized commands
        # is displayed AFTER the message we just asserted. So we'll split
        # the output on the message and check the second half.

        assert ERROR_MESSAGE_NOT_RECOGNIZED in \
            output.split(oserror_message, 1)[1]
def test_invalid_commands_do_not_invoke_put_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the put action."""

    # See tests/integration/test_close.py for details.
    with mock_input("putty"):
        main_loop(sftp)
        assert "not recognized" in capsys.readouterr().out
Exemplo n.º 3
0
def test_invalid_commands_do_not_invoke_rm_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the rm action."""

    # See tests/integration/test_close.py for details.
    test_cases = """rm
                    rm one two
                 """
    with mock_input(test_cases):
        main_loop(sftp)
        assert SUCCESS_STRING not in capsys.readouterr().out
def test_invalid_commands_do_not_invoke_mput_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the mput action."""

    inputs = """
             cluckcluckcluck
             mput
             """
    with mock_input(inputs):
        main_loop(sftp)
        assert SUCCESS_STRING not in capsys.readouterr().out
def test_invalid_commands_do_not_invoke_put_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the put action."""

    # See tests/integration/test_close.py for details.
    test_input = """
                 definitely_not_a_command
                 ls mydir
                 """
    with mock_input(test_input):
        main_loop(sftp)
        assert SUCCESS_STRING not in capsys.readouterr().out
Exemplo n.º 6
0
def test_invalid_commands_do_not_invoke_close_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the close action."""

    # Pass a fake command to main_loop() and verify that it detects that the
    # command is not recognized. Note that main_loop() terminates because
    # it reaches EOF in our simulated stdin, so it's impractical for us to
    # monkeypatch mock_close in and verify that it was NOT called. Even if
    # we could prevent main_loop from calling it, we would prevent main_loop
    # from terminating, most likely, so our test would never conclude.
    with mock_input("sayonara"):
        main_loop(sftp)
        assert "not recognized" in capsys.readouterr().out
def test_invalid_commands_do_not_invoke_put_r_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the rename action."""

    # Test inputs. They need to be a single sequence, or we'll send EOF
    # and close our SFTP connection after the first test.
    test_inputs = """doesnotexist
                     put -r 
                     put -r ham sandwich"""
    for test in test_inputs:
        with mock_input(test):
            main_loop(sftp)
            assert SUCCESS_STRING not in capsys.readouterr().out
def test_invalid_commands_do_not_invoke_lsearch_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the lsearch action."""

    # See tests/integration/test_close.py for details.
    test_inputs = [
        "doesnotexist",
        "lsearch",  # No files
        "lsearch onefile twofile"
    ]
    for test in test_inputs:
        with mock_input(test):
            main_loop(sftp)
            assert SUCCESS_STRING not in capsys.readouterr().out
def test_lsearch_invokes_lsearch_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'lsearch myname' calls the lsearch action and
    passes 'myname' as name.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(lsearch, "search_local_files", mock_lsearch)

    # Pass in a valid input
    with mock_input("lsearch {}".format(NAME)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_rename_invokes_rename_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'rename from to' calls the rename action
    and passes 'from' and 'to' as before and after, respectively.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(rename, "rename_remote_file", mock_rename)

    # Pass in a valid input
    with mock_input("rename {} {}".format(FROM, TO)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_put_file_invokes_put_function(capsys, monkeypatch, sftp):
    """Tests that writing 'put file' calls the put action and passes 'file'
    as the filename.
    """

    # Replace put_file_onto_remote_server.put with our mocked function
    monkeypatch.setattr(put_file_onto_remote_server, "put", mock_put)

    # Pass in a valid input
    with mock_input("put " + FILENAME):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 12
0
def test_mkdir_invokes_create_folder_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'mkdir foldername' calls the put action and
    passes 'foldername' as the remote path to create.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(mkdir, "create_dir_remote", mock_mkdir)

    # Pass in a valid input
    with mock_input("mkdir {}".format(FOLDER)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_put_file_invokes_put_function(capsys, monkeypatch, sftp):
    """Tests that writing 'mput file1 file1' calls the mput action and passes
    the list ["file1", "file2"] as filenames.
    """

    # Replace put_file_onto_remote_server.put with our mocked function
    monkeypatch.setattr(mput, "put_multiple", mock_mput)

    # Pass in a valid input
    with mock_input("mput " + FILENAMES):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 14
0
def test_chmod_invokes_chmod_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'chmod 555 mydir' calls the rename action
    and passes 777 and 'mydir' as permissions and filename, respectively.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(chmod, "change_permissions", mock_chmod)

    # Pass in a valid input
    with mock_input("chmod {} {}".format(MODE, PATH)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 15
0
def test_lls_invokes_list_files_local_action(capsys, monkeypatch, sftp):
    """Tests that writing 'lls' calls the 'list files local' action."""

    # Replace the real function with our mocked function
    monkeypatch.setattr(list_files_local,
                        "display_local_files",
                        mock_list_local_files)

    # Pass in a valid input
    with mock_input("lls"):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_put_file_invokes_put_function(monkeypatch, capsys, sftp):
    """Tests that writing 'put file' calls the put action and passes 'file'
    as the filename.
    """

    # Replace the action with our mocked function
    monkeypatch.setattr(list_files_remote, "list_dir", mock_list_dir)

    # Pass in a valid input
    with mock_input("ls"):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 17
0
def test_lrename_invokes_rename_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'lrename from to' calls the put action and
    passes 'from' as the original filename and 'to' as the new filename.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(rename_files_local, "rename_local_file", mock_rename)

    # Pass in a valid input
    with mock_input("lrename {} {}".format(FROM, TO)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_put_r_invokes_put_folder_action(capsys, monkeypatch, sftp):
    """Tests that writing text like 'lrename from to' calls the put action and
    passes 'from' as the original filename and 'to' as the new filename.
    """

    # Replace the real action with our mocked function
    monkeypatch.setattr(put_folder, "put_r", mock_put_r)

    # Pass in a valid input
    with mock_input("put -r {}".format(FOLDER)):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 19
0
def test_invalid_commands_do_not_invoke_rename_function(capsys, sftp):
    """Tests that writing invalid commands doesn't invoke the rename action."""

    # See tests/integration/test_close.py for details.
    test_inputs = [
        "doesnotexist",
        "lrename",  # No files
        "lrename onefile",
        "lrename onefile twofile threefile"
    ]
    for test in test_inputs:
        with mock_input(test):
            main_loop(sftp)
            assert "not recognized" in capsys.readouterr().out
Exemplo n.º 20
0
def test_close_commands_invoke_close_function(monkeypatch, capsys, sftp):
    """Tests that writing any valid close command at the program's main prompt,
    e.g. 'bye', 'exit', or 'quit', calls the close action.
    """

    # Replace the real close action with our mocked version.
    monkeypatch.setattr(close, "close", mock_close)

    # For each input, invoke the main loop with an open connection,
    # pass in the input, and verify that mock_close() was called.
    for input in INPUTS:
        with mock_input(input):
            main_loop(sftp)
            assert SUCCESS_STRING in capsys.readouterr().out
Exemplo n.º 21
0
def test_remove_file_invokes_remove_function(capsys, monkeypatch, sftp):
    """Tests that writing 'rm file' calls the remove_from_remote_server action and passes 'file'
    as the filename.
    """

    # Replace remove_from_remote_server.remove_from_remote_server with our mocked function
    monkeypatch.setattr(remove_from_remote_server, "remove_from_remote_server",
                        mock_rm)

    # Pass in a valid input
    with mock_input("rm " + FILENAME):
        main_loop(sftp)

    assert SUCCESS_STRING in capsys.readouterr().out
def test_main_loop_disconnection(sftp):
    """Tests that the app handles disconnects gracefully."""

    # In order to test unexpected disconnects, we'll pass the controller
    # a disconnected sftp object and send a request take some basic action
    # that uses it.

    sftp.close()
    with mock_input("ls"):
        assert main_loop(sftp) == -1
def test_end_of_file(sftp, capsys):
    """Tests that the app handles the EOF character (e.g. Ctrl-D)
    gracefully.
    """

    with mock_input(""):
        retval = main_loop(sftp)
        stdout = capsys.readouterr().out
        assert retval == 0, \
            "Controller should return 0 after receiving EOF."
        assert ("connection closed" in stdout.lower()), \
            "EOF response message should include 'connection closed'."
        assert stdout.startswith("\n", len(DEFAULT_USER_PROMPT)), \
            "EOF response message should start with a newline."
Exemplo n.º 24
0
def main():
    # Catch-all try block for attempting to run the program.
    try:

        # Check that we received exactly one command-line argument.
        if len(sys.argv) != 2:
            print(INVALID_ARGUMENT_MESSAGE)
            return 1

        # Split our one argument on "@", which will either give us
        # a username and a hostname or just a hostname (if there is no "@").
        tup = sys.argv[1].split("@")

        if len(tup) > 2 or len(tup) == 0:
            # The user didn't pass in user@hostname or hostname, so we
            # can't proceed. We'll print the correct invocation and exit
            # so they can try again.
            print(INVALID_ARGUMENT_MESSAGE)
            return 1

        if len(tup) == 2:
            # The user passed in user@hostname, so tup = [user, hostname].
            username = tup[0]
            hostname = tup[1]

        else:  # len(tup) == 1
            # The user passed in hostname only, so we'll retrieve
            # the currently logged-in username from the OS.
            username = getpass.getuser()
            hostname = sys.argv[1]

        # Print username@hostname and prompt for password.
        # getpass.getpass() does not echo the input, as a security measure
        #
        # Note: if you run through PyCharm, getpass() may behave very oddly.
        # It should work correctly from the terminal, though.
        print(username + "@" + hostname + "'s", end=' ', flush=True)
        password = getpass.getpass()
        sftp = login.login(hostname, username, password)

        # Type check for correct allocation of pysftp.Connection object
        if type(sftp) == pysftp.Connection:
            print("Authentication success.")
            # Run the main controller loop, and when it returns, pass along its
            # return value as the program's exit code.
            return controller.main_loop(sftp)

    except Exception as error:
        print(error)

        # Disable exception printing before exit. Note: this is super-janky
        # and should never be used unless the program is about to close!
        # We just flatly replace the standard error output with a buffer
        # that we never read.
        #
        # We have to do this because pysftp raises an exception during
        # teardown if it was passed garbage inputs like hamsandwich@beepboop.
        # If we don't disable exception printing, Python prints a stack trace
        # for an ignored exception. Why? We can't catch the exception,
        # because when it's raised, we've already called sys.exit(), so
        # we don't have any code in scope. There's nowhere for the exception
        # to go.
        sys.stderr = StringIO()

        return 1