-
-
Notifications
You must be signed in to change notification settings - Fork 237
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #916 from dorssel/rules
Add policy rules
- Loading branch information
Showing
19 changed files
with
866 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
// SPDX-FileCopyrightText: 2024 Frans van Dorsselaer | ||
// | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
using System.CommandLine; | ||
using Usbipd.Automation; | ||
|
||
namespace UnitTests; | ||
|
||
[TestClass] | ||
sealed class Parse_policy_Tests | ||
: ParseTestBase | ||
{ | ||
static readonly BusId TestBusId = BusId.Parse("3-42"); | ||
static readonly Guid TestGuid = Guid.Parse("{E863A2AF-AE47-440B-A32B-FAB1C03017AB}"); | ||
static readonly VidPid TestHardwareId = VidPid.Parse("0123:cdef"); | ||
|
||
[TestMethod] | ||
public void Help() | ||
{ | ||
Test(ExitCode.Success, "policy", "--help"); | ||
} | ||
|
||
[TestMethod] | ||
public void CommandMissing() | ||
{ | ||
Test(ExitCode.ParseError, "policy"); | ||
} | ||
|
||
[TestMethod] | ||
public void CommandInvalid() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "invalid-command"); | ||
} | ||
|
||
[TestMethod] | ||
public void OptionInvalid() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "--invalid-option"); | ||
} | ||
|
||
[TestMethod] | ||
public void list_Success() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyList(It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "list"); | ||
} | ||
|
||
[TestMethod] | ||
public void list_Help() | ||
{ | ||
Test(ExitCode.Success, "policy", "list", "--help"); | ||
} | ||
|
||
[TestMethod] | ||
public void list_OptionInvalid() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "list", "--invalid-option"); | ||
} | ||
|
||
[TestMethod] | ||
public void list_StrayArgument() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "list", "stray-argument"); | ||
} | ||
|
||
[TestMethod] | ||
public void add_BusIdSuccess() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyAdd(It.IsAny<PolicyRule>(), | ||
It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "add", "--effect", "Allow", "--operation", "AutoBind", "--busid", TestBusId.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void add_HardwareIdSuccess() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyAdd(It.IsAny<PolicyRule>(), | ||
It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "add", "--effect", "Allow", "--operation", "AutoBind", "--hardware-id", TestHardwareId.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void add_BothSuccess() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyAdd(It.IsAny<PolicyRule>(), | ||
It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "add", "--effect", "Allow", "--operation", "AutoBind", | ||
"--busid", TestBusId.ToString(), "--hardware-id", TestHardwareId.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void add_MissingCondition() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "add", "--effect", "Allow", "--operation", "AutoBind", TestHardwareId.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void remove_GuidSuccess() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyRemove(It.IsAny<Guid>(), | ||
It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "remove", "--guid", TestGuid.ToString()); | ||
} | ||
|
||
[TestMethod] | ||
public void remove_AllSuccess() | ||
{ | ||
var mock = CreateMock(); | ||
mock.Setup(m => m.PolicyRemoveAll(It.IsNotNull<IConsole>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(ExitCode.Success)); | ||
|
||
Test(ExitCode.Success, mock, "policy", "remove", "--all"); | ||
} | ||
|
||
[TestMethod] | ||
public void remove_MissingOption() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "remove"); | ||
} | ||
|
||
[TestMethod] | ||
public void remove_TooManyOptions() | ||
{ | ||
Test(ExitCode.ParseError, "policy", "remove", "--all", "--guid", TestGuid.ToString()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
// SPDX-FileCopyrightText: 2024 Frans van Dorsselaer | ||
// | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
using Microsoft.Win32; | ||
using Usbipd.Automation; | ||
|
||
namespace UnitTests; | ||
|
||
[TestClass] | ||
sealed class Policy_Tests | ||
{ | ||
static readonly BusId TestBusId = BusId.Parse("3-42"); | ||
static readonly VidPid TestHardwareId = VidPid.Parse("0123:cdef"); | ||
static readonly BusId OtherBusId = BusId.Parse("1-1"); | ||
static readonly VidPid OtherHardwareId = VidPid.Parse("4567:89ab"); | ||
|
||
static TempRegistry BaseTempRegistryKey = null!; | ||
|
||
[ClassInitialize] | ||
public static void ClassInitialize(TestContext testContext) | ||
{ | ||
_ = testContext; | ||
|
||
BaseTempRegistryKey = new TempRegistry(Registry.CurrentUser); | ||
} | ||
|
||
[ClassCleanup] | ||
public static void ClassCleanup() | ||
{ | ||
BaseTempRegistryKey.Dispose(); | ||
} | ||
|
||
static TempRegistry CreateTempRegistry() => new(BaseTempRegistryKey.Key); | ||
|
||
[TestMethod] | ||
public void Constructor_Success() | ||
{ | ||
_ = new PolicyRuleAutoBind(PolicyRuleEffect.Allow, TestBusId, TestHardwareId); | ||
} | ||
|
||
sealed class AutoBindData | ||
{ | ||
static readonly PolicyRuleAutoBind[] _Valid = [ | ||
new(PolicyRuleEffect.Allow, TestBusId, null), | ||
new(PolicyRuleEffect.Allow, null, TestHardwareId), | ||
new(PolicyRuleEffect.Allow, TestBusId, TestHardwareId), | ||
]; | ||
|
||
static readonly PolicyRuleAutoBind[] _Invalid = [ | ||
new(PolicyRuleEffect.Allow, null, null), | ||
new(PolicyRuleEffect.Allow, BusId.IncompatibleHub, null), | ||
new(PolicyRuleEffect.Allow, BusId.IncompatibleHub, TestHardwareId), | ||
]; | ||
|
||
public static IEnumerable<PolicyRuleAutoBind[]> Valid | ||
=> from value in _Valid select new PolicyRuleAutoBind[] { value }; | ||
|
||
public static IEnumerable<PolicyRuleAutoBind[]> Invalid | ||
=> from value in _Invalid select new PolicyRuleAutoBind[] { value }; | ||
} | ||
|
||
[TestMethod] | ||
[DynamicData(nameof(AutoBindData.Valid), typeof(AutoBindData))] | ||
public void Persist_AutoBind(PolicyRuleAutoBind rule) | ||
{ | ||
using var tempRegistry = CreateTempRegistry(); | ||
rule.Save(tempRegistry.Key); | ||
|
||
var verify = PolicyRuleAutoBind.Load(rule.Effect, tempRegistry.Key); | ||
|
||
Assert.AreEqual(rule.BusId, verify.BusId); | ||
Assert.AreEqual(rule.HardwareId, verify.HardwareId); | ||
} | ||
|
||
[TestMethod] | ||
[DynamicData(nameof(AutoBindData.Valid), typeof(AutoBindData))] | ||
public void Valid_AutoBind(PolicyRuleAutoBind rule) | ||
{ | ||
Assert.IsTrue(rule.IsValid()); | ||
} | ||
|
||
[TestMethod] | ||
[DynamicData(nameof(AutoBindData.Invalid), typeof(AutoBindData))] | ||
public void Invalid_AutoBind(PolicyRuleAutoBind rule) | ||
{ | ||
Assert.IsFalse(rule.IsValid()); | ||
} | ||
|
||
static UsbDevice CreateTestUsbDevice(BusId busId, VidPid hardwareId) | ||
{ | ||
return new UsbDevice($"VID_{hardwareId.Vid:X04}&PID_{hardwareId.Pid:X04}", "Description", false, busId, null, null, null); | ||
} | ||
|
||
[TestMethod] | ||
[DynamicData(nameof(AutoBindData.Invalid), typeof(AutoBindData))] | ||
public void Match_Invalid_AutoBind(PolicyRuleAutoBind rule) | ||
{ | ||
Assert.ThrowsException<InvalidOperationException>(() => | ||
{ | ||
rule.Matches(CreateTestUsbDevice(TestBusId, TestHardwareId)); | ||
}); | ||
} | ||
|
||
[TestMethod] | ||
[DynamicData(nameof(AutoBindData.Valid), typeof(AutoBindData))] | ||
public void Match_Valid_AutoBind(PolicyRuleAutoBind rule) | ||
{ | ||
Assert.IsTrue(rule.Matches(CreateTestUsbDevice(TestBusId, TestHardwareId))); | ||
Assert.IsFalse(rule.Matches(CreateTestUsbDevice(OtherBusId, OtherHardwareId))); | ||
if (rule.BusId is null) | ||
{ | ||
Assert.IsTrue(rule.Matches(CreateTestUsbDevice(OtherBusId, TestHardwareId))); | ||
} | ||
else | ||
{ | ||
Assert.IsFalse(rule.Matches(CreateTestUsbDevice(OtherBusId, TestHardwareId))); | ||
} | ||
if (rule.HardwareId is null) | ||
{ | ||
Assert.IsTrue(rule.Matches(CreateTestUsbDevice(TestBusId, OtherHardwareId))); | ||
} | ||
else | ||
{ | ||
Assert.IsFalse(rule.Matches(CreateTestUsbDevice(TestBusId, OtherHardwareId))); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// SPDX-FileCopyrightText: 2024 Frans van Dorsselaer | ||
// | ||
// SPDX-License-Identifier: GPL-3.0-only | ||
|
||
using Microsoft.Win32; | ||
|
||
namespace UnitTests; | ||
|
||
sealed class TempRegistry : IDisposable | ||
{ | ||
public string Name { get; } = Guid.NewGuid().ToString("B"); | ||
public RegistryKey Key { get; } | ||
public RegistryKey Parent { get; } | ||
|
||
public TempRegistry(RegistryKey parent) | ||
{ | ||
Parent = parent; | ||
Key = Parent.CreateSubKey(Name, true, RegistryOptions.Volatile); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
Key.Close(); | ||
Parent.DeleteSubKeyTree(Name, false); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.