"""
Test display and Python APIs on file and class static variables.
"""

from __future__ import print_function


import os
import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil


class StaticVariableTestCase(TestBase):

    mydir = TestBase.compute_mydir(__file__)

    def setUp(self):
        # Call super's setUp().
        TestBase.setUp(self)
        # Find the line number to break at.
        self.line = line_number('main.cpp', '// Set break point at this line.')

    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
    def test_with_run_command(self):
        """Test that file and class static variables display correctly."""
        self.build()
        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)

        lldbutil.run_break_set_by_file_and_line(
            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)

        self.runCmd("run", RUN_SUCCEEDED)

        # The stop reason of the thread should be breakpoint.
        self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
                    substrs=['stopped',
                             'stop reason = breakpoint'])

        # Global variables are no longer displayed with the "frame variable"
        # command.
        self.expect(
            'target variable A::g_points',
            VARIABLES_DISPLAYED_CORRECTLY,
            patterns=['\(PointType \[[1-9]*\]\) A::g_points = {'])
        self.expect('target variable g_points', VARIABLES_DISPLAYED_CORRECTLY,
                    substrs=['(PointType [2]) g_points'])

        # On Mac OS X, gcc 4.2 emits the wrong debug info for A::g_points.
        # A::g_points is an array of two elements.
        if self.platformIsDarwin() or self.getPlatform() == "linux":
            self.expect(
                "target variable A::g_points[1].x",
                VARIABLES_DISPLAYED_CORRECTLY,
                startstr="(int) A::g_points[1].x = 11")

    @expectedFailureAll(
        compiler=["gcc"],
        bugnumber="Compiler emits incomplete debug info")
    @expectedFailureAll(
        compiler=["clang"],
        compiler_version=["<", "3.9"],
        bugnumber='llvm.org/pr20550')
    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
    def test_with_run_command_complete(self):
        """
        Test that file and class static variables display correctly with
        complete debug information.
        """
        self.build()
        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
        self.assertTrue(target, VALID_TARGET)

        # Global variables are no longer displayed with the "frame variable"
        # command.
        self.expect(
            'target variable A::g_points',
            VARIABLES_DISPLAYED_CORRECTLY,
            patterns=[
                '\(PointType \[[1-9]*\]\) A::g_points = {', '(x = 1, y = 2)',
                '(x = 11, y = 22)'
            ])

        # Ensure that we take the context into account and only print
        # A::g_points.
        self.expect(
            'target variable A::g_points',
            VARIABLES_DISPLAYED_CORRECTLY,
            matching=False,
            patterns=['(x = 3, y = 4)', '(x = 33, y = 44)'])

        # Finally, ensure that we print both points when not specifying a
        # context.
        self.expect(
            'target variable g_points',
            VARIABLES_DISPLAYED_CORRECTLY,
            substrs=[
                '(PointType [2]) g_points', '(x = 1, y = 2)',
                '(x = 11, y = 22)', '(x = 3, y = 4)', '(x = 33, y = 44)'
            ])

    @expectedFailureAll(
        compiler=["gcc"],
        bugnumber="Compiler emits incomplete debug info")
    @expectedFailureAll(
        compiler=["clang"],
        compiler_version=["<", "3.9"],
        bugnumber='llvm.org/pr20550')
    @add_test_categories(['pyapi'])
    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
    def test_with_python_api(self):
        """Test Python APIs on file and class static variables."""
        self.build()
        exe = self.getBuildArtifact("a.out")

        target = self.dbg.CreateTarget(exe)
        self.assertTrue(target, VALID_TARGET)

        breakpoint = target.BreakpointCreateByLocation("main.cpp", self.line)
        self.assertTrue(breakpoint, VALID_BREAKPOINT)

        # Now launch the process, and do not stop at entry point.
        process = target.LaunchSimple(
            None, None, self.get_process_working_directory())
        self.assertTrue(process, PROCESS_IS_VALID)

        # The stop reason of the thread should be breakpoint.
        thread = lldbutil.get_stopped_thread(
            process, lldb.eStopReasonBreakpoint)
        self.assertIsNotNone(thread)

        # Get the SBValue of 'A::g_points' and 'g_points'.
        frame = thread.GetFrameAtIndex(0)

        # arguments =>     False
        # locals =>        False
        # statics =>       True
        # in_scope_only => False
        valList = frame.GetVariables(False, False, True, False)

        for val in valList:
            self.DebugSBValue(val)
            name = val.GetName()
            self.assertTrue(name in ['g_points', 'A::g_points'])
            if name == 'g_points':
                self.assertTrue(
                    val.GetValueType() == lldb.eValueTypeVariableStatic)
                self.assertEqual(val.GetNumChildren(), 2)
            elif name == 'A::g_points':
                self.assertTrue(
                    val.GetValueType() == lldb.eValueTypeVariableGlobal)
                self.assertEqual(val.GetNumChildren(), 2)
                child1 = val.GetChildAtIndex(1)
                self.DebugSBValue(child1)
                child1_x = child1.GetChildAtIndex(0)
                self.DebugSBValue(child1_x)
                self.assertTrue(child1_x.GetTypeName() == 'int' and
                                child1_x.GetValue() == '11')

        # SBFrame.FindValue() should also work.
        val = frame.FindValue("A::g_points", lldb.eValueTypeVariableGlobal)
        self.DebugSBValue(val)
        self.assertTrue(val.GetName() == 'A::g_points')

        # Also exercise the "parameter" and "local" scopes while we are at it.
        val = frame.FindValue("argc", lldb.eValueTypeVariableArgument)
        self.DebugSBValue(val)
        self.assertTrue(val.GetName() == 'argc')

        val = frame.FindValue("argv", lldb.eValueTypeVariableArgument)
        self.DebugSBValue(val)
        self.assertTrue(val.GetName() == 'argv')

        val = frame.FindValue("hello_world", lldb.eValueTypeVariableLocal)
        self.DebugSBValue(val)
        self.assertTrue(val.GetName() == 'hello_world')
