2009-03-04 01:42:32 +08:00
|
|
|
import py
|
|
|
|
|
|
|
|
def pytest_pyfuncarg_pickletransport(pyfuncitem):
|
|
|
|
return ImmutablePickleTransport()
|
|
|
|
|
|
|
|
def pytest_pyfunc_call(__call__, pyfuncitem, args, kwargs):
|
|
|
|
# for each function call we patch py._com.pyplugins
|
|
|
|
# so that the unpickling of config objects
|
|
|
|
# (which bind to this mechanism) doesn't do harm
|
|
|
|
# usually config objects are no meant to be unpickled in
|
|
|
|
# the same system
|
|
|
|
oldconfig = py.test.config
|
|
|
|
oldcom = py._com.pyplugins
|
|
|
|
print "setting py.test.config to None"
|
|
|
|
py.test.config = None
|
|
|
|
py._com.pyplugins = py._com.PyPlugins()
|
|
|
|
try:
|
|
|
|
return __call__.execute(firstresult=True)
|
|
|
|
finally:
|
|
|
|
print "setting py.test.config to", oldconfig
|
|
|
|
py.test.config = oldconfig
|
|
|
|
py._com.pyplugins = oldcom
|
|
|
|
|
|
|
|
class ImmutablePickleTransport:
|
|
|
|
def __init__(self):
|
|
|
|
from py.__.test.dsession.mypickle import ImmutablePickler
|
|
|
|
self.p1 = ImmutablePickler(uneven=0)
|
|
|
|
self.p2 = ImmutablePickler(uneven=1)
|
|
|
|
|
|
|
|
def p1_to_p2(self, obj):
|
|
|
|
return self.p2.loads(self.p1.dumps(obj))
|
|
|
|
|
|
|
|
def p2_to_p1(self, obj):
|
|
|
|
return self.p1.loads(self.p2.dumps(obj))
|
|
|
|
|
|
|
|
def unifyconfig(self, config):
|
|
|
|
p2config = self.p1_to_p2(config)
|
|
|
|
p2config._initafterpickle(config.topdir)
|
|
|
|
return p2config
|
|
|
|
|
|
|
|
class TestImmutablePickling:
|
|
|
|
def test_pickle_config(self, testdir, pickletransport):
|
|
|
|
config1 = testdir.parseconfig()
|
|
|
|
assert config1.topdir == testdir.tmpdir
|
|
|
|
testdir.chdir()
|
|
|
|
p2config = pickletransport.p1_to_p2(config1)
|
|
|
|
assert p2config.topdir == config1.topdir
|
|
|
|
config_back = pickletransport.p2_to_p1(p2config)
|
|
|
|
assert config_back is config1
|
|
|
|
|
|
|
|
def test_pickle_modcol(self, testdir, pickletransport):
|
|
|
|
modcol1 = testdir.getmodulecol("def test_one(): pass")
|
|
|
|
modcol2a = pickletransport.p1_to_p2(modcol1)
|
|
|
|
modcol2b = pickletransport.p1_to_p2(modcol1)
|
|
|
|
assert modcol2a is modcol2b
|
|
|
|
|
|
|
|
modcol1_back = pickletransport.p2_to_p1(modcol2a)
|
|
|
|
assert modcol1_back
|
|
|
|
|
|
|
|
def test_pickle_func(self, testdir, pickletransport):
|
|
|
|
modcol1 = testdir.getmodulecol("def test_one(): pass")
|
|
|
|
item = modcol1.collect_by_name("test_one")
|
|
|
|
testdir.chdir()
|
|
|
|
item2a = pickletransport.p1_to_p2(item)
|
|
|
|
assert item is not item2a # of course
|
|
|
|
assert item2a.name == item.name
|
|
|
|
modback = pickletransport.p2_to_p1(item2a.parent)
|
|
|
|
assert modback is modcol1
|
|
|
|
|
|
|
|
|
|
|
|
class TestConfigPickling:
|
|
|
|
def test_config_getstate_setstate(self, testdir):
|
|
|
|
from py.__.test.config import Config
|
|
|
|
testdir.makepyfile(__init__="", conftest="x=1; y=2")
|
|
|
|
hello = testdir.makepyfile(hello="")
|
|
|
|
tmp = testdir.tmpdir
|
|
|
|
testdir.chdir()
|
|
|
|
config1 = testdir.parseconfig(hello)
|
|
|
|
config2 = Config()
|
|
|
|
config2.__setstate__(config1.__getstate__())
|
|
|
|
assert config2.topdir == py.path.local()
|
|
|
|
config2_relpaths = [x.relto(config2.topdir) for x in config2.args]
|
|
|
|
config1_relpaths = [x.relto(config1.topdir) for x in config1.args]
|
|
|
|
|
|
|
|
assert config2_relpaths == config1_relpaths
|
|
|
|
for name, value in config1.option.__dict__.items():
|
|
|
|
assert getattr(config2.option, name) == value
|
|
|
|
assert config2.getvalue("x") == 1
|
|
|
|
|
|
|
|
def test_config_rconfig(self, testdir):
|
|
|
|
tmp = testdir.tmpdir
|
|
|
|
tmp.ensure("__init__.py")
|
|
|
|
testdir.makeconftest("""
|
|
|
|
class ConftestPlugin:
|
|
|
|
def pytest_addoption(self, parser):
|
|
|
|
group = parser.addgroup("testing group")
|
|
|
|
group.addoption('-G', '--glong', action="store", default=42,
|
|
|
|
type="int", dest="gdest", help="g value.")
|
|
|
|
""")
|
|
|
|
config = testdir.parseconfig(tmp, "-G", "11")
|
|
|
|
assert config.option.gdest == 11
|
|
|
|
repr = config.__getstate__()
|
|
|
|
|
|
|
|
config = testdir.Config()
|
|
|
|
py.test.raises(AttributeError, "config.option.gdest")
|
|
|
|
|
|
|
|
config2 = testdir.Config()
|
|
|
|
config2.__setstate__(repr)
|
|
|
|
option = config2.addoptions("testing group",
|
|
|
|
config2.Option('-G', '--glong', action="store", default=42,
|
|
|
|
type="int", dest="gdest", help="g value."))
|
|
|
|
assert config2.option.gdest == 11
|
|
|
|
assert option.gdest == 11
|
|
|
|
|
|
|
|
def test_config_picklability(self, testdir):
|
|
|
|
import cPickle
|
|
|
|
config = testdir.parseconfig()
|
|
|
|
s = cPickle.dumps(config)
|
|
|
|
newconfig = cPickle.loads(s)
|
|
|
|
assert hasattr(newconfig, "topdir")
|
|
|
|
assert newconfig.topdir == py.path.local()
|
|
|
|
|
|
|
|
def test_collector_implicit_config_pickling(self, testdir):
|
|
|
|
from cPickle import Pickler, Unpickler
|
|
|
|
tmpdir = testdir.tmpdir
|
|
|
|
testdir.chdir()
|
|
|
|
testdir.makepyfile(hello="def test_x(): pass")
|
|
|
|
config = testdir.parseconfig(tmpdir)
|
|
|
|
col = config.getfsnode(config.topdir)
|
|
|
|
io = py.std.cStringIO.StringIO()
|
|
|
|
pickler = Pickler(io)
|
|
|
|
pickler.dump(col)
|
|
|
|
io.seek(0)
|
|
|
|
unpickler = Unpickler(io)
|
|
|
|
col2 = unpickler.load()
|
|
|
|
assert col2.name == col.name
|
|
|
|
assert col2.listnames() == col.listnames()
|
|
|
|
|
|
|
|
def test_config_and_collector_pickling(self, testdir):
|
|
|
|
from cPickle import Pickler, Unpickler
|
|
|
|
tmpdir = testdir.tmpdir
|
|
|
|
dir1 = tmpdir.ensure("somedir", dir=1)
|
|
|
|
config = testdir.parseconfig()
|
|
|
|
col = config.getfsnode(config.topdir)
|
|
|
|
col1 = col.join(dir1.basename)
|
|
|
|
assert col1.parent is col
|
|
|
|
io = py.std.cStringIO.StringIO()
|
|
|
|
pickler = Pickler(io)
|
|
|
|
pickler.dump(col)
|
|
|
|
pickler.dump(col1)
|
|
|
|
pickler.dump(col)
|
|
|
|
io.seek(0)
|
|
|
|
unpickler = Unpickler(io)
|
|
|
|
topdir = tmpdir.ensure("newtopdir", dir=1)
|
|
|
|
topdir.ensure("somedir", dir=1)
|
|
|
|
old = topdir.chdir()
|
|
|
|
try:
|
|
|
|
newcol = unpickler.load()
|
|
|
|
newcol2 = unpickler.load()
|
|
|
|
newcol3 = unpickler.load()
|
2009-03-18 07:48:07 +08:00
|
|
|
assert newcol2.config is newcol.config
|
2009-03-04 01:42:32 +08:00
|
|
|
assert newcol2.parent == newcol
|
2009-03-18 07:48:07 +08:00
|
|
|
assert newcol2.config.topdir == topdir
|
2009-03-04 01:42:32 +08:00
|
|
|
assert newcol.fspath == topdir
|
|
|
|
assert newcol2.fspath.basename == dir1.basename
|
|
|
|
assert newcol2.fspath.relto(topdir)
|
|
|
|
finally:
|
|
|
|
old.chdir()
|
|
|
|
|
|
|
|
def test_config__setstate__wired_correctly_in_childprocess(testdir):
|
|
|
|
from py.__.test.dsession.mypickle import PickleChannel
|
|
|
|
gw = py.execnet.PopenGateway()
|
|
|
|
channel = gw.remote_exec("""
|
|
|
|
import py
|
|
|
|
from py.__.test.dsession.mypickle import PickleChannel
|
|
|
|
channel = PickleChannel(channel)
|
|
|
|
config = channel.receive()
|
|
|
|
assert py.test.config.pytestplugins.pyplugins == py._com.pyplugins, "pyplugins wrong"
|
|
|
|
assert py.test.config.bus == py._com.pyplugins, "bus wrong"
|
|
|
|
""")
|
|
|
|
channel = PickleChannel(channel)
|
|
|
|
config = testdir.parseconfig()
|
|
|
|
channel.send(config)
|
|
|
|
channel.waitclose() # this will raise
|
|
|
|
gw.exit()
|
|
|
|
|
|
|
|
|