anycmd 4 年之前
父節點
當前提交
af77fe2ac8

+ 0 - 1
src/AppViews0/MinerStudio/Views/Ucs/ActionCounts.xaml

@@ -32,7 +32,6 @@
             <controls:KbTextBox 
 				x:Name="TbKeyword" Width="154" Height="24"
 				Text="{Binding Keyword, UpdateSourceTrigger=LostFocus}" 
-				LostFocus="TbKeyword_LostFocus"
 				VerticalContentAlignment="Center"
 				Hint="输入显卡名关键字然后回车"
                 ToolTip="输入显卡名关键字然后回车"

+ 1 - 5
src/AppViews0/MinerStudio/Views/Ucs/ActionCounts.xaml.cs

@@ -31,13 +31,9 @@ namespace NTMiner.MinerStudio.Views.Ucs {
             InitializeComponent();
         }
 
-        private void TbKeyword_LostFocus(object sender, RoutedEventArgs e) {
-            ((ActionCountsViewModel)this.DataContext).Search.Execute(null);
-        }
-
         private void TbKeyword_KeyUp(object sender, KeyEventArgs e) {
             if (e.Key == Key.Enter) {
-                ((ActionCountsViewModel)this.DataContext).Keyword = this.TbKeyword.Text;
+                this.Vm.Keyword = this.TbKeyword.Text;
             }
         }
     }

+ 0 - 1
src/AppViews0/MinerStudio/Views/Ucs/GpuNameCounts.xaml

@@ -32,7 +32,6 @@
             <controls:KbTextBox 
 				x:Name="TbKeyword" Width="154" Height="24"
 				Text="{Binding Keyword, UpdateSourceTrigger=LostFocus}" 
-				LostFocus="TbKeyword_LostFocus"
 				VerticalContentAlignment="Center"
 				Hint="输入显卡名关键字然后回车"
                 ToolTip="输入显卡名关键字然后回车"

+ 1 - 5
src/AppViews0/MinerStudio/Views/Ucs/GpuNameCounts.xaml.cs

@@ -31,13 +31,9 @@ namespace NTMiner.MinerStudio.Views.Ucs {
             InitializeComponent();
         }
 
-        private void TbKeyword_LostFocus(object sender, RoutedEventArgs e) {
-            ((GpuNameCountsViewModel)this.DataContext).Search.Execute(null);
-        }
-
         private void TbKeyword_KeyUp(object sender, KeyEventArgs e) {
             if (e.Key == Key.Enter) {
-                ((GpuNameCountsViewModel)this.DataContext).Keyword = this.TbKeyword.Text;
+                this.Vm.Keyword = this.TbKeyword.Text;
             }
         }
     }

+ 0 - 6
src/AppViews0/MinerStudio/Views/Ucs/MinerClient.xaml.cs

@@ -6,12 +6,6 @@ using System.Windows.Input;
 
 namespace NTMiner.MinerStudio.Views.Ucs {
     public partial class MinerClient : UserControl {
-        public MinerClientViewModel Vm {
-            get {
-                return (MinerClientViewModel)this.DataContext;
-            }
-        }
-
         public MinerClient() {
             InitializeComponent();
             this.TbDateTime.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm");

+ 0 - 1
src/AppViews0/Views/KernelsWindow.xaml

@@ -97,7 +97,6 @@
 				<controls:KbTextBox 
 					x:Name="TbKeyword" Width="154" Height="24"
 					Text="{Binding Keyword, UpdateSourceTrigger=LostFocus}" 
-					LostFocus="TbKeyword_LostFocus"
 					VerticalContentAlignment="Center"
 					Hint="输入内核关键字然后回车"
                     ToolTip="输入内核关键字然后回车"

+ 0 - 4
src/AppViews0/Views/KernelsWindow.xaml.cs

@@ -71,10 +71,6 @@ namespace NTMiner.Views {
             }
         }
 
-        private void TbKeyword_LostFocus(object sender, RoutedEventArgs e) {
-            Vm.Search.Execute(null);
-        }
-
         private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) {
             WpfUtil.DataGrid_EditRow<KernelViewModel>(sender, e);
         }

+ 1 - 1
src/CalcConfigUpdater/Program.cs

@@ -84,7 +84,7 @@ namespace NTMiner {
                         if (incomeItems != null && incomeItems.Count != 0) {
                             RpcRoot.Login(new RpcUser(Config.RpcLoginName, HashUtil.Sha1(Config.RpcPassword)));
                             RpcRoot.SetIsOuterNet(false);
-                            RpcRoot.OfficialServer.CalcConfigService.GetCalcConfigsAsync(data => {
+                            RpcRoot.OfficialServer.CalcConfigBinaryService.GetCalcConfigsAsync(data => {
                                 NTMinerConsole.UserInfo($"NTMiner有{data.Count.ToString()}个币种");
                                 HashSet<string> coinCodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
                                 foreach (CalcConfigData calcConfigData in data) {

+ 1 - 1
src/NTMinerClient/Core/Impl/CalcConfigSet.cs

@@ -25,7 +25,7 @@ namespace NTMiner.Core.Impl {
             // 如果未显示主界面则收益计算器也不用更新了
             if ((_initedOn == DateTime.MinValue || NTMinerContext.IsUiVisible || ClientAppType.IsMinerStudio) && (forceRefresh || _initedOn.AddMinutes(10) < now)) {
                 _initedOn = now;
-                RpcRoot.OfficialServer.CalcConfigService.GetCalcConfigsAsync(data => {
+                RpcRoot.OfficialServer.CalcConfigBinaryService.GetCalcConfigsAsync(data => {
                     if (data != null && data.Count != 0) {
                         Init(data);
                         VirtualRoot.RaiseEvent(new CalcConfigSetInitedEvent());

+ 13 - 7
src/NTMinerHub/Hub/MessagePathHub.cs

@@ -138,12 +138,6 @@
                 return _messagePaths.ToArray();
             }
 
-            private void Sort() {
-                _messagePaths.Sort((left, right) => {
-                    return right.Priority - left.Priority;
-                });
-            }
-
             public void AddMessagePath(MessagePath<TMessage> messagePath) {
                 lock (_locker) {
                     if (typeof(ICmd).IsAssignableFrom(typeof(TMessage))) {
@@ -163,16 +157,28 @@
                         }
                     }
                     _messagePaths.Add(messagePath);
+                    // Add时排序,Remove时不需要排序
                     Sort();
                 }
             }
 
+            private void Sort() {
+                if (_messagePaths.Count <= 1) {
+                    return;
+                }
+                if (_messagePaths.All(a => a.Priority == _messagePaths[0].Priority)) {
+                    return;
+                }
+                _messagePaths.Sort((left, right) => {
+                    return right.Priority - left.Priority;
+                });
+            }
+
             public void RemoveMessagePath(IMessagePathId messagePathId) {
                 lock (_locker) {
                     var item = _messagePaths.FirstOrDefault(a => ReferenceEquals(a, messagePathId));
                     if (item != null) {
                         _messagePaths.Remove(item);
-                        Sort();
                         NTMinerConsole.DevDebug(() => "拆除路径" + messagePathId.PathName + messagePathId.Description);
                     }
                 }

+ 1 - 1
src/NTMinerRpcClient/Core/Impl/ServerMessageSet.cs

@@ -23,7 +23,7 @@ namespace NTMiner.Core.Impl {
                 if (message.KnowServerMessageTimestamp <= Timestamp.GetTimestamp(localTimestamp)) {
                     return;
                 }
-                RpcRoot.OfficialServer.ServerMessageService.GetServerMessagesAsync(localTimestamp, (response, e) => {
+                RpcRoot.OfficialServer.ServerMessageBinaryService.GetServerMessagesAsync(localTimestamp, (response, e) => {
                     if (response.IsSuccess()) {
                         if (response.Data.Count > 0) {
                             VirtualRoot.Execute(new ReceiveServerMessageCommand(response.Data));

+ 3 - 0
src/NTMinerRpcClient/NTMinerRpcClient.csproj

@@ -87,6 +87,8 @@
     <Compile Include="Services\Client\NTMinerClientService.cs" />
     <Compile Include="Services\Client\NTMinerDaemonService.cs" />
     <Compile Include="Core\Impl\KernelOutputKeywordSet.cs" />
+    <Compile Include="Services\Official\CalcConfigBinaryService.cs" />
+    <Compile Include="Services\Official\ClientDataBinaryService.cs" />
     <Compile Include="Services\Official\FileUrlService.cs" />
     <Compile Include="Services\Official\NTMinerFileService.cs" />
     <Compile Include="Services\Official\NTMinerWalletService.cs" />
@@ -96,6 +98,7 @@
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Services\Official\KernelOutputKeywordService.cs" />
     <Compile Include="Services\Official\ReportBinaryService.cs" />
+    <Compile Include="Services\Official\ServerMessageBinaryService.cs" />
     <Compile Include="Services\Official\UserAppSettingService.cs" />
     <Compile Include="Services\Official\UserService.cs" />
     <Compile Include="Services\Official\WsServerNodeService.cs" />

+ 33 - 0
src/NTMinerRpcClient/Services/Official/CalcConfigBinaryService.cs

@@ -0,0 +1,33 @@
+using NTMiner.Controllers;
+using NTMiner.Core.MinerServer;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+
+namespace NTMiner.Services.Official {
+    public class CalcConfigBinaryService {
+        private readonly string _controllerName = ControllerUtil.GetControllerName<ICalcConfigBinaryController<HttpResponseMessage>>();
+
+        internal CalcConfigBinaryService() {
+        }
+
+        #region GetCalcConfigsAsync
+        public void GetCalcConfigsAsync(Action<List<CalcConfigData>> callback) {
+            RpcRoot.JsonRequestBinaryResponseRpcHelper.PostAsync(
+                RpcRoot.OfficialServerHost,
+                RpcRoot.OfficialServerPort,
+                _controllerName,
+                nameof(ICalcConfigBinaryController<HttpResponseMessage>.CalcConfigs),
+                null,
+                callback: (DataResponse<List<CalcConfigData>> response, Exception e) => {
+                    if (response.IsSuccess()) {
+                        callback?.Invoke(response.Data);
+                    }
+                    else {
+                        callback?.Invoke(new List<CalcConfigData>());
+                    }
+                }, timeountMilliseconds: 10 * 1000);
+        }
+        #endregion
+    }
+}

+ 25 - 0
src/NTMinerRpcClient/Services/Official/ClientDataBinaryService.cs

@@ -0,0 +1,25 @@
+using NTMiner.Controllers;
+using NTMiner.Core.MinerServer;
+using System;
+using System.Net.Http;
+
+namespace NTMiner.Services.Official {
+    public partial class ClientDataBinaryService {
+        private readonly string _controllerName = ControllerUtil.GetControllerName<IClientDataBinaryController<HttpResponseMessage>>();
+
+        internal ClientDataBinaryService() {
+        }
+
+        #region QueryClientsAsync
+        public void QueryClientsAsync(QueryClientsRequest query, Action<QueryClientsResponse, Exception> callback) {
+            RpcRoot.JsonRequestBinaryResponseRpcHelper.SignPostAsync(
+                RpcRoot.OfficialServerHost, 
+                RpcRoot.OfficialServerPort, 
+                _controllerName, 
+                nameof(IClientDataBinaryController<HttpResponseMessage>.QueryClients), 
+                data: query, 
+                callback);
+        }
+        #endregion
+    }
+}

+ 0 - 1
src/NTMinerRpcClient/Services/Official/ClientDataService.cs

@@ -11,7 +11,6 @@ namespace NTMiner.Services.Official {
         }
 
         #region QueryClientsAsync
-        // 去调ClientDataBinaryService的方法了所以这个没人调了
         public void QueryClientsAsync(QueryClientsRequest query, Action<QueryClientsResponse, Exception> callback) {
             RpcRoot.JsonRpc.SignPostAsync(
                 RpcRoot.OfficialServerHost, 

+ 29 - 0
src/NTMinerRpcClient/Services/Official/ServerMessageBinaryService.cs

@@ -0,0 +1,29 @@
+using NTMiner.Controllers;
+using NTMiner.Core.MinerServer;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+
+namespace NTMiner.Services.Official {
+    public class ServerMessageBinaryService {
+        private readonly string _controllerName = ControllerUtil.GetControllerName<IServerMessageBinaryController<HttpResponseMessage>>();
+
+        internal ServerMessageBinaryService() {
+        }
+
+        #region GetServerMessagesAsync
+        public void GetServerMessagesAsync(DateTime timestamp, Action<DataResponse<List<ServerMessageData>>, Exception> callback) {
+            ServerMessagesRequest request = new ServerMessagesRequest {
+                Timestamp = Timestamp.GetTimestamp(timestamp)
+            };
+            RpcRoot.JsonRequestBinaryResponseRpcHelper.PostAsync(
+                RpcRoot.OfficialServerHost, 
+                RpcRoot.OfficialServerPort, 
+                _controllerName, 
+                nameof(IServerMessageBinaryController<HttpResponseMessage>.ServerMessages), 
+                request, 
+                callback);
+        }
+        #endregion
+    }
+}

+ 3 - 0
src/NTMinerRpcClient/Services/OfficialServices.cs

@@ -9,13 +9,16 @@
         public readonly NTMinerWalletService NTMinerWalletService = new NTMinerWalletService();
         public readonly KernelOutputKeywordService KernelOutputKeywordService = new KernelOutputKeywordService();
         public readonly CalcConfigService CalcConfigService = new CalcConfigService();
+        public readonly CalcConfigBinaryService CalcConfigBinaryService = new CalcConfigBinaryService();
         public readonly ServerMessageService ServerMessageService = new ServerMessageService();
+        public readonly ServerMessageBinaryService ServerMessageBinaryService = new ServerMessageBinaryService();
         public readonly ReportService ReportService = new ReportService();
         public readonly ReportBinaryService ReportBinaryService = new ReportBinaryService();
         public readonly UserService UserService = new UserService();
         public readonly AppSettingService AppSettingService = new AppSettingService();
         public readonly UserAppSettingService UserAppSettingService = new UserAppSettingService();
         public readonly ClientDataService ClientDataService = new ClientDataService();
+        public readonly ClientDataBinaryService ClientDataBinaryService = new ClientDataBinaryService();
         public readonly UserMinerGroupService UserMinerGroupService = new UserMinerGroupService();
         public readonly UserMineWorkService UserMineWorkService = new UserMineWorkService();
         public readonly AdminService AdminService = new AdminService();

+ 46 - 36
src/UnitTests/PathPriorityTests.cs

@@ -8,49 +8,59 @@ namespace NTMiner {
         [TestMethod]
         public void Test() {
             List<PathPriority> list = new List<PathPriority>();
-            VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
-                list.Add(PathPriority.Normal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
-                list.Add(PathPriority.BelowNormal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
-                list.Add(PathPriority.AboveNormal);
-            });
+            List<IMessagePathId> paths = new List<IMessagePathId> {
+                VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
+                    list.Add(PathPriority.Normal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
+                    list.Add(PathPriority.BelowNormal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
+                    list.Add(PathPriority.AboveNormal);
+                })
+            };
             VirtualRoot.RaiseEvent(new Event1());
-            Assert.AreEqual(list[0], PathPriority.AboveNormal);
-            Assert.AreEqual(list[1], PathPriority.Normal);
-            Assert.AreEqual(list[2], PathPriority.BelowNormal);
+            Assert.AreEqual(PathPriority.AboveNormal, list[0]);
+            Assert.AreEqual(PathPriority.Normal, list[1]);
+            Assert.AreEqual(PathPriority.BelowNormal, list[2]);
+            foreach (var path in paths) {
+                VirtualRoot.RemoveMessagePath(path);
+            }
         }
 
         [TestMethod]
         public void Test2() {
             List<PathPriority> list = new List<PathPriority>();
-            VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
-                list.Add(PathPriority.Normal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
-                list.Add(PathPriority.Normal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
-                list.Add(PathPriority.BelowNormal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
-                list.Add(PathPriority.BelowNormal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
-                list.Add(PathPriority.AboveNormal);
-            });
-            VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
-                list.Add(PathPriority.AboveNormal);
-            });
+            List<IMessagePathId> paths = new List<IMessagePathId> {
+                VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
+                    list.Add(PathPriority.Normal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("Normal", LogEnum.DevConsole, this.GetType(), PathPriority.Normal, message => {
+                    list.Add(PathPriority.Normal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
+                    list.Add(PathPriority.BelowNormal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("BelowNormal", LogEnum.DevConsole, this.GetType(), PathPriority.BelowNormal, message => {
+                    list.Add(PathPriority.BelowNormal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
+                    list.Add(PathPriority.AboveNormal);
+                }),
+                VirtualRoot.BuildEventPath<Event1>("AboveNormal", LogEnum.DevConsole, this.GetType(), PathPriority.AboveNormal, message => {
+                    list.Add(PathPriority.AboveNormal);
+                })
+            };
             VirtualRoot.RaiseEvent(new Event1());
-            Assert.AreEqual(list[0], PathPriority.AboveNormal);
-            Assert.AreEqual(list[1], PathPriority.AboveNormal);
-            Assert.AreEqual(list[2], PathPriority.Normal);
-            Assert.AreEqual(list[3], PathPriority.Normal);
-            Assert.AreEqual(list[4], PathPriority.BelowNormal);
-            Assert.AreEqual(list[5], PathPriority.BelowNormal);
+            Assert.AreEqual(PathPriority.AboveNormal, list[0]);
+            Assert.AreEqual(PathPriority.AboveNormal, list[1]);
+            Assert.AreEqual(PathPriority.Normal, list[2]);
+            Assert.AreEqual(PathPriority.Normal, list[3]);
+            Assert.AreEqual(PathPriority.BelowNormal, list[4]);
+            Assert.AreEqual(PathPriority.BelowNormal, list[5]);
+            foreach (var path in paths) {
+                VirtualRoot.RemoveMessagePath(path);
+            }
         }
 
         public class Event1 : EventBase {

+ 42 - 31
src/UnitTests/RemoteDesktopTests.cs

@@ -4,55 +4,66 @@ using NTMiner.RemoteDesktop;
 namespace NTMiner {
     [TestClass]
     public class RemoteDesktopTests {
+        private static readonly object _locker = new object();
         [TestMethod]
         public void TestMethod1() {
-            NTMiner.NTMinerRegistry.SetIsRdpEnabled(true);
-            Assert.IsTrue(NTMiner.NTMinerRegistry.GetIsRdpEnabled());
-            NTMiner.NTMinerRegistry.SetIsRdpEnabled(false);
-            Assert.IsFalse(NTMiner.NTMinerRegistry.GetIsRdpEnabled());
+            lock (_locker) {
+                NTMinerRegistry.SetIsRdpEnabled(true);
+                Assert.IsTrue(NTMinerRegistry.GetIsRdpEnabled());
+                NTMinerRegistry.SetIsRdpEnabled(false);
+                Assert.IsFalse(NTMinerRegistry.GetIsRdpEnabled());
+            }
         }
 
         [TestMethod]
         public void EnableFirewallTest() {
-            Firewall.EnableFirewall();
-            FirewallStatus state = Firewall.Status(FirewallDomain.Domain);
-            Assert.AreEqual(FirewallStatus.Enabled, state);
-            state = Firewall.Status(FirewallDomain.Private);
-            Assert.AreEqual(FirewallStatus.Enabled, state);
-            state = Firewall.Status(FirewallDomain.Public);
-            Assert.AreEqual(FirewallStatus.Enabled, state);
+            lock (_locker) {
+                Firewall.EnableFirewall();
+                FirewallStatus state = Firewall.Status(FirewallDomain.Domain);
+                Assert.AreEqual(FirewallStatus.Enabled, state);
+                state = Firewall.Status(FirewallDomain.Private);
+                Assert.AreEqual(FirewallStatus.Enabled, state);
+                state = Firewall.Status(FirewallDomain.Public);
+                Assert.AreEqual(FirewallStatus.Enabled, state);
+            }
         }
 
         [TestMethod]
         public void DisableFirewallTest() {
-            Firewall.DisableFirewall();
-            FirewallStatus state = Firewall.Status(FirewallDomain.Domain);
-            Assert.AreEqual(FirewallStatus.Disabled, state);
-            state = Firewall.Status(FirewallDomain.Private);
-            Assert.AreEqual(FirewallStatus.Disabled, state);
-            state = Firewall.Status(FirewallDomain.Public);
-            Assert.AreEqual(FirewallStatus.Disabled, state);
+            lock (_locker) {
+                Firewall.DisableFirewall();
+                FirewallStatus state = Firewall.Status(FirewallDomain.Domain);
+                Assert.AreEqual(FirewallStatus.Disabled, state);
+                state = Firewall.Status(FirewallDomain.Private);
+                Assert.AreEqual(FirewallStatus.Disabled, state);
+                state = Firewall.Status(FirewallDomain.Public);
+                Assert.AreEqual(FirewallStatus.Disabled, state);
+            }
         }
 
         [TestMethod]
         public void RdpRuleTest() {
-            Firewall.EnableFirewall();
-            Firewall.AddRdpRule();
-            Assert.IsTrue(Firewall.IsRdpRuleExists());
-            Firewall.DisableFirewall();
-            Assert.IsTrue(Firewall.IsRdpRuleExists());
-            Firewall.RemoveRdpRule();
+            lock (_locker) {
+                Firewall.EnableFirewall();
+                Firewall.AddRdpRule();
+                Assert.IsTrue(Firewall.IsRdpRuleExists());
+                Firewall.DisableFirewall();
+                Assert.IsTrue(Firewall.IsRdpRuleExists());
+                Firewall.RemoveRdpRule();
+            }
         }
 
         [TestMethod]
         public void MinerClientRuleTest() {
-            Firewall.EnableFirewall();
-            Firewall.AddMinerClientRule();
-            Assert.IsTrue(Firewall.IsMinerClientRuleExists());
-            Firewall.DisableFirewall();
-            Assert.IsTrue(Firewall.IsMinerClientRuleExists());
-            Firewall.RemoveMinerClientRule();
-            Assert.IsFalse(Firewall.IsMinerClientRuleExists());
+            lock (_locker) {
+                Firewall.EnableFirewall();
+                Firewall.AddMinerClientRule();
+                Assert.IsTrue(Firewall.IsMinerClientRuleExists());
+                Firewall.DisableFirewall();
+                Assert.IsTrue(Firewall.IsMinerClientRuleExists());
+                Firewall.RemoveMinerClientRule();
+                Assert.IsFalse(Firewall.IsMinerClientRuleExists());
+            }
         }
     }
 }