示例#1
0
        public void InitError()
        {
            var mocks = new Mockery();
            var api   = mocks.NewMock <IBluetopiaApi>();

            // Second time after try-kill BTExplorer.exe
            Expect.Exactly(2).On(api).Method("BSC_Initialize")
            .WithAnyArguments()      // TO-DO
            .Will(Return.Value((int)BluetopiaError.UNSUPPORTED_PLATFORM_ERROR));
            //----
            try {
                BluetopiaTesting.HackAllowShutdownCall(api);
                BluetopiaFactory fcty = new BluetopiaFactory(api);
                Assert.Fail("should have thrown!");
            } catch (BluetopiaSocketException ex) {
                Assert.AreEqual((int)BluetopiaError.UNSUPPORTED_PLATFORM_ERROR, ex.BluetopiaErrorCode, "BluetopiaErrorCode");
                Assert.AreEqual(BluetopiaError.UNSUPPORTED_PLATFORM_ERROR.ToString(), ex.BluetopiaError, "BluetopiaError");
                Assert.AreEqual(
                    // was: "An operation was attempted on something that is not a socket"
                    "The attempted operation is not supported for the type of object referenced"
                    + " (Bluetopia: UNSUPPORTED_PLATFORM_ERROR (-101)).",
                    ex.Message, "Message");
            }
            //
            mocks.VerifyAllExpectationsHaveBeenMet();
        }
示例#2
0
        void DoTest_HackOneSeqDeep(StackConsts.SDP_Data_Element_Type expectedET,
                                   byte[] expectedDataValue,
                                   ServiceRecord r)
        {
            var stuff = BluetopiaTesting.InitMockery_SdpCreator();
            //
            const UInt16 attrId          = 0xF234;
            var          expectedElement = new Structs.SDP_Data_Element__Class_ElementArray(
                StackConsts.SDP_Data_Element_Type.Sequence,
                1, new Structs.SDP_Data_Element__Class[] {
                new Structs.SDP_Data_Element__Class_InlineByteArray(
                    expectedET,
                    expectedDataValue.Length, expectedDataValue)
            });

            Expect.Once.On(stuff.MockApi2).Method("SDP_Add_Attribute")
            .With(
                stuff.StackId, stuff.SrHandle,
                attrId,
                expectedElement
                )
            .Will(Return.Value(BluetopiaError.OK));
            //
            stuff.DutSdpCreator.CreateServiceRecord(r);
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            VerifyDispose(stuff);
        }
示例#3
0
        public void ErrorOpenNoCallback()
        {
            var stuff = BluetopiaTesting.InitMockery_Client(new ClientTestingBluetopia.Behaviour());
            //
            const int hConn = 99;
            //
            var cli  = stuff.CreateBluetoothClient();
            var cli2 = (BluetopiaClient)cli;
            var conn = (BluetopiaRfcommStream)cli2.Testing_GetConn();

            //
            Expect.Once.On(stuff.MockedApi).Method("SPP_Open_Remote_Port")
            .With(stuff.StackId, ClientTesting.Addr1Long, ClientTesting.Port5Uint,
                  (InTheHand.Net.Bluetooth.StonestreetOne.NativeMethods.SPP_Event_Callback)
                  conn.HandleSPP_Event_Callback, (uint)0)
            .Will(Return.Value(hConn));
            //
            var remote = new BluetoothEndPoint(ClientTesting.Addr1, BluetoothService.Empty, ClientTesting.Port5);
            var ar     = cli.BeginConnect(remote, null, null);

            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            ClientTesting.Assert_IsConnected(
                ClientTesting.IsConnectedState.Closed,
                conn, cli, "after");
            Assert.IsFalse(ar.IsCompleted, "ar.IsCompleted after");
            //
            Expect.Once.On(stuff.MockedApi).Method("SPP_Close_Port")
            .With(stuff.StackId, conn.Testing_GetPortId())
            .Will(Return.Value(BluetopiaError.OK));
            cli.Dispose();
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
        public void DeviceNameErrorOnQuery_NoCallback_DoesntRefresh()
        {
            var addr       = BluetoothAddress.Parse("001122334455");
            var addrBytes8 = addr.ToByteArray();
            var addrBytes  = new byte[6];

            Array.Copy(addrBytes8, 0, addrBytes, 0, addrBytes.Length); // To-Do what endianism?
            //
            var stuff = new StuffStackBluetopia();

            BluetopiaTesting.InitMockery(stuff, 2);
            //
            var bdi = stuff.GetFactory().DoGetBluetoothDeviceInfo(
                (BluetoothAddress)addr.Clone());

            //
            Assert.AreEqual(addr, bdi.DeviceAddress, "DeviceAddress");
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            ExpectQueryRemoteName(stuff, addr, BluetopiaError.OK);
            Assert.AreEqual(addr.ToString("C"), bdi.DeviceName, "DeviceName");
            //
            // When we get an error we set the name to the address and DO NOT
            // call GAP_Query_Remote_Device_Name again.
            Assert.AreEqual(addr.ToString("C"), bdi.DeviceName, "DeviceName");
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
        public void DeviceNameErrorOnQuery_NOCALLBACK_DoRefresh()
        {
            var addr = BluetoothAddress.Parse("001122334455");
            //
            var stuff = new StuffStackBluetopia();

            BluetopiaTesting.InitMockery(stuff, 2);
            //
            var bdi = stuff.GetFactory().DoGetBluetoothDeviceInfo((BluetoothAddress)addr.Clone());

            //
            Assert.AreEqual(addr, bdi.DeviceAddress, "DeviceAddress");
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            ExpectQueryRemoteName(stuff, addr, BluetopiaError.OK);
            Assert.AreEqual(addr.ToString("C"), bdi.DeviceName, "DeviceName");
            //
            // When we get an error we set the name to the address and DO NOT
            // call GAP_Query_Remote_Device_Name again.
            // Unless we hit Refresh....
            bdi.Refresh();
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            // TO-DO This fails because the previous lookup is still pending
            // (no callback occurred) so we don't start another query!)
            ExpectQueryRemoteName(stuff, addr, BluetopiaError.OK);
            Assert.AreEqual(addr.ToString("C"), bdi.DeviceName, "DeviceName");
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
        // TODO (Mockery_VerifyAllExpectationsHaveBeenMet();
        // TODO (Uuid16).

        internal static StuffSdpQueryBluetopia Create_BluetopiaSdpQuery()
        {
            var stuff = new StuffSdpQueryBluetopia();

            BluetopiaTesting.InitMockery(stuff, 205);
            //
            stuff.SetDut(new BluetopiaSdpQuery(stuff.GetFactory()));
            return(stuff);
        }
示例#7
0
 public BluetopiaFactory GetFactory(IBluetopiaSecurity optionalSecurityInstance)
 {
     if (_fcty == null)
     {
         _fcty = new BluetopiaFactory(this.MockedApi, optionalSecurityInstance);
     }
     BluetopiaTesting.HackAllowShutdownCall(this.MockedApi);
     return(_fcty);
 }
示例#8
0
        static StuffRadio Create_Radio_A(Params p)
        {
            var stuff = new StuffRadio();
            //.
            const uint StackId         = 1;
            var        addrBytes       = new byte[] { 0xA4, 0x24, 0x4C, 0x98, 0x24, 0x08 };
            var        ExpectedAddress = BluetoothAddress.Parse("08:24:98:4C:24:A4");
            var        nameBytes       = new byte[] { (byte)'A', (byte)'b', (byte)'c', 0 };
            var        ExpectedName    = "Abc";
            var        codStruct       = (uint)0x20104;
            var        ExpectedCod     = new ClassOfDevice(0x20104);

            //
            BluetopiaTesting.InitMockery(stuff, StackId);
            Expect.Once.On(stuff.MockedApi).Method("GAP_Query_Local_BD_ADDR")
            .With(StackId, new byte[6])
            .Will(
                FillArrayIndexedParameterAction.Fill(1, addrBytes, true),
                Return.Value(BluetopiaError.OK));
            Expect.Once.On(stuff.MockedApi).Method("GAP_Query_Local_Device_Name")
            .With(StackId, 248, new byte[248])
            .Will(
                FillArrayIndexedParameterAction.Fill(2, nameBytes, false),
                Return.Value(BluetopiaError.OK));
            Expect.Once.On(stuff.MockedApi).Method("GAP_Query_Class_Of_Device")
            .With(StackId, Is.Out)
            .Will(
                new SetIndexedParameterAction(1, codStruct),
                Return.Value(BluetopiaError.OK));
            if (p.AccessesVersionsOrManufacturer)
            {
                Expect.Once.On(stuff.MockedApi).Method("HCI_Read_Local_Version_Information")
                .With(StackId,
                      Is.Out, Is.Out, Is.Out, Is.Out, Is.Out, Is.Out)
                .Will(
                    new SetIndexedParameterAction(1, (StackConsts.HCI_ERROR_CODE) 0),
                    new SetIndexedParameterAction(2, (HciVersion)0),
                    new SetIndexedParameterAction(3, (UInt16)0),
                    new SetIndexedParameterAction(4, (LmpVersion)0),
                    new SetIndexedParameterAction(5, Manufacturer.Zeevo),
                    new SetIndexedParameterAction(6, (UInt16)0),
                    Return.Value(BluetopiaError.OK));
            }
            //--
            BluetopiaTesting.HackAllowShutdownCall(stuff.MockedApi);
            BluetopiaFactory fcty = new BluetopiaFactory(stuff.MockedApi);
            IBluetoothRadio  r    = stuff.Radio = fcty.DoGetPrimaryRadio();

            Assert.AreEqual(Manufacturer.StonestreetOne, r.SoftwareManufacturer, "SoftwareManufacturer");
            Assert.AreEqual(ExpectedAddress, r.LocalAddress, "LocalAddress");
            Assert.AreEqual(ExpectedName, r.Name, "Name");
            Assert.AreEqual(ExpectedCod, r.ClassOfDevice, "ClassOfDevice");
            //
            return(stuff);
        }
示例#9
0
        //[Obsolete]
        //internal static StuffClient Open(bool toPortNumber,
        //    bool endConnectSuccess, int? socketError,
        //    StackConsts.SPP_OPEN_PORT_STATUS connConfStatusCode)
        //{
        //    return Open(new Behaviour
        //    {
        //        //toPortNumber = toPortNumber,
        //        EndConnectSuccess = endConnectSuccess,
        //        SocketError = socketError,
        //        ConnConfStatusCode = connConfStatusCode,
        //    });
        //}

        internal static StuffClientBluetopia CreateClient(Behaviour behaviour)
        {
            var stuff = BluetopiaTesting.InitMockery_Client(behaviour);
            //
            var cli  = stuff.CreateBluetoothClient();
            var cli2 = (BluetopiaClient)cli;
            var conn = (BluetopiaRfcommStream)cli2.Testing_GetConn();

            stuff.SetDut(cli, conn);
            return(stuff);
        }
示例#10
0
        void DoTest_HackOneSeqDeep(StackConsts.SDP_Data_Element_Type expectedET,
                                   byte[] expectedDataValue,
                                   ServiceElement element)
        {
            var r = new ServiceRecord(new ServiceAttribute(0xF234,
                                                           element));

            //==
            r = BluetopiaTesting.HackAddSvcClassList(r);
            //==
            DoTest_HackOneSeqDeep(expectedET, expectedDataValue, r);
        }
示例#11
0
        internal static StuffClientBluetopia InitMockery_Client(ClientTestingBluetopia.Behaviour behaviour)
        {
            StuffClientBluetopia stuff = new StuffClientBluetopia();

            stuff.Behaviour = behaviour;
            BluetopiaTesting.InitMockery(stuff, 10);
            if (stuff.Behaviour.MockIBtSecurity)
            {
                stuff.CreateMockedSecurityApi();
            }
            stuff.GetFactory();
            return(stuff);
        }
示例#12
0
        public void CallingTwice()
        {
            // Haven't decided whether to keep the instance to hold one
            // live record or like the base to create multiple records,
            // probably the first.
            //
            var stuff = BluetopiaTesting.InitMockery_SdpCreator();

            try {
                stuff.DutSdpCreator.CreateServiceRecord(BluetopiaTesting.HackAddSvcClassList(new ServiceRecord()));
                stuff.DutSdpCreator.CreateServiceRecord(BluetopiaTesting.HackAddSvcClassList(new ServiceRecord()));
            } finally {
                VerifyDispose(stuff);
            }
        }
        public void One()
        {
            var addr = BluetoothAddress.Parse("001122334455");
            //
            var stuff = new StuffStackBluetopia();

            BluetopiaTesting.InitMockery(stuff, 2);
            //
            var bdi = stuff.GetFactory().DoGetBluetoothDeviceInfo(
                (BluetoothAddress)addr.Clone());

            //
            Assert.AreEqual(addr, bdi.DeviceAddress, "DeviceAddress");
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            ExpectQueryRemoteName(stuff, addr, BluetopiaError.OK);
            Assert.AreEqual(addr.ToString("C"), bdi.DeviceName, "DeviceName");
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
示例#14
0
        //[Explicit("Causes Debug.Assert")]
        public void InitZeroHandle()
        {
            const uint BadZeroStackId = 0;
            var        mocks          = new Mockery();
            var        api            = mocks.NewMock <IBluetopiaApi>();

            Expect.Exactly(2).On(api).Method("BSC_Initialize")
            .WithAnyArguments()      // TO-DO
            .Will(Return.Value((int)BadZeroStackId));
            //----
            try {
                BluetopiaTesting.HackAllowShutdownCall(api);
                BluetopiaFactory fcty = new BluetopiaFactory(api);
                Assert.Fail("should have thrown!");
            } catch (BluetopiaSocketException ex) {
                Assert.AreEqual((int)BluetopiaError.OK, ex.BluetopiaErrorCode, "BluetopiaErrorCode");
                Assert.AreEqual(BluetopiaError.OK.ToString(), ex.BluetopiaError, "BluetopiaError");
            }
            //
            mocks.VerifyAllExpectationsHaveBeenMet();
        }
        public void NoAccessToDeviceName()
        {
            var addr = BluetoothAddress.Parse("001122334455");
            //
            var stuff = new StuffStackBluetopia();

            BluetopiaTesting.InitMockery(stuff, 2);
            //
            var bdi = stuff.GetFactory().DoGetBluetoothDeviceInfo(
                (BluetoothAddress)addr.Clone());

            //
            Assert.AreEqual(addr, bdi.DeviceAddress, "DeviceAddress");
            Assert.IsFalse(bdi.Remembered, "Remembered");
            Assert.IsFalse(bdi.Authenticated, "Authenticated");
            Assert.IsFalse(bdi.Connected, "Connected");
            Assert.AreEqual(new ClassOfDevice(0), bdi.ClassOfDevice, "ClassOfDevice");
            Assert.AreEqual(DateTime.MinValue, bdi.LastSeen, "LastSeen");
            Assert.AreEqual(DateTime.MinValue, bdi.LastUsed, "LastUsed");
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
        // The tests are included in the base class.
        protected override void DoTest(byte[] expectedRecordBytes, ServiceRecord record)
        {
            byte[] buf   = new byte[1024];
            var    stuff = BluetopiaTesting.InitMockery_SdpCreator();

            //
            if (expectedRecordBytes == Data_SdpCreator_SingleElementTests.RecordBytes_Empty)
            {
                Debug.Assert(!resultMap.ContainsKey(expectedRecordBytes), "manually handled!");
            }
            else
            {
                // All other expected results are in the mapping table.
                // Next can throw KeyNotFoundException.
                SdpServiceExpectedCall expected = resultMap[expectedRecordBytes];
                Expect.Once.On(stuff.MockApi2).Method("SDP_Add_Attribute")
                .With(
                    Is.Anything,
                    Is.Anything,
                    expected.attrId,
                    expected.element
                    )
                .Will(Return.Value(BluetopiaError.OK));
            }
            //==
            record = BluetopiaTesting.HackAddSvcClassList(record);
            //==
            stuff.DutSdpCreator.CreateServiceRecord(record);
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            //
            Expect.Once.On(stuff.MockApi2).Method("SDP_Delete_Service_Record")
            .With(
                Is.Anything,
                Is.Anything)
            .Will(Return.Value(BluetopiaError.OK));
            stuff.DutSdpCreator.Dispose();
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
示例#17
0
        public void Properties()
        {
            var stuff = BluetopiaTesting.InitMockery_Client(new ClientTestingBluetopia.Behaviour());
            var cli   = stuff.CreateBluetoothClient();

            //
            //Assert.IsFalse(cli.Authenticate, "Authenticate");
            //try {
            //    cli.Authenticate = true;
            //    Assert.Fail("should have thrown!");
            //} catch (NotSupportedException) { }
            ////
            //Assert.IsFalse(cli.Encrypt, "Encrypt");
            //try {
            //    cli.Encrypt = true;
            //    Assert.Fail("should have thrown!");
            //} catch (NotSupportedException) { }
            //
            try {
                var s = cli.Client;
                Assert.Fail("should have thrown!");
            } catch (NotSupportedException) { }
            var sock = new System.Net.Sockets.Socket(
                System.Net.Sockets.AddressFamily.InterNetwork,
                System.Net.Sockets.SocketType.Stream,
                System.Net.Sockets.ProtocolType.Unspecified);

            try {
                cli.Client = sock;
                Assert.Fail("should have thrown!");
            } catch (NotSupportedException) {
            } finally {
                sock.Close();
            }
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
示例#18
0
        public void ErrorOnCallOpenRemotePort()
        {
            var stuff = BluetopiaTesting.InitMockery_Client(new ClientTestingBluetopia.Behaviour());

            //
            Expect.Once.On(stuff.MockedApi).Method("SPP_Open_Remote_Port")
            .WithAnyArguments()
            .Will(Return.Value((int)BluetopiaError.INTERNAL_ERROR));
            //
            var cli    = stuff.CreateBluetoothClient();
            var remote = new BluetoothEndPoint(ClientTesting.Addr1, BluetoothService.Empty, ClientTesting.Port5);

            try {
                var ar = cli.BeginConnect(remote, null, null);
                cli.EndConnect(ar); // NEW
                Assert.Fail("should have thrown!");
            } catch (BluetopiaSocketException) {
                // TODO SocketError check
            }
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
            //
            cli.Dispose();
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }
示例#19
0
        public void RecordA()
        {
            var stuff = BluetopiaTesting.InitMockery_SdpCreator();
            var bldr  = new ServiceRecordBuilder();

            bldr.AddServiceClass(BluetoothService.Wap);
            bldr.AddBluetoothProfileDescriptor(BluetoothService.WapClient, 0x1, 0x2);
            //
            Expect.AtLeastOnce.On(stuff.MockApi2).Method("SDP_Add_Attribute")
            .With(
                stuff.StackId, stuff.SrHandle,
                (ushort)UniversalAttributeId.ProtocolDescriptorList,
                //Is.Anything
                new Structs.SDP_Data_Element__Class_ElementArray(
                    StackConsts.SDP_Data_Element_Type.Sequence,
                    2,
                    new Structs.SDP_Data_Element__Class_ElementArray(
                        StackConsts.SDP_Data_Element_Type.Sequence,
                        1,
                        new Structs.SDP_Data_Element__Class_InlineByteArray(
                            StackConsts.SDP_Data_Element_Type.UUID_16,
                            2, new byte[] { 0x01, 0x00 }
                            )
                        ),
                    new Structs.SDP_Data_Element__Class_ElementArray(
                        StackConsts.SDP_Data_Element_Type.Sequence,
                        2,
                        new Structs.SDP_Data_Element__Class_InlineByteArray(
                            StackConsts.SDP_Data_Element_Type.UUID_16,
                            2, new byte[] { 0x00, 0x03 }
                            ),
                        new Structs.SDP_Data_Element__Class_InlineByteArray(
                            StackConsts.SDP_Data_Element_Type.UnsignedInteger1Byte,
                            1, new byte[] { 0 }
                            )
                        )
                    )
                )
            .Will(Return.Value(BluetopiaError.OK));
            Expect.AtLeastOnce.On(stuff.MockApi2).Method("SDP_Add_Attribute")
            .With(
                stuff.StackId, stuff.SrHandle,
                (ushort)UniversalAttributeId.BluetoothProfileDescriptorList,
                new Structs.SDP_Data_Element__Class_ElementArray(
                    StackConsts.SDP_Data_Element_Type.Sequence,
                    1,
                    new Structs.SDP_Data_Element__Class_ElementArray(
                        StackConsts.SDP_Data_Element_Type.Sequence,
                        2,
                        new Structs.SDP_Data_Element__Class_InlineByteArray(
                            StackConsts.SDP_Data_Element_Type.UUID_16,
                            2, new byte[] { 0x11, 0x14, }
                            ),
                        new Structs.SDP_Data_Element__Class_InlineByteArray(
                            StackConsts.SDP_Data_Element_Type.UnsignedInteger2Bytes,
                            2, new byte[] { 0x02, 0x01, }    //endian!
                            )
                        )
                    )
                )
            .Will(Return.Value(BluetopiaError.OK));
            //
            stuff.DutSdpCreator.CreateServiceRecord(bldr.ServiceRecord);
            //--
            VerifyDispose(stuff);
        }
示例#20
0
        public void One()
        {
            var stuff = BluetopiaTesting.InitMockery_Client(new ClientTestingBluetopia.Behaviour());
            //
            const uint NullPeriodLengths = 0;
            const uint InquiryLen        = 12;
            const uint CallbackParameter = 0;
            const uint MaximumResponses  = 255;
            var        callback          = stuff.GetFactory()._inquiryEventCallback;

            Expect.Once.On(stuff.MockedApi).Method("GAP_Perform_Inquiry")
            .With(stuff.StackId, StackConsts.GAP_Inquiry_Type.GeneralInquiry,
                  NullPeriodLengths, NullPeriodLengths,
                  InquiryLen, MaximumResponses,
                  callback, CallbackParameter)
            .Will(Return.Value(BluetopiaError.OK));
            //
            IBluetoothClient cli = stuff.CreateBluetoothClient();
            var ar = cli.BeginDiscoverDevices(255, false, false, false, true, null, null);

            Assert.IsFalse(ar.IsCompleted, "IsCompleted 0");
            //
            IntPtr pItemData     = IntPtr.Zero;
            IntPtr pCompleteData = IntPtr.Zero;

            try {
                Structs.GAP_Inquiry_Entry_Event_Data itemData = new Structs.GAP_Inquiry_Entry_Event_Data(
                    Addr1Bytes,
                    new byte[] { 0x03, 0x02, 0x01 }
                    );
                pItemData = Marshal.AllocHGlobal(Marshal.SizeOf(itemData));
                Marshal.StructureToPtr(itemData, pItemData, false);
                Structs.GAP_Event_Data item1 = new Structs.GAP_Event_Data(
                    StackConsts.GAP_Event_Type.Inquiry_Entry_Result,
                    pItemData);
                //
                const ushort NumDevices = 1;
                Structs.GAP_Inquiry_Event_Data completeData = new Structs.GAP_Inquiry_Event_Data(
                    NumDevices /*, pCompleteDeviceData*/);
                pCompleteData = Marshal.AllocHGlobal(Marshal.SizeOf(completeData));
                Marshal.StructureToPtr(completeData, pCompleteData, false);
                Structs.GAP_Event_Data complete = new Structs.GAP_Event_Data(
                    StackConsts.GAP_Event_Type.Inquiry_Result,
                    pCompleteData);
                //
                //
                using (var done = new ManualResetEvent(false)) {
                    ThreadPool.QueueUserWorkItem(delegate {
                        try {
                            callback(stuff.StackId, ref item1, CallbackParameter);
                            callback(stuff.StackId, ref complete, CallbackParameter);
                        } finally {
                            done.Set();
                        }
                    });
                    bool signalled = done.WaitOne(30000);
                    Debug.Assert(signalled, "NOT signalled");
                }
            } finally {
                if (pItemData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pItemData);
                }
                if (pCompleteData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pCompleteData);
                }
            }
            //
            Thread.Sleep(200);
            Assert.IsFalse(ar.IsCompleted, "notIsCompleted2 before rnr");
            Thread.Sleep(2500); // Space for (possible!) name queries
            Thread.Sleep(200);
            Assert.IsTrue(ar.IsCompleted, "IsCompleted3");
            var deviceList = cli.EndDiscoverDevices(ar);

            Assert.AreEqual(1, deviceList.Length, "deviceList.Length");
            var dev = deviceList[0];

            Assert.AreEqual(BluetoothAddress.Parse("001122334455"), dev.DeviceAddress, "dev.DeviceAddress");
            Assert.AreEqual(new ClassOfDevice(0x010203), dev.ClassOfDevice, "dev.ClassOfDevice");
            //
            stuff.Mockery_VerifyAllExpectationsHaveBeenMet();
        }