Beispiel #1
0
def test_bad_posargspec():
    # issue #11
    assert PosArgSpec(name=None).display.name is not None
    assert PosArgDisplay(name=None).name is not None

    posargs_args = [{
        'name': None
    }, {
        'provides': 'x'
    }, {
        'display': {
            'doc': 'wee'
        }
    }, {
        'display': {
            'name': 'better_name'
        }
    }]

    for arg in posargs_args:
        cmd = Command(lambda targs: None, name='cmd', posargs=arg)
        cmd_chk = CommandChecker(cmd, mix_stderr=True)
        res = cmd_chk.run(['cmd', '-h'])
        assert res.stdout.startswith('Usage')

    return
Beispiel #2
0
def test_err_subcmd_prog_name():
    cmd = Command(lambda: print("foo"), "foo")
    subcmd = Command(lambda: print("bar"), "bar")
    subcmd.add(Command(lambda: print("baz"), "baz"))
    cmd.add(subcmd)

    cc = CommandChecker(cmd)
    res = cc.fail('fred.py bar ba')
    assert 'fred.py' in res.stderr
    assert 'foo' not in res.stderr
Beispiel #3
0
def test_cc_mixed(tmpdir):
    cmd = get_calc_cmd()
    cc_mixed = CommandChecker(cmd, mix_stderr=True)
    res = cc_mixed.fail_1('calc halve nonexistentarg', chdir=tmpdir)
    assert type(res.exception) is CommandLineError
    assert res.stdout.startswith("error: calc halve: unexpected positional arguments: ['nonexistentarg']")
    assert repr(res)

    with pytest.raises(ValueError):
        res.stderr

    return
Beispiel #4
0
def test_calc_stream():
    cmd = get_calc_cmd()

    tc = CommandChecker(cmd, reraise=True)

    res = tc.run(['calc', 'add', '1', '2'])

    assert res.stdout.strip() == '3.0'

    res = tc.run(['calc', 'halve'], input='30')
    assert res.stdout.strip() == 'Enter a number: \n15.0'

    res = tc.run('calc halve', input='4', env={'CALC_TWO': '-2'})
    assert res.stdout.strip() == 'Enter a number: \n-2.0'
    assert not res.exception

    with pytest.raises(ZeroDivisionError):
        tc.run('calc halve', input='4', env={'CALC_TWO': '0'})

    return
Beispiel #5
0
def test_cc_getpass():
    cmd = get_calc_cmd()
    cc = CommandChecker(cmd, mix_stderr=True)
    res = cc.run('calc blackjack', input=['20', '20', '1'])
    assert res.stdout.endswith('blackjack!\n')

    # check newline-autoadding behavior when getpass is aborted
    cc = CommandChecker(cmd)
    def _raise_eof(*a, **kw):
        raise EOFError()

    real_getpass = getpass.getpass
    try:
        getpass.getpass = _raise_eof
        res = cc.fail('calc blackjack')
    finally:
        getpass.getpass = real_getpass
    assert res.stderr.endswith('\n')
Beispiel #6
0
def test_cc_exc():
    cmd = get_calc_cmd()
    cc_no_reraise = CommandChecker(cmd)
    res = cc_no_reraise.fail('calc halve', input='4', env={'CALC_TWO': '0'})
    assert res.exception
    assert res.stdout == 'Enter a number: \n'

    res = cc_no_reraise.fail('calc halve nonexistentarg')
    assert type(res.exception) is CommandLineError

    # NB: expect to update these as error messaging improves
    assert str(res.exception) == "error: calc halve: unexpected positional arguments: ['nonexistentarg']"
    assert res.stderr.startswith("error: calc halve: unexpected positional arguments: ['nonexistentarg']")
    assert 'stderr=' in repr(res)

    with pytest.raises(TypeError):
        cc_no_reraise.run('calc halve', input=object())
    return
Beispiel #7
0
def test_cli(tmp_path, _fast_crypto):
    cmd = cli._get_cmd()
    cc = CommandChecker(cmd, reraise=True)

    assert cc.run('pprotect version').stdout.startswith(
        'pocket_protector version')

    tmp_path = str(tmp_path)
    protected_path = tmp_path + '/protected.yaml'

    # fail init and ensure that file isn't created
    cc.fail_1('pprotect init --file %s' % protected_path,
              input=[KURT_EMAIL, KURT_PHRASE, KURT_PHRASE + 'nope'])
    assert not os.path.exists(protected_path)

    # successfully create protected
    res = cc.run('pprotect init --file %s' % protected_path,
                 input=[KURT_EMAIL, KURT_PHRASE, KURT_PHRASE])
    assert res.stdout == 'Adding new key custodian.\nUser email: '
    assert res.stderr == 'Passphrase: Retype passphrase: '

    # check we can only create it once
    res = cc.fail_2('pprotect init --file %s' % protected_path,
                    input=[KURT_EMAIL, KURT_PHRASE, KURT_PHRASE])

    file_data = ruamel.yaml.YAML().load(open(protected_path).read())
    assert list(file_data['key-custodians'])[0] == KURT_EMAIL
    assert len(file_data['audit-log']) == 2

    res = cc.run('pprotect list-audit-log --file %s' % protected_path)
    audit_lines = res.stdout.splitlines()
    assert len(audit_lines) == 2
    assert 'created' in audit_lines[0]

    # make a new cc, with env and tmp_path baked in (also tests
    # protected.yaml in the cur dir being the default file)
    kurt_env = {
        'PPROTECT_USER': KURT_EMAIL,
        'PPROTECT_PASSPHRASE': KURT_PHRASE
    }
    cc = CommandChecker(cmd, chdir=tmp_path, env=kurt_env, reraise=True)

    res = cc.run(['pprotect', 'add-domain'], input=[DOMAIN_NAME])
    assert 'Adding new domain.' in res.stdout

    res = cc.run(['pprotect', 'list_domains'])
    assert res.stdout.splitlines() == [DOMAIN_NAME]

    cc.run(['pprotect', 'add-secret'],
           input=[DOMAIN_NAME, SECRET_NAME, 'tmpval'])
    cc.run(['pprotect', 'update-secret'],
           input=[DOMAIN_NAME, SECRET_NAME, SECRET_VALUE])
    res = cc.run(['pprotect', 'list-domain-secrets', DOMAIN_NAME])
    assert res.stdout == SECRET_NAME + '\n'

    res = cc.run(['pprotect', 'decrypt-domain', DOMAIN_NAME])
    res_data = json.loads(res.stdout)
    assert res_data[SECRET_NAME] == SECRET_VALUE

    cc.fail(['pprotect', 'decrypt-domain', 'nonexistent-domain'])

    # already exists
    cc.fail_1('pprotect add-key-custodian', input=[KURT_EMAIL, ''])

    cc.run('pprotect add-key-custodian',
           input=[MH_EMAIL, MH_PHRASE, MH_PHRASE])

    cc.run('pprotect add-owner', input=[DOMAIN_NAME, MH_EMAIL])

    # missing protected
    cc.fail_2('pprotect list-all-secrets', chdir=tmp_path + '/..')

    cc.run('pprotect list-all-secrets')
    assert SECRET_NAME in res.stdout

    cc.run(['pprotect', 'rotate_domain_keys'], input=[DOMAIN_NAME])

    # test mixed env var and entry
    res = cc.run(['pprotect', 'decrypt-domain', DOMAIN_NAME],
                 env={
                     'PPROTECT_USER': MH_EMAIL,
                     'PPROTECT_PASSPHRASE': None
                 },
                 input=[MH_PHRASE])
    assert json.loads(res.stdout)[SECRET_NAME] == SECRET_VALUE
    assert 'Verify passphrase' in res.stderr

    # test bad creds
    cc.fail_1(['pprotect', 'decrypt-domain', DOMAIN_NAME],
              env={
                  'PPROTECT_USER': None,
                  'PPROTECT_PASSPHRASE': 'nope'
              },
              input=[KURT_EMAIL])

    res = cc.fail_1(
        'pprotect set-key-custodian-passphrase',
        input=[KURT_EMAIL, KURT_PHRASE, KURT_PHRASE, KURT_PHRASE + 'nope'])
    assert 'did not match' in res.stderr

    # correctly reset passphrase
    new_kurt_phrase = KURT_PHRASE + 'yep'
    res = cc.run(
        'pprotect set-key-custodian-passphrase',
        input=[KURT_EMAIL, KURT_PHRASE, new_kurt_phrase, new_kurt_phrase])

    # try new passphrase with a passphrase file why not
    ppfile_path = str(tmp_path) + 'tmp_passphrase'
    with open(ppfile_path, 'wb') as f:
        f.write(new_kurt_phrase.encode('utf8'))
    res = cc.run([
        'pprotect', 'decrypt-domain', '--non-interactive', '--passphrase-file',
        ppfile_path, DOMAIN_NAME
    ])

    res_data = json.loads(res.stdout)
    assert res_data[SECRET_NAME] == SECRET_VALUE

    # test mutual exclusivity of check env and interactive
    cc.fail_2([
        'pprotect', 'decrypt-domain', '--non-interactive', '--ignore-env',
        DOMAIN_NAME
    ])

    res = cc.fail_1('pprotect decrypt-domain --non-interactive ' + DOMAIN_NAME,
                    env={'PPROTECT_PASSPHRASE': None})
    assert 'Warning: Empty passphrase' in res.stderr

    # print(open(protected_path).read())

    # test removals
    cc.run(['pprotect', 'rm-owner'], input=[DOMAIN_NAME, MH_EMAIL])
    cc.run(['pprotect', 'rm-secret'], input=[DOMAIN_NAME, SECRET_NAME])
    cc.run(['pprotect', 'rm-domain', '--confirm'], input=[DOMAIN_NAME, 'y'])
Beispiel #8
0
def cc():
    cmd = cli.get_command()
    # TODO: don't mix stderr
    return CommandChecker(cmd, mix_stderr=True)
Beispiel #9
0
def test_cc_edge_cases():
    cmd = get_calc_cmd()
    cc = CommandChecker(cmd)

    with pytest.raises(AttributeError):
        cc.nonexistentattr
    with pytest.raises(AttributeError, match='end in integers'):
        cc.fail_x

    with pytest.raises(TypeError, match='Container of ints'):
        cc.run('calc blackjack', exit_code=object())

    # disable automatic checking
    res = cc.run('calc blackjack', input=['20', '20', '1'], exit_code=None)
    assert res.exit_code == 0
    assert res.stderr == 'Bottom card: Retype bottom card: '

    # CheckError is also an AssertionError
    with pytest.raises(AssertionError) as exc_info:
        cc.run('calc halve nonexistentarg', input='tldr')
    assert exc_info.value.result.stderr.startswith('error: calc halve: unexpected')

    with pytest.raises(CheckError):
        cc.fail('calc halve', input='4')

    with pytest.raises(CheckError):
        cc.fail('calc halve', input='4', exit_code=(1, 2))