mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2024-11-05 10:36:30 +01:00
271 lines
16 KiB
C#
271 lines
16 KiB
C#
|
using NSubstitute;
|
|||
|
using NUnit.Framework;
|
|||
|
using Plugin.BLE.Abstractions.Contracts;
|
|||
|
using System;
|
|||
|
using System.Threading.Tasks;
|
|||
|
using TINK.Services.BluetoothLock.Tdo;
|
|||
|
using TINK.Services.BluetoothLock.Exception;
|
|||
|
using TINK.Services.BluetoothLock.BLE;
|
|||
|
using DeviceState = Plugin.BLE.Abstractions.DeviceState;
|
|||
|
using System.Threading;
|
|||
|
|
|||
|
namespace TestLockItBLE.Services.BluetoothLock.BLE
|
|||
|
{
|
|||
|
public class TestLockItPolling
|
|||
|
{
|
|||
|
[Test]
|
|||
|
public void TestOpen()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'o', (byte)'a', (byte)'w', (byte)'m', (byte)'X', (byte)'8', (byte)'T', (byte)'X', (byte)'Q', (byte)'Z', (byte)'d', (byte)'l', (byte)'k', (byte)'3', (byte)'e', (byte)'V', },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to open functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 1 /* state read after sending open commant: closed */ }), Task.FromResult(new byte[] { 0 /* state read after sending open commant: open */}));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(lockIt.OpenAsync().Result, Is.EqualTo(LockitLockingState.Open));
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestOpen_ThrowsCouldntOpenInconsistentStateExecption()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'n', (byte)'l', (byte)'Q', (byte)'I', (byte)'S', (byte)'z', (byte)'p', (byte)'H', (byte)'m', (byte)'n', (byte)'V', (byte)'n', (byte)'7', (byte)'f', (byte)'i', (byte)'3' },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to open functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 1 /* closed */})); // Closed is returned twice => Inconsistent state ....
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(async () => { var result = await lockIt.OpenAsync(); }, Throws.InstanceOf<CouldntOpenInconsistentStateExecption>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestOpen_ThrowsCouldntOpenBoldBlockedException()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'h', (byte)'r', (byte)'F', (byte)'h', (byte)'G', (byte)'T', (byte)'z', (byte)'P', (byte)'F', (byte)'Z', (byte)'n', (byte)'z', (byte)'Y', (byte)'B', (byte)'s', (byte)'9' },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to open functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 1 /* closed */}), Task.FromResult(new byte[] { 4 /* bold blocked */ }));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(async () => { var result = await lockIt.OpenAsync(); }, Throws.InstanceOf<CouldntOpenBoldBlockedException>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestClose()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'H', (byte)'7', (byte)'y', (byte)'B', (byte)'f', (byte)'s', (byte)'v', (byte)'L', (byte)'G', (byte)'L', (byte)'7', (byte)'b', (byte)'7', (byte)'X', (byte)'z', (byte)'t' },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to close functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 0 /* open */ }), Task.FromResult(new byte[] { 1 /* closed */}));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(lockIt.CloseAsync().Result, Is.EqualTo(LockitLockingState.Closed));
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestClose_ThrowsCouldntOpenInconsistentStateExecption()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'7', (byte)'q', (byte)'3', (byte)'9', (byte)'i', (byte)'6', (byte)'c', (byte)'g', (byte)'9', (byte)'L', (byte)'V', (byte)'7', (byte)'T', (byte)'G', (byte)'l', (byte)'f' },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to close functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 0 /* opened */}));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(async () => { var result = await lockIt.CloseAsync(); }, Throws.InstanceOf<CouldntCloseInconsistentStateExecption>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestClose_ThrowsCouldntOpenBoldBlockedException()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var controlService = Substitute.For<IService>();
|
|||
|
var controlCharacteristic = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authTdo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
Id = 12,
|
|||
|
K_seed = new byte[] { (byte)'u', (byte)'f', (byte)'u', (byte)'v', (byte)'j', (byte)'E', (byte)'b', (byte)'x', (byte)'p', (byte)'z', (byte)'a', (byte)'h', (byte)'V', (byte)'5', (byte)'9', (byte)'i' },
|
|||
|
K_u = new byte[16]
|
|||
|
}.Build();
|
|||
|
|
|||
|
// Calls related to Authenticate functionality.
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("0000f00d-1212-efde-1523-785fef13d123"));
|
|||
|
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(controlService));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(auth));
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8]));
|
|||
|
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
|
|||
|
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
|
|||
|
auth.WriteAsync(Arg.Any<byte[]>()).Returns(true);
|
|||
|
|
|||
|
device.Name.Returns("ISHAREIT+123");
|
|||
|
|
|||
|
// Calls related to Close functionality.
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(controlCharacteristic));
|
|||
|
controlCharacteristic.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[] { 0 /* open */}), Task.FromResult(new byte[] { 5 /* bold blocked */ }));
|
|||
|
controlService.GetCharacteristicAsync(new Guid("0000beee-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(activateLock));
|
|||
|
activateLock.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true));
|
|||
|
|
|||
|
|
|||
|
// Use factory to create LockIt-object.
|
|||
|
var lockIt = LockItPolling.Authenticate(device, authTdo, adapter, cipher).Result;
|
|||
|
Assert.That(async () => { var result = await lockIt.CloseAsync(); }, Throws.InstanceOf<CouldntCloseBoldBlockedException>());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|