| import py |
| import svntestbase |
| from py.path import SvnAuth |
| import time |
| import sys |
| |
| svnbin = py.path.local.sysfind('svn') |
| |
| def make_repo_auth(repo, userdata): |
| """ write config to repo |
| |
| user information in userdata is used for auth |
| userdata has user names as keys, and a tuple (password, readwrite) as |
| values, where 'readwrite' is either 'r' or 'rw' |
| """ |
| confdir = py.path.local(repo).join('conf') |
| confdir.join('svnserve.conf').write('''\ |
| [general] |
| anon-access = none |
| password-db = passwd |
| authz-db = authz |
| realm = TestRepo |
| ''') |
| authzdata = '[/]\n' |
| passwddata = '[users]\n' |
| for user in userdata: |
| authzdata += '%s = %s\n' % (user, userdata[user][1]) |
| passwddata += '%s = %s\n' % (user, userdata[user][0]) |
| confdir.join('authz').write(authzdata) |
| confdir.join('passwd').write(passwddata) |
| |
| def serve_bg(repopath): |
| pidfile = py.path.local(repopath).join('pid') |
| port = 10000 |
| e = None |
| while port < 10010: |
| cmd = 'svnserve -d -T --listen-port=%d --pid-file=%s -r %s' % ( |
| port, pidfile, repopath) |
| print(cmd) |
| try: |
| py.process.cmdexec(cmd) |
| except py.process.cmdexec.Error: |
| e = sys.exc_info()[1] |
| else: |
| # XXX we assume here that the pid file gets written somewhere, I |
| # guess this should be relatively safe... (I hope, at least?) |
| counter = pid = 0 |
| while counter < 10: |
| counter += 1 |
| try: |
| pid = pidfile.read() |
| except py.error.ENOENT: |
| pass |
| if pid: |
| break |
| time.sleep(0.2) |
| return port, int(pid) |
| port += 1 |
| raise IOError('could not start svnserve: %s' % (e,)) |
| |
| class TestSvnAuth(object): |
| def test_basic(self): |
| auth = SvnAuth('foo', 'bar') |
| assert auth.username == 'foo' |
| assert auth.password == 'bar' |
| assert str(auth) |
| |
| def test_makecmdoptions_uname_pw_makestr(self): |
| auth = SvnAuth('foo', 'bar') |
| assert auth.makecmdoptions() == '--username="foo" --password="bar"' |
| |
| def test_makecmdoptions_quote_escape(self): |
| auth = SvnAuth('fo"o', '"ba\'r"') |
| assert auth.makecmdoptions() == '--username="fo\\"o" --password="\\"ba\'r\\""' |
| |
| def test_makecmdoptions_no_cache_auth(self): |
| auth = SvnAuth('foo', 'bar', cache_auth=False) |
| assert auth.makecmdoptions() == ('--username="foo" --password="bar" ' |
| '--no-auth-cache') |
| |
| def test_makecmdoptions_no_interactive(self): |
| auth = SvnAuth('foo', 'bar', interactive=False) |
| assert auth.makecmdoptions() == ('--username="foo" --password="bar" ' |
| '--non-interactive') |
| |
| def test_makecmdoptions_no_interactive_no_cache_auth(self): |
| auth = SvnAuth('foo', 'bar', cache_auth=False, |
| interactive=False) |
| assert auth.makecmdoptions() == ('--username="foo" --password="bar" ' |
| '--no-auth-cache --non-interactive') |
| |
| class svnwc_no_svn(py.path.svnwc): |
| def __new__(cls, *args, **kwargs): |
| self = super(svnwc_no_svn, cls).__new__(cls, *args, **kwargs) |
| self.commands = [] |
| return self |
| |
| def _svn(self, *args): |
| self.commands.append(args) |
| |
| class TestSvnWCAuth(object): |
| def setup_method(self, meth): |
| if not svnbin: |
| py.test.skip("svn binary required") |
| self.auth = SvnAuth('user', 'pass', cache_auth=False) |
| |
| def test_checkout(self): |
| wc = svnwc_no_svn('foo', auth=self.auth) |
| wc.checkout('url') |
| assert wc.commands[0][-1] == ('--username="user" --password="pass" ' |
| '--no-auth-cache') |
| |
| def test_commit(self): |
| wc = svnwc_no_svn('foo', auth=self.auth) |
| wc.commit('msg') |
| assert wc.commands[0][-1] == ('--username="user" --password="pass" ' |
| '--no-auth-cache') |
| |
| def test_checkout_no_cache_auth(self): |
| wc = svnwc_no_svn('foo', auth=self.auth) |
| wc.checkout('url') |
| assert wc.commands[0][-1] == ('--username="user" --password="pass" ' |
| '--no-auth-cache') |
| |
| def test_checkout_auth_from_constructor(self): |
| wc = svnwc_no_svn('foo', auth=self.auth) |
| wc.checkout('url') |
| assert wc.commands[0][-1] == ('--username="user" --password="pass" ' |
| '--no-auth-cache') |
| |
| class svnurl_no_svn(py.path.svnurl): |
| cmdexec_output = 'test' |
| popen_output = 'test' |
| def __new__(cls, *args, **kwargs): |
| self = super(svnurl_no_svn, cls).__new__(cls, *args, **kwargs) |
| self.commands = [] |
| return self |
| |
| def _cmdexec(self, cmd): |
| self.commands.append(cmd) |
| return self.cmdexec_output |
| |
| def _popen(self, cmd): |
| self.commands.append(cmd) |
| return self.popen_output |
| |
| class TestSvnURLAuth(object): |
| def setup_method(self, meth): |
| self.auth = SvnAuth('foo', 'bar') |
| |
| def test_init(self): |
| u = svnurl_no_svn('http://foo.bar/svn') |
| assert u.auth is None |
| |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| assert u.auth is self.auth |
| |
| def test_new(self): |
| u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth) |
| new = u.new(basename='bar') |
| assert new.auth is self.auth |
| assert new.url == 'http://foo.bar/svn/bar' |
| |
| def test_join(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| new = u.join('foo') |
| assert new.auth is self.auth |
| assert new.url == 'http://foo.bar/svn/foo' |
| |
| def test_listdir(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| u.cmdexec_output = '''\ |
| 1717 johnny 1529 Nov 04 14:32 LICENSE.txt |
| 1716 johnny 5352 Nov 04 14:28 README.txt |
| ''' |
| paths = u.listdir() |
| assert paths[0].auth is self.auth |
| assert paths[1].auth is self.auth |
| assert paths[0].basename == 'LICENSE.txt' |
| |
| def test_info(self): |
| u = svnurl_no_svn('http://foo.bar/svn/LICENSE.txt', auth=self.auth) |
| def dirpath(self): |
| return self |
| u.cmdexec_output = '''\ |
| 1717 johnny 1529 Nov 04 14:32 LICENSE.txt |
| 1716 johnny 5352 Nov 04 14:28 README.txt |
| ''' |
| org_dp = u.__class__.dirpath |
| u.__class__.dirpath = dirpath |
| try: |
| info = u.info() |
| finally: |
| u.dirpath = org_dp |
| assert info.size == 1529 |
| |
| def test_open(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| foo = u.join('foo') |
| foo.check = lambda *args, **kwargs: True |
| ret = foo.open() |
| assert ret == 'test' |
| assert '--username="foo" --password="bar"' in foo.commands[0] |
| |
| def test_dirpath(self): |
| u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth) |
| parent = u.dirpath() |
| assert parent.auth is self.auth |
| |
| def test_mkdir(self): |
| u = svnurl_no_svn('http://foo.bar/svn/qweqwe', auth=self.auth) |
| assert not u.commands |
| u.mkdir(msg='created dir foo') |
| assert u.commands |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def test_copy(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| u2 = svnurl_no_svn('http://foo.bar/svn2') |
| u.copy(u2, 'copied dir') |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def test_rename(self): |
| u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth) |
| u.rename('http://foo.bar/svn/bar', 'moved foo to bar') |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def test_remove(self): |
| u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth) |
| u.remove(msg='removing foo') |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def test_export(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| target = py.path.local('/foo') |
| u.export(target) |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def test_log(self): |
| u = svnurl_no_svn('http://foo.bar/svn/foo', auth=self.auth) |
| u.popen_output = py.io.TextIO(py.builtin._totext('''\ |
| <?xml version="1.0"?> |
| <log> |
| <logentry revision="51381"> |
| <author>guido</author> |
| <date>2008-02-11T12:12:18.476481Z</date> |
| <msg>Creating branch to work on auth support for py.path.svn*. |
| </msg> |
| </logentry> |
| </log> |
| ''', 'ascii')) |
| u.check = lambda *args, **kwargs: True |
| ret = u.log(10, 20, verbose=True) |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| assert len(ret) == 1 |
| assert int(ret[0].rev) == 51381 |
| assert ret[0].author == 'guido' |
| |
| def test_propget(self): |
| u = svnurl_no_svn('http://foo.bar/svn', auth=self.auth) |
| u.propget('foo') |
| assert '--username="foo" --password="bar"' in u.commands[0] |
| |
| def pytest_funcarg__setup(request): |
| return Setup(request) |
| |
| class Setup: |
| def __init__(self, request): |
| if not svnbin: |
| py.test.skip("svn binary required") |
| if not request.config.option.runslowtests: |
| py.test.skip('use --runslowtests to run these tests') |
| |
| tmpdir = request.getfuncargvalue("tmpdir") |
| repodir = tmpdir.join("repo") |
| py.process.cmdexec('svnadmin create %s' % repodir) |
| if sys.platform == 'win32': |
| repodir = '/' + str(repodir).replace('\\', '/') |
| self.repo = py.path.svnurl("file://%s" % repodir) |
| if py.std.sys.platform == 'win32': |
| # remove trailing slash... |
| repodir = repodir[1:] |
| self.repopath = py.path.local(repodir) |
| self.temppath = tmpdir.mkdir("temppath") |
| self.auth = SvnAuth('johnny', 'foo', cache_auth=False, |
| interactive=False) |
| make_repo_auth(self.repopath, {'johnny': ('foo', 'rw')}) |
| self.port, self.pid = serve_bg(self.repopath.dirpath()) |
| # XXX caching is too global |
| py.path.svnurl._lsnorevcache._dict.clear() |
| request.addfinalizer(lambda: py.process.kill(self.pid)) |
| |
| class TestSvnWCAuthFunctional: |
| def test_checkout_constructor_arg(self, setup): |
| wc = py.path.svnwc(setup.temppath, auth=setup.auth) |
| wc.checkout( |
| 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)) |
| assert wc.join('.svn').check() |
| |
| def test_checkout_function_arg(self, setup): |
| wc = py.path.svnwc(setup.temppath, auth=setup.auth) |
| wc.checkout( |
| 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)) |
| assert wc.join('.svn').check() |
| |
| def test_checkout_failing_non_interactive(self, setup): |
| auth = SvnAuth('johnny', 'bar', cache_auth=False, |
| interactive=False) |
| wc = py.path.svnwc(setup.temppath, auth) |
| py.test.raises(Exception, |
| ("wc.checkout('svn://localhost:%(port)s/%(repopath)s')" % |
| setup.__dict__)) |
| |
| def test_log(self, setup): |
| wc = py.path.svnwc(setup.temppath, setup.auth) |
| wc.checkout( |
| 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)) |
| foo = wc.ensure('foo.txt') |
| wc.commit('added foo.txt') |
| log = foo.log() |
| assert len(log) == 1 |
| assert log[0].msg == 'added foo.txt' |
| |
| def test_switch(self, setup): |
| wc = py.path.svnwc(setup.temppath, auth=setup.auth) |
| svnurl = 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename) |
| wc.checkout(svnurl) |
| wc.ensure('foo', dir=True).ensure('foo.txt').write('foo') |
| wc.commit('added foo dir with foo.txt file') |
| wc.ensure('bar', dir=True) |
| wc.commit('added bar dir') |
| bar = wc.join('bar') |
| bar.switch(svnurl + '/foo') |
| assert bar.join('foo.txt') |
| |
| def test_update(self, setup): |
| wc1 = py.path.svnwc(setup.temppath.ensure('wc1', dir=True), |
| auth=setup.auth) |
| wc2 = py.path.svnwc(setup.temppath.ensure('wc2', dir=True), |
| auth=setup.auth) |
| wc1.checkout( |
| 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)) |
| wc2.checkout( |
| 'svn://localhost:%s/%s' % (setup.port, setup.repopath.basename)) |
| wc1.ensure('foo', dir=True) |
| wc1.commit('added foo dir') |
| wc2.update() |
| assert wc2.join('foo').check() |
| |
| auth = SvnAuth('unknown', 'unknown', interactive=False) |
| wc2.auth = auth |
| py.test.raises(Exception, 'wc2.update()') |
| |
| def test_lock_unlock_status(self, setup): |
| port = setup.port |
| wc = py.path.svnwc(setup.temppath, auth=setup.auth) |
| wc.checkout( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename,)) |
| wc.ensure('foo', file=True) |
| wc.commit('added foo file') |
| foo = wc.join('foo') |
| foo.lock() |
| status = foo.status() |
| assert status.locked |
| foo.unlock() |
| status = foo.status() |
| assert not status.locked |
| |
| auth = SvnAuth('unknown', 'unknown', interactive=False) |
| foo.auth = auth |
| py.test.raises(Exception, 'foo.lock()') |
| py.test.raises(Exception, 'foo.unlock()') |
| |
| def test_diff(self, setup): |
| port = setup.port |
| wc = py.path.svnwc(setup.temppath, auth=setup.auth) |
| wc.checkout( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename,)) |
| wc.ensure('foo', file=True) |
| wc.commit('added foo file') |
| wc.update() |
| rev = int(wc.status().rev) |
| foo = wc.join('foo') |
| foo.write('bar') |
| diff = foo.diff() |
| assert '\n+bar\n' in diff |
| foo.commit('added some content') |
| diff = foo.diff() |
| assert not diff |
| diff = foo.diff(rev=rev) |
| assert '\n+bar\n' in diff |
| |
| auth = SvnAuth('unknown', 'unknown', interactive=False) |
| foo.auth = auth |
| py.test.raises(Exception, 'foo.diff(rev=rev)') |
| |
| class TestSvnURLAuthFunctional: |
| def test_listdir(self, setup): |
| port = setup.port |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=setup.auth) |
| u.ensure('foo') |
| paths = u.listdir() |
| assert len(paths) == 1 |
| assert paths[0].auth is setup.auth |
| |
| auth = SvnAuth('foo', 'bar', interactive=False) |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=auth) |
| py.test.raises(Exception, 'u.listdir()') |
| |
| def test_copy(self, setup): |
| port = setup.port |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=setup.auth) |
| foo = u.mkdir('foo') |
| assert foo.check() |
| bar = u.join('bar') |
| foo.copy(bar) |
| assert bar.check() |
| assert bar.auth is setup.auth |
| |
| auth = SvnAuth('foo', 'bar', interactive=False) |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=auth) |
| foo = u.join('foo') |
| bar = u.join('bar') |
| py.test.raises(Exception, 'foo.copy(bar)') |
| |
| def test_write_read(self, setup): |
| port = setup.port |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=setup.auth) |
| foo = u.ensure('foo') |
| fp = foo.open() |
| try: |
| data = fp.read() |
| finally: |
| fp.close() |
| assert data == '' |
| |
| auth = SvnAuth('foo', 'bar', interactive=False) |
| u = py.path.svnurl( |
| 'svn://localhost:%s/%s' % (port, setup.repopath.basename), |
| auth=auth) |
| foo = u.join('foo') |
| py.test.raises(Exception, 'foo.open()') |
| |
| # XXX rinse, repeat... :| |