"""
Tests basic UndefinedBehaviorSanitizer support (detecting an alignment error).
"""

import os
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import json


class UbsanBasicTestCase(TestBase):
    @skipUnlessUndefinedBehaviorSanitizer
    @no_debug_info_test
    def test(self):
        self.build()
        self.ubsan_tests()

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        self.line_align = line_number("main.c", "// align line")

    def ubsan_tests(self):
        # Load the test
        exe = self.getBuildArtifact("a.out")
        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)
        self.registerSanitizerLibrariesWithTarget(target)

        self.runCmd("run")

        process = self.dbg.GetSelectedTarget().process
        thread = process.GetSelectedThread()
        frame = thread.GetSelectedFrame()

        # the stop reason of the thread should be breakpoint.
        self.expect(
            "thread list",
            "A ubsan issue should be detected",
            substrs=["stopped", "stop reason ="],
        )

        stop_reason = thread.GetStopReason()
        self.assertStopReason(stop_reason, lldb.eStopReasonInstrumentation)

        # test that the UBSan dylib is present
        self.expect(
            "image lookup -n __ubsan_on_report",
            "__ubsan_on_report should be present",
            substrs=["1 match found"],
        )

        # We should be stopped in __ubsan_on_report
        self.assertIn("__ubsan_on_report", frame.GetFunctionName())

        # The stopped thread backtrace should contain either 'align line'
        found = False
        for i in range(thread.GetNumFrames()):
            frame = thread.GetFrameAtIndex(i)
            if frame.GetLineEntry().GetFileSpec().GetFilename() == "main.c":
                if frame.GetLineEntry().GetLine() == self.line_align:
                    found = True
        self.assertTrue(found)

        backtraces = thread.GetStopReasonExtendedBacktraces(
            lldb.eInstrumentationRuntimeTypeUndefinedBehaviorSanitizer
        )
        self.assertEquals(backtraces.GetSize(), 1)

        self.expect(
            "thread info -s",
            "The extended stop info should contain the UBSan provided fields",
            substrs=[
                "col",
                "description",
                "filename",
                "instrumentation_class",
                "line",
                "memory_address",
            ],
        )

        output_lines = self.res.GetOutput().split("\n")
        json_line = "\n".join(output_lines[2:])
        data = json.loads(json_line)

        self.assertEqual(data["instrumentation_class"], "UndefinedBehaviorSanitizer")
        self.assertEqual(data["description"], "misaligned-pointer-use")
        self.assertEqual(os.path.basename(data["filename"]), "main.c")
        self.assertEqual(data["line"], self.line_align)

        for count in range(0, 8):
            process.Continue()
            stop_reason = thread.GetStopReason()
            self.assertEqual(
                stop_reason,
                lldb.eStopReasonInstrumentation,
                "Round {0} wasn't instrumentation".format(count),
            )
