aboutsummaryrefslogtreecommitdiffstats
path: root/Tests/Test_QtVsTools.Package/QtVsTestClient.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Tests/Test_QtVsTools.Package/QtVsTestClient.cs')
-rw-r--r--Tests/Test_QtVsTools.Package/QtVsTestClient.cs144
1 files changed, 144 insertions, 0 deletions
diff --git a/Tests/Test_QtVsTools.Package/QtVsTestClient.cs b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs
new file mode 100644
index 00000000..2372314e
--- /dev/null
+++ b/Tests/Test_QtVsTools.Package/QtVsTestClient.cs
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt VS Tools.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.IO.Pipes;
+using System.Linq;
+using System.Text;
+
+namespace QtVsTools.Test
+{
+ public class QtVsTestClient : IDisposable
+ {
+ public NamedPipeClientStream Stream { get; }
+
+ public QtVsTestClient(int vsProcId)
+ {
+ Stream = new NamedPipeClientStream(".", $"QtVSTest_{vsProcId}", PipeDirection.InOut);
+ }
+
+ public static QtVsTestClient Attach(int? vsProcId = null)
+ {
+ if (vsProcId == null) {
+ var procs = Process.GetProcessesByName("devenv");
+ var vsProc = procs
+ .Where(p => p.Id != Process.GetCurrentProcess().Id
+ && !p.MainWindowTitle.StartsWith("vstools"))
+ .FirstOrDefault();
+ if (vsProc == null)
+ throw new InvalidOperationException("VS process not found");
+ vsProcId = vsProc.Id;
+ }
+ var client = new QtVsTestClient(vsProcId.Value);
+ client.Connect();
+ return client;
+ }
+
+ public void Connect() => Stream.Connect();
+
+ public void Dispose() => Stream?.Dispose();
+
+ public string RunMacro(string macroCode)
+ {
+ if (!Stream.IsConnected)
+ Connect();
+
+ var macroData = Encoding.UTF8.GetBytes(macroCode);
+ int macroDataSize = macroData.Length;
+ byte[] sizeData = BitConverter.GetBytes(macroDataSize);
+
+ Stream.Write(sizeData, 0, sizeof(int));
+ Stream.Write(macroData, 0, macroData.Length);
+ Stream.Flush();
+ if (!Stream.IsConnected)
+ return Error("Disconnected");
+
+ Stream.WaitForPipeDrain();
+ if (!Stream.IsConnected)
+ return Error("Disconnected");
+
+ for (int i = 0; i < sizeof(int); i++) {
+ int c = Stream.ReadByte();
+ if (c == -1)
+ return Error("Disconnected");
+ if (c < Byte.MinValue || c > Byte.MaxValue)
+ return Error("Pipe error");
+ sizeData[i] = (byte)c;
+ }
+
+ int replyDataSize = BitConverter.ToInt32(sizeData, 0);
+ byte[] replyData = new byte[replyDataSize];
+ int bytesRead = 0;
+ while (bytesRead < replyDataSize) {
+ if (!Stream.IsConnected)
+ return Error("Disconnected");
+ bytesRead += Stream.Read(replyData, bytesRead, replyDataSize - bytesRead);
+ }
+
+ return Encoding.UTF8.GetString(replyData);
+ }
+
+ public string RunMacroFile(string macroPath)
+ {
+ return LoadAndRunMacro(macroPath);
+ }
+
+ public string StoreMacro(string macroName, string macroCode)
+ {
+ if (string.IsNullOrEmpty(macroName))
+ return Error("Invalid macro name");
+ return RunMacro($"//# macro {macroName}\r\n{macroCode}");
+ }
+
+ public string StoreMacroFile(string macroName, string macroPath)
+ {
+ if (string.IsNullOrEmpty(macroName))
+ return Error("Invalid macro name");
+ return LoadAndRunMacro(macroPath, $"//# macro {macroName}");
+ }
+
+ string LoadAndRunMacro(string macroPath, string macroHeader = null)
+ {
+ var macroCode = File.ReadAllText(macroPath, Encoding.UTF8);
+ if (string.IsNullOrEmpty(macroCode))
+ return Error("Macro load failed");
+ if (!string.IsNullOrEmpty(macroHeader))
+ return RunMacro($"{macroHeader}\r\n{macroCode}");
+ else
+ return RunMacro(macroCode);
+ }
+
+ public const string MacroOk = "(ok)";
+ public const string MacroWarn = "(warn)";
+ public const string MacroError = "(error)";
+
+ static string Error(string msg) => $"{MacroError}\r\n{msg}";
+ }
+}