bluenrg 0.0.3

Interface to ST Micro BlueNRG Bluetooth radios
Documentation
extern crate bluenrg;
extern crate bluetooth_hci as hci;
extern crate byteorder;

use bluenrg::event::*;
use byteorder::{ByteOrder, LittleEndian};
use hci::event::{Error as HciError, VendorEvent};
use std::time::Duration;

#[test]
fn hal_initialized() {
    let buffer = [0x01, 0x00, 0x01];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::HalInitialized(reason)) => assert_eq!(reason, ResetReason::Normal),
        event => panic!("Did not get HalInitialized; got {:?}", event),
    }
}

#[test]
fn hal_initialized_failure() {
    let buffer = [0x01, 0x00, 0x00];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownResetReason(val))) => assert_eq!(val, 0),
        other => panic!("Did not get unknown reset reason: {:?}", other),
    }
}

#[test]
#[cfg(feature = "ms")]
fn hal_events_lost() {
    let buffer = [
        0x02, 0x00, 0b10101010, 0b11001100, 0b11110000, 0b00001111, 0b00110011, 0b01010101,
        0b00000000, 0b00000000,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::EventsLost(flags)) => assert_eq!(
            flags,
            EventFlags::ENCRYPTION_CHANGE
                | EventFlags::COMMAND_COMPLETE
                | EventFlags::HARDWARE_ERROR
                | EventFlags::ENCRYPTION_KEY_REFRESH
                | EventFlags::GAP_PAIRING_COMPLETE
                | EventFlags::GAP_PASS_KEY_REQUEST
                | EventFlags::GAP_BOND_LOST
                | EventFlags::GAP_PROCEDURE_COMPLETE
                | EventFlags::GATT_ATTRIBUTE_MODIFIED
                | EventFlags::GATT_PROCEDURE_TIMEOUT
                | EventFlags::ATT_EXCHANGE_MTU_RESPONSE
                | EventFlags::ATT_FIND_INFORMATION_RESPONSE
                | EventFlags::ATT_FIND_BY_TYPE_VALUE_RESPONSE
                | EventFlags::ATT_READ_BY_TYPE_RESPONSE
                | EventFlags::ATT_READ_RESPONSE
                | EventFlags::ATT_READ_BLOB_RESPONSE
                | EventFlags::ATT_EXECUTE_WRITE_RESPONSE
                | EventFlags::GATT_INDICATION
                | EventFlags::GATT_ERROR_RESPONSE
                | EventFlags::GATT_DISCOVER_OR_READ_CHARACTERISTIC_BY_UUID_RESPONSE
                | EventFlags::GATT_READ_MULTIPLE_PERMIT_REQUEST
                | EventFlags::GATT_SERVER_RX_CONFIRMATION
                | EventFlags::LINK_LAYER_CONNECTION_COMPLETE
                | EventFlags::LINK_LAYER_CONNECTION_UPDATE_COMPLETE
        ),
        other => panic!("Did not get events lost event: {:?}", other),
    }
}

#[test]
#[cfg(feature = "ms")]
fn hal_events_lost_failure() {
    // 41 event flags (bits 0 - 40) are defined. In this buffer, bit 41 (one past the max) is set,
    // which causes the failure. The test value will need to be updated if more event flags are
    // defined.
    let buffer = [
        0x02, 0x00, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
        0b00000010, 0b00000000,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadEventFlags(_))) => (),
        other => panic!("Did not get BadEventFlags: {:?}", other),
    }
}

#[test]
#[cfg(not(feature = "ms"))]
fn hal_events_lost_unknown() {
    let buffer = [
        0x02, 0x00, 0b10101010, 0b11001100, 0b11110000, 0b00001111, 0b00110011, 0b01010101,
        0b00000000, 0b00000000,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownEvent(0x0002))) => (),
        other => panic!("Did not get unknown event: {:?}", other),
    }
}

#[test]
#[cfg(feature = "ms")]
fn hal_crash_info() {
    let mut buffer = [0; 46];
    buffer[0] = 0x03; // event code
    buffer[1] = 0x00;
    buffer[2] = 0x00; // crash_reason
    buffer[3] = 0x01; // sp
    buffer[4] = 0x02;
    buffer[5] = 0x03;
    buffer[6] = 0x04;
    buffer[7] = 0x05; // r0
    buffer[8] = 0x06;
    buffer[9] = 0x07;
    buffer[10] = 0x08;
    buffer[11] = 0x09; // r1
    buffer[12] = 0x0a;
    buffer[13] = 0x0b;
    buffer[14] = 0x0c;
    buffer[15] = 0x0d; // r2
    buffer[16] = 0x0e;
    buffer[17] = 0x0f;
    buffer[18] = 0x10;
    buffer[19] = 0x11; // r3
    buffer[20] = 0x12;
    buffer[21] = 0x13;
    buffer[22] = 0x14;
    buffer[23] = 0x15; // r12
    buffer[24] = 0x16;
    buffer[25] = 0x17;
    buffer[26] = 0x18;
    buffer[27] = 0x19; // lr
    buffer[28] = 0x1a;
    buffer[29] = 0x1b;
    buffer[30] = 0x1c;
    buffer[31] = 0x1d; // pc
    buffer[32] = 0x1e;
    buffer[33] = 0x1f;
    buffer[34] = 0x20;
    buffer[35] = 0x21; // xPSR
    buffer[36] = 0x22;
    buffer[37] = 0x23;
    buffer[38] = 0x24;
    buffer[39] = 6; // debug data len
    buffer[40] = 0x25; // debug data
    buffer[41] = 0x26;
    buffer[42] = 0x27;
    buffer[43] = 0x28;
    buffer[44] = 0x29;
    buffer[45] = 0x2a;
    let buffer = buffer;
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::CrashReport(info)) => {
            assert_eq!(info.reason, CrashReason::Assertion);
            assert_eq!(info.sp, 0x04030201);
            assert_eq!(info.r0, 0x08070605);
            assert_eq!(info.r1, 0x0c0b0a09);
            assert_eq!(info.r2, 0x100f0e0d);
            assert_eq!(info.r3, 0x14131211);
            assert_eq!(info.r12, 0x18171615);
            assert_eq!(info.lr, 0x1c1b1a19);
            assert_eq!(info.pc, 0x201f1e1d);
            assert_eq!(info.xpsr, 0x24232221);
            assert_eq!(info.debug_data(), [0x25, 0x26, 0x27, 0x28, 0x29, 0x2a]);
        }
        other => panic!("Did not get crash info: {:?}", other),
    }
}

#[test]
#[cfg(feature = "ms")]
fn hal_crash_info_failed_bad_crash_reason() {
    let mut buffer = [0; 40];
    buffer[0] = 0x03;
    buffer[1] = 0x00;
    buffer[2] = 0x03;
    let buffer = buffer;
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownCrashReason(byte))) => assert_eq!(byte, 0x03),
        other => panic!("Did not get bad crash type: {:?}", other),
    }
}

#[test]
#[cfg(feature = "ms")]
fn hal_crash_info_failed_bad_debug_data_len() {
    let mut buffer = [0; 40];
    buffer[0] = 0x03;
    buffer[1] = 0x00;
    buffer[39] = 1; // Says we have one byte of debug data, but the buffer isn't large enough
    let buffer = buffer;
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, 40);
            assert_eq!(expected, 41);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[test]
#[cfg(not(feature = "ms"))]
fn hal_crash_info_unknown() {
    let mut buffer = [0; 46];
    buffer[0] = 0x03; // event code
    buffer[1] = 0x00;
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownEvent(0x0003))) => (),
        other => panic!("Did not get unknown event: {:?}", other),
    }
}

fn l2cap_connection_update_response_buffer(
    event_data_len: u8,
    response_code: u8,
    l2cap_len: u16,
    result: u16,
) -> [u8; 11] {
    let mut buffer = [0; 11];
    LittleEndian::write_u16(&mut buffer[0..], 0x0800);
    LittleEndian::write_u16(&mut buffer[2..], 0x0201);
    buffer[4] = event_data_len;
    buffer[5] = response_code;
    buffer[6] = 0x03; // identifier
    LittleEndian::write_u16(&mut buffer[7..], l2cap_len);
    LittleEndian::write_u16(&mut buffer[9..], result);
    buffer
}

const CONNECTION_UPDATE_RESP_EVENT_DATA_LEN: u8 = 6;
const CONNECTION_UPDATE_RESP_L2CAP_LEN: u16 = 2;
fn l2cap_connection_update_response_command_rejected_buffer() -> [u8; 11] {
    l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x01,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0000,
    )
}

#[test]
fn l2cap_connection_update_response_cmd_rejected() {
    let buffer = l2cap_connection_update_response_command_rejected_buffer();
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::L2CapConnectionUpdateResponse(resp)) => {
            assert_eq!(resp.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(
                resp.result,
                L2CapConnectionUpdateResult::CommandRejected(
                    L2CapRejectionReason::CommandNotUnderstood
                )
            );
        }
        other => panic!("Did not get L2CAP connection update response: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_updated_accepted() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x13,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0000,
    );
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::L2CapConnectionUpdateResponse(resp)) => {
            assert_eq!(resp.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(resp.result, L2CapConnectionUpdateResult::ParametersUpdated);
        }
        other => panic!("Did not get L2CAP connection update response: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_updated_param_rejected() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x13,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0001,
    );

    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::L2CapConnectionUpdateResponse(resp)) => {
            assert_eq!(resp.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(resp.result, L2CapConnectionUpdateResult::ParametersRejected);
        }
        other => panic!("Did not get L2CAP connection update response: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_failed_code() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x02,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0504,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapConnectionResponseCode(code))) => {
            assert_eq!(code, 0x02)
        }
        other => panic!("Did not get bad response code: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_failed_data_length() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN - 1,
        0x01,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0504,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapDataLength(len, 6))) => {
            assert_eq!(len, CONNECTION_UPDATE_RESP_EVENT_DATA_LEN - 1)
        }
        other => panic!("Did not get L2Cap data length code: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_failed_l2cap_length() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x01,
        CONNECTION_UPDATE_RESP_L2CAP_LEN + 1,
        0x0504,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapLength(len, 2))) => {
            assert_eq!(len, CONNECTION_UPDATE_RESP_L2CAP_LEN + 1)
        }
        other => panic!("Did not get L2CAP length: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_failed_unknown_result() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x13,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0002,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapConnectionResponseResult(result))) => {
            assert_eq!(result, 0x0002)
        }
        other => panic!("Did not get bad result: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_response_failed_unknown_rejection_reason() {
    let buffer = l2cap_connection_update_response_buffer(
        CONNECTION_UPDATE_RESP_EVENT_DATA_LEN,
        0x01,
        CONNECTION_UPDATE_RESP_L2CAP_LEN,
        0x0003,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapRejectionReason(reason))) => {
            assert_eq!(reason, 0x0003)
        }
        other => panic!("Did not get bad rejection reason: {:?}", other),
    }
}

#[test]
fn l2cap_procedure_timeout() {
    let buffer = [0x01, 0x08, 0x01, 0x02, 0x00];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::L2CapProcedureTimeout(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201));
        }
        other => panic!("Did not get L2CAP procedure timeout: {:?}", other),
    }
}

#[test]
fn l2cap_procedure_timeout_failed() {
    let buffer = [0x01, 0x08, 0x01, 0x02, 0x01];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapDataLength(len, 0))) => assert_eq!(len, 1),
        other => panic!("Did not get L2Cap data length code: {:?}", other),
    }
}

const L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN: u8 = 11;
const L2CAP_CONN_UPDATE_REQ_L2CAP_LEN: u16 = 8;
fn l2cap_connection_update_request_buffer(
    event_data_len: u8,
    l2cap_len: u16,
    interval_min: u16,
    interval_max: u16,
    conn_latency: u16,
    timeout_mult: u16,
) -> [u8; 16] {
    let mut buffer = [0; 16];
    LittleEndian::write_u16(&mut buffer[0..], 0x0802);
    LittleEndian::write_u16(&mut buffer[2..], 0x0001);
    buffer[4] = event_data_len;
    buffer[5] = 0x02;
    LittleEndian::write_u16(&mut buffer[6..], l2cap_len);
    LittleEndian::write_u16(&mut buffer[8..], interval_min);
    LittleEndian::write_u16(&mut buffer[10..], interval_max);
    LittleEndian::write_u16(&mut buffer[12..], conn_latency);
    LittleEndian::write_u16(&mut buffer[14..], timeout_mult);

    buffer
}

#[test]
fn l2cap_connection_update_request() {
    let buffer = l2cap_connection_update_request_buffer(
        L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN,
        L2CAP_CONN_UPDATE_REQ_L2CAP_LEN,
        6,
        10,
        10,
        3200,
    );
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::L2CapConnectionUpdateRequest(req)) => {
            assert_eq!(req.conn_handle, ConnectionHandle(1));
            assert_eq!(req.identifier, 2);
            assert_eq!(
                req.conn_interval.interval(),
                (Duration::from_micros(7500), Duration::from_micros(12500))
            );
            assert_eq!(req.conn_interval.conn_latency(), 10);
            assert_eq!(
                req.conn_interval.supervision_timeout(),
                Duration::from_millis(32000)
            );
        }
        other => panic!("Did not get L2CAP connection update request: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_request_failed_event_data_len() {
    let buffer = l2cap_connection_update_request_buffer(
        L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN - 1,
        L2CAP_CONN_UPDATE_REQ_L2CAP_LEN,
        6,
        3200,
        499,
        3200,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapDataLength(
            len,
            L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN,
        ))) => assert_eq!(len, L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN - 1),
        other => panic!("Did not get L2CAP data length code: {:?}", other),
    }
}

#[test]
fn l2cap_connection_update_request_failed_l2cap_len() {
    let buffer = l2cap_connection_update_request_buffer(
        L2CAP_CONN_UPDATE_REQ_EVENT_DATA_LEN,
        L2CAP_CONN_UPDATE_REQ_L2CAP_LEN - 1,
        6,
        3200,
        499,
        3200,
    );
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadL2CapLength(
            len,
            L2CAP_CONN_UPDATE_REQ_L2CAP_LEN,
        ))) => assert_eq!(len, L2CAP_CONN_UPDATE_REQ_L2CAP_LEN - 1),
        other => panic!("Did not get L2CAP length: {:?}", other),
    }
}

#[test]
fn gap_limited_discoverable() {
    let buffer = [0x00, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapLimitedDiscoverableTimeout) => (),
        other => panic!("Did not get GAP Limited discoverable timeout: {:?}", other),
    }
}

#[test]
fn gap_pairing_complete() {
    let buffer = [0x01, 0x04, 0x01, 0x02, 0x00];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapPairingComplete(evt)) => {
            assert_eq!(evt.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(evt.status, GapPairingStatus::Success);
        }
        other => panic!("Did not get GAP Pairing complete: {:?}", other),
    }
}

#[test]
fn gap_pairing_complete_failed() {
    let buffer = [0x01, 0x04, 0x01, 0x02, 0x03];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGapPairingStatus(value))) => assert_eq!(value, 3),
        other => panic!("Did not get bad pairing status: {:?}", other),
    }
}

#[test]
fn gap_pass_key_request() {
    let buffer = [0x02, 0x04, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapPassKeyRequest(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201))
        }
        other => panic!("Did not get GAP pass key request: {:?}", other),
    }
}

#[test]
fn gap_authorization_request() {
    let buffer = [0x03, 0x04, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapAuthorizationRequest(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201))
        }
        other => panic!("Did not get GAP authorization request: {:?}", other),
    }
}

#[test]
fn gap_peripheral_security_initiated() {
    let buffer = [0x04, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapPeripheralSecurityInitiated) => (),
        other => panic!("Did not get GAP peripheral security initiated: {:?}", other),
    }
}

#[test]
fn gap_bond_lost() {
    let buffer = [0x05, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapBondLost) => (),
        other => panic!("Did not get GAP bond lost: {:?}", other),
    }
}

#[test]
fn gap_device_found() {
    let buffer = [
        0x06, 0x04, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 3, 0x01, 0x02, 0x03, 0x04,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapDeviceFound(event)) => {
            assert_eq!(event.event, GapDeviceFoundEvent::Advertisement);
            assert_eq!(event.bdaddr, BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])));
            assert_eq!(event.rssi, Some(0x04));
            assert_eq!(event.data(), [1, 2, 3]);
        }
        other => panic!("Did not get GAP Device found: {:?}", other),
    }
}

#[test]
fn gap_device_found_failure_bad_event() {
    let buffer = [
        0x06, 0x04, 0x05, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 3, 0x01, 0x02, 0x03, 0x04,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGapDeviceFoundEvent(code))) => {
            assert_eq!(code, 0x05);
        }
        other => panic!("Did not get bad GAP device found event: {:?}", other),
    }
}

#[test]
fn gap_device_found_failure_bad_bdaddr_type() {
    let buffer = [
        0x06, 0x04, 0x04, 0x02, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 3, 0x01, 0x02, 0x03, 0x04,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGapBdAddrType(bdaddr_type))) => {
            assert_eq!(bdaddr_type, 0x02);
        }
        other => panic!("Did not get bad GAP device found event: {:?}", other),
    }
}

#[test]
fn gap_device_found_failure_bad_data_length() {
    let buffer = [
        0x06, 0x04, 0x04, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 4, 0x01, 0x02, 0x03, 0x04,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() + 1);
        }
        other => panic!("Did not get bad GAP device found length: {:?}", other),
    }
}

#[test]
fn gap_device_found_failure_bad_rssi() {
    let buffer = [
        0x06, 0x04, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 3, 0x01, 0x02, 0x03, 0x7F,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapDeviceFound(event)) => {
            assert_eq!(event.event, GapDeviceFoundEvent::Advertisement);
            assert_eq!(event.bdaddr, BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])));
            assert_eq!(event.rssi, None);
            assert_eq!(event.data(), [1, 2, 3]);
        }
        other => panic!("Did not get GAP Device found: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete() {
    let buffer = [0x07, 0x04, 0x01, 0x00];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapProcedureComplete(evt)) => {
            assert_eq!(evt.procedure, GapProcedure::LimitedDiscovery);
            assert_eq!(evt.status, GapProcedureStatus::Success);
        }
        other => panic!("Did not get GAP Procedure Complete: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete_name_discovery() {
    let buffer = [0x07, 0x04, 0x04, 0x00, 0x41, 0x42, 0x43];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapProcedureComplete(evt)) => {
            let mut name = NameBuffer([0; MAX_NAME_LEN]);
            name.0[0] = 0x41;
            name.0[1] = 0x42;
            name.0[2] = 0x43;
            let name = name;
            assert_eq!(evt.procedure, GapProcedure::NameDiscovery(3, name));
            assert_eq!(evt.status, GapProcedureStatus::Success);
        }
        other => panic!("Did not get GAP Procedure Complete: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete_general_connection_establishment() {
    let buffer = [0x07, 0x04, 0x10, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapProcedureComplete(evt)) => {
            assert_eq!(
                evt.procedure,
                GapProcedure::GeneralConnectionEstablishment(BdAddr([1, 2, 3, 4, 5, 6]))
            );
            assert_eq!(evt.status, GapProcedureStatus::Success);
        }
        other => panic!("Did not get GAP Procedure Complete: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete_failed_bad_procedure() {
    let buffer = [0x07, 0x04, 0x03, 0x00];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGapProcedure(code))) => assert_eq!(code, 0x03),
        other => panic!("Did not get bad GAP Procedure code: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete_failed_bad_status() {
    let buffer = [0x07, 0x04, 0x02, 0x01];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGapProcedureStatus(code))) => assert_eq!(code, 0x01),
        other => panic!("Did not get bad GAP Procedure status: {:?}", other),
    }
}

#[test]
fn gap_procedure_complete_failed_general_connection_establishment_length() {
    let buffer = [
        0x07, 0x04, 0x10, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(11, 10)) => (),
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn gap_addr_not_resolved() {
    let buffer = [0x08, 0x04, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapAddressNotResolved(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201))
        }
        other => panic!("Did not get Address not Resolved event: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn gap_addr_not_resolved() {
    let buffer = [0x08, 0x04, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GapReconnectionAddress(bdaddr)) => {
            assert_eq!(bdaddr, BdAddr([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]))
        }
        other => panic!("Did not get Address not Resolved event: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn gatt_attribute_modified() {
    let buffer = [
        0x01, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x02, 0x05, 0x86, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattAttributeModified(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attr_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
            assert_eq!(event.continued, true);
            assert_eq!(event.data(), [0x07, 0x08]);
        }
        other => panic!("Did not get Gatt attribute modified: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn gatt_attribute_modified_failed_bad_data_len() {
    let buffer = [
        0x01, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x03, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() + 1);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn gatt_attribute_modified() {
    let buffer = [0x01, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x02, 0x07, 0x08];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattAttributeModified(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attr_handle, AttributeHandle(0x0403));
            assert_eq!(event.data(), [0x07, 0x08]);
        }
        other => panic!("Did not get Gatt attribute modified: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn gatt_attribute_modified_failed_bad_data_len() {
    let buffer = [0x01, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x03, 0x07, 0x08];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() + 1);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[test]
fn gatt_procedure_timeout() {
    let buffer = [0x02, 0x0C, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattProcedureTimeout(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201));
        }
        other => panic!("Did not get GATT procedure timeout: {:?}", other),
    }
}

#[test]
fn att_exchange_mtu_response() {
    let buffer = [0x03, 0x0C, 0x01, 0x02, 0x01, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttExchangeMtuResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.server_rx_mtu, 0x0403);
        }
        other => panic!("Did not get ATT Exchange MTU Response: {:?}", other),
    }
}

#[test]
fn att_find_information_response_16bit_uuids() {
    let buffer = [
        0x04, 0x0C, 0x01, 0x02, 13, 1, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
        0x0d, 0x0e,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttFindInformationResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            if let HandleUuidPairIterator::Format16(mut iter) = event.handle_uuid_pair_iter() {
                let actual = iter.next().unwrap();
                assert_eq!(actual.handle, AttributeHandle(0x0403));
                assert_eq!(actual.uuid, Uuid16(0x0605));

                let actual = iter.next().unwrap();
                assert_eq!(actual.handle, AttributeHandle(0x0807));
                assert_eq!(actual.uuid, Uuid16(0x0a09));

                let actual = iter.next().unwrap();
                assert_eq!(actual.handle, AttributeHandle(0x0c0b));
                assert_eq!(actual.uuid, Uuid16(0x0e0d));

                match iter.next() {
                    Some(actual) => panic!("Found extra HandleUuidPair: {:?}", actual),
                    None => (),
                }
            } else {
                panic!("Did not get HandleUuidPair::Format16")
            }
        }
        other => panic!("Did not get ATT find info response: {:?}", other),
    }
}

#[test]
fn att_find_information_response_128bit_uuids() {
    let buffer = [
        0x04, 0x0C, 0x01, 0x02, 37, 2, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
        0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
        0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttFindInformationResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            if let HandleUuidPairIterator::Format128(mut iter) = event.handle_uuid_pair_iter() {
                let actual = iter.next().unwrap();
                assert_eq!(actual.handle, AttributeHandle(0x0403));
                assert_eq!(
                    actual.uuid,
                    Uuid128([
                        0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
                        0x11, 0x12, 0x13, 0x14,
                    ])
                );

                let actual = iter.next().unwrap();
                assert_eq!(actual.handle, AttributeHandle(0x1615));
                assert_eq!(
                    actual.uuid,
                    Uuid128([
                        0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22,
                        0x23, 0x24, 0x25, 0x26,
                    ])
                );

                match iter.next() {
                    Some(actual) => panic!("Found extra HandleUuidPair: {:?}", actual),
                    None => (),
                }
            } else {
                panic!("Did not get HandleUuidPair::Format128")
            }
        }
        other => panic!("Did not get ATT find info response: {:?}", other),
    }
}

#[test]
fn att_find_information_response_failed_format() {
    let buffer = [0x04, 0x0C, 0x01, 0x02, 1, 3];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadAttFindInformationResponseFormat(3))) => (),
        other => panic!("Did not get bad ATT Find info response format: {:?}", other),
    }
}

#[test]
fn att_find_information_response_failed_partial_uuid() {
    let buffer = [
        0x04, 0x0C, 0x01, 0x02, 11, 1, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::AttFindInformationResponsePartialPair16)) => (),
        other => panic!(
            "Did not get bad ATT Find info response partial pair: {:?}",
            other
        ),
    }
}

#[test]
fn att_find_by_type_value_response() {
    let buffer = [
        0x05, 0x0C, 0x01, 0x02, 8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttFindByTypeValueResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));

            assert_eq!(event.handle_pairs_iter().count(), 2);
            for (actual, expected) in event.handle_pairs_iter().zip(&[
                HandleInfoPair {
                    attribute: AttributeHandle(0x0201),
                    group_end: GroupEndHandle(0x0403),
                },
                HandleInfoPair {
                    attribute: AttributeHandle(0x0605),
                    group_end: GroupEndHandle(0x0807),
                },
            ]) {
                assert_eq!(actual.attribute, expected.attribute);
                assert_eq!(actual.group_end, expected.group_end);
            }
        }
        other => panic!("Did not get find-by-type-value response: {:?}", other),
    }
}

#[test]
fn att_find_by_type_value_response_failed_partial_pair() {
    let buffer = [
        0x05, 0x0C, 0x01, 0x02, 7, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::AttFindByTypeValuePartial)) => (),
        other => panic!(
            "Did not get find-by-type-value response failure: {:?}",
            other
        ),
    }
}

#[test]
fn att_read_by_type_response() {
    let buffer = [
        0x06, 0x0C, 0x01, 0x02, 13, 6, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14,
        0x15, 0x16,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadByTypeResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));

            let mut iter = event.handle_value_pair_iter();
            let actual = iter.next().unwrap();
            assert_eq!(actual.handle, AttributeHandle(0x0201));
            assert_eq!(actual.value, [0x03, 0x04, 0x05, 0x06]);

            let actual = iter.next().unwrap();
            assert_eq!(actual.handle, AttributeHandle(0x1211));
            assert_eq!(actual.value, [0x13, 0x14, 0x15, 0x16]);

            match iter.next() {
                Some(_) => panic!("Found extra HandleValuePair"),
                None => (),
            }
        }
        other => panic!("Did not get read-by-type response: {:?}", other),
    }
}

#[test]
fn att_read_by_type_response_failed_partial_pair() {
    let buffer = [
        0x06, 0x0C, 0x01, 0x02, 12, 6, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x11, 0x12, 0x13, 0x14,
        0x15,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::AttReadByTypeResponsePartial)) => (),
        other => panic!("Did not get partial read-by-type response: {:?}", other),
    }
}

#[test]
fn att_read_response() {
    let buffer = [0x07, 0x0C, 0x01, 0x02, 4, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), [0x01, 0x02, 0x03, 0x04]);
        }
        other => panic!("Did not get ATT read response: {:?}", other),
    }
}

#[test]
fn att_read_response_empty() {
    let buffer = [0x07, 0x0C, 0x01, 0x02, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT read response: {:?}", other),
    }
}

#[test]
fn att_read_response_failed() {
    let buffer = [0x07, 0x0C, 0x01, 0x02, 3, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() - 1);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[test]
fn att_read_blob_response() {
    let buffer = [0x08, 0x0C, 0x01, 0x02, 4, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadBlobResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), [0x01, 0x02, 0x03, 0x04]);
        }
        other => panic!("Did not get ATT Read Blob Response: {:?}", other),
    }
}

#[test]
fn att_read_blob_response_empty() {
    let buffer = [0x08, 0x0C, 0x01, 0x02, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadBlobResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT Read Blob Response: {:?}", other),
    }
}

#[test]
fn att_read_blob_response_failed() {
    let buffer = [0x08, 0x0C, 0x01, 0x02, 2, 0x01];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() + 1);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[test]
fn att_read_multiple_response() {
    let buffer = [0x09, 0x0C, 0x01, 0x02, 4, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadMultipleResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), [0x01, 0x02, 0x03, 0x04]);
        }
        other => panic!("Did not get ATT Read Multiple Response: {:?}", other),
    }
}

#[test]
fn att_read_multiple_response_empty() {
    let buffer = [0x09, 0x0C, 0x01, 0x02, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadMultipleResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT Read Multiple Response: {:?}", other),
    }
}

#[test]
fn att_read_multiple_response_failed() {
    let buffer = [0x09, 0x0C, 0x01, 0x02, 2, 0x01];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::BadLength(actual, expected)) => {
            assert_eq!(actual, buffer.len());
            assert_eq!(expected, buffer.len() + 1);
        }
        other => panic!("Did not get bad length: {:?}", other),
    }
}

#[test]
fn att_read_by_group_type_response() {
    let buffer = [
        0x0A, 0x0C, 0x01, 0x02, 17, 8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadByGroupTypeResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));

            let mut iter = event.attribute_data_iter();
            let actual = iter.next().unwrap();
            assert_eq!(actual.attribute_handle, AttributeHandle(0x0201));
            assert_eq!(actual.group_end_handle, GroupEndHandle(0x0403));
            assert_eq!(actual.value, [0x05, 0x06, 0x07, 0x08]);

            let actual = iter.next().unwrap();
            assert_eq!(actual.attribute_handle, AttributeHandle(0x1211));
            assert_eq!(actual.group_end_handle, GroupEndHandle(0x1413));
            assert_eq!(actual.value, [0x15, 0x16, 0x17, 0x18]);

            match iter.next() {
                Some(_) => panic!("Found extra HandleValuePair"),
                None => (),
            }
        }
        other => panic!("Did not get Read by Group Type Response: {:?}", other),
    }
}

#[test]
fn att_read_by_group_type_response_failed() {
    let buffer = [
        0x0A, 0x0C, 0x01, 0x02, 16, 8, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x11, 0x12,
        0x13, 0x14, 0x15, 0x16, 0x17,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::AttReadByGroupTypeResponsePartial)) => (),
        other => panic!(
            "Did not get partial Read by Group Type Response: {:?}",
            other
        ),
    }
}

#[test]
fn att_prepare_write_response() {
    let buffer = [
        0x0C, 0x0C, 0x01, 0x02, 8, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttPrepareWriteResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
            assert_eq!(event.value(), [0x07, 0x08, 0x09, 0x0a]);
        }
        other => panic!("Did not get ATT prepare write response: {:?}", other),
    }
}

#[test]
fn att_prepare_write_response_empty() {
    let buffer = [0x0C, 0x0C, 0x01, 0x02, 4, 0x03, 0x04, 0x05, 0x06];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttPrepareWriteResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT prepare write response: {:?}", other),
    }
}

#[test]
fn att_execute_write_response() {
    let buffer = [0x0D, 0x0C, 0x01, 0x02, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttExecuteWriteResponse(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201));
        }
        other => panic!("Did not get ATT Execute Write Response: {:?}", other),
    }
}

#[test]
fn gatt_indication() {
    let buffer = [
        0x0E, 0x0C, 0x01, 0x02, 6, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattIndication(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), [0x05, 0x06, 0x07, 0x08]);
        }
        other => panic!("Did not get GATT Indication: {:?}", other),
    }
}

#[test]
fn gatt_indication_empty() {
    let buffer = [0x0E, 0x0C, 0x01, 0x02, 2, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattIndication(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get GATT Indication: {:?}", other),
    }
}

#[test]
fn gatt_notification() {
    let buffer = [
        0x0F, 0x0C, 0x01, 0x02, 6, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattNotification(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), [0x05, 0x06, 0x07, 0x08]);
        }
        other => panic!("Did not get GATT Notification: {:?}", other),
    }
}

#[test]
fn gatt_notification_empty() {
    let buffer = [0x0F, 0x0C, 0x01, 0x02, 2, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattNotification(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get GATT Notification: {:?}", other),
    }
}

#[test]
fn gatt_procedure_complete_success() {
    let buffer = [0x10, 0x0C, 0x01, 0x02, 1, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattProcedureComplete(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.status, GattProcedureStatus::Success);
        }
        other => panic!("Did not get GATT Procedure Complete: {:?}", other),
    }
}

#[test]
fn gatt_procedure_complete_failed() {
    let buffer = [0x10, 0x0C, 0x01, 0x02, 1, 0x41];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattProcedureComplete(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.status, GattProcedureStatus::Failed);
        }
        other => panic!("Did not get GATT Procedure Complete: {:?}", other),
    }
}

#[test]
fn gatt_procedure_complete_error_unknown_code() {
    let buffer = [0x10, 0x0C, 0x01, 0x02, 1, 0x40];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadGattProcedureStatus(code))) => {
            assert_eq!(code, 0x40);
        }
        other => panic!("Did not get Bad GATT Procedure Status: {:?}", other),
    }
}

#[test]
fn att_error_response() {
    let buffer = [0x11, 0x0C, 0x01, 0x02, 4, 0x03, 0x04, 0x05, 0x07];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttErrorResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.request, AttRequest::ExchangeMtuResponse);
            assert_eq!(event.attribute_handle, AttributeHandle(0x0504));
            assert_eq!(event.error, AttError::InvalidOffset);
        }
        other => panic!("Did not get ATT error response: {:?}", other),
    }
}

#[test]
fn att_error_response_failed_bad_request_opcode() {
    let buffer = [0x11, 0x0C, 0x01, 0x02, 4, 0x48, 0x04, 0x05, 0x07];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadAttRequestOpcode(code))) => {
            assert_eq!(code, 0x48);
        }
        other => panic!("Did not get bad ATT request opcode: {:?}", other),
    }
}

#[test]
fn att_error_response_failed_bad_error_code() {
    let buffer = [0x11, 0x0C, 0x01, 0x02, 4, 0x03, 0x04, 0x05, 0x12];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::BadAttError(code))) => {
            assert_eq!(code, 0x12);
        }
        other => panic!("Did not get bad ATT error code: {:?}", other),
    }
}

#[test]
fn gatt_discover_or_read_characteristic_by_uuid_response() {
    let buffer = [
        0x12, 0x0C, 0x01, 0x02, 6, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattDiscoverOrReadCharacteristicByUuidResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), [0x05, 0x06, 0x07, 0x08]);
        }
        other => panic!("Did not get GATT Notification: {:?}", other),
    }
}

#[test]
fn gatt_discover_or_read_characteristic_by_uuid_response_empty() {
    let buffer = [0x12, 0x0C, 0x01, 0x02, 2, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattDiscoverOrReadCharacteristicByUuidResponse(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get GATT Notification: {:?}", other),
    }
}

#[test]
fn att_write_permit_request() {
    let buffer = [
        0x13, 0x0C, 0x01, 0x02, 0x03, 0x04, 4, 0x05, 0x06, 0x07, 0x08,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttWritePermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), [0x05, 0x06, 0x07, 0x08]);
        }
        other => panic!("Did not get ATT Write Permit Request: {:?}", other),
    }
}

#[test]
fn att_write_permit_request_empty() {
    let buffer = [0x13, 0x0C, 0x01, 0x02, 0x03, 0x04, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttWritePermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT Write Permit Request: {:?}", other),
    }
}

#[test]
fn att_read_permit_request() {
    let buffer = [0x14, 0x0C, 0x01, 0x02, 0x03, 0x04, 2, 0x05, 0x06];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadPermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
        }
        other => panic!("Did not get ATT Read Permit Request: {:?}", other),
    }
}

#[test]
fn att_read_multiple_permit_request() {
    let buffer = [0x15, 0x0C, 0x01, 0x02, 4, 0x03, 0x04, 0x05, 0x06];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttReadMultiplePermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(
                event.handles(),
                [AttributeHandle(0x0403), AttributeHandle(0x0605)]
            );
        }
        other => panic!("Did not get ATT Read Multiple Permit Request: {:?}", other),
    }
}

#[test]
fn att_read_multiple_permit_request_failed() {
    let buffer = [0x15, 0x0C, 0x01, 0x02, 3, 0x03, 0x04, 0x05];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::AttReadMultiplePermitRequestPartial)) => (),
        other => panic!(
            "Did not get partial ATT Read Multiple Permit Request: {:?}",
            other
        ),
    }
}

#[cfg(feature = "ms")]
#[test]
fn gatt_tx_pool_available() {
    let buffer = [0x16, 0x0C, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattTxPoolAvailable(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.available_buffers, 0x0403);
        }
        other => panic!("Did not get GATT TX Pool Available event: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn gatt_tx_pool_available_unknown() {
    let buffer = [0x16, 0x0C, 0x01, 0x02, 0x03, 0x04];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownEvent(0x0C16))) => (),
        other => panic!("Did not get unknown event: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn gatt_server_confirmation() {
    let buffer = [0x17, 0x0C, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::GattServerConfirmation(conn_handle)) => {
            assert_eq!(conn_handle, ConnectionHandle(0x0201));
        }
        other => panic!("Did not get GATT Server Confirmation event: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn gatt_server_confirmation_unknown() {
    let buffer = [0x17, 0x0C, 0x01, 0x02];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownEvent(0x0C17))) => (),
        other => panic!("Did not get unknown event: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn att_prepare_write_permit_request() {
    let buffer = [
        0x18, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 4, 0x07, 0x08, 0x09, 0x0a,
    ];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttPrepareWritePermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
            assert_eq!(event.value(), [0x07, 0x08, 0x09, 0x0a]);
        }
        other => panic!("Did not get ATT Prepare Write Permit Request: {:?}", other),
    }
}

#[cfg(feature = "ms")]
#[test]
fn att_prepare_write_permit_request_empty() {
    let buffer = [0x18, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0];
    match BlueNRGEvent::new(&buffer) {
        Ok(BlueNRGEvent::AttPrepareWritePermitRequest(event)) => {
            assert_eq!(event.conn_handle, ConnectionHandle(0x0201));
            assert_eq!(event.attribute_handle, AttributeHandle(0x0403));
            assert_eq!(event.offset, 0x0605);
            assert_eq!(event.value(), []);
        }
        other => panic!("Did not get ATT Prepare Write Permit Request: {:?}", other),
    }
}

#[cfg(not(feature = "ms"))]
#[test]
fn att_prepare_write_permit_request_unknown() {
    let buffer = [
        0x18, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 4, 0x07, 0x08, 0x09, 0x0a,
    ];
    match BlueNRGEvent::new(&buffer) {
        Err(HciError::Vendor(BlueNRGError::UnknownEvent(0x0C18))) => (),
        other => panic!("Did not get unknown event: {:?}", other),
    }
}