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

USE_LIBSTDCPP = "USE_LIBSTDCPP"
USE_LIBCPP = "USE_LIBCPP"


class GenericDequeDataFormatterTestCase(TestBase):
    def findVariable(self, name):
        var = self.frame().FindVariable(name)
        self.assertTrue(var.IsValid())
        return var

    def getVariableType(self, name):
        var = self.findVariable(name)
        return var.GetType().GetDisplayTypeName()

    def check_size(self, var_name, size):
        var = self.findVariable(var_name)
        self.assertEqual(var.GetNumChildren(), size)

    def do_test(self, stdlib_type):
        self.build(dictionary={stdlib_type: "1"})
        lldbutil.run_to_source_breakpoint(
            self, "break here", lldb.SBFileSpec("main.cpp")
        )

        self.expect_expr("empty", result_children=[])
        self.expect_expr(
            "deque_1",
            result_children=[
                ValueCheck(name="[0]", value="1"),
            ],
        )
        self.expect_expr(
            "deque_3",
            result_children=[
                ValueCheck(name="[0]", value="3"),
                ValueCheck(name="[1]", value="1"),
                ValueCheck(name="[2]", value="2"),
            ],
        )

        self.check_size("deque_200_small", 200)
        for i in range(0, 100):
            self.expect_var_path(
                "deque_200_small[%d]" % (i),
                children=[
                    ValueCheck(name="a", value=str(-99 + i)),
                    ValueCheck(name="b", value=str(-100 + i)),
                    ValueCheck(name="c", value=str(-101 + i)),
                ],
            )
            self.expect_var_path(
                "deque_200_small[%d]" % (i + 100),
                children=[
                    ValueCheck(name="a", value=str(i)),
                    ValueCheck(name="b", value=str(1 + i)),
                    ValueCheck(name="c", value=str(2 + i)),
                ],
            )

        self.check_size("deque_200_large", 200)
        for i in range(0, 100):
            self.expect_var_path(
                "deque_200_large[%d]" % (i),
                children=[
                    ValueCheck(name="a", value=str(-99 + i)),
                    ValueCheck(name="b", value=str(-100 + i)),
                    ValueCheck(name="c", value=str(-101 + i)),
                    ValueCheck(name="d"),
                ],
            )
            self.expect_var_path(
                "deque_200_large[%d]" % (i + 100),
                children=[
                    ValueCheck(name="a", value=str(i)),
                    ValueCheck(name="b", value=str(1 + i)),
                    ValueCheck(name="c", value=str(2 + i)),
                    ValueCheck(name="d"),
                ],
            )

    @add_test_categories(["libstdcxx"])
    def test_libstdcpp(self):
        self.do_test(USE_LIBSTDCPP)

    @add_test_categories(["libc++"])
    def test_libcpp(self):
        self.do_test(USE_LIBCPP)
