예제 #1
0
    def test_native_logging(self):
        expected_msg = "\[DEBUG\] engine::scheduler: Launching \d+ root"
        pants_run = self.run_pants(["-linfo", "list", "src/scala::"])
        assertNotRegex(self, pants_run.stderr_data, expected_msg)

        pants_run = self.run_pants(["-ldebug", "list", "src/scala::"])
        assertRegex(self, pants_run.stderr_data, expected_msg)
    def test_pantsd_parent_runner_killed(self):
        with self.pantsd_test_context() as (workdir, config, checker):
            # Launch a run that will wait for a file to be created (but do not create that file).
            file_to_make = os.path.join(workdir, 'some_magic_file')
            waiter_handle = self.run_pants_with_workdir_without_waiting(
                [
                    'run', 'testprojects/src/python/coordinated_runs:waiter',
                    '--', file_to_make
                ],
                workdir,
                config,
            )

            # Wait for the python run to be running.
            time.sleep(5)
            checker.assert_started()

            # Locate the single "parent" pantsd-runner process, and kill it.
            pantsd_runner_processes = [
                p for p in checker.runner_process_context.current_processes()
                if p.ppid() == 1
            ]
            self.assertEquals(1, len(pantsd_runner_processes))
            parent_runner_process = pantsd_runner_processes[0]
            # Send SIGTERM
            parent_runner_process.terminate()
            waiter_run = waiter_handle.join()

            # Ensure that we saw the pantsd-runner process's failure in the client's stderr.
            self.assert_failure(waiter_run)
            assertRegex(
                self, waiter_run.stderr_data, """\
Signal {signum} was raised\\. Exiting with failure\\. \\(backtrace omitted\\)
""".format(signum=signal.SIGTERM))
    def test_pantsd_invalidation_file_tracking(self):
        test_file = 'testprojects/src/python/print_env/main.py'
        config = {
            'GLOBAL': {
                'pantsd_invalidation_globs':
                '["testprojects/src/python/print_env/*"]'
            }
        }
        with self.pantsd_successful_run_context(
                extra_config=config) as (pantsd_run, checker, workdir, _):
            pantsd_run(['help'])
            checker.assert_started()

            # Let any fs events quiesce.
            time.sleep(5)

            def full_pantsd_log():
                return '\n'.join(read_pantsd_log(workdir))

            # Check the logs.
            assertRegex(self, full_pantsd_log(),
                        r'watching invalidating files:.*{}'.format(test_file))

            checker.assert_running()
            touch(test_file)
            # Permit ample time for the async file event propagate in CI.
            time.sleep(10)
            checker.assert_stopped()

            self.assertIn('saw file events covered by invalidation globs',
                          full_pantsd_log())
예제 #4
0
 def test_no_fast(self):
     args = ['test.go', '--no-fast', 'contrib/go/examples/src/go/libA']
     pants_run = self.run_pants(args)
     self.assert_success(pants_run)
     # libA depends on libB, so both tests should be run.
     assertRegex(self, pants_run.stdout_data, r'ok\s+libA')
     assertRegex(self, pants_run.stdout_data, r'ok\s+libB')
예제 #5
0
    def test_pantsd_invalidation_stale_sources(self):
        test_path = 'tests/python/pants_test/daemon_correctness_test_0001'
        test_build_file = os.path.join(test_path, 'BUILD')
        test_src_file = os.path.join(test_path, 'some_file.py')
        has_source_root_regex = r'"source_root": ".*/{}"'.format(test_path)
        export_cmd = ['export', test_path]

        try:
            with self.pantsd_successful_run_context() as (pantsd_run, checker,
                                                          workdir, _):
                safe_mkdir(test_path, clean=True)

                pantsd_run(['help'])
                checker.assert_started()

                safe_file_dump(
                    test_build_file,
                    "python_library(sources=globs('some_non_existent_file.py'))"
                )
                result = pantsd_run(export_cmd)
                checker.assert_running()
                assertNotRegex(self, result.stdout_data, has_source_root_regex)

                safe_file_dump(test_build_file,
                               "python_library(sources=globs('*.py'))")
                result = pantsd_run(export_cmd)
                checker.assert_running()
                assertNotRegex(self, result.stdout_data, has_source_root_regex)

                safe_file_dump(test_src_file, 'import this\n')
                result = pantsd_run(export_cmd)
                checker.assert_running()
                assertRegex(self, result.stdout_data, has_source_root_regex)
        finally:
            rm_rf(test_path)
예제 #6
0
 def test_rst_normal(self):
     pants_run = self.run_pants([
         'markdown',
         'testprojects/src/java/org/pantsbuild/testproject/page:senserst'
     ])
     self.assert_success(pants_run)
     out_path = os.path.join(
         get_buildroot(), 'dist', 'markdown/html',
         'testprojects/src/java/org/pantsbuild/testproject/page',
         'sense.html')
     with safe_open(out_path, 'r') as outfile:
         page_html = outfile.read()
         # should get Sense and Sensibility in title (or TITLE, sheesh):
         assertRegex(
             self, page_html,
             r'(?i).*<title[^>]*>\s*Sense\s+and\s+Sensibility\s*</title')
         # should get formatted with h1:
         assertRegex(
             self, page_html,
             r'(?i).*<h1[^>]*>\s*They\s+Heard\s+Her\s+With\s+Surprise\s*</h1>'
         )
         # should get formatted with _something_
         assertRegex(self, page_html, r'.*>\s*inhabiting\s*</')
         assertRegex(self, page_html, r'.*>\s*civilly\s*</')
         # there should be a link that has href="http://www.calderdale.gov.uk/"
         assertRegex(self, page_html,
                     r'.*<a [^>]*href\s*=\s*[\'"]http://www.calderdale')
예제 #7
0
    def test_backup_logging_on_fatal_error(self):
        sink = self._gen_sink_subclass()
        with self.captured_logging(level=logging.ERROR) as captured:
            with temporary_dir() as tmpdir:
                sink.reset_log_location(tmpdir)
                with mock.patch.object(sink,
                                       '_try_write_with_flush',
                                       autospec=sink) as mock_write:
                    mock_write.side_effect = ExceptionSink.ExceptionSinkError(
                        'fake write failure')
                    sink.log_exception('XXX')
        errors = list(captured.errors())
        self.assertEqual(2, len(errors))

        def format_log_rx(log_file_type):
            return '.*'.join(
                re.escape(s) for s in [
                    "pants.base.exception_sink: Error logging the message 'XXX' to the {log_file_type} file "
                    "handle for".format(log_file_type=log_file_type),
                    "at pid {pid}".format(pid=os.getpid()),
                    "\nfake write failure",
                ])

        assertRegex(self, str(errors[0]), format_log_rx('pid-specific'))
        assertRegex(self, str(errors[1]), format_log_rx('shared'))
예제 #8
0
  def test_pantsd_invalidation_file_tracking(self):
    test_dir = 'testprojects/src/python/print_env'
    config = {'GLOBAL': {'pantsd_invalidation_globs': '["%s/*"]' %(test_dir)}}
    with self.pantsd_successful_run_context(extra_config=config) as (
      pantsd_run, checker, workdir, _
    ):
      pantsd_run(['help'])
      checker.assert_started()

      # Let any fs events quiesce.
      time.sleep(5)

      def full_pantsd_log():
        return '\n'.join(read_pantsd_log(workdir))

      # Check the logs.
      assertRegex(
        self,
        full_pantsd_log(),
        r'watching invalidating files:.*{}'.format(test_dir)
      )

      checker.assert_running()

      # Create a new file in test_dir
      with temporary_file(suffix='.py', binary_mode=False, root_dir=test_dir) as temp_f:
        temp_f.write("import that\n")
        temp_f.close()

        time.sleep(10)
        checker.assert_stopped()

      self.assertIn('saw file events covered by invalidation globs', full_pantsd_log())
예제 #9
0
    def test_logs_unhandled_exception(self):
        with temporary_dir() as tmpdir:
            pants_run = self.run_pants_with_workdir(
                [
                    '--no-enable-pantsd', 'list',
                    '//:this-target-does-not-exist'
                ],
                workdir=tmpdir,
                # The backtrace should be omitted when --print-exception-stacktrace=False.
                print_exception_stacktrace=False)
            self.assert_failure(pants_run)
            assertRegex(
                self, pants_run.stderr_data, """\\A\
timestamp: ([^\n]+)
Exception caught: \\(pants\\.build_graph\\.address_lookup_error\\.AddressLookupError\\) \\(backtrace omitted\\)
Exception message: Build graph construction failed: ExecutionError 1 Exception encountered:
  ResolveError: "this-target-does-not-exist" was not found in namespace ""\\. Did you mean one of:
""")
            pid_specific_log_file, shared_log_file = self._get_log_file_paths(
                tmpdir, pants_run)
            self._assert_unhandled_exception_log_matches(
                pants_run.pid,
                read_file(pid_specific_log_file, binary_mode=False))
            self._assert_unhandled_exception_log_matches(
                pants_run.pid, read_file(shared_log_file, binary_mode=False))
  def test_pantsd_invalidation_stale_sources(self):
    test_path = 'tests/python/pants_test/daemon_correctness_test_0001'
    test_build_file = os.path.join(test_path, 'BUILD')
    test_src_file = os.path.join(test_path, 'some_file.py')
    has_source_root_regex = r'"source_root": ".*/{}"'.format(test_path)
    export_cmd = ['export', test_path]

    try:
      with self.pantsd_successful_run_context() as (pantsd_run, checker, workdir, _):
        safe_mkdir(test_path, clean=True)

        pantsd_run(['help'])
        checker.assert_started()

        safe_file_dump(test_build_file, "python_library(sources=globs('some_non_existent_file.py'))")
        result = pantsd_run(export_cmd)
        checker.assert_running()
        assertNotRegex(self, result.stdout_data, has_source_root_regex)

        safe_file_dump(test_build_file, "python_library(sources=globs('*.py'))")
        result = pantsd_run(export_cmd)
        checker.assert_running()
        assertNotRegex(self, result.stdout_data, has_source_root_regex)

        safe_file_dump(test_src_file, 'import this\n')
        result = pantsd_run(export_cmd)
        checker.assert_running()
        assertRegex(self, result.stdout_data, has_source_root_regex)
    finally:
      rm_rf(test_path)
예제 #11
0
 def test_list_parse_java_targets(self):
   pants_run = self.do_command('list',
                               'testprojects/tests/java/org/pantsbuild/build_parsing::',
                               success=True)
   assertRegex(self,
     pants_run.stdout_data,
     r'testprojects/tests/java/org/pantsbuild/build_parsing:trailing_glob_doublestar'
   )
예제 #12
0
 def test_engine_list(self):
     pants_run = self.run_pants(['-ldebug', 'list', '3rdparty::'])
     self.assert_success(pants_run)
     assertRegex(self, pants_run.stderr_data,
                 'build_graph is: .*LegacyBuildGraph')
     assertRegex(self, pants_run.stderr_data, 'computed \d+ nodes in')
     assertNotRegex(self, pants_run.stderr_data,
                    'pantsd is running at pid \d+')
예제 #13
0
    def _assert_graceful_signal_log_matches(self, pid, signum, contents):
        assertRegex(
            self, contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Signal {signum} was raised\\. Exiting with failure\\. \\(backtrace omitted\\)
""".format(pid=pid, signum=signum))
예제 #14
0
 def test_run_repl_with_3(self):
   # Run a Python 3 repl on a Python 2/3 library target. Avoid some known-to-choke-on interpreters.
   command = ['repl',
              '--python-setup-interpreter-constraints=["CPython>=3.3"]',
              'testprojects/src/python/interpreter_selection:echo_interpreter_version_lib',
              '--quiet']
   program = 'from interpreter_selection.echo_interpreter_version import say_hello; say_hello()'
   pants_run = self.run_pants(command=command, stdin_data=program)
   assertRegex(self, pants_run.stdout_data, r'3\.\d\.\d')
예제 #15
0
    def assertWarnInfoOutput(self, lines):
        """Check to see that only warn and info output appears in the stream.

    The first line may start with WARN] or WARNING] depending on whether 'WARN'
    has been registered as a global log level.  See options_bootstrapper.py.
    """
        self.assertEqual(2, len(lines))
        assertRegex(self, lines[0], '^WARN\w*] warn')
        self.assertEqual('INFO] info', lines[1])
 def test_no_fast(self):
   args = ['test.go',
           '--no-fast',
           'contrib/go/examples/src/go/libA']
   pants_run = self.run_pants(args)
   self.assert_success(pants_run)
   # libA depends on libB, so both tests should be run.
   assertRegex(self, pants_run.stdout_data, r'ok\s+libA')
   assertRegex(self, pants_run.stdout_data, r'ok\s+libB')
예제 #17
0
 def test_list_parse_java_targets(self):
     pants_run = self.do_command(
         'list',
         'testprojects/tests/java/org/pantsbuild/build_parsing::',
         success=True)
     assertRegex(
         self, pants_run.stdout_data,
         r'testprojects/tests/java/org/pantsbuild/build_parsing:trailing_glob_doublestar'
     )
예제 #18
0
 def test_run_repl_with_3(self):
     # Run a Python 3 repl on a Python 2/3 library target. Avoid some known-to-choke-on interpreters.
     command = [
         'repl', '--python-setup-interpreter-constraints=["CPython>=3.3"]',
         'testprojects/src/python/interpreter_selection:echo_interpreter_version_lib',
         '--quiet'
     ]
     program = 'from interpreter_selection.echo_interpreter_version import say_hello; say_hello()'
     pants_run = self.run_pants(command=command, stdin_data=program)
     assertRegex(self, pants_run.stdout_data, r'3\.\d\.\d')
예제 #19
0
  def test_exclude_invalid_string(self):
    build_path = os.path.join(self.PATH_PREFIX, 'BUILD.invalid')
    build_content = '''python_library(name='exclude_strings_disallowed',
                                      sources=rglobs('*.py', exclude='aa.py'))'''

    with self.temporary_file_content(build_path, build_content, binary_mode=False):
      pants_run = self.do_command('filemap',
                                  self._mk_target('exclude_strings_disallowed'),
                                  success=False)
      assertRegex(self, pants_run.stderr_data,
                               r'Excludes of type `.*` are not supported')
예제 #20
0
  def test_go_command_gopath(self):
    go_distribution = self.distribution()
    go_cmd = go_distribution.create_go_cmd(cmd='env', gopath='/tmp/fred', args=['GOROOT'])

    self.assertEqual({'GOROOT': go_distribution.goroot,
                      'GOPATH': '/tmp/fred'}, go_cmd.env)
    self.assertEqual('go', os.path.basename(go_cmd.cmdline[0]))
    self.assertEqual(['env', 'GOROOT'], go_cmd.cmdline[1:])

    regex = GoDistributionTest._generate_go_command_regex(gopath='/tmp/fred', final_value='GOROOT')
    assertRegex(self, str(go_cmd), regex)
예제 #21
0
  def test_prints_traceback_on_sigusr2(self):
    with self._make_waiter_handle() as (workdir, pid, join):
      # Send SIGUSR2, then sleep so the signal handler from faulthandler.register() can run.
      os.kill(pid, signal.SIGUSR2)
      time.sleep(1)

      waiter_run = join()
      self.assert_success(waiter_run)
      assertRegex(self, waiter_run.stderr_data, """\
Current thread [^\n]+ \\(most recent call first\\):
""")
  def test_prints_traceback_on_sigusr2(self):
    with self._make_waiter_handle() as (workdir, pid, join):
      # Send SIGUSR2, then sleep so the signal handler from faulthandler.register() can run.
      os.kill(pid, signal.SIGUSR2)
      time.sleep(1)

      waiter_run = join()
      self.assert_success(waiter_run)
      assertRegex(self, waiter_run.stderr_data, """\
Current thread [^\n]+ \\(most recent call first\\):
""")
  def test_native_logging(self):
    expected_msg = "\[DEBUG\] engine::scheduler: Launching \d+ root"
    pants_run = self.run_pants([
      "-linfo", "list", "src/scala::"
    ])
    assertNotRegex(self, pants_run.stderr_data, expected_msg)

    pants_run = self.run_pants([
      "-ldebug", "list", "src/scala::"
    ])
    assertRegex(self, pants_run.stderr_data, expected_msg)
예제 #24
0
  def _assert_graceful_signal_log_matches(self, pid, signum, signame, contents):
    assertRegex(self, contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Signal {signum} \\({signame}\\) was raised\\. Exiting with failure\\.
""".format(pid=pid, signum=signum, signame=signame))
    # Ensure we write all output such as stderr and reporting files before closing any streams.
    self.assertNotIn(
      'Exception message: I/O operation on closed file.',
      contents)
  def _assert_graceful_signal_log_matches(self, pid, signum, signame, contents):
    assertRegex(self, contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Signal {signum} \\({signame}\\) was raised\\. Exiting with failure\\.
""".format(pid=pid, signum=signum, signame=signame))
    # Ensure we write all output such as stderr and reporting files before closing any streams.
    self.assertNotIn(
      'Exception message: I/O operation on closed file.',
      contents)
예제 #26
0
    def _assert_pantsd_keyboardinterrupt_signal(self,
                                                signum,
                                                regexps=[],
                                                quit_timeout=None):
        """Send a signal to the thin pailgun client and observe the error messaging.

    :param int signum: The signal to send.
    :param regexps: Assert that all of these regexps match somewhere in stderr.
    :type regexps: list of str
    :param float quit_timeout: The duration of time to wait for the pailgun client to flush all of
                               its output and die after being killed.
    """
        # TODO: This tests that pantsd-runner processes actually die after the thin client receives the
        # specified signal.
        with self.pantsd_test_context() as (workdir, config, checker):
            # Launch a run that will wait for a file to be created (but do not create that file).
            file_to_make = os.path.join(workdir, 'some_magic_file')

            if quit_timeout is not None:
                timeout_args = [
                    '--pantsd-pailgun-quit-timeout={}'.format(quit_timeout)
                ]
            else:
                timeout_args = []
            argv = timeout_args + [
                'run', 'testprojects/src/python/coordinated_runs:waiter', '--',
                file_to_make
            ]
            waiter_handle = self.run_pants_with_workdir_without_waiting(
                argv, workdir, config)
            client_pid = waiter_handle.process.pid

            checker.assert_started()
            checker.assert_pantsd_runner_started(client_pid)

            # Get all the pantsd-runner processes while they're still around.
            pantsd_runner_processes = checker.runner_process_context.current_processes(
            )
            # This should kill the pantsd-runner processes through the RemotePantsRunner signal handler.
            os.kill(client_pid, signum)
            waiter_run = waiter_handle.join()
            self.assert_failure(waiter_run)

            for regexp in regexps:
                assertRegex(self, waiter_run.stderr_data, regexp)

            time.sleep(1)
            for proc in pantsd_runner_processes:
                # TODO: we could be checking the return codes of the subprocesses, but psutil is currently
                # limited on non-Windows hosts -- see https://psutil.readthedocs.io/en/latest/#processes.
                # The pantsd-runner processes should be dead, and they should have exited with 1.
                self.assertFalse(proc.is_running())
예제 #27
0
 def test_dumps_stack_trace(self):
   graph = ExecutionGraph([self.job('A', raising_wrapper, [])], True)
   capturing_logger = CapturingLogger()
   with self.assertRaises(ExecutionFailure):
     graph.execute(ImmediatelyExecutingPool(), capturing_logger)
   error_logs = capturing_logger.log_entries['error']
   self.assertEqual(2, len(error_logs), msg='Wanted one error log, got: {}'.format(error_logs))
   self.assertEqual("A failed: I'm an error", error_logs[0])
   regex = re.compile(
     "Traceback:.*in raising_wrapper.*raise Exception\\(\"I'm an error\"\\)",
     re.DOTALL,
   )
   assertRegex(self, error_logs[1], regex)
  def test_dumps_traceback_on_sigabrt(self):
    # SIGABRT sends a traceback to the log file for the current process thanks to
    # faulthandler.enable().
    with self._send_signal_to_waiter_handle(signal.SIGABRT) as (workdir, waiter_run):
      # Check that the logs show an abort signal and the beginning of a traceback.
      pid_specific_log_file, shared_log_file = self._get_log_file_paths(workdir, waiter_run)
      assertRegex(self, read_file(pid_specific_log_file), """\
Fatal Python error: Aborted

Thread [^\n]+ \\(most recent call first\\):
""")
      # faulthandler.enable() only allows use of a single logging file at once for fatal tracebacks.
      self.assertEqual('', read_file(shared_log_file))
예제 #29
0
  def test_dumps_traceback_on_sigabrt(self):
    # SIGABRT sends a traceback to the log file for the current process thanks to
    # faulthandler.enable().
    with self._send_signal_to_waiter_handle(signal.SIGABRT) as (workdir, waiter_run):
      # Check that the logs show an abort signal and the beginning of a traceback.
      pid_specific_log_file, shared_log_file = self._get_log_file_paths(workdir, waiter_run)
      assertRegex(self, read_file(pid_specific_log_file, binary_mode=False), """\
Fatal Python error: Aborted

Thread [^\n]+ \\(most recent call first\\):
""")
      # faulthandler.enable() only allows use of a single logging file at once for fatal tracebacks.
      self.assertEqual('', read_file(shared_log_file, binary_mode=False))
예제 #30
0
  def test_nailgun_connect_timeout(self):
    pants_run = self.run_pants(
      ['compile', self.target],
      # Override the PANTS_CONFIG_FILES="pants.travis-ci.ini" used within TravisCI to enable
      # nailgun usage for the purpose of exercising that stack in the integration test.
      config={'DEFAULT': {'execution_strategy': 'nailgun'},
              'compile.zinc': {'nailgun_timeout_seconds': '0.00002'}}
    )
    self.assert_failure(pants_run)
    assertRegex(self, pants_run.stdout_data, """\
compile\\(examples/src/java/org/pantsbuild/example/hello/greet:greet\\) failed: \
Problem launching via <no nailgun connection> command org\\.pantsbuild\\.zinc\\.compiler\\.Main .*: \
Failed to read nailgun output after 2e\-05 seconds!""")
예제 #31
0
    def _assert_unhandled_exception_log_matches(self, pid, file_contents):
        assertRegex(
            self, file_contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Exception caught: \\(pants\\.build_graph\\.address_lookup_error\\.AddressLookupError\\)
(.|\n)*

Exception message: Build graph construction failed: ExecutionError 1 Exception encountered:
  ResolveError: "this-target-does-not-exist" was not found in namespace ""\\. Did you mean one of:
""".format(pid=pid))
  def test_go_test_with_options(self):
    args = [
      'test.go', '--shlexed-build-and-test-flags=["-v"]',
      'contrib/go/examples/src/go/libA',
    ]
    pants_run = self.run_pants(args)
    self.assert_success(pants_run)
    assertRegex(self, pants_run.stdout_data, r'ok\s+libA')
    assertRegex(self, pants_run.stdout_data, r'ok\s+libB')

    # Ensure that more verbose output is presented.
    self.assertIn('=== RUN   TestAdd', pants_run.stdout_data)
    self.assertIn('PASS', pants_run.stdout_data)
 def test_changed_with_deleted_target_transitive(self):
     with create_isolated_git_repo() as worktree:
         safe_delete(
             os.path.join(
                 worktree,
                 'src/resources/org/pantsbuild/resourceonly/BUILD'))
         pants_run = self.run_pants([
             'list', '--changed-parent=HEAD',
             '--changed-include-dependees=transitive'
         ])
         self.assert_failure(pants_run)
         assertRegex(
             self, pants_run.stderr_data,
             'src/resources/org/pantsbuild/resourceonly:.*did not exist')
예제 #34
0
    def test_prints_traceback_on_sigusr2(self):
        with self._make_waiter_handle() as (workdir, waiter_handle):
            time.sleep(5)
            # Send SIGUSR2, then sleep so the signal handler from faulthandler.register() can run.
            os.kill(waiter_handle.process.pid, signal.SIGUSR2)
            time.sleep(1)
            # This target will wait forever, so kill the process and ensure its output is correct.
            os.kill(waiter_handle.process.pid, signal.SIGKILL)
            waiter_run = waiter_handle.join()
            self.assert_failure(waiter_run)
            assertRegex(
                self, waiter_run.stderr_data, """\
Current thread [^\n]+ \\(most recent call first\\):
""")
예제 #35
0
    def test_go_test_with_options(self):
        args = [
            'test.go',
            '--shlexed-build-and-test-flags=["-v"]',
            'contrib/go/examples/src/go/libA',
        ]
        pants_run = self.run_pants(args)
        self.assert_success(pants_run)
        assertRegex(self, pants_run.stdout_data, r'ok\s+libA')
        assertRegex(self, pants_run.stdout_data, r'ok\s+libB')

        # Ensure that more verbose output is presented.
        self.assertIn('=== RUN   TestAdd', pants_run.stdout_data)
        self.assertIn('PASS', pants_run.stdout_data)
  def _assert_unhandled_exception_log_matches(self, pid, file_contents):
    assertRegex(self, file_contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Exception caught: \\([^)]*\\)
(.|\n)*

Exception message:.* 1 Exception encountered:
  ResolveError: "this-target-does-not-exist" was not found in namespace ""\\. Did you mean one of:
""".format(pid=pid))
    # Ensure we write all output such as stderr and reporting files before closing any streams.
    self.assertNotIn(
      'Exception message: I/O operation on closed file.',
      file_contents)
예제 #37
0
 def test_pants_binary(self):
   with temporary_dir() as tmp_dir:
     pex = os.path.join(tmp_dir, 'main.pex')
     command=[
       '--pants-distdir={}'.format(tmp_dir), 'binary', '{}:main'.format(self.fasthello_project)]
     pants_run = self.run_pants(command=command)
     self.assert_success(pants_run)
     # Check that the pex was built.
     self.assertTrue(os.path.isfile(pex))
     # Check that the pex runs.
     output = subprocess.check_output(pex).decode('utf-8')
     self._assert_native_greeting(output)
     # Check that we have exactly one wheel output.
     single_wheel_output = assert_single_element(glob.glob(os.path.join(tmp_dir, '*.whl')))
     assertRegex(self, os.path.basename(single_wheel_output),
                              r'\A{}'.format(re.escape('fasthello-1.0.0+')))
예제 #38
0
  def _assert_unhandled_exception_log_matches(self, pid, file_contents):
    assertRegex(self, file_contents, """\
timestamp: ([^\n]+)
process title: ([^\n]+)
sys\\.argv: ([^\n]+)
pid: {pid}
Exception caught: \\(pants\\.build_graph\\.address_lookup_error\\.AddressLookupError\\)
(.|\n)*

Exception message: Build graph construction failed: ExecutionError 1 Exception encountered:
  ResolveError: "this-target-does-not-exist" was not found in namespace ""\\. Did you mean one of:
""".format(pid=pid))
    # Ensure we write all output such as stderr and reporting files before closing any streams.
    self.assertNotIn(
      'Exception message: I/O operation on closed file.',
      file_contents)
예제 #39
0
    def test_dumps_logs_on_terminate(self):
        # Send a SIGTERM to the local pants process.
        with self._send_signal_to_waiter_handle(
                signal.SIGTERM) as (workdir, waiter_run):
            assertRegex(
                self, waiter_run.stderr_data, """\
timestamp: ([^\n]+)
Signal {signum} was raised. Exiting with failure. \\(backtrace omitted\\)
""".format(signum=signal.SIGTERM))
            # Check that the logs show a graceful exit by SIGTERM.
            pid_specific_log_file, shared_log_file = self._get_log_file_paths(
                workdir, waiter_run)
            self._assert_graceful_signal_log_matches(
                waiter_run.pid, signal.SIGTERM,
                read_file(pid_specific_log_file, binary_mode=False))
            self._assert_graceful_signal_log_matches(
                waiter_run.pid, signal.SIGTERM,
                read_file(shared_log_file, binary_mode=False))
  def test_dumps_logs_on_signal(self):
    """Send signals which are handled, but don't get converted into a KeyboardInterrupt."""
    signal_names = {
      signal.SIGQUIT: 'SIGQUIT',
      signal.SIGTERM: 'SIGTERM',
    }
    for (signum, signame) in signal_names.items():
      with self._send_signal_to_waiter_handle(signum) as (workdir, waiter_run):
        assertRegex(self, waiter_run.stderr_data, """\
timestamp: ([^\n]+)
Signal {signum} \\({signame}\\) was raised\\. Exiting with failure\\.
""".format(signum=signum, signame=signame))
        # Check that the logs show a graceful exit by SIGTERM.
        pid_specific_log_file, shared_log_file = self._get_log_file_paths(workdir, waiter_run)
        self._assert_graceful_signal_log_matches(
          waiter_run.pid, signum, signame, read_file(pid_specific_log_file))
        self._assert_graceful_signal_log_matches(
          waiter_run.pid, signum, signame, read_file(shared_log_file))
예제 #41
0
  def test_dumps_logs_on_signal(self):
    """Send signals which are handled, but don't get converted into a KeyboardInterrupt."""
    signal_names = {
      signal.SIGQUIT: 'SIGQUIT',
      signal.SIGTERM: 'SIGTERM',
    }
    for (signum, signame) in signal_names.items():
      with self._send_signal_to_waiter_handle(signum) as (workdir, waiter_run):
        assertRegex(self, waiter_run.stderr_data, """\
timestamp: ([^\n]+)
Signal {signum} \\({signame}\\) was raised\\. Exiting with failure\\.
""".format(signum=signum, signame=signame))
        # Check that the logs show a graceful exit by SIGTERM.
        pid_specific_log_file, shared_log_file = self._get_log_file_paths(workdir, waiter_run)
        self._assert_graceful_signal_log_matches(
          waiter_run.pid, signum, signame, read_file(pid_specific_log_file, binary_mode=False))
        self._assert_graceful_signal_log_matches(
          waiter_run.pid, signum, signame, read_file(shared_log_file, binary_mode=False))
  def _assert_pantsd_keyboardinterrupt_signal(self, signum, regexps=[], quit_timeout=None):
    """Send a signal to the thin pailgun client and observe the error messaging.

    :param int signum: The signal to send.
    :param regexps: Assert that all of these regexps match somewhere in stderr.
    :type regexps: list of str
    :param float quit_timeout: The duration of time to wait for the pailgun client to flush all of
                               its output and die after being killed.
    """
    # TODO: This tests that pantsd-runner processes actually die after the thin client receives the
    # specified signal.
    with self.pantsd_test_context() as (workdir, config, checker):
      # Launch a run that will wait for a file to be created (but do not create that file).
      file_to_make = os.path.join(workdir, 'some_magic_file')

      if quit_timeout is not None:
        timeout_args = ['--pantsd-pailgun-quit-timeout={}'.format(quit_timeout)]
      else:
        timeout_args = []
      argv = timeout_args + [
        'run', 'testprojects/src/python/coordinated_runs:waiter', '--', file_to_make
      ]
      waiter_handle = self.run_pants_with_workdir_without_waiting(argv, workdir, config)
      client_pid = waiter_handle.process.pid

      checker.assert_started()
      checker.assert_pantsd_runner_started(client_pid)

      # Get all the pantsd-runner processes while they're still around.
      pantsd_runner_processes = checker.runner_process_context.current_processes()
      # This should kill the pantsd-runner processes through the RemotePantsRunner signal handler.
      os.kill(client_pid, signum)
      waiter_run = waiter_handle.join()
      self.assert_failure(waiter_run)

      for regexp in regexps:
        assertRegex(self, waiter_run.stderr_data, regexp)

      time.sleep(1)
      for proc in pantsd_runner_processes:
        # TODO: we could be checking the return codes of the subprocesses, but psutil is currently
        # limited on non-Windows hosts -- see https://psutil.readthedocs.io/en/latest/#processes.
        # The pantsd-runner processes should be dead, and they should have exited with 1.
        self.assertFalse(proc.is_running())
 def test_pydist_binary(self):
   with temporary_dir() as tmp_dir:
     pex = os.path.join(tmp_dir, 'main_with_no_conflict.pex')
     command = [
       '--pants-distdir={}'.format(tmp_dir),
       'binary',
       '{}:main_with_no_conflict'.format(self.hello_install_requires_dir),
     ]
     pants_run = self.run_pants(command=command)
     self.assert_success(pants_run)
     # Check that the pex was built.
     self.assertTrue(os.path.isfile(pex))
     # Check that the pex runs.
     output = subprocess.check_output(pex).decode('utf-8')
     self._assert_nation_and_greeting(output)
     # Check that we have exactly one wheel output.
     single_wheel_output = assert_single_element(glob.glob(os.path.join(tmp_dir, '*.whl')))
     assertRegex(self, os.path.basename(single_wheel_output),
                 r'\A{}'.format(re.escape('hello_with_install_requires-1.0.0+')))
  def test_logs_unhandled_exception(self):
    with temporary_dir() as tmpdir:
      pants_run = self.run_pants_with_workdir(
        ['--no-enable-pantsd', 'list', '//:this-target-does-not-exist'],
        workdir=tmpdir,
        # The backtrace should be omitted when --print-exception-stacktrace=False.
        print_exception_stacktrace=False)
      self.assert_failure(pants_run)
      assertRegex(self, pants_run.stderr_data, """\
timestamp: ([^\n]+)
Exception caught: \\(pants\\.engine\\.scheduler\\.ExecutionError\\) \\(backtrace omitted\\)
Exception message: 1 Exception encountered:
  ResolveError: "this-target-does-not-exist" was not found in namespace ""\\. Did you mean one of:
""")
      pid_specific_log_file, shared_log_file = self._get_log_file_paths(tmpdir, pants_run)
      self._assert_unhandled_exception_log_matches(
        pants_run.pid, read_file(pid_specific_log_file))
      self._assert_unhandled_exception_log_matches(
        pants_run.pid, read_file(shared_log_file))
 def test_rst_normal(self):
   pants_run = self.run_pants(['markdown',
                               'testprojects/src/java/org/pantsbuild/testproject/page:senserst'])
   self.assert_success(pants_run)
   out_path = os.path.join(get_buildroot(), 'dist', 'markdown/html',
                           'testprojects/src/java/org/pantsbuild/testproject/page',
                           'sense.html')
   with safe_open(out_path, 'r') as outfile:
     page_html = outfile.read()
     # should get Sense and Sensibility in title (or TITLE, sheesh):
     assertRegex(self, page_html,
                              r'(?i).*<title[^>]*>\s*Sense\s+and\s+Sensibility\s*</title')
     # should get formatted with h1:
     assertRegex(self, page_html,
                              r'(?i).*<h1[^>]*>\s*They\s+Heard\s+Her\s+With\s+Surprise\s*</h1>')
     # should get formatted with _something_
     assertRegex(self, page_html, r'.*>\s*inhabiting\s*</')
     assertRegex(self, page_html, r'.*>\s*civilly\s*</')
     # there should be a link that has href="http://www.calderdale.gov.uk/"
     assertRegex(self, page_html, r'.*<a [^>]*href\s*=\s*[\'"]http://www.calderdale')
  def test_go_test_simple(self):
    args = ['test',
            'contrib/go/examples/src/go/libA']
    pants_run = self.run_pants(args)
    self.assert_success(pants_run)
    # libA depends on libB, so both tests should be run.
    assertRegex(self, pants_run.stdout_data, r'ok\s+libA')
    assertRegex(self, pants_run.stdout_data, r'ok\s+libB')

    # Run a second time and see that they are cached.
    # TODO: this is better done with a unit test, and as noted in #7188, testing interaction with a
    # remote cache should probably be added somewhere.
    pants_run = self.run_pants(args)
    self.assert_success(pants_run)
    assertRegex(self, pants_run.stdout_data, r'contrib/go/examples/src/go/libA\s+\.+\s+SUCCESS')
    assertRegex(self, pants_run.stdout_data, r'contrib/go/examples/src/go/libB\s+\.+\s+SUCCESS')

    # Assert that we do *not* contain verbose output.
    self.assertNotIn('=== RUN   TestAdd', pants_run.stdout_data)
    self.assertNotIn('PASS', pants_run.stdout_data)
 def test_go_run_cgo(self):
   args = ['-q', 'run', 'contrib/go/examples/src/go/cgo']
   pants_run = self.run_pants(args)
   self.assert_success(pants_run)
   assertRegex(self, pants_run.stdout_data.strip(), r'^Random from C: \d+$')
 def test_changed_with_deleted_target_transitive(self):
   with create_isolated_git_repo() as worktree:
     safe_delete(os.path.join(worktree, 'src/resources/org/pantsbuild/resourceonly/BUILD'))
     pants_run = self.run_pants(['list', '--changed-parent=HEAD', '--changed-include-dependees=transitive'])
     self.assert_failure(pants_run)
     assertRegex(self, pants_run.stderr_data, 'src/resources/org/pantsbuild/resourceonly:.*did not exist')