summaryrefslogtreecommitdiffstats
path: root/lldb/packages/Python/lldbsuite/test/darwin_log.py
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/darwin_log.py')
-rw-r--r--lldb/packages/Python/lldbsuite/test/darwin_log.py430
1 files changed, 0 insertions, 430 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/darwin_log.py b/lldb/packages/Python/lldbsuite/test/darwin_log.py
deleted file mode 100644
index f2d4f1df6e2..00000000000
--- a/lldb/packages/Python/lldbsuite/test/darwin_log.py
+++ /dev/null
@@ -1,430 +0,0 @@
-"""
-Base class for DarwinLog tests.
-"""
-
-# System imports
-from __future__ import print_function
-
-import json
-import os
-import pexpect
-import platform
-import re
-import sys
-import threading
-
-
-# lldb imports
-import lldb
-from lldb import SBProcess, SBTarget
-
-from lldbsuite.test import decorators
-from lldbsuite.test import lldbtest
-from lldbsuite.test import lldbtest_config
-from lldbsuite.test import lldbutil
-
-
-def expand_darwinlog_command(command):
- return "plugin structured-data darwin-log " + command
-
-
-def expand_darwinlog_settings_set_command(command):
- return "settings set plugin.structured-data.darwin-log." + command
-
-
-class DarwinLogTestBase(lldbtest.TestBase):
- """Base class for DarwinLog test cases that are pexpect-based."""
- NO_DEBUG_INFO_TESTCASE = True
-
- CONTINUE_REGEX = re.compile(r"Process \d+ resuming")
-
- def setUp(self):
- # Call super's setUp().
- super(DarwinLogTestBase, self).setUp()
-
- # Until other systems support this, exit
- # early if we're not macOS version 10.12
- # or greater.
- version = platform.mac_ver()[0].split('.')
- if ((int(version[0]) == 10) and (int(version[1]) < 12) or
- (int(version[0]) < 10)):
- self.skipTest("DarwinLog tests currently require macOS 10.12+")
- return
-
- self.child = None
- self.child_prompt = '(lldb) '
- self.strict_sources = False
- self.enable_process_monitor_logging = False
-
- def run_lldb_to_breakpoint(self, exe, source_file, line,
- enable_command=None, settings_commands=None):
-
- # Set self.child_prompt, which is "(lldb) ".
- prompt = self.child_prompt
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn('%s %s %s' % (lldbtest_config.lldbExec,
- self.lldbOption, exe))
- child = self.child
-
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- if self.enable_process_monitor_logging:
- if platform.system() == 'Darwin':
- self.runCmd("settings set target.process.extra-startup-command "
- "QSetLogging:bitmask=LOG_DARWIN_LOG;")
- self.expect_prompt()
-
- # Run the enable command if we have one.
- if enable_command is not None:
- self.runCmd(enable_command)
- self.expect_prompt()
-
- # Disable showing of source lines at our breakpoint.
- # This is necessary for the logging tests, because the very
- # text we want to match for output from the running inferior
- # will show up in the source as well. We don't want the source
- # output to erroneously make a match with our expected output.
- self.runCmd("settings set stop-line-count-before 0")
- self.expect_prompt()
- self.runCmd("settings set stop-line-count-after 0")
- self.expect_prompt()
-
- # While we're debugging, turn on packet logging.
- self.runCmd("log enable -f /tmp/packets.log gdb-remote packets")
- self.expect_prompt()
-
- # Prevent mirroring of NSLog/os_log content to stderr. We want log
- # messages to come exclusively through our log channel.
- self.runCmd("settings set target.env-vars IDE_DISABLED_OS_ACTIVITY_DT_MODE=1")
- self.expect_prompt()
-
- # Run any darwin-log settings commands now, before we enable logging.
- if settings_commands is not None:
- for setting_command in settings_commands:
- self.runCmd(
- expand_darwinlog_settings_set_command(setting_command))
- self.expect_prompt()
-
- # Set breakpoint right before the os_log() macros. We don't
- # set it on the os_log*() calls because these are a number of
- # nested-scoped calls that will cause the debugger to stop
- # multiple times on the same line. That is difficult to match
- # os_log() content by since it is non-deterministic what the
- # ordering between stops and log lines will be. This is why
- # we stop before, and then have the process run in a sleep
- # afterwards, so we get the log messages while the target
- # process is "running" (sleeping).
- child.sendline('breakpoint set -f %s -l %d' % (source_file, line))
- child.expect_exact(prompt)
-
- # Now run to the breakpoint that we just set.
- child.sendline('run')
- child.expect_exact(prompt)
-
- # Ensure we stopped at a breakpoint.
- self.runCmd("thread list")
- self.expect(re.compile(r"stop reason = breakpoint"))
-
- # Now we're ready to check if DarwinLog is available.
- if not self.darwin_log_available():
- self.skipTest("DarwinLog not available")
-
- def runCmd(self, cmd):
- self.child.sendline(cmd)
-
- def expect_prompt(self, exactly=True):
- self.expect(self.child_prompt, exactly=exactly)
-
- def expect(self, pattern, exactly=False, *args, **kwargs):
- if exactly:
- return self.child.expect_exact(pattern, *args, **kwargs)
- return self.child.expect(pattern, *args, **kwargs)
-
- def darwin_log_available(self):
- self.runCmd("plugin structured-data darwin-log status")
- self.expect(re.compile(r"Availability: ([\S]+)"))
- return self.child.match is not None and (
- self.child.match.group(1) == "available")
-
- def do_test(self, enable_options, expect_regexes=None,
- settings_commands=None):
- """Test that a single fall-through reject rule rejects all logging."""
- self.build(dictionary=self.d)
- self.setTearDownCleanup(dictionary=self.d)
-
- # Build the darwin-log enable command.
- enable_cmd = expand_darwinlog_command('enable')
- if enable_options is not None and len(enable_options) > 0:
- enable_cmd += ' ' + ' '.join(enable_options)
-
- exe = os.path.join(os.getcwd(), self.exe_name)
- self.run_lldb_to_breakpoint(exe, self.source, self.line,
- enable_command=enable_cmd,
- settings_commands=settings_commands)
- self.expect_prompt()
-
- # Now go.
- self.runCmd("process continue")
- self.expect(self.CONTINUE_REGEX)
-
- if expect_regexes is None:
- # Expect matching a log line or program exit.
- # Test methods determine which ones are valid.
- expect_regexes = (
- [re.compile(r"source-log-([^-]+)-(\S+)"),
- re.compile(r"exited with status")
- ])
- self.expect(expect_regexes)
-
-
-def remove_add_mode_entry(log_entries):
- """libtrace creates an "Add Mode:..." message when logging is enabled.
- Strip this out of results since our test subjects don't create it."""
- return [entry for entry in log_entries
- if "message" in entry and
- not entry["message"].startswith("Add Mode:")]
-
-
-class DarwinLogEventBasedTestBase(lldbtest.TestBase):
- """Base class for event-based DarwinLog tests."""
- NO_DEBUG_INFO_TESTCASE = True
-
- class EventListenerThread(threading.Thread):
- def __init__(self, listener, process, trace_on, max_entry_count):
- super(DarwinLogEventBasedTestBase.EventListenerThread, self).__init__()
- self.process = process
- self.listener = listener
- self.trace_on = trace_on
- self.max_entry_count = max_entry_count
- self.exception = None
- self.structured_data_event_count = 0
- self.wait_seconds = 2
- self.max_timeout_count = 4
- self.log_entries = []
-
- def handle_structured_data_event(self, event):
- structured_data = SBProcess.GetStructuredDataFromEvent(event)
- if not structured_data.IsValid():
- if self.trace_on:
- print("invalid structured data")
- return
-
- # Track that we received a valid structured data event.
- self.structured_data_event_count += 1
-
- # Grab the individual log entries from the JSON.
- stream = lldb.SBStream()
- structured_data.GetAsJSON(stream)
- dict = json.loads(stream.GetData())
- self.log_entries.extend(dict["events"])
- if self.trace_on:
- print("Structured data (raw):", stream.GetData())
-
- # Print the pretty-printed version.
- if self.trace_on:
- stream.Clear()
- structured_data.PrettyPrint(stream)
- print("Structured data (pretty print):",
- stream.GetData())
-
- def done(self, timeout_count):
- """Returns True when we're done listening for events."""
- # See if we should consider the number of events retrieved.
- if self.max_entry_count is not None:
- if len(self.log_entries) >= self.max_entry_count:
- # We've received the max threshold of events expected,
- # we can exit here.
- if self.trace_on:
- print("Event listener thread exiting due to max "
- "expected log entry count being reached.")
- return True
-
- # If our event timeout count has exceeded our maximum timeout count,
- # we're done.
- if timeout_count >= self.max_timeout_count:
- if self.trace_on:
- print("Event listener thread exiting due to max number of "
- "WaitForEvent() timeouts being reached.")
- return True
-
- # If our process is dead, we're done.
- if not self.process.is_alive:
- if self.trace_on:
- print("Event listener thread exiting due to test inferior "
- "exiting.")
- return True
-
- # We're not done.
- return False
-
- def run(self):
- event = lldb.SBEvent()
- try:
- timeout_count = 0
-
- # Wait up to 4 times for the event to arrive.
- while not self.done(timeout_count):
- if self.trace_on:
- print("Calling wait for event...")
- if self.listener.WaitForEvent(self.wait_seconds, event):
- while event.IsValid():
- # Check if it's a process event.
- if SBProcess.EventIsStructuredDataEvent(event):
- self.handle_structured_data_event(event)
- else:
- if self.trace_on:
- print("ignoring unexpected event:",
- lldbutil.get_description(event))
- # Grab the next event, if there is one.
- event.Clear()
- if not self.listener.GetNextEvent(event):
- if self.trace_on:
- print("listener has no more events "
- "available at this time")
- else:
- if self.trace_on:
- print("timeout occurred waiting for event...")
- timeout_count += 1
- self.listener.Clear()
- except Exception as e:
- self.exception = e
-
- def setUp(self):
- # Call super's setUp().
- super(DarwinLogEventBasedTestBase, self).setUp()
-
- # Source filename.
- self.source = 'main.c'
-
- # Output filename.
- self.exe_name = 'a.out'
- self.d = {'C_SOURCES': self.source, 'EXE': self.exe_name}
-
- # Locate breakpoint.
- self.line = lldbtest.line_number(self.source, '// break here')
-
- # Enable debugserver logging of the darwin log collection
- # mechanism.
- self.runCmd("settings set target.process.extra-startup-command "
- "QSetLogging:bitmask=LOG_DARWIN_LOG;")
-
- def do_test(self, enable_options, settings_commands=None,
- run_enable_after_breakpoint=False, max_entry_count=None):
- """Runs the test inferior, returning collected events.
-
- This method runs the test inferior to the first breakpoint hit.
- It then adds a listener for structured data events, and collects
- all events from that point forward until end of execution of the
- test inferior. It then returns those events.
-
- @return
- A list of structured data events received, in the order they
- were received.
- """
- self.build(dictionary=self.d)
- self.setTearDownCleanup(dictionary=self.d)
-
- exe = os.path.join(os.getcwd(), self.exe_name)
-
- # Create a target by the debugger.
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, lldbtest.VALID_TARGET)
-
- # Run the darwin-log settings commands.
- if settings_commands is not None:
- for setting_command in settings_commands:
- self.runCmd(
- expand_darwinlog_settings_set_command(setting_command))
-
- # Build the darwin-log enable command.
- enable_cmd = expand_darwinlog_command("enable")
- if enable_options is not None and len(enable_options) > 0:
- enable_cmd += ' ' + ' '.join(enable_options)
-
- # Run the darwin-log enable command now if we are not supposed
- # to do it at the first breakpoint. This tests the start-up
- # code, which has the benefit of being able to set os_log-related
- # environment variables.
- if not run_enable_after_breakpoint:
- self.runCmd(enable_cmd)
-
- # Create the breakpoint.
- breakpoint = target.BreakpointCreateByLocation(self.source, self.line)
- self.assertIsNotNone(breakpoint)
- self.assertTrue(breakpoint.IsValid())
- self.assertEqual(1, breakpoint.GetNumLocations(),
- "Should have found one breakpoint")
-
- # Enable packet logging.
- # self.runCmd("log enable -f /tmp/packets.log gdb-remote packets")
- # self.runCmd("log enable lldb process")
-
- # Launch the process - doesn't stop at entry.
- process = target.LaunchSimple(None, None, os.getcwd())
- self.assertIsNotNone(process, lldbtest.PROCESS_IS_VALID)
-
- # Keep track of whether we're tracing output.
- trace_on = self.TraceOn()
-
- # Get the next thread that stops.
- from lldbsuite.test.lldbutil import get_stopped_thread
- thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
-
- self.assertIsNotNone(thread, "There should be a thread stopped "
- "due to breakpoint")
-
- # The process should be stopped at this point.
- self.expect("process status", lldbtest.PROCESS_STOPPED,
- patterns=['Process .* stopped'])
-
- # The stop reason of the thread should be breakpoint.
- self.expect("thread list", lldbtest.STOPPED_DUE_TO_BREAKPOINT,
- substrs=['stopped', 'stop reason = breakpoint'])
-
- # And our one and only breakpoint should have been hit.
- self.assertEquals(breakpoint.GetHitCount(), 1)
-
- # Now setup the structured data listener.
- #
- # Grab the broadcaster for the process. We'll be attaching our
- # listener to it.
- broadcaster = process.GetBroadcaster()
- self.assertIsNotNone(broadcaster)
-
- listener = lldb.SBListener("SBStructuredData listener")
- self.assertIsNotNone(listener)
-
- rc = broadcaster.AddListener(listener,
- lldb.SBProcess.eBroadcastBitStructuredData)
- self.assertTrue(rc, "Successfully add listener to process broadcaster")
-
- # Start the listening thread to retrieve the events.
- # Bump up max entry count for the potentially included Add Mode:
- # entry.
- if max_entry_count is not None:
- max_entry_count += 1
- event_thread = self.EventListenerThread(listener, process, trace_on,
- max_entry_count)
- event_thread.start()
-
- # Continue the test inferior. We should get any events after this.
- process.Continue()
-
- # Wait until the event thread terminates.
- # print("main thread now waiting for event thread to receive events.")
- event_thread.join()
-
- # If the process is still alive, we kill it here.
- if process.is_alive:
- process.Kill()
-
- # Fail on any exceptions that occurred during event execution.
- if event_thread.exception is not None:
- # Re-raise it here so it shows up as a test error.
- raise event_thread
-
- # Return the collected logging events.
- return remove_add_mode_entry(event_thread.log_entries)
OpenPOWER on IntegriCloud