"""
Base class for DarwinLog tests.
"""

# System imports
from __future__ import print_function

import json
import os
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):

        import pexpect
        # 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 = self.getBuildArtifact(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()

        # 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

        # 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 darwin_log_available(self):
        match = self.match("plugin structured-data darwin-log status",
                           patterns=[r"Availability: ([\S]+)"])
        return match is not None and (match.group(1) == "available")

    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 = self.getBuildArtifact(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, self.getBuildDir())
        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)

        # Check if DarwinLog is available.  This check cannot be done
        # until after the process has started, as the feature availability
        # comes through the stub.  The stub isn't running until
        # the target process is running.  So this is really the earliest
        # we can check.
        if not self.darwin_log_available():
            self.skipTest("DarwinLog not available")

        # 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)
