mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2024-12-25 08:36:27 +01:00
200 lines
10 KiB
C#
200 lines
10 KiB
C#
|
using NSubstitute;
|
|||
|
using NUnit.Framework;
|
|||
|
using Plugin.BLE.Abstractions;
|
|||
|
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 System.Threading;
|
|||
|
|
|||
|
namespace TestTINKLib.Fixtures.ObjectTests.Settings.BluetoothLock
|
|||
|
{
|
|||
|
[TestFixture]
|
|||
|
public class TestLockIt
|
|||
|
{
|
|||
|
[Test]
|
|||
|
public void TestAuthenticate_InvalidSeed()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var ciper = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder {
|
|||
|
K_seed = new byte[] { 0 },
|
|||
|
K_u = new byte[] { 1 }
|
|||
|
}.Build();
|
|||
|
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
|
|||
|
device.Id.Returns(new Guid("00000000-0000-0000-0000-000000000001"));
|
|||
|
|
|||
|
Assert.That(() => LockItEventBased.Authenticate(device, authInfo, adapter, ciper), Throws.InstanceOf<AuthKeyException>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestAuthenticate_InvalidAuthKey()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var ciper = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
K_seed = new byte[] { (byte)'t', (byte)'q', (byte)'2', (byte)'n', (byte)'c', (byte)'A', (byte)'I', (byte)'v', (byte)'M', (byte)'t', (byte)'h', (byte)'g', (byte)'x', (byte)'a', (byte)'z', (byte)'B' },
|
|||
|
K_u = new byte[] { }
|
|||
|
}.Build();
|
|||
|
|
|||
|
device.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("00000000-0000-0000-0000-000000000001"));
|
|||
|
|
|||
|
Assert.That(async () => { await LockItEventBased.Authenticate(device, authInfo, adapter, ciper); }, Throws.InstanceOf<AuthKeyException>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestAuthenticate_Invalidated()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var lockControl = Substitute.For<IService>();
|
|||
|
var state = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
K_seed = new byte[] { (byte)'z', (byte)'D', (byte)'G', (byte)'x', (byte)'q', (byte)'M', (byte)'f', (byte)'A', (byte)'F', (byte)'q', (byte)'g', (byte)'N', (byte)'V', (byte)'r', (byte)'N', (byte)'Y' },
|
|||
|
K_u = new byte[] { 1 }
|
|||
|
}.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(lockControl));
|
|||
|
lockControl.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.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("00000000-0000-0000-0000-000000000001"));
|
|||
|
|
|||
|
// Call authenticate to invalidate seed
|
|||
|
var lockIt = LockItEventBased.Authenticate(device, authInfo, adapter, cipher).Result;
|
|||
|
|
|||
|
// Authenticate again to
|
|||
|
var execption = Assert.Throws<AggregateException>(() => { var dummy = LockItEventBased.Authenticate(device, authInfo, adapter, cipher).Result; });
|
|||
|
|
|||
|
Assert.That(
|
|||
|
execption.InnerExceptions[0].Message,
|
|||
|
Does.Contain ("Seed 122,68,71,120,113,77,102,65,70,113,103,78,86,114,78,89 was already used."));
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestAuthenticate_GetAuthCharacteristicThrowsException()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var lockControl = Substitute.For<IService>();
|
|||
|
var state = Substitute.For<ICharacteristic>();
|
|||
|
var activateLock = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
K_seed = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|||
|
K_u = new byte[] { 1 }
|
|||
|
}.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(lockControl));
|
|||
|
lockControl.GetCharacteristicAsync(new Guid("0000baab-1212-efde-1523-785fef13d123")).Returns(Task.FromResult((ICharacteristic)null));
|
|||
|
|
|||
|
// Authenticate again to
|
|||
|
Assert.That(() => LockItEventBased.Authenticate(device, authInfo, adapter, cipher), Throws.InstanceOf<CoundntGetCharacteristicException>());
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public async Task TestAuthenticate_GetLockState_Closed()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var lockControl = Substitute.For<IService>();
|
|||
|
var state = Substitute.For<ICharacteristic>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
K_seed = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
|||
|
K_u = new byte[] { 1 }
|
|||
|
}.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(lockControl));
|
|||
|
lockControl.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.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("00000000-0000-0000-0000-000000000001"));
|
|||
|
// Calls related to get lock state.
|
|||
|
|
|||
|
// Call authenticate to invalidate seed
|
|||
|
lockControl.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult(state));
|
|||
|
state.ReadAsync(Arg.Any<CancellationToken>()).Returns(new byte[] { 1 });
|
|||
|
|
|||
|
var lockIt = LockItEventBased.Authenticate(device, authInfo, adapter, cipher).Result;
|
|||
|
|
|||
|
Assert.That((await lockIt.GetLockStateAsync()).State, Is.EqualTo(LockitLockingState.Closed));
|
|||
|
}
|
|||
|
|
|||
|
[Test]
|
|||
|
public void TestAuthenticate_GetLockState_GetStateCharacteristicThrowsException()
|
|||
|
{
|
|||
|
var device = Substitute.For<IDevice>();
|
|||
|
var adapter = Substitute.For<IAdapter>();
|
|||
|
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
|
|||
|
var auth = Substitute.For<ICharacteristic>();
|
|||
|
var lockControl = Substitute.For<IService>();
|
|||
|
|
|||
|
var authInfo = new LockInfoAuthTdo.Builder
|
|||
|
{
|
|||
|
K_seed = new byte[] { (byte)'y', (byte)'D', (byte)'G', (byte)'x', (byte)'q', (byte)'M', (byte)'f', (byte)'A', (byte)'F', (byte)'q', (byte)'g', (byte)'N', (byte)'V', (byte)'r', (byte)'N', (byte)'Y' },
|
|||
|
K_u = new byte[] { 1 }
|
|||
|
}.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(lockControl));
|
|||
|
lockControl.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.State.Returns(DeviceState.Connected);
|
|||
|
device.Id.Returns(new Guid("00000000-0000-0000-0000-000000000001"));
|
|||
|
|
|||
|
// Calls related to get lock state.
|
|||
|
lockControl.GetCharacteristicAsync(new Guid("0000baaa-1212-efde-1523-785fef13d123")).Returns(Task.FromResult((ICharacteristic)null));
|
|||
|
|
|||
|
var lockIt = LockItEventBased.Authenticate(device, authInfo, adapter, cipher).Result;
|
|||
|
|
|||
|
Assert.That(async () => (await lockIt.GetLockStateAsync()).State, Throws.InstanceOf<CoundntGetCharacteristicException>());
|
|||
|
}
|
|||
|
}
|
|||
|
}
|