Add MI protocol break-update-line command.
authorMikhail Kurinnoi <m.kurinnoi@samsung.com>
Thu, 12 Jan 2023 14:40:59 +0000 (17:40 +0300)
committerGleb Balykov/Platform Lab /SRR/Staff Engineer/Samsung Electronics <g.balykov@samsung.com>
Tue, 17 Jan 2023 16:28:57 +0000 (19:28 +0300)
Command format:
    break-update-line ID NEW_LINE
where
    ID - ID of previously added breakpoint, that should be changed;
    NEW_LINE - new line number in source file.

17 files changed:
src/debugger/breakpoints.cpp
src/debugger/breakpoints.h
src/debugger/breakpoints_line.cpp
src/debugger/breakpoints_line.h
src/debugger/manageddebugger.cpp
src/debugger/manageddebugger.h
src/interfaces/idebugger.h
src/protocols/miprotocol.cpp
src/protocols/protocol_utils.cpp
src/protocols/protocol_utils.h
test-suite/MITestBreakpointUpdate/MITestBreakpointUpdate.csproj [new file with mode: 0644]
test-suite/MITestBreakpointUpdate/Program.cs [new file with mode: 0644]
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 4947ea6fdc7716146d709237743b89cba8f7e1b7..4ef92cfa188df12534c02ff928c3c01b80b6b127 100644 (file)
@@ -96,6 +96,11 @@ HRESULT Breakpoints::SetFuncBreakpoints(bool haveProcess, const std::vector<Func
     });
 }
 
+HRESULT Breakpoints::UpdateLineBreakpoint(bool haveProcess, int id, int linenum, Breakpoint &breakpoint)
+{
+    return m_uniqueLineBreakpoints->UpdateLineBreakpoint(haveProcess, id, linenum, breakpoint);
+}
+
 HRESULT Breakpoints::SetLineBreakpoints(bool haveProcess, const std::string& filename, const std::vector<LineBreakpoint> &lineBreakpoints, std::vector<Breakpoint> &breakpoints)
 {
     return m_uniqueLineBreakpoints->SetLineBreakpoints(haveProcess, filename, lineBreakpoints, breakpoints, [&]() -> uint32_t
index 22c1ed5598fc29a7487c26b13d2fadc498521025..08db479441e2353b84234fb00682e7cbc3084325 100644 (file)
@@ -44,6 +44,7 @@ public:
     void DeleteAll();
     HRESULT DisableAll(ICorDebugProcess *pProcess);
 
+    HRESULT UpdateLineBreakpoint(bool haveProcess, int id, int linenum, Breakpoint &breakpoint);
     HRESULT SetFuncBreakpoints(bool haveProcess, const std::vector<FuncBreakpoint> &funcBreakpoints, std::vector<Breakpoint> &breakpoints);
     HRESULT SetLineBreakpoints(bool haveProcess, const std::string &filename, const std::vector<LineBreakpoint> &lineBreakpoints, std::vector<Breakpoint> &breakpoints);
     HRESULT SetExceptionBreakpoints(const std::vector<ExceptionBreakpoint> &exceptionBreakpoints, std::vector<Breakpoint> &breakpoints);
index f5dac6f6a5128a99bae27a1c1a0501538b20077e..83d02ebbd2c3996463ac56d4f6853fb04b851259 100644 (file)
@@ -256,6 +256,87 @@ HRESULT LineBreakpoints::ManagedCallbackLoadModule(ICorDebugModule *pModule, std
     return S_OK;\r
 }\r
 \r
+HRESULT LineBreakpoints::UpdateLineBreakpoint(bool haveProcess, int id, int linenum, Breakpoint &breakpoint)\r
+{\r
+    for (auto &initialBreakpoints : m_lineBreakpointMapping)\r
+    {\r
+        for (auto &initialBreakpoint : initialBreakpoints.second)\r
+        {\r
+            if (initialBreakpoint.id != (unsigned)id)\r
+                continue;\r
+\r
+            initialBreakpoint.breakpoint.line = linenum;\r
+\r
+            if (!haveProcess)\r
+            {\r
+                initialBreakpoint.resolved_linenum = 0;\r
+                initialBreakpoint.resolved_fullname_index = 0;\r
+                breakpoint.message = "The breakpoint is pending and will be resolved when debugging starts.";\r
+                return S_OK;\r
+            }\r
+\r
+            CORDB_ADDRESS modAddress = 0;\r
+            if (initialBreakpoint.resolved_linenum)\r
+            {\r
+                auto bMap_it = m_lineResolvedBreakpoints.find(initialBreakpoint.resolved_fullname_index);\r
+                if (bMap_it == m_lineResolvedBreakpoints.end())\r
+                    return E_FAIL;\r
+\r
+                auto bList_it = bMap_it->second.find(initialBreakpoint.resolved_linenum);\r
+                if (bList_it == bMap_it->second.end())\r
+                    return E_FAIL;\r
+\r
+                for (auto itList = bList_it->second.begin(); itList != bList_it->second.end();)\r
+                {\r
+                    if ((*itList).id == initialBreakpoint.id)\r
+                    {\r
+                        modAddress = (*itList).modAddress;\r
+\r
+                        bList_it->second.erase(itList);\r
+                        initialBreakpoint.resolved_linenum = 0;\r
+                        initialBreakpoint.resolved_fullname_index = 0;\r
+                        EnableOneICorBreakpointForLine(bList_it->second);\r
+                        break;\r
+                    }\r
+                    else\r
+                        ++itList;\r
+                }\r
+            }\r
+\r
+            ManagedLineBreakpoint bp;\r
+            bp.id = initialBreakpoint.id;\r
+            bp.module = initialBreakpoint.breakpoint.module;\r
+            bp.enabled = initialBreakpoint.enabled;\r
+            bp.linenum = initialBreakpoint.breakpoint.line;\r
+            bp.endLine = initialBreakpoint.breakpoint.line;\r
+            bp.condition = initialBreakpoint.breakpoint.condition;\r
+\r
+            unsigned resolved_fullname_index = 0;\r
+            std::vector<ModulesSources::resolved_bp_t> resolvedPoints;\r
+            if (FAILED(m_sharedModules->ResolveBreakpoint(modAddress, initialBreakpoints.first, resolved_fullname_index, bp.linenum, resolvedPoints)) ||\r
+                FAILED(ActivateLineBreakpoint(bp, initialBreakpoints.first, m_justMyCode, resolvedPoints)))\r
+            {\r
+                return S_OK;\r
+            }\r
+\r
+            std::string resolved_fullname;\r
+            m_sharedModules->GetSourceFullPathByIndex(resolved_fullname_index, resolved_fullname);\r
+\r
+            initialBreakpoint.resolved_fullname_index = resolved_fullname_index;\r
+            initialBreakpoint.resolved_linenum = bp.linenum;\r
+\r
+            bp.ToBreakpoint(breakpoint, resolved_fullname);\r
+\r
+            m_lineResolvedBreakpoints[resolved_fullname_index][initialBreakpoint.resolved_linenum].push_back(std::move(bp));\r
+            EnableOneICorBreakpointForLine(m_lineResolvedBreakpoints[resolved_fullname_index][initialBreakpoint.resolved_linenum]);\r
+            return S_OK;\r
+        }\r
+    }\r
+\r
+    LOGE("UpdateLineBreakpoint error, no line breakpoint with ID %i", id);\r
+    return E_INVALIDARG;\r
+}\r
+\r
 HRESULT LineBreakpoints::SetLineBreakpoints(bool haveProcess, const std::string& filename, const std::vector<LineBreakpoint> &lineBreakpoints,\r
                                             std::vector<Breakpoint> &breakpoints, std::function<uint32_t()> getId)\r
 {\r
index dc0b429ad9f49b0f360a5c66f0e84410141489c3..4c2dfa5c5aaf9190104b78f647dfc27998675251 100644 (file)
@@ -34,6 +34,7 @@ public:
 \r
     void SetJustMyCode(bool enable) { m_justMyCode = enable; };\r
     void DeleteAll();\r
+    HRESULT UpdateLineBreakpoint(bool haveProcess, int id, int linenum, Breakpoint &breakpoint);\r
     HRESULT SetLineBreakpoints(bool haveProcess, const std::string &filename, const std::vector<LineBreakpoint> &lineBreakpoints,\r
                                std::vector<Breakpoint> &breakpoints, std::function<uint32_t()> getId);\r
     HRESULT UpdateBreakpointsOnHotReload(ICorDebugModule *pModule, std::unordered_set<mdMethodDef> &methodTokens, std::vector<BreakpointEvent> &events);\r
index c5033ed07d65755bb9a2df91c48a16dcfe65096f..89e94acc6b37b2911d755e82ebcacd28a2bfdf85 100644 (file)
@@ -890,6 +890,14 @@ HRESULT ManagedDebugger::SetEnableCustomNotification(BOOL fEnable)
     return InternalSetEnableCustomNotification(m_sharedModules.get(), fEnable);
 }
 
+HRESULT ManagedDebugger::UpdateLineBreakpoint(int id, int linenum, Breakpoint &breakpoint)
+{
+    LogFuncEntry();
+
+    bool haveProcess = HaveDebugProcess(m_debugProcessRWLock, m_iCorProcess, m_processAttachedMutex, m_processAttachedState);
+    return m_uniqueBreakpoints->UpdateLineBreakpoint(haveProcess, id, linenum, breakpoint);
+}
+
 HRESULT ManagedDebugger::SetLineBreakpoints(const std::string& filename,
                                             const std::vector<LineBreakpoint> &lineBreakpoints,
                                             std::vector<Breakpoint> &breakpoints)
index 74137fb967948457a94d4b3bf80bb881301b3f48..a33d1925c3533f17aadd0bc968550f888e438a29 100644 (file)
@@ -146,6 +146,7 @@ public:
     HRESULT Continue(ThreadId threadId) override;
     HRESULT Pause(ThreadId lastStoppedThread) override;
     HRESULT GetThreads(std::vector<Thread> &threads) override;
+    HRESULT UpdateLineBreakpoint(int id, int linenum, Breakpoint &breakpoint) override;
     HRESULT SetLineBreakpoints(const std::string& filename, const std::vector<LineBreakpoint> &lineBreakpoints, std::vector<Breakpoint> &breakpoints) override;
     HRESULT SetFuncBreakpoints(const std::vector<FuncBreakpoint> &funcBreakpoints, std::vector<Breakpoint> &breakpoints) override;
     HRESULT SetExceptionBreakpoints(const std::vector<ExceptionBreakpoint> &exceptionBreakpoints, std::vector<Breakpoint> &breakpoints) override;
index 79f50d1487d6af69fa42c04b8110be391fd7fc3a..01f4c9501e72cdf4103489f59ce90ca329497a29 100644 (file)
@@ -85,6 +85,7 @@ public:
     virtual HRESULT Continue(ThreadId threadId) = 0;
     virtual HRESULT Pause(ThreadId lastStoppedThread) = 0;
     virtual HRESULT GetThreads(std::vector<Thread> &threads) = 0;
+    virtual HRESULT UpdateLineBreakpoint(int id, int linenum, Breakpoint &breakpoint) = 0;
     virtual HRESULT SetLineBreakpoints(const std::string& filename, const std::vector<LineBreakpoint> &lineBreakpoints, std::vector<Breakpoint> &breakpoints) = 0;
     virtual HRESULT SetFuncBreakpoints(const std::vector<FuncBreakpoint> &funcBreakpoints, std::vector<Breakpoint> &breakpoints) = 0;
     virtual HRESULT SetExceptionBreakpoints(const std::vector<ExceptionBreakpoint> &exceptionBreakpoints, std::vector<Breakpoint> &breakpoints) = 0;
index 8e50a8aaeea18dede4697da223f5b4992a7c65f0..6d2dee43b56494acf6514c921b425a54ee36164e 100644 (file)
@@ -562,6 +562,44 @@ static HRESULT HandleCommand(std::shared_ptr<IDebugger> &sharedDebugger, Breakpo
         output = "^done";
         return S_OK;
     } },
+    { "break-update-line", [&](const std::vector<std::string> &args, std::string &output) -> HRESULT {
+        // Custom MI protocol command for line breakpoint update.
+        // Command format:
+        //    break-update-line ID NEW_LINE
+        // where
+        //    ID - ID of previously added breakpoint, that should be changed;
+        //    NEW_LINE - new line number in source file.
+        if (args.size() != 2)
+        {
+            output = "Command requires 2 arguments";
+            return E_FAIL;
+        }
+
+        bool ok;
+        int id = ProtocolUtils::ParseInt(args.at(0), ok);
+        if (!ok)
+        {
+            output = "Unknown breakpoint id";
+            return E_FAIL;
+        }
+
+        int linenum = ProtocolUtils::ParseInt(args.at(1), ok);
+        if (!ok)
+        {
+            output = "Unknown breakpoint new line";
+            return E_FAIL;
+        }
+
+        Breakpoint breakpoint;
+        if (SUCCEEDED(breakpointsHandle.UpdateLineBreakpoint(sharedDebugger, id, linenum, breakpoint)))
+        {
+            PrintBreakpoint(breakpoint, output);
+            return S_OK;
+        }
+
+        output = "Unknown breakpoint location, breakpoint was not updated";
+        return E_FAIL;
+    } },
     { "break-insert", [&](const std::vector<std::string> &unmutable_args, std::string &output) -> HRESULT {
         HRESULT Status = E_FAIL;
         Breakpoint breakpoint;
index e9a78d43bd062cdcf86c75a53417f0660ca303aa..8b2259121dc3f1187776acabf4d1b18ce9835ee7 100644 (file)
@@ -23,6 +23,32 @@ void BreakpointsHandle::Cleanup()
     m_exceptionBreakpoints.clear();
 }
 
+HRESULT BreakpointsHandle::UpdateLineBreakpoint(std::shared_ptr<IDebugger> &sharedDebugger, int id, int linenum, Breakpoint &breakpoint)
+{
+    for (auto &breakpointsInSource : m_lineBreakpoints)
+    {
+        for (auto &brk : breakpointsInSource.second)
+        {
+            if (brk.first != (unsigned)id)
+                continue;
+
+            brk.second.line = linenum;
+
+            breakpoint.id = brk.first;
+            breakpoint.verified = false;
+            breakpoint.condition = brk.second.condition;
+            breakpoint.source = breakpointsInSource.first;
+            breakpoint.line = brk.second.line;
+            breakpoint.endLine = brk.second.line;
+            breakpoint.hitCount = 0;
+
+            return sharedDebugger->UpdateLineBreakpoint(id, linenum, breakpoint);
+        }
+    }
+
+    return E_INVALIDARG;
+}
+
 HRESULT BreakpointsHandle::SetLineBreakpoint(std::shared_ptr<IDebugger> &sharedDebugger,
                                              const std::string &module, const std::string &filename, int linenum,
                                              const std::string &condition, Breakpoint &breakpoint)
index 3b6460cbca380aba23a1f5e5e67e6732f6473ba0..81379ac8ece88500f99651e22bf66ef404916011 100644 (file)
@@ -42,6 +42,7 @@ private:
     std::unordered_map<uint32_t, ExceptionBreakpoint> m_exceptionBreakpoints;
 
 public:
+    HRESULT UpdateLineBreakpoint(std::shared_ptr<IDebugger> &sharedDebugger, int id, int linenum, Breakpoint &breakpoint);
     HRESULT SetLineBreakpoint(std::shared_ptr<IDebugger> &sharedDebugger, const std::string &module, const std::string &filename,
                               int linenum, const std::string &condition, Breakpoint &breakpoints);
     HRESULT SetFuncBreakpoint(std::shared_ptr<IDebugger> &sharedDebugger, const std::string &module, const std::string &funcname,
diff --git a/test-suite/MITestBreakpointUpdate/MITestBreakpointUpdate.csproj b/test-suite/MITestBreakpointUpdate/MITestBreakpointUpdate.csproj
new file mode 100644 (file)
index 0000000..2512674
--- /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>netcoreapp3.1</TargetFramework>\r
+  </PropertyGroup>\r
+\r
+</Project>\r
diff --git a/test-suite/MITestBreakpointUpdate/Program.cs b/test-suite/MITestBreakpointUpdate/Program.cs
new file mode 100644 (file)
index 0000000..413467a
--- /dev/null
@@ -0,0 +1,283 @@
+using System;\r
+using System.IO;\r
+using System.Diagnostics;\r
+\r
+using NetcoreDbgTest;\r
+using NetcoreDbgTest.MI;\r
+using NetcoreDbgTest.Script;\r
+\r
+namespace NetcoreDbgTest.Script\r
+{\r
+    class Context\r
+    {\r
+        public void Prepare(string caller_trace)\r
+        {\r
+            // Explicitly enable JMC for this test.\r
+            Assert.Equal(MIResultClass.Done,\r
+                         MIDebugger.Request("-gdb-set just-my-code 1").Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            Assert.Equal(MIResultClass.Done,\r
+                         MIDebugger.Request("-file-exec-and-symbols " + ControlInfo.CorerunPath).Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            Assert.Equal(MIResultClass.Done,\r
+                         MIDebugger.Request("-exec-arguments " + ControlInfo.TargetAssemblyPath).Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            Assert.Equal(MIResultClass.Running,\r
+                         MIDebugger.Request("-exec-run").Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        bool IsStoppedEvent(MIOutOfBandRecord record)\r
+        {\r
+            if (record.Type != MIOutOfBandRecordType.Async) {\r
+                return false;\r
+            }\r
+\r
+            var asyncRecord = (MIAsyncRecord)record;\r
+\r
+            if (asyncRecord.Class != MIAsyncRecordClass.Exec ||\r
+                asyncRecord.Output.Class != MIAsyncOutputClass.Stopped) {\r
+                return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        public void WasEntryPointHit(string caller_trace)\r
+        {\r
+            Func<MIOutOfBandRecord, bool> filter = (record) => {\r
+                if (!IsStoppedEvent(record)) {\r
+                    return false;\r
+                }\r
+\r
+                var output = ((MIAsyncRecord)record).Output;\r
+                var reason = (MIConst)output["reason"];\r
+\r
+                if (reason.CString != "entry-point-hit") {\r
+                    return false;\r
+                }\r
+\r
+                var frame = (MITuple)output["frame"];\r
+                var func = (MIConst)frame["func"];\r
+                if (func.CString == ControlInfo.TestName + ".Program.Main()") {\r
+                    return true;\r
+                }\r
+\r
+                return false;\r
+            };\r
+\r
+            Assert.True(MIDebugger.IsEventReceived(filter), @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public void WasBreakpointWithIdHit(string caller_trace, string bpName, string id)\r
+        {\r
+            var bp = (LineBreakpoint)ControlInfo.Breakpoints[bpName];\r
+\r
+            Func<MIOutOfBandRecord, bool> filter = (record) => {\r
+                if (!IsStoppedEvent(record)) {\r
+                    return false;\r
+                }\r
+\r
+                var output = ((MIAsyncRecord)record).Output;\r
+                var reason = (MIConst)output["reason"];\r
+\r
+                if (reason.CString != "breakpoint-hit") {\r
+                    return false;\r
+                }\r
+\r
+                var frame = (MITuple)output["frame"];\r
+                var bkptno = (MIConst)output["bkptno"];\r
+                var fileName = (MIConst)frame["file"];\r
+                var line = ((MIConst)frame["line"]).Int;\r
+\r
+                if (fileName.CString == bp.FileName &&\r
+                    bkptno.CString == id &&\r
+                    line == bp.NumLine) {\r
+                    return true;\r
+                }\r
+\r
+                return false;\r
+            };\r
+\r
+            Assert.True(MIDebugger.IsEventReceived(filter),\r
+                        @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public void Continue(string caller_trace)\r
+        {\r
+            Assert.Equal(MIResultClass.Running,\r
+                         MIDebugger.Request("-exec-continue").Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public void WasExit(string caller_trace)\r
+        {\r
+            Func<MIOutOfBandRecord, bool> filter = (record) => {\r
+                if (!IsStoppedEvent(record)) {\r
+                    return false;\r
+                }\r
+\r
+                var output = ((MIAsyncRecord)record).Output;\r
+                var reason = (MIConst)output["reason"];\r
+\r
+                if (reason.CString != "exited") {\r
+                    return false;\r
+                }\r
+\r
+                var exitCode = (MIConst)output["exit-code"];\r
+\r
+                if (exitCode.CString == "0") {\r
+                    return true;\r
+                }\r
+\r
+                return false;\r
+            };\r
+\r
+            Assert.True(MIDebugger.IsEventReceived(filter), @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public void DebuggerExit(string caller_trace)\r
+        {\r
+            Assert.Equal(MIResultClass.Exit,\r
+                         MIDebugger.Request("-gdb-exit").Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public string EnableBreakpoint(string caller_trace, string bpName, int realLineNum = 0)\r
+        {\r
+            Breakpoint bp = ControlInfo.Breakpoints[bpName];\r
+\r
+            Assert.Equal(BreakpointType.Line, bp.Type, @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            var lbp = (LineBreakpoint)bp;\r
+            if (realLineNum == 0)\r
+                realLineNum = lbp.NumLine;\r
+\r
+            var insBpResp = MIDebugger.Request("-break-insert -f " + lbp.FileName + ":" + realLineNum);\r
+            Assert.Equal(MIResultClass.Done, insBpResp.Class, @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+            return ((MIConst)((MITuple)insBpResp["bkpt"])["number"]).CString;\r
+        }\r
+\r
+        public void UpdateBreakpoint(string caller_trace, string bpID, string bpName)\r
+        {\r
+            Breakpoint bp = ControlInfo.Breakpoints[bpName];\r
+\r
+            Assert.Equal(BreakpointType.Line, bp.Type, @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            var lbp = (LineBreakpoint)bp;\r
+            \r
+            Assert.Equal(MIResultClass.Done,\r
+                         MIDebugger.Request("-break-update-line " + bpID + " " + lbp.NumLine).Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public void UpdateBreakpointWithError(string caller_trace, string bpID, string bpName)\r
+        {\r
+            Breakpoint bp = ControlInfo.Breakpoints[bpName];\r
+\r
+            Assert.Equal(BreakpointType.Line, bp.Type, @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+\r
+            var lbp = (LineBreakpoint)bp;\r
+            \r
+            Assert.Equal(MIResultClass.Error,\r
+                         MIDebugger.Request("-break-update-line " + bpID + " " + lbp.NumLine).Class,\r
+                         @"__FILE__:__LINE__"+"\n"+caller_trace);\r
+        }\r
+\r
+        public Context(ControlInfo controlInfo, NetcoreDbgTestCore.DebuggerClient debuggerClient)\r
+        {\r
+            ControlInfo = controlInfo;\r
+            MIDebugger = new MIDebugger(debuggerClient);\r
+        }\r
+\r
+        public ControlInfo ControlInfo { get; private set; }\r
+        public MIDebugger MIDebugger { get; private set; }\r
+        public string id1 = null;\r
+        public string id2 = null;\r
+        public string id3 = null;\r
+        public string id4 = null;\r
+    }\r
+}\r
+\r
+namespace MITestBreakpointUpdate\r
+{\r
+    class Program\r
+    {\r
+        static void Main(string[] args)\r
+        {\r
+            Label.Checkpoint("init", "test_update1", (Object context) => {\r
+                Context Context = (Context)context;\r
+\r
+                Context.id1 = Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK1");\r
+                Context.UpdateBreakpoint(@"__FILE__:__LINE__", Context.id1, "BREAK2");\r
+\r
+                Context.id2 = Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK3");\r
+\r
+                Context.Prepare(@"__FILE__:__LINE__");\r
+                Context.WasEntryPointHit(@"__FILE__:__LINE__");\r
+\r
+                Context.UpdateBreakpoint(@"__FILE__:__LINE__", Context.id2, "BREAK4");\r
+\r
+                Context.id3 = Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK5");\r
+                Assert.Equal(MIResultClass.Done,\r
+                             Context.MIDebugger.Request("-break-update-line " + Context.id3 + " 10000").Class,\r
+                             @"__FILE__:__LINE__");\r
+\r
+                Context.id4 = Context.EnableBreakpoint(@"__FILE__:__LINE__", "BREAK6", 9000);\r
+                Context.UpdateBreakpoint(@"__FILE__:__LINE__", Context.id4, "BREAK6");\r
+\r
+                Context.UpdateBreakpointWithError(@"__FILE__:__LINE__", "1000", "BREAK1"); // Test with not exist breakpoint ID.\r
+\r
+                Context.Continue(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            // Test for breakpoint set and update before process creation and initial breakpoint resolve.\r
+\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK1");\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK2");\r
+\r
+            Label.Checkpoint("test_update1", "test_update2", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasBreakpointWithIdHit(@"__FILE__:__LINE__", "BREAK2", Context.id1);\r
+\r
+                Context.Continue(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            // Test for breakpoint set before process creation and initial breakpoint resolve and update after it was resolved.\r
+\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK3");\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK4");\r
+\r
+            Label.Checkpoint("test_update2", "test_update3", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasBreakpointWithIdHit(@"__FILE__:__LINE__", "BREAK4", Context.id2);\r
+\r
+                Context.Continue(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            // Test for breakpoint set and resolved and updated to line out of source file.\r
+\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK5");\r
+\r
+            // Test for breakpoint set to line out of source file and update with resolve.\r
+\r
+            Console.WriteLine("Hello World!");      Label.Breakpoint("BREAK6");\r
+\r
+            Label.Checkpoint("test_update3", "finish", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasBreakpointWithIdHit(@"__FILE__:__LINE__", "BREAK6", Context.id4);\r
+\r
+                Context.Continue(@"__FILE__:__LINE__");\r
+            });\r
+\r
+            Label.Checkpoint("finish", "", (Object context) => {\r
+                Context Context = (Context)context;\r
+                Context.WasExit(@"__FILE__:__LINE__");\r
+                Context.DebuggerExit(@"__FILE__:__LINE__");\r
+            });\r
+        }\r
+    }\r
+}\r
index f7f1dd7c2db33f4230fc511d7693d2aa5bd6852d..b2991393917659f3a3cd12e9f27278d37c4f332d 100644 (file)
@@ -38,6 +38,7 @@ $ALL_TEST_NAMES = @(
     "MITestGeneric"
     "MITestEvalArraysIndexers"
     "MITestBreakpointWithoutStop"
+    "MITestBreakpointUpdate"
     "VSCodeExampleTest"
     "VSCodeTestBreakpoint"
     "VSCodeTestFuncBreak"
index ab3813a8f5ff24b13ef0952556a4e316e5341df4..68af0d7d45b43e58e8e361ceb4c2028903a18b9e 100755 (executable)
@@ -47,6 +47,7 @@ ALL_TEST_NAMES=(
     "MITestGeneric"
     "MITestEvalArraysIndexers"
     "MITestBreakpointWithoutStop"
+    "MITestBreakpointUpdate"
     "VSCodeExampleTest"
     "VSCodeTestBreakpoint"
     "VSCodeTestFuncBreak"
index 5b95a523ee67d27279d607045d59bfe65acb71cd..d081c804cc39b8193a07950977af2565ae77235d 100644 (file)
@@ -32,6 +32,7 @@ $ALL_TEST_NAMES = @(
     "MITestGeneric"
     "MITestEvalArraysIndexers"
     "MITestBreakpointWithoutStop"
+    "MITestBreakpointUpdate"
     "VSCodeExampleTest"
     "VSCodeTestBreakpoint"
     "VSCodeTestFuncBreak"
index d5f30a490a1890c99197d53f710e18c582f45d3e..2fa0bbf932359cb750f6f124bef685964e4f5394 100755 (executable)
@@ -69,6 +69,7 @@ ALL_TEST_NAMES=(
     "MITestGeneric"
     "MITestEvalArraysIndexers"
     "MITestBreakpointWithoutStop"
+    "MITestBreakpointUpdate"
     "VSCodeExampleTest"
     "VSCodeTestBreakpoint"
     "VSCodeTestFuncBreak"
index 940875cc4fcce15797013298757d920f84397270..b427f4d41e88c68c6bf969ab633dabbc3556ea9c 100644 (file)
@@ -125,6 +125,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MITestBreakpointWithoutStop
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSCodeTestBreakpointWithoutStop", "VSCodeTestBreakpointWithoutStop\VSCodeTestBreakpointWithoutStop.csproj", "{B46CCE8C-49FA-403C-BC5B-1817CAD09130}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MITestBreakpointUpdate", "MITestBreakpointUpdate\MITestBreakpointUpdate.csproj", "{440BEDAD-6094-4FCA-A941-E44300A378C9}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -882,5 +884,17 @@ Global
                {B46CCE8C-49FA-403C-BC5B-1817CAD09130}.Release|x64.Build.0 = Release|Any CPU
                {B46CCE8C-49FA-403C-BC5B-1817CAD09130}.Release|x86.ActiveCfg = Release|Any CPU
                {B46CCE8C-49FA-403C-BC5B-1817CAD09130}.Release|x86.Build.0 = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|x64.ActiveCfg = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|x64.Build.0 = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Debug|x86.Build.0 = Debug|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|Any CPU.Build.0 = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|x64.ActiveCfg = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|x64.Build.0 = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|x86.ActiveCfg = Release|Any CPU
+               {440BEDAD-6094-4FCA-A941-E44300A378C9}.Release|x86.Build.0 = Release|Any CPU
        EndGlobalSection
 EndGlobal