class BluetoothCentral {

    public void connectPeripheral(@NotNull BluetoothPeripheral peripheral, @NotNull BluetoothPeripheralCallback peripheralCallback) {
        synchronized (connectLock) {
            Objects.requireNonNull(peripheral, "no valid peripheral specified");
            Objects.requireNonNull(peripheralCallback, "no valid peripheral callback specified");

            // Check if we are already connected to this peripheral
            if (connectedPeripherals.containsKey(peripheral.getAddress())) {
                Timber.w("already connected to %s'", peripheral.getAddress());
                return;
            }

            // Check if we already have an outstanding connection request for this peripheral
            if (unconnectedPeripherals.containsKey(peripheral.getAddress())) {
                Timber.w("already connecting to %s'", peripheral.getAddress());
                return;
            }

            // Check if the peripheral is cached or not. If not, issue a warning
            int deviceType = peripheral.getType();
            if (deviceType == BluetoothDevice.DEVICE_TYPE_UNKNOWN) {
                // The peripheral is not cached so connection is likely to fail
                Timber.w("peripheral with address '%s' is not in the Bluetooth cache, hence connection may fail", peripheral.getAddress());
            }

            // It is all looking good! Set the callback and prepare to connect
            peripheral.setPeripheralCallback(peripheralCallback);
            scannedPeripherals.remove(peripheral.getAddress());
            unconnectedPeripherals.put(peripheral.getAddress(), peripheral);

            // Now connect
            peripheral.connect();
        }
    }

}

class BluetoothCentralTest {

    private BluetoothCentral central;
    private ShadowApplication application;
    private ShadowBluetoothLEAdapter bluetoothAdapter;
    private Context context;
    @Mock
    private BluetoothLeScanner scanner;
    @Mock
    private BluetoothCentralCallback callback;
    @Mock
    private BluetoothPeripheralCallback peripheralCallback;
    private Handler handler;

    @Test
    public void connectPeripheralAlreadyConnectedTest() throws Exception {

        application.grantPermissions(Manifest.permission.ACCESS_COARSE_LOCATION);
        BluetoothPeripheral peripheral = mock(BluetoothPeripheral.class);
        when(peripheral.getAddress()).thenReturn("12:23:34:98:76:54");
        when(peripheral.getType()).thenReturn(BluetoothDevice.DEVICE_TYPE_LE);

        central.connectPeripheral(peripheral, peripheralCallback);

        verify(peripheral).connect();

        // Grab the scan callback that is used
        Field field = BluetoothCentral.class.getDeclaredField("internalCallback");
        field.setAccessible(true);
        BluetoothPeripheral.InternalCallback internalCallback = (BluetoothPeripheral.InternalCallback) field.get(central);

        // Give connected event and see if we get callback
        internalCallback.connected(peripheral);

        verify(callback).onConnectedPeripheral(peripheral);

        central.connectPeripheral(peripheral, peripheralCallback);

        verify(peripheral, times(1)).connect();
    }

}