Passed ENV and CWD for VSCode protocol (#208)
authorAnton Zhukov/AI Compiler Lab /SRR/Engineer/Samsung Electronics <a.zhukov@samsung.com>
Wed, 8 Jul 2020 15:20:08 +0000 (18:20 +0300)
committerAlexander Soldatov/AI Compiler Lab /SRR/Staff Engineer/Samsung Electronics <soldatov.a@samsung.com>
Wed, 8 Jul 2020 15:20:08 +0000 (18:20 +0300)
26 files changed:
src/debug/netcoredbg/debugger.h
src/debug/netcoredbg/manageddebugger.cpp
src/debug/netcoredbg/manageddebugger.h
src/debug/netcoredbg/miprotocol.cpp
src/debug/netcoredbg/platform.cpp
src/debug/netcoredbg/platform.h
src/debug/netcoredbg/vscodeprotocol.cpp
test-suite/NetcoreDbgTest/VSCode/VSCodeProtocolRequest.cs
test-suite/VSCodeExampleTest/Program.cs
test-suite/VSCodeTestBreakpoint/Program.cs
test-suite/VSCodeTestDisconnect/Program.cs
test-suite/VSCodeTestEnv/Program.cs [new file with mode: 0644]
test-suite/VSCodeTestEnv/VSCodeTestEnv.csproj [new file with mode: 0644]
test-suite/VSCodeTestEvaluate/Program.cs
test-suite/VSCodeTestFuncBreak/Program.cs
test-suite/VSCodeTestPause/Program.cs
test-suite/VSCodeTestStepping/Program.cs
test-suite/VSCodeTestThreads/Program.cs
test-suite/VSCodeTestVariables/Program.cs
test-suite/XunitTests/LocalTest.cs
test-suite/XunitTests/XunitTests.csproj
test-suite/run_tests.ps1
test-suite/run_tests.sh
test-suite/sdb_run_tests.ps1
test-suite/sdb_run_tests.sh
test-suite/test-suite.sln

index 20320889f43e56be5909614b302d60382f574e1f..233176a8528ae5494231b624f81e54991601c164 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <string>
 #include <vector>
+#include <map>
 
 // For `HRESULT` definition
 #ifdef FEATURE_PAL
@@ -39,7 +40,8 @@ public:
 
     virtual HRESULT Initialize() = 0;
     virtual HRESULT Attach(int pid) = 0;
-    virtual HRESULT Launch(std::string fileExec, std::vector<std::string> execArgs, bool stopAtEntry = false) = 0;
+    virtual HRESULT Launch(const std::string &fileExec, const std::vector<std::string> &execArgs, const std::map<std::string, std::string> &env,
+        const std::string &cwd, bool stopAtEntry = false) = 0;
     virtual HRESULT ConfigurationDone() = 0;
 
     virtual HRESULT Disconnect(DisconnectAction action = DisconnectDefault) = 0;
index eeb6994aac1b518041dcc5c1ccb719185daee30b..4cd7eadf779deae396db25be8bbecfd0e495c30e 100644 (file)
@@ -2,13 +2,18 @@
 // Distributed under the MIT License.
 // See the LICENSE file in the project root for more information.
 
-#include "manageddebugger.h"
-
 #include <sstream>
 #include <mutex>
 #include <memory>
 #include <chrono>
 #include <stdexcept>
+#include <vector>
+#include <map>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "manageddebugger.h"
 
 #include "valueprint.h"
 #include "symbolreader.h"
@@ -19,6 +24,8 @@
 #include "logger.h"
 
 using std::string;
+using std::vector;
+using std::map;
 
 // From dbgshim.h
 struct dbgshim_t
@@ -1068,7 +1075,7 @@ HRESULT ManagedDebugger::Attach(int pid)
     return RunIfReady();
 }
 
-HRESULT ManagedDebugger::Launch(string fileExec, std::vector<string> execArgs, bool stopAtEntry)
+HRESULT ManagedDebugger::Launch(const string &fileExec, const vector<string> &execArgs, const map<string, string> &env, const string &cwd, bool stopAtEntry)
 {
     LogFuncEntry();
 
@@ -1076,6 +1083,8 @@ HRESULT ManagedDebugger::Launch(string fileExec, std::vector<string> execArgs, b
     m_execPath = fileExec;
     m_execArgs = execArgs;
     m_stopAtEntry = stopAtEntry;
+    m_cwd = cwd;
+    m_env = env;
     m_breakpoints.SetStopAtEntry(m_stopAtEntry);
     return RunIfReady();
 }
@@ -1515,6 +1524,19 @@ static string EscapeShellArg(const string &arg)
     return s;
 }
 
+static bool IsDirExists(const char* const path)
+{
+    struct stat info;
+
+    if (stat(path, &info) != 0)
+        return false;
+
+    if (!(info.st_mode & S_IFDIR))
+        return false;
+
+    return true;
+}
+
 HRESULT ManagedDebugger::RunProcess(string fileExec, std::vector<string> execArgs)
 {
     static const auto startupCallbackWaitTimeout = std::chrono::milliseconds(5000);
@@ -1532,10 +1554,38 @@ HRESULT ManagedDebugger::RunProcess(string fileExec, std::vector<string> execArg
 
     HANDLE resumeHandle; // Fake thread handle for the process resume
 
+    vector<char> outEnv;
+    if (!m_env.empty()) {
+        // We need to append the environ values with keeping the current process environment block.
+        // It works equal for any platrorms in coreclr CreateProcessW(), but not critical for Linux.
+        map<string, string> envMap;
+        if (GetSystemEnvironmentAsMap(envMap) != -1) {
+            auto it = m_env.begin();
+            auto end = m_env.end();
+            // Override the system value (PATHs appending needs a complex implementation)
+            while (it != end) {
+                envMap[it->first] = it->second;
+                ++it;
+            }
+            for (const auto &pair : envMap) {
+                outEnv.insert(outEnv.end(), pair.first.begin(), pair.first.end());
+                outEnv.push_back('=');
+                outEnv.insert(outEnv.end(), pair.second.begin(), pair.second.end());
+                outEnv.push_back('\0');
+            }
+            outEnv.push_back('\0');
+        }
+    }
+
+    // cwd in launch.json set working directory for debugger https://code.visualstudio.com/docs/python/debugging#_cwd
+    if (!m_cwd.empty())
+        if (!IsDirExists(m_cwd.c_str()) || !SetWorkDir(m_cwd))
+            m_cwd.clear();
+
     IfFailRet(g_dbgshim.CreateProcessForLaunch(reinterpret_cast<LPWSTR>(const_cast<WCHAR*>(to_utf16(ss.str()).c_str())),
                                      /* Suspend process */ TRUE,
-                                     /* Current environment */ NULL,
-                                     /* Current working directory */ NULL,
+                                     outEnv.empty() ? NULL : &outEnv[0],
+                                     m_cwd.empty() ? NULL : reinterpret_cast<LPCWSTR>(to_utf16(m_cwd).c_str()),
                                      &m_processId, &resumeHandle));
 
     IfFailRet(g_dbgshim.RegisterForRuntimeStartup(m_processId, ManagedDebugger::StartupCallback, this, &m_unregisterToken));
index 150eaf4033d0cf20dedcdc2381a6a38ebea50736..f5ddfc3bf4bae29207ecdf4c3581ccdfdbb498b6 100644 (file)
@@ -10,6 +10,7 @@
 #include <unordered_map>
 #include <unordered_set>
 #include <vector>
+#include <map>
 #include <condition_variable>
 #include <future>
 
@@ -567,6 +568,8 @@ private:
     } m_startMethod;
     std::string m_execPath;
     std::vector<std::string> m_execArgs;
+    std::string m_cwd;
+    std::map<std::string, std::string> m_env;
     bool m_stopAtEntry;
     bool m_isConfigurationDone;
 
@@ -625,7 +628,8 @@ public:
 
     HRESULT Initialize() override;
     HRESULT Attach(int pid) override;
-    HRESULT Launch(std::string fileExec, std::vector<std::string> execArgs, bool stopAtEntry = false) override;
+    HRESULT Launch(const std::string &fileExec, const std::vector<std::string> &execArgs, const std::map<std::string, std::string> &env,
+        const std::string &cwd, bool stopAtEntry = false) override;
     HRESULT ConfigurationDone() override;
 
     HRESULT Disconnect(DisconnectAction action = DisconnectDefault) override;
index 369e506e4e7a18192a10e82b69890e470e2e9d44..89a075318b4380bdb0ce7eb2ad3e1d0fceb12df6 100644 (file)
@@ -1092,7 +1092,7 @@ HRESULT MIProtocol::HandleCommand(std::string command,
     { "exec-run", [this](const std::vector<std::string> &args, std::string &output) -> HRESULT {
         HRESULT Status;
         m_debugger->Initialize();
-        IfFailRet(m_debugger->Launch(m_fileExec, m_execArgs, true));
+        IfFailRet(m_debugger->Launch(m_fileExec, m_execArgs, {}, "", true));
         Status = m_debugger->ConfigurationDone();
         if (SUCCEEDED(Status))
             output = "^running";
index 2e5cdbf208d0c3f6b3c1eefad9b68c0fddf5ba28..2d288ff22a5a8bf8b60b5170cb856c5826209b4c 100644 (file)
@@ -19,6 +19,7 @@
 #include <fstream>
 #include <thread>
 #include <algorithm>
+#include <map>
 
 #ifdef FEATURE_PAL
 #include <dirent.h>
@@ -41,6 +42,9 @@
 #include <winsock2.h>
 #endif
 
+using std::string;
+using std::map;
+
 unsigned long OSPageSize()
 {
     static unsigned long pageSize = 0;
@@ -844,6 +848,38 @@ bool IsFullPath(const std::string &path)
     return true;
 }
 
+char** GetSystemEnvironment()
+{
+    char** sysEnviron;
+
+#if __APPLE__
+    sysEnviron = *(_NSGetEnviron());
+#else   // __APPLE__
+    extern char** environ;
+    sysEnviron = environ;
+#endif  // __APPLE__
+
+    return sysEnviron;
+}
+
+int GetSystemEnvironmentAsMap(map<string, string>& outMap) {
+    char*const*const pEnv = GetSystemEnvironment();
+
+    if (pEnv == nullptr)
+        return -1;
+
+    int counter = 0;
+    while (pEnv[counter] != nullptr) {
+        const string env = pEnv[counter];
+        size_t pos = env.find_first_of("=");
+        if (pos != string::npos && pos != 0) {
+            outMap.emplace(env.substr(0, pos), env.substr(pos+1));
+        }
+        ++counter;
+    }
+
+    return 0;
+}
 
 IORedirectServer::operator bool() const
 {
index 7a3dfc8b1fdeffd04607152579b94b1cf7246e5d..cfb2af196f17899652409b19d2ed992cc8da3478 100644 (file)
@@ -3,9 +3,10 @@
 // See the LICENSE file in the project root for more information.
 #pragma once
 
-#include <string>
 #include <iostream>
 #include <functional>
+#include <string>
+#include <map>
 
 #include <palclr.h>
 
@@ -21,6 +22,8 @@ void UnsetCoreCLREnv();
 std::string GetTempFolder();
 std::string GetBasename(const std::string &path);
 bool IsFullPath(const std::string &path);
+char** GetSystemEnvironment();
+int GetSystemEnvironmentAsMap(std::map<std::string, std::string> &out);
 
 class IORedirectServerHandles;
 
index 2019bb46ff279f62bf2bc0c4a3411c58d6c98fbc..7cf69287c29e19c4d2e4c586744b5ead16718e73 100644 (file)
@@ -2,19 +2,25 @@
 // Distributed under the MIT License.
 // See the LICENSE file in the project root for more information.
 
-#include "vscodeprotocol.h"
-
 #include <iostream>
+#include <string>
+#include <vector>
 #include <unordered_map>
+#include <map>
+
+#include <exception>
 
 #include <winerror.h>
 
+#include "vscodeprotocol.h"
+
 #include "torelease.h"
 #include "cputil.h"
 #include "logger.h"
 
 using std::string;
 using std::vector;
+using std::map;
 using std::min;
 
 // for convenience
@@ -415,14 +421,23 @@ HRESULT VSCodeProtocol::HandleCommand(const std::string &command, const json &ar
 
         return S_OK;
     } },
-    { "launch", [this](const json &arguments, json &body){
-        if (!m_fileExec.empty())
-        {
-            return m_debugger->Launch(m_fileExec, m_execArgs, arguments.value("stopAtEntry", false));
+    {"launch", [this](const json &arguments, json &body) {
+        const string cwd = arguments.at("cwd").get<string>();
+        map<string, string> env;
+        try {
+            env = arguments.at("env").get<map<string, string> >();
+        }
+        catch (std::exception &ex) {
+            Logger::levelLog(LOG_INFO, "'%s'", ex.what());
+            // If we catch inconsistent state on the interrupted reading
+            env.clear();
+        }
+        if (!m_fileExec.empty()) {
+            return m_debugger->Launch(m_fileExec, m_execArgs, env, cwd, arguments.value("stopAtEntry", false));
         }
-        std::vector<std::string> args = arguments.value("args", std::vector<std::string>());
+        vector<string> args = arguments.value("args", vector<string>());
         args.insert(args.begin(), arguments.at("program").get<std::string>());
-        return m_debugger->Launch("dotnet", args, arguments.value("stopAtEntry", false));
+        return m_debugger->Launch("dotnet", args, env, cwd, arguments.value("stopAtEntry", false));
     } },
     { "threads", [this](const json &arguments, json &body){
         HRESULT Status;
index 0c3370046b822c07ddd0c6d702786b25055a472e..1df5e64fe3453515e8de3601fa5d51d5973e764b 100644 (file)
@@ -50,6 +50,7 @@ namespace NetcoreDbgTest.VSCode
         public string program;
         public List<string> args;
         public string cwd;
+        public Dictionary<string, string> env;
         public string console;
         public bool stopAtEntry;
         public string internalConsoleOptions;
index 437ee5a9a31b106dd77c4e748e78aba5d45e0600..fc68d02b8f43aa8d032b38280df26169dd75a38b 100644 (file)
@@ -35,8 +35,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index 3663008919d5c0c6cbc2974404483098680a73d7..27d39994c9dda035de8eee73c99d46c24224001d 100644 (file)
@@ -33,8 +33,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index 48a6c085610aec0479da87f11107793884d16247..baa6b1dd365d4f6f239bf87c83e9bdbeef8151d4 100644 (file)
@@ -33,8 +33,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
diff --git a/test-suite/VSCodeTestEnv/Program.cs b/test-suite/VSCodeTestEnv/Program.cs
new file mode 100644 (file)
index 0000000..447e5d5
--- /dev/null
@@ -0,0 +1,156 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading;
+
+using NetcoreDbgTest;
+using NetcoreDbgTest.VSCode;
+using NetcoreDbgTest.Script;
+
+using Xunit;
+using Newtonsoft.Json;
+
+namespace NetcoreDbgTest.Script
+{
+    class Context
+    {
+        public static void PrepareStart()
+        {
+            InitializeRequest initializeRequest = new InitializeRequest();
+            initializeRequest.arguments.clientID = "vscode";
+            initializeRequest.arguments.clientName = "Visual Studio Code";
+            initializeRequest.arguments.adapterID = "coreclr";
+            initializeRequest.arguments.pathFormat = "path";
+            initializeRequest.arguments.linesStartAt1 = true;
+            initializeRequest.arguments.columnsStartAt1 = true;
+            initializeRequest.arguments.supportsVariableType = true;
+            initializeRequest.arguments.supportsVariablePaging = true;
+            initializeRequest.arguments.supportsRunInTerminalRequest = true;
+            initializeRequest.arguments.locale = "en-us";
+            Assert.True(VSCodeDebugger.Request(initializeRequest).Success);
+
+            LaunchRequest launchRequest = new LaunchRequest();
+            launchRequest.arguments.name = ".NET Core Launch (web)";
+            launchRequest.arguments.type = "coreclr";
+            launchRequest.arguments.preLaunchTask = "build";
+
+            launchRequest.arguments.program = Path.GetFileName(DebuggeeInfo.TargetAssemblyPath);
+            string targetAssemblyPath = Path.GetFileName(DebuggeeInfo.TargetAssemblyPath);
+            int subLength = DebuggeeInfo.TargetAssemblyPath.Length - targetAssemblyPath.Length;
+            string dllPath = DebuggeeInfo.TargetAssemblyPath.Substring(0, subLength);
+            launchRequest.arguments.cwd = dllPath;
+
+            launchRequest.arguments.env = new Dictionary<string, string>();
+            launchRequest.arguments.env.Add("ASPNETCORE_ENVIRONMENT", VALUE_A);
+            launchRequest.arguments.env.Add("ASPNETCORE_URLS", VALUE_B);
+            launchRequest.arguments.console = "internalConsole";
+            launchRequest.arguments.stopAtEntry = true;
+            launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
+            launchRequest.arguments.__sessionId = Guid.NewGuid().ToString();
+            Assert.True(VSCodeDebugger.Request(launchRequest).Success);
+        }
+
+        public static void PrepareEnd()
+        {
+            ConfigurationDoneRequest configurationDoneRequest = new ConfigurationDoneRequest();
+            Assert.True(VSCodeDebugger.Request(configurationDoneRequest).Success);
+        }
+
+        public static void WasExit()
+        {
+            bool wasExited = false;
+            int ?exitCode = null;
+            bool wasTerminated = false;
+
+            Func<string, bool> filter = (resJSON) => {
+                if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "exited")) {
+                    wasExited = true;
+                    ExitedEvent exitedEvent = JsonConvert.DeserializeObject<ExitedEvent>(resJSON);
+                    exitCode = exitedEvent.body.exitCode;
+                }
+                if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "terminated")) {
+                    wasTerminated = true;
+                }
+                if (wasExited && exitCode == 0 && wasTerminated)
+                    return true;
+
+                return false;
+            };
+
+            if (!VSCodeDebugger.IsEventReceived(filter))
+                throw new NetcoreDbgTestCore.ResultNotSuccessException();
+        }
+
+        public static void DebuggerExit()
+        {
+            DisconnectRequest disconnectRequest = new DisconnectRequest();
+            disconnectRequest.arguments = new DisconnectArguments();
+            disconnectRequest.arguments.restart = false;
+            Assert.True(VSCodeDebugger.Request(disconnectRequest).Success);
+        }
+
+        public static void WasEntryPointHit()
+        {
+            Func<string, bool> filter = (resJSON) => {
+                if (VSCodeDebugger.isResponseContainProperty(resJSON, "event", "stopped")
+                    && VSCodeDebugger.isResponseContainProperty(resJSON, "reason", "entry")) {
+                    threadId = Convert.ToInt32(VSCodeDebugger.GetResponsePropertyValue(resJSON, "threadId"));
+                    return true;
+                }
+                return false;
+            };
+
+            if (!VSCodeDebugger.IsEventReceived(filter))
+                throw new NetcoreDbgTestCore.ResultNotSuccessException();
+        }
+
+        public static void Continue()
+        {
+            ContinueRequest continueRequest = new ContinueRequest();
+            continueRequest.arguments.threadId = threadId;
+            Assert.True(VSCodeDebugger.Request(continueRequest).Success);
+        }
+
+        static VSCodeDebugger VSCodeDebugger = new VSCodeDebugger();
+        static int threadId = -1;
+
+        public const string VALUE_A = "Development";
+        public const string VALUE_B = "https://localhost:25001";
+    }
+}
+
+namespace VSCodeTestEnv
+{
+    class Program
+    {
+        public static void Main(string[] args)
+        {
+            Label.Checkpoint("init", "finish", () => {
+                Context.PrepareStart();
+                Context.PrepareEnd();
+                Context.WasEntryPointHit();
+                Context.Continue();
+            });
+
+            // Begin user code
+            user_code();
+            // End user code
+
+            Label.Checkpoint("finish", "", () => {
+                Context.WasExit();
+                Context.DebuggerExit();
+            });
+        }
+
+        public static void user_code()
+        {
+            var read_a = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
+            var read_b = Environment.GetEnvironmentVariable("ASPNETCORE_URLS");
+
+            // xunit Asserts() has a wrong behavior under Tizen devices
+            if (!String.Equals(Context.VALUE_A, read_a) || !String.Equals(Context.VALUE_B, read_b))
+                throw new NotImplementedException("TEST FAILED");
+        }
+    }
+}
diff --git a/test-suite/VSCodeTestEnv/VSCodeTestEnv.csproj b/test-suite/VSCodeTestEnv/VSCodeTestEnv.csproj
new file mode 100644 (file)
index 0000000..83f43fb
--- /dev/null
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+  <ItemGroup>\r
+    <ProjectReference Include="..\NetcoreDbgTest\NetcoreDbgTest.csproj" />\r
+  </ItemGroup>\r
+\r
+  <PropertyGroup>\r
+    <OutputType>Exe</OutputType>\r
+    <TargetFramework>netcoreapp2.1</TargetFramework>\r
+  </PropertyGroup>\r
+\r
+</Project>\r
index 1540d5de66f37943421d8ac9dc551da8e2db7ee3..faa7bf47eac935937fd6ddfdb31b132fef8ac057 100644 (file)
@@ -33,8 +33,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index e66af304df75e31df17dd3f80c171e5ca814ef66..4390e19be60adb9c40404183a0013ca7f55407e5 100644 (file)
@@ -33,8 +33,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index 9f0a8ffe8e529bfe725b9f29442e7a5b5827c38a..902f6f5507ca3e8e605d6ecba93e1950ba91405c 100644 (file)
@@ -32,8 +32,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index 95c4ba5f50b12a673725f92262d6e6395c7ebd26..3b0c2facff02fd9545c2f63cac6810dbc876cb8a 100644 (file)
@@ -33,8 +33,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index 5c5a517babdc67317c75495753a596f7a68162b1..cfd5c200cfa75576051e6dbe6675cffa46ff64cc 100644 (file)
@@ -35,8 +35,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index b10a6079311d2f4ed63b5cda59d33bd40af168de..c10bbd55a880c582e5e629e5afda109b10b6a157 100644 (file)
@@ -35,8 +35,7 @@ namespace NetcoreDbgTest.Script
             launchRequest.arguments.type = "coreclr";
             launchRequest.arguments.preLaunchTask = "build";
             launchRequest.arguments.program = DebuggeeInfo.TargetAssemblyPath;
-            // NOTE this code works only with one source file
-            launchRequest.arguments.cwd = Directory.GetParent(DebuggeeInfo.SourceFilesPath).FullName;
+            launchRequest.arguments.cwd = "";
             launchRequest.arguments.console = "internalConsole";
             launchRequest.arguments.stopAtEntry = true;
             launchRequest.arguments.internalConsoleOptions = "openOnSessionStart";
index bdae9b309abd1cddda07de70917df8ebbb7a014c..6a422bc339f9229c62d24c572bf780718aa5903c 100644 (file)
@@ -44,6 +44,7 @@ namespace XUnitTests
         [InlineData("VSCodeTestVariables", "Program.cs")]
         [InlineData("VSCodeTestEvaluate", "Program.cs")]
         [InlineData("VSCodeTestStepping", "Program.cs")]
+        [InlineData("VSCodeTestEnv", "Program.cs")]
         public void Run(string testCaseName, string testCourceList)
         {
             string testSuiteRoot = Path.GetFullPath(
index 09bd0ab097ed103140ae1bde89c8b59b762d0a36..59981a35a02c79b28b260e2a4f60e968c4f67429 100644 (file)
@@ -42,6 +42,7 @@
     <ProjectReference Include="..\VSCodeTestVariables\VSCodeTestVariables.csproj" />\r
     <ProjectReference Include="..\VSCodeTestEvaluate\VSCodeTestEvaluate.csproj" />\r
     <ProjectReference Include="..\VSCodeTestStepping\VSCodeTestStepping.csproj" />\r
+    <ProjectReference Include="..\VSCodeTestEnv\VSCodeTestEnv.csproj" />\r
   </ItemGroup>\r
 \r
 </Project>\r
index b5a9478074fccc5e6c0233f79f3afbe2604297aa..5b5658d5263a6a059f4fac80b42923b10353e43e 100644 (file)
@@ -25,6 +25,7 @@ $ALL_TEST_NAMES = @(
     "VSCodeTestVariables"
     "VSCodeTestEvaluate"
     "VSCodeTestStepping"
+    "VSCodeTestEnv"
 )
 
 $TEST_NAMES = $args
index aae39c6a65baaec5ebbded263a08a207dce07ad4..73af249675a9e3d02ca9fa32587915622bc40bf0 100755 (executable)
@@ -27,6 +27,7 @@ ALL_TEST_NAMES=(
     "VSCodeTestVariables"
     "VSCodeTestEvaluate"
     "VSCodeTestStepping"
+    "VSCodeTestEnv"
 )
 
 TEST_NAMES="$@"
index 2dabf7064cc6f683bf4281721172f0f7b12ae14e..b065ba49d55afe4f75840e98b25381170ac457fd 100644 (file)
@@ -27,6 +27,7 @@ $ALL_TEST_NAMES = @(
     "VSCodeTestVariables"
     "VSCodeTestEvaluate"
     "VSCodeTestStepping"
+    "VSCodeTestEnv"
 )
 
 $TEST_NAMES = $args
@@ -73,7 +74,8 @@ foreach ($TEST_NAME in $TEST_NAMES) {
             --tcp localhost 4712 `
             --proto $PROTO `
             --test $TEST_NAME `
-            --sources $SOURCE_FILES
+            --sources $SOURCE_FILES `
+            --assembly /tmp/$TEST_NAME.dll
     } else {
         $PROTO = "mi"
 
index 6003af5d71e41532d83807e2ad8abf13ad83cd33..84e053206209fe993655088f460e083e23657f1f 100755 (executable)
@@ -41,6 +41,7 @@ ALL_TEST_NAMES=(
     "VSCodeTestVariables"
     "VSCodeTestEvaluate"
     "VSCodeTestStepping"
+    "VSCodeTestEnv"
 )
 
 SDB=${SDB:-sdb}
@@ -169,7 +170,8 @@ for TEST_NAME in $TEST_NAMES; do
             --tcp localhost $PORT \
             --proto $PROTO \
             --test $TEST_NAME \
-            --sources $SOURCE_FILES
+            --sources $SOURCE_FILES \
+            --assembly $REMOTETESTDIR/$TEST_NAME.dll
     else
         PROTO="mi"
 
index 9932cbc4ac2b279559a127c2548a9e5f161e01c2..fd79e0ce4db11fd13285a0730ccc0e55082593a9 100644 (file)
@@ -59,6 +59,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSCodeTestStepping", "VSCod
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MITestExceptionBreakpoint", "MITestExceptionBreakpoint\MITestExceptionBreakpoint.csproj", "{41431C99-59DF-4B7D-9647-BDF4258B048D}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSCodeTestEnv", "VSCodeTestEnv\VSCodeTestEnv.csproj", "{7555F581-C632-4490-A0E4-E4F1539E9209}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -408,5 +410,17 @@ Global
                {41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x64.Build.0 = Release|Any CPU
                {41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x86.ActiveCfg = Release|Any CPU
                {41431C99-59DF-4B7D-9647-BDF4258B048D}.Release|x86.Build.0 = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x64.ActiveCfg = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x64.Build.0 = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Debug|x86.Build.0 = Debug|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|Any CPU.Build.0 = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x64.ActiveCfg = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x64.Build.0 = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x86.ActiveCfg = Release|Any CPU
+               {7555F581-C632-4490-A0E4-E4F1539E9209}.Release|x86.Build.0 = Release|Any CPU
        EndGlobalSection
 EndGlobal