def runWatchTests(self, config, expect): with WatchmanInstance.Instance(config=config) as inst: inst.start() client = self.getClient(inst) for filetype, name, expect_pass in expect: for watch_type in ["watch", "watch-project"]: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily d = self.mkdtemp(suffix="-%s-%s-%s-%s" % (filetype, name, expect_pass, watch_type)) if filetype == "directory": os.mkdir(os.path.join(d, name)) elif filetype == "file": self.touchRelative(d, name) assert_functions = { (True, "watch"): self.assertWatchSucceeds, (True, "watch-project"): self.assertWatchProjectSucceeds, (False, "watch"): self.assertWatchIsRestricted, (False, "watch-project"): self.assertWatchProjectIsRestricted, } assert_function = assert_functions[(expect_pass, watch_type)] assert_function(inst, client, d)
def test_Illegal(self): config = { "illegal_fstypes": [ # This should include any/all fs types. If this test fails on # your platform, look in /tmp/watchman-test.log for a line like: # "path /var/tmp/a3osdzvzqnco0sok is on filesystem type zfs" # then add the type name to this list, in sorted order "NTFS", "apfs", "cifs", "hfs", "nfs", "smb", "tmpfs", "ufs", "unknown", "zfs", ], "illegal_fstypes_advice": "just cos", } with WatchmanInstance.Instance(config=config) as inst: inst.start() client = self.getClient(inst) d = self.mkdtemp() with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query("watch", d) self.assertIn( ("filesystem and is disallowed by global config" + " illegal_fstypes: just cos"), str(ctx.exception), )
def setUp(self): # the eden home directory. We use the global dir for the test runner # rather than one scoped to the test because we have very real length # limits on the socket path name that we're likely to hit otherwise. # fake a home dir so that eden is isolated from the settings # of the user running these tests. self.eden_home = tempfile.mkdtemp(prefix='eden_home') self.eden_dir = os.path.join(self.eden_home, 'local/.eden') os.makedirs(self.eden_dir) self.etc_eden_dir = os.path.join(self.eden_home, 'etc-eden') os.mkdir(self.etc_eden_dir) # The directory holding the system configuration files self.system_config_dir = os.path.join(self.etc_eden_dir, 'config.d') os.mkdir(self.system_config_dir) # where we'll mount the eden client(s) self.mounts_dir = self.mkdtemp(prefix='eden_mounts') self.save_home = os.environ['HOME'] os.environ['HOME'] = self.eden_home self.eden = edenclient.EdenFS(self.eden_dir, etc_eden_dir=self.etc_eden_dir, home_dir=self.eden_home) self.eden.start() # Watchman also needs to start up with the same HOME, otherwise # it won't be able to locate the eden socket self.eden_watchman = WatchmanInstance.Instance() self.eden_watchman.start() self.client = self.getClient(self.eden_watchman)
def setUp(self): super(WatchmanEdenTestCase, self).setUp() # The test EdenFS instance. # We let it create and manage its own temporary test directory, rather than # using the one scoped to the test because we have very real length limits on # the socket path name that we're likely to hit otherwise. self.eden = edenclient.EdenFS() self.addCleanup(lambda: self.cleanUpEden()) # where we'll mount the eden client(s) self.mounts_dir = self.mkdtemp(prefix="eden_mounts") # Watchman needs to start up with the same HOME as eden, otherwise # it won't be able to locate the eden socket self.save_home = os.environ["HOME"] os.environ["HOME"] = str(self.eden.home_dir) self.addCleanup(lambda: self._restoreHome()) self.system_hgrc = None self.eden_watchman = WatchmanInstance.Instance() self.eden_watchman.start() self.addCleanup(self.cleanUpWatchman) self.client = self.getClient(self.eden_watchman) # chg can interfere with eden, so disable it up front os.environ["CHGDISABLE"] = "1" # Start the EdenFS instance self.eden.start()
def test_Illegal(self): config = { 'illegal_fstypes': [ # This should include any/all fs types. If this test fails on # your platform, look in /tmp/watchman-test.log for a line like: # "path /var/tmp/a3osdzvzqnco0sok is on filesystem type zfs" # then add the type name to this list, in sorted order 'NTFS', 'apfs', 'cifs', 'hfs', 'nfs', 'smb', 'tmpfs', 'ufs', 'unknown', 'zfs', ], 'illegal_fstypes_advice': 'just cos', } inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst) d = self.mkdtemp() with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query('watch', d) self.assertIn(('filesystem and is disallowed by global config' + ' illegal_fstypes: just cos'), str(ctx.exception)) finally: inst.stop()
def runner(): global results_queue global tests_queue try: # Start up a shared watchman instance for the tests. inst = WatchmanInstance.Instance() inst.start() # Allow tests to locate this default instance WatchmanInstance.setSharedInstance(inst) except Exception as e: print('This is going to suck:', e) return while True: test = tests_queue.get() try: if test == 'terminate': break if Interrupt.wasInterrupted(): continue try: result = Result() test.run(result) results_queue.put(result) except Exception as e: print(e) finally: tests_queue.task_done() inst.stop()
def _async_runner(self, test_core): wminst = WatchmanInstance.Instance() wminst.start() try: return asyncio.new_event_loop().run_until_complete(test_core(wminst)) finally: wminst.stop()
def test_failing_to_start_when_nice(self): if sys.platform == "darwin": self.skipTest("launchd renders this test invalid on macOS") inst = WatchmanInstance.Instance() stdout, stderr = inst.commandViaCLI(["version"], prefix=["nice"]) print("stdout", stdout) print("stderr", stderr) stderr = stderr.decode("ascii") self.assertEqual(b"", stdout) self.assertRegex(stderr, "refusing to start")
def test_spawner(self): config = {"spawn_watchman_service": os.path.join(THIS_DIR, "site_spawn.py")} inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(["version"]) parsed = json.loads(stdout.decode("ascii")) self.assertTrue("version" in parsed) # Shut down that process, as we have no automatic way to deal with it inst.commandViaCLI(["--no-spawn", "--no-local", "shutdown-server"])
def test_bulkstat_off(self): config = {"_use_bulkstat": False} with WatchmanInstance.Instance(config=config) as inst: inst.start() self.getClient(inst, replace_cached=True) root = self.mkdtemp() self.client.query("watch", root) self.touchRelative(root, "foo") self.touchRelative(root, "bar") self.assertFileList(root, ["foo", "bar"])
def runProjectTests(self, config, expect, touch_watchmanconfig=False): inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst) for touch, expect_watch, expect_rel, expect_pass in expect: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily suffix = "-%s-%s-%s-%s" % (touch, expect_watch, expect_rel, expect_pass) suffix = suffix.replace("/", "Z") d = self.mkdtemp(suffix=suffix) dir_to_watch = os.path.join(d, "a", "b", "c") os.makedirs(dir_to_watch, 0o777) dir_to_watch = self.normAbsolutePath(dir_to_watch) self.touchRelative(d, touch) if touch_watchmanconfig: self.touchRelative(d, ".watchmanconfig") if expect_watch: expect_watch = os.path.join(d, expect_watch) else: expect_watch = d if expect_pass: res = client.query("watch-project", dir_to_watch) self.assertEqual( self.normAbsolutePath(os.path.join(d, expect_watch)), self.normAbsolutePath(res["watch"]), ) if not expect_rel: self.assertEqual(None, res.get("relative_path")) else: self.assertEqual( self.normRelativePath(expect_rel), self.normRelativePath(res.get("relative_path")), ) else: with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query("watch-project", dir_to_watch) self.assertIn( ("None of the files listed in global config " + "root_files are present in path `" + dir_to_watch + "` or any of its parent directories. " + "root_files is defined by the"), str(ctx.exception), ) finally: inst.stop()
def test_rootRestrict(self): config = {"root_restrict_files": [".git", ".hg", ".foo", ".bar"]} inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst) expect = [ ("directory", ".git", True), ("directory", ".hg", True), ("file", ".foo", True), ("file", ".bar", True), ("directory", ".bar", True), (None, None, False), ("directory", ".svn", False), ("file", "baz", False), ] for filetype, name, expect_pass in expect: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily d = self.mkdtemp(suffix="-%s-%s-%s" % (filetype, name, expect_pass)) if filetype == "directory": os.mkdir(os.path.join(d, name)) elif filetype == "file": self.touchRelative(d, name) if expect_pass: client.query("watch", d) else: with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query("watch", d) self.assertRegex( str(ctx.exception), ("unable to resolve root .*" + ": Your watchman administrator has configured watchman " + "to prevent watching path `.*`. " + "None of the files listed in global config root_files " + "are present and enforce_root_files is set to true. " + "root_files is defined by the `.*` config file and " + "includes `.watchmanconfig`, `.git`, `.hg`, `.foo`, " + "and `.bar`. One or more of these files must be " + "present in order to allow a watch. Try pulling " + "and checking out a newer version of the project?"), ) finally: inst.stop()
def runProjectTests(self, config, expect, touch_watchmanconfig=False): inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst) for touch, expect_watch, expect_rel, expect_pass in expect: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily suffix = '-%s-%s-%s-%s' % ( touch, expect_watch, expect_rel, expect_pass ) suffix = suffix.replace('/', 'Z') d = self.mkdtemp(suffix=suffix) dir_to_watch = os.path.join(d, 'a', 'b', 'c') os.makedirs(dir_to_watch, 0o777) self.touchRelative(d, touch) if touch_watchmanconfig: self.touchRelative(d, '.watchmanconfig') if expect_watch: expect_watch = os.path.join(d, expect_watch) else: expect_watch = d if expect_pass: res = client.query('watch-project', dir_to_watch) self.assertEqual( self.normAbsolutePath(os.path.join(d, expect_watch)), self.normAbsolutePath(res['watch']) ) if not expect_rel: self.assertEqual(None, res.get('relative_path')) else: self.assertEqual(self.normRelativePath(expect_rel), self.normRelativePath(res.get('relative_path'))) else: with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query('watch-project', dir_to_watch) self.assertIn( ( 'none of the files listed in global config ' + 'root_files are present in path `' + os.path.join( d, 'a', 'b', 'c' ) + ' or any of its parent directories' ), str(ctx.exception) ) finally: inst.stop()
def test_failingSpawner(self): config = { 'spawn_watchman_service': os.path.join(THIS_DIR, 'site_spawn_fail.py') } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(['version']) self.assertEqual(b'', stdout) self.assertRegexpMatches(stderr.decode('ascii'), 'site_spawn_fail.py: exited with status 1') with open(inst.log_file_name, 'r') as f: self.assertEqual('failed to start\n', f.read())
def test_spawner(self): config = { 'spawn_watchman_service': os.path.join(THIS_DIR, 'site_spawn.py') } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(['version']) parsed = json.loads(stdout.decode('ascii')) self.assertTrue('version' in parsed) # Shut down that process, as we have no automatic way to deal with it inst.commandViaCLI(['--no-spawn', '--no-local', 'shutdown-server'])
def test_failingSpawner(self): config = { "spawn_watchman_service": os.path.join(THIS_DIR, "site_spawn_fail.py") } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(["version"]) print("stdout", stdout) print("stderr", stderr) stderr = stderr.decode("ascii") self.assertEqual(b"", stdout) self.assertRegex(stderr, "failed to start\n") self.assertRegex(stderr, "site_spawn_fail.py: exited with status 1")
def test_no_site_spawner(self): """With a site spawner configured to otherwise fail, pass `--no-site-spawner` and ensure that a failure didn't occur.""" config = { 'spawn_watchman_service': os.path.join(THIS_DIR, 'site_spawn_fail.py') } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(['version', '--no-site-spawner']) parsed = json.loads(stdout.decode('ascii')) self.assertTrue('version' in parsed) inst.commandViaCLI(['--no-spawn', '--no-local', 'shutdown-server'])
def test_failingSpawner(self): config = { 'spawn_watchman_service': os.path.join(THIS_DIR, 'site_spawn_fail.py') } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(['version']) print('stdout', stdout) print('stderr', stderr) stderr = stderr.decode('ascii') self.assertEqual(b'', stdout) self.assertRegex(stderr, 'failed to start\n') self.assertRegex(stderr, 'site_spawn_fail.py: exited with status 1')
def test_no_site_spawner(self): """With a site spawner configured to otherwise fail, pass `--no-site-spawner` and ensure that a failure didn't occur.""" config = { "spawn_watchman_service": os.path.join(THIS_DIR, "site_spawn_fail.py") } inst = WatchmanInstance.Instance(config=config) stdout, stderr = inst.commandViaCLI(["version", "--no-site-spawner"]) parsed = json.loads(stdout.decode("ascii")) self.assertTrue("version" in parsed) inst.commandViaCLI(["--no-spawn", "--no-local", "shutdown-server"])
def test_bulkstat_off(self): config = {'_use_bulkstat': False} inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst, replace_cached=True) root = self.mkdtemp() self.client.query('watch', root) self.touchRelative(root, 'foo') self.touchRelative(root, 'bar') self.assertFileList(root, ['foo', 'bar']) finally: inst.stop()
def test_bulkstat_on(self): config = {"_use_bulkstat": True} inst = WatchmanInstance.Instance(config=config) try: inst.start() self.getClient(inst, replace_cached=True) root = self.mkdtemp() self.client.query("watch", root) self.touchRelative(root, "foo") self.touchRelative(root, "bar") self.assertFileList(root, ["foo", "bar"]) finally: inst.stop()
def test_rootRestrict(self): config = { 'root_restrict_files': ['.git', '.hg', '.foo', '.bar'] } inst = WatchmanInstance.Instance(config=config) try: inst.start() client = self.getClient(inst) expect = [ ('directory', '.git', True), ('directory', '.hg', True), ('file', '.foo', True), ('file', '.bar', True), ('directory', '.bar', True), (None, None, False), ('directory', '.svn', False), ('file', 'baz', False), ] for filetype, name, expect_pass in expect: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily d = self.mkdtemp(suffix='-%s-%s-%s' % ( filetype, name, expect_pass)) if filetype == 'directory': os.mkdir(os.path.join(d, name)) elif filetype == 'file': self.touchRelative(d, name) if expect_pass: client.query('watch', d) else: with self.assertRaises(pywatchman.WatchmanError) as ctx: client.query('watch', d) self.assertIn( ("unable to resolve root " + d + ": Your watchman administrator has configured watchman "+ "to prevent watching this path. "+ "None of the files listed in global config root_files "+ "are present and enforce_root_files is set to true").lower(), str(ctx.exception).lower()) finally: inst.stop()
def test_failing_to_start_when_nice_foreground(self): inst = WatchmanInstance.Instance() stdout, stderr = inst.commandViaCLI(["--foreground", "version"], prefix=["nice"]) print("stdout", stdout) print("stderr", stderr) output = stderr.decode("ascii") try: output += inst.getServerLogContents() except IOError: # on macos, we may not have gotten as far # as creating the log file when the error # triggers, so we're fine with passing # on io errors here pass self.assertRegex(output, "refusing to start")
def runWatchTests(self, config, expect): with WatchmanInstance.Instance(config=config) as inst: inst.start() client = self.getClient(inst) for filetype, name, expect_pass in expect: # encode the test criteria in the dirname so that we can # figure out which test scenario failed more easily d = self.mkdtemp(suffix="-%s-%s-%s" % (filetype, name, expect_pass)) if filetype == "directory": os.mkdir(os.path.join(d, name)) elif filetype == "file": self.touchRelative(d, name) if expect_pass: self.assertWatchSucceeds(client, d) else: self.assertWatchIsRestricted(client, d)
def setUp(self): super(WatchmanEdenTestCase, self).setUp() # the eden home directory. We use the global dir for the test runner # rather than one scoped to the test because we have very real length # limits on the socket path name that we're likely to hit otherwise. # fake a home dir so that eden is isolated from the settings # of the user running these tests. self.eden_home = tempfile.mkdtemp(prefix="eden_home") self.eden_dir = os.path.join(self.eden_home, "local/.eden") os.makedirs(self.eden_dir) self.etc_eden_dir = os.path.join(self.eden_home, "etc-eden") os.mkdir(self.etc_eden_dir) # The directory holding the system configuration files self.system_config_dir = os.path.join(self.etc_eden_dir, "config.d") os.mkdir(self.system_config_dir) self.hooks_dir = os.path.join(self.etc_eden_dir, "hooks") os.mkdir(self.hooks_dir) self.edenrc = os.path.join(self.eden_home, ".edenrc") # where we'll mount the eden client(s) self.mounts_dir = self.mkdtemp(prefix="eden_mounts") self.save_home = os.environ["HOME"] os.environ["HOME"] = self.eden_home # chg can interfere with eden, so disable it up front os.environ["CHGDISABLE"] = "1" self.eden = edenclient.EdenFS( self.eden_dir, etc_eden_dir=self.etc_eden_dir, home_dir=self.eden_home ) self.eden.start() # Watchman also needs to start up with the same HOME, otherwise # it won't be able to locate the eden socket self.eden_watchman = WatchmanInstance.Instance() self.eden_watchman.start() self.client = self.getClient(self.eden_watchman)
def runner(): global results_queue global tests_queue broken = False try: # Start up a shared watchman instance for the tests. inst = WatchmanInstance.Instance({ "watcher": args.watcher }, debug_watchman=args.debug_watchman) inst.start() # Allow tests to locate this default instance WatchmanInstance.setSharedInstance(inst) except Exception as e: print('while starting watchman: %s' % str(e)) traceback.print_exc() broken = True while not broken: test = tests_queue.get() try: if test == 'terminate': break if Interrupt.wasInterrupted() or broken: continue try: result = Result() test.run(result) results_queue.put(result) except Exception as e: print(e) finally: tests_queue.task_done() if not broken: inst.stop()
def runner(): global results_queue global tests_queue broken = False try: # Start up a shared watchman instance for the tests. inst = WatchmanInstance.Instance({"watcher": args.watcher}, debug_watchman=args.debug_watchman) inst.start() # Allow tests to locate this default instance WatchmanInstance.setSharedInstance(inst) if has_asyncio: # Each thread will have its own event loop asyncio.set_event_loop(asyncio.new_event_loop()) except Exception as e: print('while starting watchman: %s' % str(e)) traceback.print_exc() broken = True while not broken: test = tests_queue.get() try: if test == 'terminate': break if Interrupt.wasInterrupted() or broken: continue result = None for attempt in range(0, args.retry_flaky + 1): try: result = Result() result.setAttemptNumber(attempt) if hasattr(test, 'setAttemptNumber'): test.setAttemptNumber(attempt) test.run(result) if hasattr(test, 'setAttemptNumber') and \ not result.wasSuccessful(): # Facilitate retrying this possibly flaky test continue break except Exception as e: print(e) if hasattr(test, 'setAttemptNumber') and \ not result.wasSuccessful(): # Facilitate retrying this possibly flaky test continue if not result.wasSuccessful() and \ 'TRAVIS' in os.environ and \ hasattr(test, 'dumpLogs'): test.dumpLogs() results_queue.put(result) finally: tests_queue.task_done() if not broken: inst.stop()
def runner(): global results_queue global tests_queue broken = False try: # Start up a shared watchman instance for the tests. inst = WatchmanInstance.Instance({"watcher": args.watcher}, debug_watchman=args.debug_watchman) inst.start() # Allow tests to locate this default instance WatchmanInstance.setSharedInstance(inst) if has_asyncio: # Each thread will have its own event loop asyncio.set_event_loop(asyncio.new_event_loop()) except Exception as e: print("while starting watchman: %s" % str(e)) traceback.print_exc() broken = True while not broken: test = tests_queue.get() try: if test == "terminate": break if Interrupt.wasInterrupted() or broken: continue result = None for attempt in range(0, args.retry_flaky + 1): # Check liveness of the server try: client = pywatchman.client(timeout=3.0, sockpath=inst.getSockPath()) client.query("version") client.close() except Exception as exc: print( "Failed to connect to watchman server: %s; starting a new one" % exc) try: inst.stop() except Exception: pass try: inst = WatchmanInstance.Instance( {"watcher": args.watcher}, debug_watchman=args.debug_watchman, ) inst.start() # Allow tests to locate this default instance WatchmanInstance.setSharedInstance(inst) except Exception as e: print("while starting watchman: %s" % str(e)) traceback.print_exc() broken = True continue try: result = Result() result.setAttemptNumber(attempt) if hasattr(test, "setAttemptNumber"): test.setAttemptNumber(attempt) test.run(result) if hasattr( test, "setAttemptNumber") and not result.wasSuccessful(): # Facilitate retrying this possibly flaky test continue break except Exception as e: print(e) if hasattr( test, "setAttemptNumber") and not result.wasSuccessful(): # Facilitate retrying this possibly flaky test continue if (not result.wasSuccessful() and "TRAVIS" in os.environ and hasattr(test, "dumpLogs")): test.dumpLogs() results_queue.put(result) finally: tests_queue.task_done() if not broken: inst.stop()