"""
Test lldb-vscode logpoints feature.
"""


import unittest2
import vscode
import shutil
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
import lldbvscode_testcase
import os


class TestVSCode_logpoints(lldbvscode_testcase.VSCodeTestCaseBase):

    def setUp(self):
        lldbvscode_testcase.VSCodeTestCaseBase.setUp(self)

        self.main_basename = 'main-copy.cpp'
        self.main_path = os.path.realpath(self.getBuildArtifact(self.main_basename))

    @skipIfWindows
    @skipIfRemote
    def test_logmessage_basic(self):
        '''Tests breakpoint logmessage basic functionality.'''
        before_loop_line = line_number('main.cpp', '// before loop')
        loop_line = line_number('main.cpp', '// break loop')
        after_loop_line = line_number('main.cpp', '// after loop')

        program = self.getBuildArtifact("a.out")
        self.build_and_launch(program)

        # Set a breakpoint at a line before loop
        before_loop_breakpoint_ids = self.set_source_breakpoints(
            self.main_path,
            [before_loop_line])
        self.assertEquals(len(before_loop_breakpoint_ids), 1, "expect one breakpoint")

        self.vscode.request_continue()

        # Verify we hit the breakpoint before loop line
        self.verify_breakpoint_hit(before_loop_breakpoint_ids)

        # Swallow old console output
        self.get_console()

        # Set two breakpoints:
        # 1. First at the loop line with logMessage
        # 2. Second guard breakpoint at a line after loop
        logMessage_prefix = "This is log message for { -- "
        # Trailing newline is needed for splitlines()
        logMessage = logMessage_prefix + "{i + 3}\n"
        [loop_breakpoint_id, post_loop_breakpoint_id] = self.set_source_breakpoints(
            self.main_path,
            [loop_line, after_loop_line],
            [{'logMessage': logMessage}, {}]
        )

        # Continue to trigger the breakpoint with log messages
        self.vscode.request_continue()

        # Verify we hit the breakpoint after loop line
        self.verify_breakpoint_hit([post_loop_breakpoint_id])

        output = self.get_console()
        lines = output.splitlines()
        logMessage_output = []
        for line in lines:
            if line.startswith(logMessage_prefix):
                logMessage_output.append(line)

        # Verify logMessage count
        loop_count = 10
        self.assertEqual(len(logMessage_output), loop_count)

        # Verify log message match
        for idx, logMessage_line in enumerate(logMessage_output):
            result = idx + 3
            self.assertEqual(logMessage_line, logMessage_prefix + str(result))


    @skipIfWindows
    @skipIfRemote
    def test_logmessage_advanced(self):
        '''Tests breakpoint logmessage functionality for complex expression.'''
        before_loop_line = line_number('main.cpp', '// before loop')
        loop_line = line_number('main.cpp', '// break loop')
        after_loop_line = line_number('main.cpp', '// after loop')

        program = self.getBuildArtifact("a.out")
        self.build_and_launch(program)

        # Set a breakpoint at a line before loop
        before_loop_breakpoint_ids = self.set_source_breakpoints(
            self.main_path,
            [before_loop_line])
        self.assertEquals(len(before_loop_breakpoint_ids), 1, "expect one breakpoint")

        self.vscode.request_continue()

        # Verify we hit the breakpoint before loop line
        self.verify_breakpoint_hit(before_loop_breakpoint_ids)

        # Swallow old console output
        self.get_console()

        # Set two breakpoints:
        # 1. First at the loop line with logMessage
        # 2. Second guard breakpoint at a line after loop
        logMessage_prefix = "This is log message for { -- "
        # Trailing newline is needed for splitlines()
        logMessage = logMessage_prefix + "{int y = 0; if (i % 3 == 0) { y = i + 3;} else {y = i * 3;} y}\n"
        [loop_breakpoint_id, post_loop_breakpoint_id] = self.set_source_breakpoints(
            self.main_path,
            [loop_line, after_loop_line],
            [{'logMessage': logMessage}, {}]
        )

        # Continue to trigger the breakpoint with log messages
        self.vscode.request_continue()

        # Verify we hit the breakpoint after loop line
        self.verify_breakpoint_hit([post_loop_breakpoint_id])

        output = self.get_console()
        lines = output.splitlines()
        logMessage_output = []
        for line in lines:
            if line.startswith(logMessage_prefix):
                logMessage_output.append(line)

        # Verify logMessage count
        loop_count = 10
        self.assertEqual(len(logMessage_output), loop_count)

        # Verify log message match
        for idx, logMessage_line in enumerate(logMessage_output):
            result = idx + 3 if idx % 3 == 0 else idx * 3
            self.assertEqual(logMessage_line, logMessage_prefix + str(result))
