| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| //===-- SBStructuredData.h --------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef SBStructuredData_h | ||
| #define SBStructuredData_h | ||
|
|
||
| #include "lldb/API/SBDefines.h" | ||
| #include "lldb/API/SBModule.h" | ||
|
|
||
| namespace lldb { | ||
|
|
||
| class SBStructuredData | ||
| { | ||
| public: | ||
|
|
||
| SBStructuredData(); | ||
|
|
||
| SBStructuredData(const lldb::SBStructuredData &rhs); | ||
|
|
||
| SBStructuredData(const lldb::EventSP &event_sp); | ||
|
|
||
| ~SBStructuredData(); | ||
|
|
||
| lldb::SBStructuredData & | ||
| operator =(const lldb::SBStructuredData &rhs); | ||
|
|
||
| bool | ||
| IsValid() const; | ||
|
|
||
| void | ||
| Clear(); | ||
|
|
||
| lldb::SBError | ||
| GetAsJSON(lldb::SBStream &stream) const; | ||
|
|
||
| lldb::SBError | ||
| GetDescription(lldb::SBStream &stream) const; | ||
|
|
||
| private: | ||
|
|
||
| class Impl; | ||
| std::unique_ptr<Impl> m_impl_up; | ||
| }; | ||
| } | ||
|
|
||
| #endif /* SBStructuredData_h */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| //===-- StructuredDataPlugin.h ----------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef StructuredDataPlugin_h | ||
| #define StructuredDataPlugin_h | ||
|
|
||
| #include "lldb/Core/PluginInterface.h" | ||
| #include "lldb/Core/StructuredData.h" | ||
|
|
||
| namespace lldb_private | ||
| { | ||
|
|
||
| class CommandObjectMultiword; | ||
|
|
||
| // ----------------------------------------------------------------------------- | ||
| /// Plugin that supports process-related structured data sent asynchronously | ||
| /// from the debug monitor (e.g. debugserver, lldb-server, etc.) | ||
| /// | ||
| /// This plugin type is activated by a Process-derived instance when that | ||
| /// instance detects that a given structured data feature is available. | ||
| /// | ||
| /// StructuredDataPlugin instances are inherently tied to a process. The | ||
| /// main functionality they support is the ability to consume asynchronously- | ||
| /// delivered structured data from the process monitor, and do something | ||
| /// reasonable with it. Something reasonable can include broadcasting a | ||
| /// StructuredData event, which other parts of the system can then do with | ||
| /// as they please. An IDE could use this facility to retrieve CPU usage, | ||
| /// memory usage, and other run-time aspects of the process. That data | ||
| /// can then be displayed meaningfully to the user through the IDE. | ||
|
|
||
| /// For command-line LLDB, the Debugger instance listens for the structured | ||
| /// data events raised by the plugin, and give the plugin both the output | ||
| /// and error streams such that the plugin can display something about the | ||
| /// event, at a time when the debugger ensures it is safe to write to the | ||
| /// output or error streams. | ||
| // ----------------------------------------------------------------------------- | ||
|
|
||
| class StructuredDataPlugin : | ||
| public PluginInterface, | ||
| public std::enable_shared_from_this<StructuredDataPlugin> | ||
| { | ||
| public: | ||
|
|
||
| virtual ~StructuredDataPlugin(); | ||
|
|
||
| lldb::ProcessSP | ||
| GetProcess() const; | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| // Public instance API | ||
| // ------------------------------------------------------------------------- | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Return whether this plugin supports the given StructuredData feature. | ||
| /// | ||
| /// When Process is informed of a list of process-monitor-supported | ||
| /// structured data features, Process will go through the list of plugins, | ||
| /// one at a time, and have the first plugin that supports a given feature | ||
| /// be the plugin instantiated to handle that feature. There is a 1-1 | ||
| /// correspondence between a Process instance and a StructuredDataPlugin | ||
| /// mapped to that process. A plugin can support handling multiple | ||
| /// features, and if that happens, there is a single plugin instance | ||
| /// created covering all of the mapped features for a given process. | ||
| /// | ||
| /// @param[in] type_name | ||
| /// The name of the feature tag supported by a process. | ||
| /// e.g. "darwin-log". | ||
| /// | ||
| /// @return | ||
| /// true if the plugin supports the feature; otherwise, false. | ||
| // ------------------------------------------------------------------------- | ||
| virtual bool | ||
| SupportsStructuredDataType(const ConstString &type_name) = 0; | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Handle the arrival of asynchronous structured data from the process. | ||
| /// | ||
| /// When asynchronous structured data arrives from the process monitor, | ||
| /// it is immediately delivered to the plugin mapped for that feature | ||
| /// if one exists. The structured data that arrives from a process | ||
| /// monitor must be a dictionary, and it must have a string field named | ||
| /// "type" that must contain the StructuredData feature name set as the | ||
| /// value. This is the manner in which the data is routed to the proper | ||
| /// plugin instance. | ||
| /// | ||
| /// @param[in] process | ||
| /// The process instance that just received the structured data. | ||
| /// This will always be the same process for a given instance of | ||
| /// a plugin. | ||
| /// | ||
| /// @param[in] type_name | ||
| /// The name of the feature tag for the asynchronous structured data. | ||
| /// Note this data will also be present in the \b object_sp dictionary | ||
| /// under the string value with key "type". | ||
| /// | ||
| /// @param[in] object_sp | ||
| /// A shared pointer to the structured data that arrived. This must | ||
| /// be a dictionary. The only key required is the aforementioned | ||
| /// key named "type" that must be a string value containing the | ||
| /// structured data type name. | ||
| // ------------------------------------------------------------------------- | ||
| virtual void | ||
| HandleArrivalOfStructuredData(Process &process, | ||
| const ConstString &type_name, | ||
| const StructuredData::ObjectSP | ||
| &object_sp) = 0; | ||
|
|
||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Get a human-readable description of the contents of the data. | ||
| /// | ||
| /// In command-line LLDB, this method will be called by the Debugger | ||
| /// instance for each structured data event generated, and the output | ||
| /// will be printed to the LLDB console. If nothing is added to the stream, | ||
| /// nothing will be printed; otherwise, a newline will be added to the end | ||
| /// when displayed. | ||
| /// | ||
| /// @param[in] object_sp | ||
| /// A shared pointer to the structured data to format. | ||
| /// | ||
| /// @param[in] stream | ||
| /// The stream where the structured data should be pretty printed. | ||
| /// | ||
| /// @return | ||
| /// The error if formatting the object contents failed; otherwise, | ||
| /// success. | ||
| // ------------------------------------------------------------------------- | ||
| virtual Error | ||
| GetDescription(const StructuredData::ObjectSP &object_sp, | ||
| lldb_private::Stream &stream) = 0; | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Returns whether the plugin's features are enabled. | ||
| /// | ||
| /// This is a convenience method for plugins that can enable or disable | ||
| /// their functionality. It allows retrieval of this state without | ||
| /// requiring a cast. | ||
| /// | ||
| /// @param[in] type_name | ||
| /// The name of the feature tag for the asynchronous structured data. | ||
| /// This is needed for plugins that support more than one feature. | ||
| // ------------------------------------------------------------------------- | ||
| virtual bool | ||
| GetEnabled(const ConstString &type_name) const; | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Allow the plugin to do work related to modules that loaded in the | ||
| /// the corresponding process. | ||
| /// | ||
| /// This method defaults to doing nothing. Plugins can override it | ||
| /// if they have any behavior they want to enable/modify based on loaded | ||
| /// modules. | ||
| /// | ||
| /// @param[in] process | ||
| /// The process that just was notified of modules having been loaded. | ||
| /// This will always be the same process for a given instance of | ||
| /// a plugin. | ||
| /// | ||
| /// @param[in] module_list | ||
| /// The list of modules that the process registered as having just | ||
| /// loaded. See \b Process::ModulesDidLoad(...). | ||
| // ------------------------------------------------------------------------- | ||
| virtual void | ||
| ModulesDidLoad(Process &process, ModuleList &module_list); | ||
|
|
||
| protected: | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| // Derived-class API | ||
| // ------------------------------------------------------------------------- | ||
| StructuredDataPlugin(const lldb::ProcessWP &process_wp); | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| /// Derived classes must call this before attempting to hook up commands | ||
| /// to the 'plugin structured-data' tree. | ||
| /// | ||
| /// This ensures the relevant command and options hook points for all | ||
| /// StructuredDataPlugin derived classes are available for this debugger. | ||
| /// If this has already happened, this call is a no-op. | ||
| /// | ||
| /// @param[in] debugger | ||
| /// The Debugger instance for which we're creating the required shared | ||
| /// components for the StructuredDataPlugin derived classes. | ||
| // ------------------------------------------------------------------------- | ||
| static void | ||
| InitializeBasePluginForDebugger(Debugger &debugger); | ||
|
|
||
| private: | ||
|
|
||
| lldb::ProcessWP m_process_wp; | ||
|
|
||
| DISALLOW_COPY_AND_ASSIGN(StructuredDataPlugin); | ||
|
|
||
| }; | ||
|
|
||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| //===-- ThreadPlanCallOnFunctionExit.h --------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef ThreadPlanCallOnFunctionExit_h | ||
| #define ThreadPlanCallOnFunctionExit_h | ||
|
|
||
| #include "lldb/Target/ThreadPlan.h" | ||
|
|
||
| #include <functional> | ||
|
|
||
| namespace lldb_private { | ||
|
|
||
| // ============================================================================= | ||
| /// This thread plan calls a function object when the current function exits. | ||
| // ============================================================================= | ||
|
|
||
| class ThreadPlanCallOnFunctionExit : public ThreadPlan | ||
| { | ||
| public: | ||
|
|
||
| /// Definition for the callback made when the currently executing thread | ||
| /// finishes executing its function. | ||
| using Callback = std::function<void()>; | ||
|
|
||
| ThreadPlanCallOnFunctionExit(Thread &thread, const Callback &callback); | ||
|
|
||
| void | ||
| DidPush() override; | ||
|
|
||
| // ------------------------------------------------------------------------- | ||
| // ThreadPlan API | ||
| // ------------------------------------------------------------------------- | ||
|
|
||
| void | ||
| GetDescription (Stream *s, lldb::DescriptionLevel level) override; | ||
|
|
||
| bool | ||
| ValidatePlan (Stream *error) override; | ||
|
|
||
| bool | ||
| ShouldStop (Event *event_ptr) override; | ||
|
|
||
| bool | ||
| WillStop () override; | ||
|
|
||
| protected: | ||
|
|
||
| bool | ||
| DoPlanExplainsStop (Event *event_ptr) override; | ||
|
|
||
| lldb::StateType | ||
| GetPlanRunState () override; | ||
|
|
||
| private: | ||
|
|
||
| Callback m_callback; | ||
| lldb::ThreadPlanSP m_step_out_threadplan_sp; | ||
|
|
||
| }; | ||
|
|
||
| } | ||
|
|
||
| #endif /* ThreadPlanCallOnFunctionExit_h */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| # System imports | ||
| from __future__ import print_function | ||
|
|
||
| # LLDB imports | ||
| from lldbsuite.test import darwin_log | ||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
|
|
||
|
|
||
| class TestDarwinLogBasic(darwin_log.DarwinLogEventBasedTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| @decorators.add_test_categories(['pyapi']) | ||
| @decorators.skipUnlessDarwin | ||
| def test_SBStructuredData_gets_broadcasted(self): | ||
| """Exercise SBStructuredData API.""" | ||
|
|
||
| # Run the test. | ||
| log_entries = self.do_test(None, max_entry_count=2) | ||
|
|
||
| # Validate that we received our two log entries. | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Expected one log entry to arrive via events.") | ||
| self.assertEqual(log_entries[0]['message'], "Hello, world", | ||
| "Log message should match expected content.") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger = os_log_create("org.llvm.lldb.test", "basic-test"); | ||
| if (!logger) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_log(logger, "Hello, world"); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // The number of seconds to wait at the end of the test inferior before | ||
| // exiting. This delay is needed to ensure the logging infrastructure | ||
| // has flushed out the message. If we finished before all messages were | ||
| // flushed, then the test will never see the unflushed messages, causing | ||
| // some test logic to fail. | ||
| #define FINAL_WAIT_SECONDS 5 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterMatchActivityChain(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterMatchActivityChain, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterMatchActivityChain, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # activity-chain filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_chain_match(self): | ||
| """Test that fall-through reject, accept full-match activity chain works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain match " | ||
| "parent-activity:child-activity\""]) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_chain_partial_match(self): | ||
| """Test that fall-through reject, doesn't accept only partial match of activity-chain.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain match parent-activity:child-activity\"", # Match the second fully. | ||
| "--filter \"accept activity-chain match parent-ac\""]) # Only partially match the first. | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_chain_full_match(self): | ||
| """Test that fall-through accept, reject match activity-chain works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity-chain match parent-activity\""]) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity-chain rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_chain_second_rule(self): | ||
| """Test that fall-through reject, accept activity-chain on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain match non-existent\"", | ||
| "--filter \"accept activity-chain match parent-activity:child-activity\""]) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the activity-chain of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterMatchActivity(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterMatchActivity, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterMatchActivity, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # activity filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_match(self): | ||
| """Test that fall-through reject, accept match activity works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity match child-activity\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_partial_match(self): | ||
| """Test that fall-through reject, accept match activity via partial match does not accept.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity match child-activity\"", # Fully match second message. | ||
| "--filter \"accept activity match parent-\""] # Only partially match first message. | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_full_match(self): | ||
| """Test that fall-through accept, reject match activity works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity match parent-activity\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_second_rule(self): | ||
| """Test that fall-through reject, accept regex activity on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity match non-existent\"", | ||
| "--filter \"accept activity match child-activity\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the activity of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterMatchCategory(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterMatchCategory, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterMatchCategory, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # category filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_full_match(self): | ||
| """Test that fall-through reject, accept match single category works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category match cat2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that category. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_category_partial_match(self): | ||
| """Test that fall-through reject, accept regex category via partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category match cat2\"", # Fully match the second message. | ||
| "--filter \"accept category match at1\""] # Only partially match first message. Should not show up. | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that category. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_category_full_match(self): | ||
| """Test that fall-through accept, reject match category works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject category match cat1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via category rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_second_rule(self): | ||
| """Test that fall-through reject, accept match category on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category match non-existent\"", | ||
| "--filter \"accept category match cat2\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the category of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterMatchMessage(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterMatchMessage, 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') | ||
|
|
||
| self.strict_sources = True | ||
|
|
||
| # Turn on process monitor logging while we work out issues. | ||
| self.enable_process_monitor_logging = True | ||
|
|
||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterMatchMessage, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # category filter tests | ||
| # ========================================================================== | ||
|
|
||
| EXPECT_REGEXES = [ | ||
| re.compile(r"log message ([^-]+)-(\S+)"), | ||
| re.compile(r"exited with status") | ||
| ] | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_message_full_match(self): | ||
| """Test that fall-through reject, accept match whole message works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept message match log message sub2-cat2\""], | ||
| expect_regexes=self.EXPECT_REGEXES | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that message contents. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_no_accept_message_partial_match(self): | ||
| """Test that fall-through reject, match message via partial content match doesn't accept.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept message match log message sub2-cat2\"", | ||
| "--filter \"accept message match sub1-cat1\""], | ||
| expect_regexes=self.EXPECT_REGEXES | ||
| ) | ||
|
|
||
| # We should only see the second log message as the partial match on | ||
| # the first message should not pass. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_category_full_match(self): | ||
| """Test that fall-through accept, reject match message works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject message match log message sub1-cat1\""], | ||
| expect_regexes=self.EXPECT_REGEXES | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via message contents rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_second_rule(self): | ||
| """Test that fall-through reject, accept match category on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept message match non-existent\"", | ||
| "--filter \"accept message match log message sub2-cat2\""], | ||
| expect_regexes=self.EXPECT_REGEXES | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the category of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_log(logger_sub1, "log message sub%d-cat%d", 1, 1); | ||
| os_log(logger_sub2, "log message sub%d-cat%d", 2, 2); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(1); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterMatchSubsystem(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterMatchSubsystem, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterMatchSubsystem, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # subsystem filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_subsystem_full_match(self): | ||
| """Test that fall-through reject, accept match single subsystem works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem match org.llvm.lldb.test.sub2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that subsystem. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_subsystem_partial_match(self): | ||
| """Test that fall-through reject, doesn't accept match subsystem via partial-match.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem match org.llvm.lldb.test.sub2\"", # Fully match second message subsystem. | ||
| "--filter \"accept subsystem match sub1\""] # Only partially match first subsystem. | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that subsystem. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_subsystem_full_match(self): | ||
| """Test that fall-through accept, reject match subsystem works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject subsystem match org.llvm.lldb.test.sub1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via subsystem rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_subsystem_second_rule(self): | ||
| """Test that fall-through reject, accept match subsystem on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem match non-existent\"", | ||
| "--filter \"accept subsystem match org.llvm.lldb.test.sub2\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the subsystem of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterRegexActivityChain(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterRegexActivityChain, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterRegexActivityChain, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # activity-chain filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_chain_full_match(self): | ||
| """Test that fall-through reject, accept full-match activity chain works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain regex " | ||
| "parent-activity:child-activity\""]) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_chain_partial_match(self): | ||
| """Test that fall-through reject, accept activity-chain via partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain regex :child-activity\""]) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_chain_full_match(self): | ||
| """Test that fall-through accept, reject activity-chain works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity-chain regex parent-activity:child-..tivity\""]) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity-chain rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat1"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_chain_partial_match(self): | ||
| """Test that fall-through accept, reject activity-chain by partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity-chain regex ^p[^:]+$\""]) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity-chain rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_chain_second_rule(self): | ||
| """Test that fall-through reject, accept activity-chain on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity-chain regex non-existent\"", | ||
| "--filter \"accept activity-chain regex child-activity\""]) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the activity-chain of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterRegexActivity(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterRegexActivity, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterRegexActivity, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # activity filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_full_match(self): | ||
| """Test that fall-through reject, accept regex full-match activity works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity regex child-activity\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_partial_match(self): | ||
| """Test that fall-through reject, regex accept activity via partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity regex child-.*\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that activity. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_full_match(self): | ||
| """Test that fall-through accept, reject regex activity works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity regex parent-activity\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_activity_partial_match(self): | ||
| """Test that fall-through accept, reject regex activity by partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject activity regex p.+-activity\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via activity rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_activity_second_rule(self): | ||
| """Test that fall-through reject, accept regex activity on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept activity regex non-existent\"", | ||
| "--filter \"accept activity regex child-activity\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the activity of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterRegexCategory(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterRegexCategory, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterRegexCategory, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # category filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_full_match(self): | ||
| """Test that fall-through reject, accept regex single category works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category regex cat2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that category. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_partial_match(self): | ||
| """Test that fall-through reject, accept regex category via partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category regex .+2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that category. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_category_full_match(self): | ||
| """Test that fall-through accept, reject regex category works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject category regex cat1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via category rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_category_partial_match(self): | ||
| """Test that fall-through accept, reject regex category by partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject category regex t1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via category rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_category_second_rule(self): | ||
| """Test that fall-through reject, accept regex category on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept category regex non-existent\"", | ||
| "--filter \"accept category regex cat2\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the category of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 1) and | ||
| (self.child.match.group(2) == "cat2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_activity_t parent_activity = os_activity_create("parent-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(parent_activity, ^{ | ||
| os_log(logger_sub1, "source-log-sub1-cat1"); | ||
| os_activity_t child_activity = os_activity_create("child-activity", | ||
| OS_ACTIVITY_CURRENT, OS_ACTIVITY_FLAG_DEFAULT); | ||
| os_activity_apply(child_activity, ^{ | ||
| os_log(logger_sub2, "source-log-sub2-cat2"); | ||
| }); | ||
| }); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| # System imports | ||
| from __future__ import print_function | ||
|
|
||
| import re | ||
|
|
||
| # LLDB imports | ||
| import lldb | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterRegexMessage(darwin_log.DarwinLogEventBasedTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_message_full_match(self): | ||
| """Test that fall-through reject, accept regex whole message works.""" | ||
| log_entries = self.do_test( | ||
| ["--no-match-accepts false", | ||
| # Note below, the four '\' characters are to get us two | ||
| # backslashes over on the gdb-remote side, which then | ||
| # becomes one as the cstr interprets it as an escape | ||
| # sequence. This needs to be rationalized. Initially I | ||
| # supported std::regex ECMAScript, which has the | ||
| # [[:digit:]] character classes and such. That was much | ||
| # more tenable. The backslashes have to travel through | ||
| # so many layers of escaping. (And note if you take | ||
| # off the Python raw string marker here, you need to put | ||
| # in 8 backslashes to go to two on the remote side.) | ||
| r'--filter "accept message regex log message sub2-cat\\\\d+"']) | ||
|
|
||
| # We should have received at least one log entry. | ||
| self.assertIsNotNone(log_entries, | ||
| "Log entry list should not be None.") | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Should receive one log entry.") | ||
| self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", | ||
| "First os_log call should have been skipped.") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_message_partial_match(self): | ||
| """Test that fall-through reject, accept regex message via partial | ||
| match works.""" | ||
| log_entries = self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept message regex [^-]+2\""]) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that message contents. | ||
| self.assertIsNotNone(log_entries, | ||
| "Log entry list should not be None.") | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Should receive one log entry.") | ||
| self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", | ||
| "First os_log call should have been skipped.") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_message_full_match(self): | ||
| """Test that fall-through accept, reject regex message works.""" | ||
| log_entries = self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject message regex log message sub1-cat1\""]) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via message contents rejection. | ||
| self.assertIsNotNone(log_entries, | ||
| "Log entry list should not be None.") | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Should receive one log entry.") | ||
| self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", | ||
| "First os_log call should have been skipped.") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_message_partial_match(self): | ||
| """Test that fall-through accept, reject regex message by partial | ||
| match works.""" | ||
| log_entries = self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject message regex t1\""]) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via partial message contents rejection. | ||
| self.assertIsNotNone(log_entries, | ||
| "Log entry list should not be None.") | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Should receive one log entry.") | ||
| self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", | ||
| "First os_log call should have been skipped.") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_message_second_rule(self): | ||
| """Test that fall-through reject, accept regex message on second rule | ||
| works.""" | ||
| log_entries = self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept message regex non-existent\"", | ||
| "--filter \"accept message regex cat2\""]) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the message of the second log message. | ||
| self.assertIsNotNone(log_entries, | ||
| "Log entry list should not be None.") | ||
| self.assertEqual(len(log_entries), 1, | ||
| "Should receive one log entry.") | ||
| self.assertRegexpMatches(log_entries[0]["message"], r"sub2-cat2", | ||
| "First os_log call should have been skipped.") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| //===-- main.c --------------------------------------------------*- C++ -*-===// | ||
| // | ||
| // The LLVM Compiler Infrastructure | ||
| // | ||
| // This file is distributed under the University of Illinois Open Source | ||
| // License. See LICENSE.TXT for details. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include <os/activity.h> | ||
| #include <os/log.h> | ||
| #include <stdio.h> | ||
|
|
||
| #include "../../../common/darwin_log_common.h" | ||
|
|
||
| int main(int argc, char** argv) | ||
| { | ||
| os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); | ||
| os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); | ||
| if (!logger_sub1 || !logger_sub2) | ||
| return 1; | ||
|
|
||
| // Note we cannot use the os_log() line as the breakpoint because, as of | ||
| // the initial writing of this test, we get multiple breakpoints for that | ||
| // line, which confuses the pexpect test logic. | ||
| printf("About to log\n"); // break here | ||
| os_log(logger_sub1, "log message sub%d-cat%d", 1, 1); | ||
| os_log(logger_sub2, "log message sub%d-cat%d", 2, 2); | ||
|
|
||
| // Sleep, as the darwin log reporting doesn't always happen until a bit | ||
| // later. We need the message to come out before the process terminates. | ||
| sleep(FINAL_WAIT_SECONDS); | ||
|
|
||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| LEVEL = ../../../../../make | ||
|
|
||
| C_SOURCES := main.c | ||
|
|
||
| include $(LEVEL)/Makefile.rules |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,150 @@ | ||
| """ | ||
| Test basic DarwinLog functionality provided by the StructuredDataDarwinLog | ||
| plugin. | ||
| These tests are currently only supported when running against Darwin | ||
| targets. | ||
| """ | ||
|
|
||
| from __future__ import print_function | ||
|
|
||
| import lldb | ||
| import os | ||
| import re | ||
|
|
||
| from lldbsuite.test import decorators | ||
| from lldbsuite.test import lldbtest | ||
| from lldbsuite.test import darwin_log | ||
|
|
||
|
|
||
| class TestDarwinLogFilterRegexSubsystem(darwin_log.DarwinLogTestBase): | ||
|
|
||
| mydir = lldbtest.TestBase.compute_mydir(__file__) | ||
|
|
||
| def setUp(self): | ||
| # Call super's setUp(). | ||
| super(TestDarwinLogFilterRegexSubsystem, 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') | ||
|
|
||
| def tearDown(self): | ||
| # Shut down the process if it's still running. | ||
| if self.child: | ||
| self.runCmd('process kill') | ||
| self.expect_prompt() | ||
| self.runCmd('quit') | ||
|
|
||
| # Let parent clean up | ||
| super(TestDarwinLogFilterRegexSubsystem, self).tearDown() | ||
|
|
||
| # ========================================================================== | ||
| # basic filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_fallthrough_reject(self): | ||
| """Test that a single fall-through reject regex rule rejects all logging.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false"] | ||
| ) | ||
|
|
||
| # We should not match any log lines. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertFalse((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) in ["sub1", "sub2"]), | ||
| "log line should not have been received") | ||
|
|
||
| # ========================================================================== | ||
| # subsystem filter tests | ||
| # ========================================================================== | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_subsystem_full_match(self): | ||
| """Test that fall-through reject, accept regex single subsystem works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem regex org.llvm.lldb.test.sub2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that subsystem. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_subsystem_partial_match(self): | ||
| """Test that fall-through reject, accept regex subsystem via partial-match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem regex org.llvm.+.sub2\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we only accept | ||
| # that subsystem. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_subsystem_full_match(self): | ||
| """Test that fall-through accept, reject regex subsystem works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject subsystem regex org.llvm.lldb.test.sub1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via subsystem rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_reject_subsystem_partial_match(self): | ||
| """Test that fall-through accept, reject regex subsystem by partial match works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts true", | ||
| "--filter \"reject subsystem regex org.*sub1\""] | ||
| ) | ||
|
|
||
| # We should only see the second log message as we rejected the first | ||
| # via subsystem rejection. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") | ||
|
|
||
| @decorators.skipUnlessDarwin | ||
| def test_filter_accept_subsystem_second_rule(self): | ||
| """Test that fall-through reject, accept regex subsystem on second rule works.""" | ||
| self.do_test( | ||
| ["--no-match-accepts false", | ||
| "--filter \"accept subsystem regex non-existent\"", | ||
| "--filter \"accept subsystem regex org.llvm.lldb.test.sub2\"" | ||
| ] | ||
| ) | ||
|
|
||
| # We should only see the second message since we reject by default, | ||
| # the first filter doesn't match any, and the second filter matches | ||
| # the subsystem of the second log message. | ||
| self.assertIsNotNone(self.child.match) | ||
| self.assertTrue((len(self.child.match.groups()) > 0) and | ||
| (self.child.match.group(1) == "sub2"), | ||
| "first log line should not be present, second log line " | ||
| "should be") |