2022-08-30 15:42:25 +02:00
using System ;
using System.Threading ;
using System.Threading.Tasks ;
2021-05-13 17:25:46 +02:00
using NSubstitute ;
using NUnit.Framework ;
using Plugin.BLE.Abstractions.Contracts ;
2022-08-30 15:42:25 +02:00
using Plugin.BLE.Abstractions.EventArgs ;
2021-05-13 17:25:46 +02:00
using TINK.Services.BluetoothLock.BLE ;
2022-08-30 15:42:25 +02:00
using TINK.Services.BluetoothLock.Exception ;
using TINK.Services.BluetoothLock.Tdo ;
2021-05-13 17:25:46 +02:00
using DeviceState = Plugin . BLE . Abstractions . DeviceState ;
namespace TestLockItBLE
{
public class Tests
{
[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 stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) 'p' , ( 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 before open action: closed */ } ) ) ;
controlService . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateCharacteristic ) ) ;
activateCharacteristic . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . Open /* State passed as event argument after opening. */ } ) ;
// Use factory to create LockIt-object.
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
var lockState = lockIt . OpenAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
Assert . That ( lockState . 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 stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateLock = Substitute . For < ICharacteristic > ( ) ;
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) 'm' , ( 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 /* State read before open action: closed */ } ) ) ;
controlService . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateLock ) ) ;
activateLock . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . Closed /* State passed as event argument after opening. */ } ) ;
// Use factory to create LockIt-object.
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
2022-08-30 15:42:25 +02:00
Assert . That ( async ( ) = >
2021-05-13 17:25:46 +02:00
{
var lockState = lockIt . OpenAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
await lockState ;
2022-08-30 15:42:25 +02:00
} ,
2021-05-13 17:25:46 +02:00
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 lockControl = Substitute . For < IService > ( ) ;
var controlCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateLock = Substitute . For < ICharacteristic > ( ) ;
var stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
2022-08-30 15:42:25 +02:00
2021-05-13 17:25:46 +02:00
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) 'i' , ( 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 ( 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 . Name . Returns ( "ISHAREIT+123" ) ;
// Calls related to open functionality.
lockControl . 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 */ } ) ) ;
lockControl . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateLock ) ) ;
activateLock . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . CouldntOpenBoldBlocked /* State passed as event argument after opening. */ } ) ;
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
// Use factory to create LockIt-object.
Assert . That ( async ( ) = >
{
var lockState = lockIt . OpenAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
await lockState ;
} ,
2021-06-26 20:57:55 +02:00
Throws . InstanceOf < CouldntOpenBoldIsBlockedException > ( ) ) ;
2021-05-13 17:25:46 +02:00
}
[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 lockControl = Substitute . For < IService > ( ) ;
var controlCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateLock = Substitute . For < ICharacteristic > ( ) ;
var stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) 'I' , ( 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 ( 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 . Name . Returns ( "ISHAREIT+123" ) ;
// Calls related to close functionality.
lockControl . 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 */ } ) ) ;
lockControl . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateLock ) ) ;
activateLock . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . Closed /* State passed as event argument after closing. */ } ) ;
// Use factory to create LockIt-object.
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
var lockState = lockIt . CloseAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
Assert . That ( lockState . Result , Is . EqualTo ( LockitLockingState . Closed ) ) ;
}
[Test]
public void TestClose_ThrowsCouldntCloseInconsistentStateExecption ( )
{
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 controlCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateLock = Substitute . For < ICharacteristic > ( ) ;
var stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) '8' , ( 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 ( 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 . Name . Returns ( "ISHAREIT+123" ) ;
// Calls related to close functionality.
lockControl . GetCharacteristicAsync ( new Guid ( "0000baaa-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( controlCharacteristic ) ) ;
controlCharacteristic . ReadAsync ( Arg . Any < CancellationToken > ( ) ) . Returns ( Task . FromResult ( new byte [ ] { 0 /* opened */ } ) ) ;
lockControl . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateLock ) ) ;
activateLock . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . Open /* State passed as event argument after closing. */ } ) ;
// Use factory to create LockIt-object.
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
// Use factory to create LockIt-object.
Assert . That ( async ( ) = >
{
var lockState = lockIt . CloseAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
await lockState ;
} ,
Throws . InstanceOf < CouldntCloseInconsistentStateExecption > ( ) ) ;
}
[Test]
public void TestClose_ThrowsCouldntCloseBoldBlockedException ( )
{
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 controlCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var activateLock = Substitute . For < ICharacteristic > ( ) ;
var stateCharacteristic = Substitute . For < ICharacteristic > ( ) ;
var authTdo = new LockInfoAuthTdo . Builder
{
Id = 12 ,
K_seed = new byte [ ] { ( byte ) 'v' , ( 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 ( 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 . Name . Returns ( "ISHAREIT+123" ) ;
// Calls related to Close functionality.
lockControl . GetCharacteristicAsync ( new Guid ( "0000baaa-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( controlCharacteristic ) ) ;
controlCharacteristic . ReadAsync ( Arg . Any < CancellationToken > ( ) ) . Returns ( Task . FromResult ( new byte [ ] { 0 /* open */ } ) ) ;
lockControl . GetCharacteristicAsync ( new Guid ( "0000beee-1212-efde-1523-785fef13d123" ) ) . Returns ( Task . FromResult ( activateLock ) ) ;
activateLock . WriteAsync ( Arg . Any < byte [ ] > ( ) ) . Returns ( Task . FromResult ( true ) ) ;
stateCharacteristic . Value . Returns ( new byte [ ] { ( byte ) LockitLockingState . CouldntCloseBoldBlocked /* State passed as event argument after opening. */ } ) ;
// Use factory to create LockIt-object.
var lockIt = LockItEventBased . Authenticate ( device , authTdo , adapter , cipher ) . Result ;
// Use factory to create LockIt-object.
Assert . That ( async ( ) = >
{
var lockState = lockIt . CloseAsync ( ) ;
controlCharacteristic . ValueUpdated + = Raise . EventWith ( new object ( ) , new CharacteristicUpdatedEventArgs ( stateCharacteristic ) ) ;
await lockState ;
} ,
Throws . InstanceOf < CouldntCloseBoldBlockedException > ( ) ) ;
}
}
}