1""" 2Test lldb-vscode runInTerminal reverse request 3""" 4 5 6import unittest2 7import vscode 8from lldbsuite.test.decorators import * 9from lldbsuite.test.lldbtest import * 10from lldbsuite.test import lldbutil 11import lldbvscode_testcase 12import time 13import os 14import subprocess 15import shutil 16import json 17from threading import Thread 18 19 20class TestVSCode_runInTerminal(lldbvscode_testcase.VSCodeTestCaseBase): 21 22 mydir = TestBase.compute_mydir(__file__) 23 24 def readPidMessage(self, fifo_file): 25 with open(fifo_file, "r") as file: 26 self.assertIn("pid", file.readline()) 27 28 def sendDidAttachMessage(self, fifo_file): 29 with open(fifo_file, "w") as file: 30 file.write(json.dumps({"kind": "didAttach"}) + "\n") 31 32 def readErrorMessage(self, fifo_file): 33 with open(fifo_file, "r") as file: 34 return file.readline() 35 36 @skipIfWindows 37 @skipIfRemote 38 @skipIf(archs=no_match(['x86_64'])) 39 def test_runInTerminal(self): 40 ''' 41 Tests the "runInTerminal" reverse request. It makes sure that the IDE can 42 launch the inferior with the correct environment variables and arguments. 43 ''' 44 if "debug" in str(os.environ["LLDBVSCODE_EXEC"]).lower(): 45 # We skip this test for debug builds because it takes too long parsing lldb's own 46 # debug info. Release builds are fine. 47 # Checking this environment variable seems to be a decent proxy for a quick 48 # detection 49 return 50 program = self.getBuildArtifact("a.out") 51 source = 'main.c' 52 self.build_and_launch( 53 program, stopOnEntry=True, runInTerminal=True, args=["foobar"], 54 env=["FOO=bar"]) 55 56 breakpoint_line = line_number(source, '// breakpoint') 57 58 self.set_source_breakpoints(source, [breakpoint_line]) 59 self.continue_to_next_stop() 60 61 # We verify we actually stopped inside the loop 62 counter = int(self.vscode.get_local_variable_value('counter')) 63 self.assertTrue(counter > 0) 64 65 # We verify we were able to set the launch arguments 66 argc = int(self.vscode.get_local_variable_value('argc')) 67 self.assertEqual(argc, 2) 68 69 argv1 = self.vscode.request_evaluate('argv[1]')['body']['result'] 70 self.assertIn('foobar', argv1) 71 72 # We verify we were able to set the environment 73 env = self.vscode.request_evaluate('foo')['body']['result'] 74 self.assertIn('bar', env) 75 76 @skipIfWindows 77 @skipIfRemote 78 @skipIf(archs=no_match(['x86_64'])) 79 def test_runInTerminalInvalidTarget(self): 80 self.build_and_create_debug_adaptor() 81 response = self.launch( 82 "INVALIDPROGRAM", stopOnEntry=True, runInTerminal=True, args=["foobar"], env=["FOO=bar"], expectFailure=True) 83 self.assertFalse(response['success']) 84 self.assertIn("Could not create a target for a program 'INVALIDPROGRAM': unable to find executable", 85 response['message']) 86 87 @skipIfWindows 88 @skipIfRemote 89 @skipIf(archs=no_match(['x86_64'])) 90 def test_missingArgInRunInTerminalLauncher(self): 91 proc = subprocess.run([self.lldbVSCodeExec, "--launch-target", "INVALIDPROGRAM"], 92 capture_output=True, universal_newlines=True) 93 self.assertTrue(proc.returncode != 0) 94 self.assertIn('"--launch-target" requires "--comm-file" to be specified', proc.stderr) 95 96 @skipIfWindows 97 @skipIfRemote 98 @skipIf(archs=no_match(['x86_64'])) 99 def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): 100 comm_file = os.path.join(self.getBuildDir(), "comm-file") 101 os.mkfifo(comm_file) 102 103 proc = subprocess.Popen( 104 [self.lldbVSCodeExec, "--comm-file", comm_file, "--launch-target", "INVALIDPROGRAM"], 105 universal_newlines=True, stderr=subprocess.PIPE) 106 107 self.readPidMessage(comm_file) 108 self.sendDidAttachMessage(comm_file) 109 self.assertIn("No such file or directory", self.readErrorMessage(comm_file)) 110 111 _, stderr = proc.communicate() 112 self.assertIn("No such file or directory", stderr) 113 114 @skipIfWindows 115 @skipIfRemote 116 @skipIf(archs=no_match(['x86_64'])) 117 def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): 118 comm_file = os.path.join(self.getBuildDir(), "comm-file") 119 os.mkfifo(comm_file) 120 121 proc = subprocess.Popen( 122 [self.lldbVSCodeExec, "--comm-file", comm_file, "--launch-target", "echo", "foo"], 123 universal_newlines=True, stdout=subprocess.PIPE) 124 125 self.readPidMessage(comm_file) 126 self.sendDidAttachMessage(comm_file) 127 128 stdout, _ = proc.communicate() 129 self.assertIn("foo", stdout) 130 131 @skipIfWindows 132 @skipIfRemote 133 @skipIf(archs=no_match(['x86_64'])) 134 def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): 135 comm_file = os.path.join(self.getBuildDir(), "comm-file") 136 os.mkfifo(comm_file) 137 138 proc = subprocess.Popen( 139 [self.lldbVSCodeExec, "--comm-file", comm_file, "--launch-target", "env"], 140 universal_newlines=True, stdout=subprocess.PIPE, 141 env={**os.environ, "FOO": "BAR"}) 142 143 self.readPidMessage(comm_file) 144 self.sendDidAttachMessage(comm_file) 145 146 stdout, _ = proc.communicate() 147 self.assertIn("FOO=BAR", stdout) 148 149 @skipIfWindows 150 @skipIfRemote 151 @skipIf(archs=no_match(['x86_64'])) 152 def test_NonAttachedRunInTerminalLauncher(self): 153 comm_file = os.path.join(self.getBuildDir(), "comm-file") 154 os.mkfifo(comm_file) 155 156 proc = subprocess.Popen( 157 [self.lldbVSCodeExec, "--comm-file", comm_file, "--launch-target", "echo", "foo"], 158 universal_newlines=True, stderr=subprocess.PIPE, 159 env={**os.environ, "LLDB_VSCODE_RIT_TIMEOUT_IN_MS": "1000"}) 160 161 self.readPidMessage(comm_file) 162 163 _, stderr = proc.communicate() 164 self.assertIn("Timed out trying to get messages from the debug adaptor", stderr) 165