sapling/tests/test-fb-hgext-extutil.py
Jun Wu 9dc21f8d0b codemod: import from the edenscm package
Summary:
D13853115 adds `edenscm/` to `sys.path` and code still uses `import mercurial`.
That has nasty problems if both `import mercurial` and
`import edenscm.mercurial` are used, because Python would think `mercurial.foo`
and `edenscm.mercurial.foo` are different modules so code like
`try: ... except mercurial.error.Foo: ...`, or `isinstance(x, mercurial.foo.Bar)`
would fail to handle the `edenscm.mercurial` version. There are also some
module-level states (ex. `extensions._extensions`) that would cause trouble if
they have multiple versions in a single process.

Change imports to use the `edenscm` so ideally the `mercurial` is no longer
imported at all. Add checks in extensions.py to catch unexpected extensions
importing modules from the old (wrong) locations when running tests.

Reviewed By: phillco

Differential Revision: D13868981

fbshipit-source-id: f4e2513766957fd81d85407994f7521a08e4de48
2019-01-29 17:25:32 -08:00

81 lines
2.5 KiB
Python

# Copyright 2004-present Facebook. All Rights Reserved.
import errno
import os
import time
import unittest
import silenttestrunner
from edenscm.hgext import extutil
from edenscm.mercurial import error, vfs, worker
locktimeout = 25
locksuccess = 24
class ExtutilTests(unittest.TestCase):
def testbgcommandnoblock(self):
"""runbgcommand() should return without waiting for the process to
finish."""
env = os.environ.copy()
start = time.time()
extutil.runbgcommand(["sleep", "5"], env)
end = time.time()
if end - start >= 1.0:
self.fail(
"runbgcommand() took took %s seconds, should have "
"returned immediately" % (end - start)
)
def testbgcommandfailure1(self):
"""runbgcommand() should throw if executing the process fails."""
env = os.environ.copy()
try:
extutil.runbgcommand(["no_such_program", "arg1", "arg2"], env)
self.fail("expected runbgcommand to fail with ENOENT")
except OSError as ex:
self.assertEqual(ex.errno, errno.ENOENT)
def testbgcommandfailure2(self):
"""runbgcommand() should throw if executing the process fails."""
env = os.environ.copy()
try:
extutil.runbgcommand([os.devnull, "arg1", "arg2"], env)
self.fail("expected runbgcommand to fail with EACCES")
except OSError as ex:
self.assertEqual(ex.errno, errno.EACCES)
def testflock(self):
testtmp = os.environ["TESTTMP"]
opener = vfs.vfs(testtmp)
name = "testlock"
with extutil.flock(opener.join(name), "testing a lock", timeout=0):
otherlock = self.otherprocesslock(opener, name)
self.assertEquals(
otherlock, locktimeout, "other process should not have taken the lock"
)
otherlock = self.otherprocesslock(opener, name)
self.assertEquals(
otherlock, locksuccess, "other process should have taken the lock"
)
def otherprocesslock(self, opener, name):
pid = os.fork()
if pid == 0:
try:
with extutil.flock(opener.join(name), "other process lock", timeout=0):
os._exit(locksuccess)
except error.LockHeld:
os._exit(locktimeout)
else:
p, st = os.waitpid(pid, 0)
st = worker._exitstatus(st) # Convert back to an int
return st
if __name__ == "__main__":
silenttestrunner.main(__name__)