diff options
author | Sven Gothel <[email protected]> | 2022-05-07 01:38:59 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2022-05-07 01:38:59 +0200 |
commit | 5544b00ee8f8560618aac8edb9ffa830fc294d97 (patch) | |
tree | 98c8ac179939f8ff5098ae6c3dee90e1a884e529 /trial/direct_bt | |
parent | 662486318a7509f2d610dbbcb39f1073d8b413c1 (diff) |
trial i470 test_provoke (C++) / TestDBTProvoke (Java) demonstrating C++ survives while Java crashes (known issue)
Diffstat (limited to 'trial/direct_bt')
-rw-r--r-- | trial/direct_bt/dbt_client01.hpp | 166 | ||||
-rw-r--r-- | trial/direct_bt/dbt_client_server1x.hpp | 160 | ||||
-rw-r--r-- | trial/direct_bt/dbt_server01.hpp | 34 | ||||
-rw-r--r-- | trial/direct_bt/test_provoke_client_server_i470.cpp | 53 |
4 files changed, 222 insertions, 191 deletions
diff --git a/trial/direct_bt/dbt_client01.hpp b/trial/direct_bt/dbt_client01.hpp index 8d8c78db..2f86976d 100644 --- a/trial/direct_bt/dbt_client01.hpp +++ b/trial/direct_bt/dbt_client01.hpp @@ -67,17 +67,16 @@ class DBTClient01 : public DBTClientTest { jau::sc_atomic_int disconnectCount = 0; jau::sc_atomic_int notificationsReceived = 0; jau::sc_atomic_int indicationsReceived = 0; - jau::sc_atomic_int completedGATTCommands = 0; jau::sc_atomic_int completedMeasurementsTotal = 0; jau::sc_atomic_int completedMeasurementsSuccess = 0; jau::sc_atomic_int measurementsLeft = 0; + bool do_disconnect = false; + private: const uint64_t timestamp_t0 = getCurrentMilliseconds(); // const fraction_i64 timestamp_t0 = jau::getMonotonicMicroseconds(); - const uint8_t cmd_arg = 0x44; - class MyAdapterStatusListener : public AdapterStatusListener { public: DBTClient01& parent; @@ -197,6 +196,19 @@ class DBTClient01 : public DBTClientTest { } } + void disconnectDevice(BTDeviceRef device) { + // sleep range: 100 - 1500 ms + // sleep range: 100 - 1500 ms + static const int sleep_min = 100; + static const int sleep_max = 1500; + static std::random_device rng_hw;; + static std::uniform_int_distribution<int> rng_dist(sleep_min, sleep_max); + const int64_t sleep_dur = rng_dist(rng_hw); + jau::sleep_for( sleep_dur * 1_ms ); + fprintf_td(stderr, "****** Client i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, device->toString().c_str()); + device->disconnect(); + } + void deviceReady(BTDeviceRef device, const uint64_t timestamp) override { (void)timestamp; { @@ -207,6 +219,11 @@ class DBTClient01 : public DBTClientTest { std::thread dc(&DBTClient01::processReadyDevice, &parent, device); dc.detach(); // processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution! + + if( parent.do_disconnect ) { + std::thread disconnectThread(&MyAdapterStatusListener::disconnectDevice, this, device); + disconnectThread.detach(); + } } } @@ -272,10 +289,11 @@ class DBTClient01 : public DBTClientTest { std::shared_ptr<AdapterStatusListener> myAdapterStatusListener = std::make_shared<MyAdapterStatusListener>(*this); public: - DBTClient01(const std::string& adapterName_, const EUI48 useAdapter_, const BTMode btMode_) { + DBTClient01(const std::string& adapterName_, const EUI48 useAdapter_, const BTMode btMode_, const bool do_disconnect_) { this->adapterName = adapterName_; this->useAdapter = useAdapter_; this->btMode = btMode_; + this->do_disconnect = do_disconnect_; } std::string getName() override { return adapterName; } @@ -314,7 +332,6 @@ class DBTClient01 : public DBTClientTest { private: void resetLastProcessingStats() { - completedGATTCommands = 0; notificationsReceived = 0; indicationsReceived = 0; } @@ -421,97 +438,63 @@ class DBTClient01 : public DBTClientTest { td13, td12, td23, td35); } - { - BTGattCmd cmd = BTGattCmd(*device, "TestCmd", DBTConstants::CommandUUID, DBTConstants::ResponseUUID, 256); - cmd.setVerbose(true); - const bool cmd_resolved = cmd.isResolved(); - fprintf_td(stderr, "Command test: %s, resolved %d\n", cmd.toString().c_str(), cmd_resolved); - POctets cmd_data(1, endian::little); - cmd_data.put_uint8_nc(0, cmd_arg); - const HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3_s); - if( HCIStatusCode::SUCCESS == cmd_res ) { - const jau::TROOctets& resp = cmd.getResponse(); - if( 1 == resp.size() && resp.get_uint8_nc(0) == cmd_arg ) { - fprintf_td(stderr, "Client Success: %s -> %s (echo response)\n", cmd.toString().c_str(), resp.toString().c_str()); - completedGATTCommands++; - } else { - fprintf_td(stderr, "Client Failure: %s -> %s (different response)\n", cmd.toString().c_str(), resp.toString().c_str()); - } - } else { - fprintf_td(stderr, "Client Failure: %s -> %s\n", cmd.toString().c_str(), to_string(cmd_res).c_str()); - } - // cmd.close(); // done via dtor - } - - for(size_t i=0; i<primServices.size(); i++) { - BTGattService & primService = *primServices.at(i); - if( GATT_VERBOSE ) { - fprintf_td(stderr, " [%2.2d] Service UUID %s (%s)\n", i, - primService.type->toUUID128String().c_str(), - primService.type->getTypeSizeString().c_str()); - fprintf_td(stderr, " [%2.2d] %s\n", i, primService.toString().c_str()); - } - jau::darray<BTGattCharRef> & serviceCharacteristics = primService.characteristicList; - for(size_t j=0; j<serviceCharacteristics.size(); j++) { - BTGattCharRef & serviceChar = serviceCharacteristics.at(j); + do { + for(size_t i=0; i<primServices.size(); i++) { + BTGattService & primService = *primServices.at(i); if( GATT_VERBOSE ) { - fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic: UUID %s (%s)\n", i, j, - serviceChar->value_type->toUUID128String().c_str(), - serviceChar->value_type->getTypeSizeString().c_str()); - fprintf_td(stderr, " [%2.2d.%2.2d] %s\n", i, j, serviceChar->toString().c_str()); + fprintf_td(stderr, " [%2.2d] Service UUID %s (%s)\n", i, + primService.type->toUUID128String().c_str(), + primService.type->getTypeSizeString().c_str()); + fprintf_td(stderr, " [%2.2d] %s\n", i, primService.toString().c_str()); } - if( serviceChar->hasProperties(BTGattChar::PropertyBitVal::Read) ) { - POctets value(BTGattHandler::number(BTGattHandler::Defaults::MAX_ATT_MTU), 0, jau::endian::little); - if( serviceChar->readValue(value) ) { - std::string sval = dfa_utf8_decode(value.get_ptr(), value.size()); + jau::darray<BTGattCharRef> & serviceCharacteristics = primService.characteristicList; + for(size_t j=0; j<serviceCharacteristics.size(); j++) { + BTGattCharRef & serviceChar = serviceCharacteristics.at(j); + if( GATT_VERBOSE ) { + fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic: UUID %s (%s)\n", i, j, + serviceChar->value_type->toUUID128String().c_str(), + serviceChar->value_type->getTypeSizeString().c_str()); + fprintf_td(stderr, " [%2.2d.%2.2d] %s\n", i, j, serviceChar->toString().c_str()); + } + if( serviceChar->hasProperties(BTGattChar::PropertyBitVal::Read) ) { + POctets value(BTGattHandler::number(BTGattHandler::Defaults::MAX_ATT_MTU), 0, jau::endian::little); + if( serviceChar->readValue(value) ) { + std::string sval = dfa_utf8_decode(value.get_ptr(), value.size()); + if( GATT_VERBOSE ) { + fprintf_td(stderr, " [%2.2d.%2.2d] value: %s ('%s')\n", (int)i, (int)j, value.toString().c_str(), sval.c_str()); + } + } + } + jau::darray<BTGattDescRef> & charDescList = serviceChar->descriptorList; + for(size_t k=0; k<charDescList.size(); k++) { + BTGattDesc & charDesc = *charDescList.at(k); if( GATT_VERBOSE ) { - fprintf_td(stderr, " [%2.2d.%2.2d] value: %s ('%s')\n", (int)i, (int)j, value.toString().c_str(), sval.c_str()); + fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] Descriptor: UUID %s (%s)\n", i, j, k, + charDesc.type->toUUID128String().c_str(), + charDesc.type->getTypeSizeString().c_str()); + fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] %s\n", i, j, k, charDesc.toString().c_str()); } } - } - jau::darray<BTGattDescRef> & charDescList = serviceChar->descriptorList; - for(size_t k=0; k<charDescList.size(); k++) { - BTGattDesc & charDesc = *charDescList.at(k); - if( GATT_VERBOSE ) { - fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] Descriptor: UUID %s (%s)\n", i, j, k, - charDesc.type->toUUID128String().c_str(), - charDesc.type->getTypeSizeString().c_str()); - fprintf_td(stderr, " [%2.2d.%2.2d.%2.2d] %s\n", i, j, k, charDesc.toString().c_str()); + bool cccdEnableResult[2]; + if( serviceChar->enableNotificationOrIndication( cccdEnableResult ) ) { + // ClientCharConfigDescriptor (CCD) is available + std::shared_ptr<BTGattChar::Listener> cl = std::make_shared<MyGATTEventListener>(*this, i, j); + bool clAdded = serviceChar->addCharListener( cl ); + if( GATT_VERBOSE ) { + fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic-Listener: Notification(%d), Indication(%d): Added %d\n", + (int)i, (int)j, cccdEnableResult[0], cccdEnableResult[1], clAdded); + fprintf_td(stderr, "\n"); + } } } - bool cccdEnableResult[2]; - if( serviceChar->enableNotificationOrIndication( cccdEnableResult ) ) { - // ClientCharConfigDescriptor (CCD) is available - std::shared_ptr<BTGattChar::Listener> cl = std::make_shared<MyGATTEventListener>(*this, i, j); - bool clAdded = serviceChar->addCharListener( cl ); - if( GATT_VERBOSE ) { - fprintf_td(stderr, " [%2.2d.%2.2d] Characteristic-Listener: Notification(%d), Indication(%d): Added %d\n", - (int)i, (int)j, cccdEnableResult[0], cccdEnableResult[1], clAdded); - fprintf_td(stderr, "\n"); - } + if( GATT_VERBOSE ) { + fprintf_td(stderr, "\n"); } } - if( GATT_VERBOSE ) { - fprintf_td(stderr, "\n"); - } - } + success = notificationsReceived >= 2 || indicationsReceived >= 2; + } while( !success && device->getConnected() ); - { - const fraction_timespec t0 = getMonotonicTime(); - bool timeout = false; - do { - success = completedGATTCommands >= 1 && ( notificationsReceived >= 2 || indicationsReceived >= 2 ); - if( !success ) { - const fraction_i64 td = ( getMonotonicTime() - t0 ).to_fraction_i64(); - timeout = 3_s < td; - if( !timeout ) { - jau::sleep_for( 17_ms ); - } - } - } while( !success && !timeout ); - } - - { + if( device->getConnected() ) { // Tell server we have successfully completed the test. BTGattCmd cmd = BTGattCmd(*device, "FinalHandshake", DBTConstants::CommandUUID, DBTConstants::ResponseUUID, 256); cmd.setVerbose(true); @@ -568,16 +551,15 @@ class DBTClient01 : public DBTClientTest { completedMeasurementsTotal++; if( success ) { completedMeasurementsSuccess++; - } - if( 0 < measurementsLeft ) { - measurementsLeft--; + if( 0 < measurementsLeft ) { + measurementsLeft--; + } } fprintf_td(stderr, "****** Client Processing Ready Device: Success %d; Measurements completed %d" - ", left %d; Received notitifications %d, indications %d" - "; Completed GATT commands %d: %s\n", + ", left %d; Received notitifications %d, indications %d: %s\n", success, completedMeasurementsSuccess.load(), measurementsLeft.load(), notificationsReceived.load(), indicationsReceived.load(), - completedGATTCommands.load(), device->getAddressAndType().toString().c_str()); + device->getAddressAndType().toString().c_str()); } void removeDevice(BTDeviceRef device) { diff --git a/trial/direct_bt/dbt_client_server1x.hpp b/trial/direct_bt/dbt_client_server1x.hpp index 4ed2a0cc..9952042a 100644 --- a/trial/direct_bt/dbt_client_server1x.hpp +++ b/trial/direct_bt/dbt_client_server1x.hpp @@ -46,6 +46,9 @@ using namespace direct_bt; */ class DBTClientServer1x { private: + // timeout check: timeout_value < test_duration + timeout_preempt_diff; // let's timeout here before our timeout timer + static constexpr const fraction_i64 timeout_preempt_diff = 500_ms; + std::mutex mtx_sync; BTDeviceRef lastCompletedDevice = nullptr; PairingMode lastCompletedDevicePairingMode = PairingMode::NONE; @@ -59,12 +62,16 @@ class DBTClientServer1x { { std::shared_ptr<DBTServer00> server = std::make_shared<DBTServer00>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer); std::shared_ptr<DBTClient00> client = std::make_shared<DBTClient00>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL); - test8x_fullCycle(suffix, protocolSessionCount, server_client_order, + test8x_fullCycle(suffix, + protocolSessionCount, DBTConstants::max_connections_per_session, true /* expSuccess */, + server_client_order, server, secLevelServer, serverExpPairing, client, secLevelClient, clientExpPairing); } - void test8x_fullCycle(const std::string& suffix, const int protocolSessionCount, const bool server_client_order, + void test8x_fullCycle(const std::string& suffix, + const int protocolSessionCount, const int max_connections_per_session, const bool expSuccess, + const bool server_client_order, std::shared_ptr<DBTServerTest> server, const BTSecurityLevel secLevelServer, const ExpectedPairing serverExpPairing, std::shared_ptr<DBTClientTest> client, const BTSecurityLevel secLevelClient, const ExpectedPairing clientExpPairing) { @@ -155,9 +162,9 @@ class DBTClientServer1x { nullptr == lastCompletedDevice || lastCompletedDevice->getConnected() ); } - max_connections_hit = ( protocolSessionCount * DBTConstants::max_connections_per_session ) <= server->getDisconnectCount(); + max_connections_hit = ( protocolSessionCount * max_connections_per_session ) <= server->getDisconnectCount(); test_duration = ( jau::getMonotonicTime() - t0 ).to_fraction_i64(); - timeout = 0_s < timeout_value && timeout_value <= test_duration + 500_ms; // let's timeout here before our timeout timer + timeout = 0_s < timeout_value && timeout_value <= test_duration + timeout_preempt_diff; // let's timeout here before our timeout timer if( !done && !max_connections_hit && !timeout ) { jau::sleep_for( 88_ms ); } @@ -169,100 +176,105 @@ class DBTClientServer1x { test_duration.to_ms(), timeout, timeout_value.to_string(true).c_str(), max_connections_hit); fprintf_td(stderr, " Server ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n", server->getProtocolSessionsDoneSuccess(), server->getProtocolSessionsDoneTotal(), protocolSessionCount, - server->getDisconnectCount(), ( protocolSessionCount * DBTConstants::max_connections_per_session )); + server->getDisconnectCount(), ( protocolSessionCount * max_connections_per_session )); fprintf_td(stderr, " Client ProtocolSessions[success %d/%d total, requested %d], disconnects %d of %d max\n", client->getProtocolSessionsDoneSuccess(), client->getProtocolSessionsDoneTotal(), protocolSessionCount, - client->getDisconnectCount(), ( protocolSessionCount * DBTConstants::max_connections_per_session )); + client->getDisconnectCount(), ( protocolSessionCount * max_connections_per_session )); fprintf_td(stderr, "\n\n"); - REQUIRE( false == max_connections_hit ); - REQUIRE( false == timeout ); - { - const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor - REQUIRE( protocolSessionCount <= server->getProtocolSessionsDoneTotal() ); - REQUIRE( protocolSessionCount == server->getProtocolSessionsDoneSuccess() ); - REQUIRE( protocolSessionCount <= client->getProtocolSessionsDoneTotal() ); - REQUIRE( protocolSessionCount == client->getProtocolSessionsDoneSuccess() ); - REQUIRE( nullptr != lastCompletedDevice ); - REQUIRE( EIRDataType::NONE != lastCompletedDeviceEIR.getEIRDataMask() ); - REQUIRE( false == lastCompletedDevice->getConnected() ); - REQUIRE( ( protocolSessionCount * DBTConstants::max_connections_per_session ) > server->getDisconnectCount() ); + if( expSuccess ) { + REQUIRE( false == max_connections_hit ); + REQUIRE( false == timeout ); + { + const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor + REQUIRE( protocolSessionCount <= server->getProtocolSessionsDoneTotal() ); + REQUIRE( protocolSessionCount == server->getProtocolSessionsDoneSuccess() ); + REQUIRE( protocolSessionCount <= client->getProtocolSessionsDoneTotal() ); + REQUIRE( protocolSessionCount == client->getProtocolSessionsDoneSuccess() ); + REQUIRE( nullptr != lastCompletedDevice ); + REQUIRE( EIRDataType::NONE != lastCompletedDeviceEIR.getEIRDataMask() ); + REQUIRE( false == lastCompletedDevice->getConnected() ); + REQUIRE( ( protocolSessionCount * max_connections_per_session ) > server->getDisconnectCount() ); + } } // // Client stop // - DBTClientTest::stopDiscovery(client, true /* current_exp_discovering_state */, "test"+suffix+"_stopDiscovery"); + const bool current_exp_discovering_state = expSuccess ? true : client->getAdapter()->isDiscovering(); + DBTClientTest::stopDiscovery(client, current_exp_discovering_state, "test"+suffix+"_stopDiscovery"); client->close("test"+suffix+"_close"); // // Server stop // - DBTServerTest::stop(server, false /* current_exp_advertising_state */, "test"+suffix+"_stopAdvertising"); + const bool current_exp_advertising_state = expSuccess ? false : server->getAdapter()->isAdvertising(); + DBTServerTest::stop(server, current_exp_advertising_state, "test"+suffix+"_stopAdvertising"); server->close("test"+suffix+"_close"); - // - // Validating Security Mode - // - SMPKeyBin clientKeys = SMPKeyBin::read(DBTConstants::CLIENT_KEY_PATH, *lastCompletedDevice, true /* verbose */); - REQUIRE( true == clientKeys.isValid() ); - const BTSecurityLevel clientKeysSecLevel = clientKeys.getSecLevel(); - REQUIRE( secLevelClient == clientKeysSecLevel); - { - if( ExpectedPairing::PREPAIRED == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { - // Using encryption: pre-paired - REQUIRE( PairingMode::PRE_PAIRED == lastCompletedDevicePairingMode ); - REQUIRE( BTSecurityLevel::ENC_ONLY == lastCompletedDeviceSecurityLevel ); // pre-paired fixed level, no auth - } else if( ExpectedPairing::NEW_PAIRING == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { - // Using encryption: Newly paired - REQUIRE( PairingMode::PRE_PAIRED != lastCompletedDevicePairingMode ); - REQUIRE_MSG( "PairingMode client "+to_string(lastCompletedDevicePairingMode)+" not > NONE", PairingMode::NONE < lastCompletedDevicePairingMode ); - REQUIRE_MSG( "SecurityLevel client "+to_string(lastCompletedDeviceSecurityLevel)+" not >= "+to_string(secLevelClient), secLevelClient <= lastCompletedDeviceSecurityLevel ); - } else if( ExpectedPairing::DONT_CARE == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { - // Any encryption, any pairing - REQUIRE_MSG( "PairingMode client "+to_string(lastCompletedDevicePairingMode)+" not > NONE", PairingMode::NONE < lastCompletedDevicePairingMode ); - REQUIRE_MSG( "SecurityLevel client "+to_string(lastCompletedDeviceSecurityLevel)+" not >= "+to_string(secLevelClient), secLevelClient <= lastCompletedDeviceSecurityLevel ); - } else { - // No encryption: No pairing - REQUIRE( PairingMode::NONE == lastCompletedDevicePairingMode ); - REQUIRE( BTSecurityLevel::NONE == lastCompletedDeviceSecurityLevel ); + if( expSuccess ) { + // + // Validating Security Mode + // + SMPKeyBin clientKeys = SMPKeyBin::read(DBTConstants::CLIENT_KEY_PATH, *lastCompletedDevice, true /* verbose */); + REQUIRE( true == clientKeys.isValid() ); + const BTSecurityLevel clientKeysSecLevel = clientKeys.getSecLevel(); + REQUIRE( secLevelClient == clientKeysSecLevel); + { + if( ExpectedPairing::PREPAIRED == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { + // Using encryption: pre-paired + REQUIRE( PairingMode::PRE_PAIRED == lastCompletedDevicePairingMode ); + REQUIRE( BTSecurityLevel::ENC_ONLY == lastCompletedDeviceSecurityLevel ); // pre-paired fixed level, no auth + } else if( ExpectedPairing::NEW_PAIRING == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { + // Using encryption: Newly paired + REQUIRE( PairingMode::PRE_PAIRED != lastCompletedDevicePairingMode ); + REQUIRE_MSG( "PairingMode client "+to_string(lastCompletedDevicePairingMode)+" not > NONE", PairingMode::NONE < lastCompletedDevicePairingMode ); + REQUIRE_MSG( "SecurityLevel client "+to_string(lastCompletedDeviceSecurityLevel)+" not >= "+to_string(secLevelClient), secLevelClient <= lastCompletedDeviceSecurityLevel ); + } else if( ExpectedPairing::DONT_CARE == clientExpPairing && BTSecurityLevel::NONE < secLevelClient ) { + // Any encryption, any pairing + REQUIRE_MSG( "PairingMode client "+to_string(lastCompletedDevicePairingMode)+" not > NONE", PairingMode::NONE < lastCompletedDevicePairingMode ); + REQUIRE_MSG( "SecurityLevel client "+to_string(lastCompletedDeviceSecurityLevel)+" not >= "+to_string(secLevelClient), secLevelClient <= lastCompletedDeviceSecurityLevel ); + } else { + // No encryption: No pairing + REQUIRE( PairingMode::NONE == lastCompletedDevicePairingMode ); + REQUIRE( BTSecurityLevel::NONE == lastCompletedDeviceSecurityLevel ); + } } - } - // - // Validating EIR - // - { - const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor - fprintf_td(stderr, "lastCompletedDevice.connectedEIR: %s\n", lastCompletedDeviceEIR.toString().c_str()); - REQUIRE( EIRDataType::NONE != lastCompletedDeviceEIR.getEIRDataMask() ); - REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::FLAGS) ); - REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::SERVICE_UUID) ); - REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::NAME) ); - REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::CONN_IVAL) ); - REQUIRE( serverName == lastCompletedDeviceEIR.getName() ); + // + // Validating EIR + // { - const EInfoReport eir = *lastCompletedDevice->getEIR(); - fprintf_td(stderr, "lastCompletedDevice.currentEIR: %s\n", eir.toString().c_str()); - REQUIRE( EIRDataType::NONE == eir.getEIRDataMask() ); - REQUIRE( 0 == eir.getName().length()); + const std::lock_guard<std::mutex> lock(mtx_sync); // RAII-style acquire and relinquish via destructor + fprintf_td(stderr, "lastCompletedDevice.connectedEIR: %s\n", lastCompletedDeviceEIR.toString().c_str()); + REQUIRE( EIRDataType::NONE != lastCompletedDeviceEIR.getEIRDataMask() ); + REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::FLAGS) ); + REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::SERVICE_UUID) ); + REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::NAME) ); + REQUIRE( true == lastCompletedDeviceEIR.isSet(EIRDataType::CONN_IVAL) ); + REQUIRE( serverName == lastCompletedDeviceEIR.getName() ); + { + const EInfoReport eir = *lastCompletedDevice->getEIR(); + fprintf_td(stderr, "lastCompletedDevice.currentEIR: %s\n", eir.toString().c_str()); + REQUIRE( EIRDataType::NONE == eir.getEIRDataMask() ); + REQUIRE( 0 == eir.getName().length()); + } } - } - // - // Now reuse adapter for client mode -> Start discovery + Stop Discovery - // - { - const BTAdapterRef adapter = server->getAdapter(); - { // if( false ) { - adapter->removeAllStatusListener(); - } + // + // Now reuse adapter for client mode -> Start discovery + Stop Discovery + // + { + const BTAdapterRef adapter = server->getAdapter(); + { // if( false ) { + adapter->removeAllStatusListener(); + } - DBTEndpoint::startDiscovery(adapter, false /* current_exp_discovering_state */); + DBTEndpoint::startDiscovery(adapter, false /* current_exp_discovering_state */); - DBTEndpoint::stopDiscovery(adapter, true /* current_exp_discovering_state */); + DBTEndpoint::stopDiscovery(adapter, true /* current_exp_discovering_state */); + } } - const int count = manager.removeChangedAdapterSetCallback(myChangedAdapterSetFunc); fprintf_td(stderr, "****** EOL Removed ChangedAdapterSetCallback %d\n", count); } diff --git a/trial/direct_bt/dbt_server01.hpp b/trial/direct_bt/dbt_server01.hpp index 9bcbe984..7dfe07ed 100644 --- a/trial/direct_bt/dbt_server01.hpp +++ b/trial/direct_bt/dbt_server01.hpp @@ -25,6 +25,8 @@ #ifndef DBT_SERVER01_HPP_ #define DBT_SERVER01_HPP_ +#include <random> + #include "dbt_constants.hpp" #include "dbt_server_test.hpp" @@ -75,6 +77,8 @@ class DBTServer01 : public DBTServerTest { jau::sc_atomic_int servedProtocolSessionsSuccess = 0; jau::sc_atomic_int servingProtocolSessionsLeft = 1; + bool do_disconnect = false; + DBGattServerRef dbGattServer = std::make_shared<DBGattServer>( /* services: */ jau::make_darray( // DBGattService @@ -381,14 +385,17 @@ class DBTServer01 : public DBTServerTest { } } - bool onceDisconnect = true; - void disconnectDevice() { - jau::sleep_for( 300_ms ); + // sleep range: 100 - 1500 ms + // sleep range: 100 - 1500 ms + static const int sleep_min = 100; + static const int sleep_max = 1500; + static std::random_device rng_hw;; + static std::uniform_int_distribution<int> rng_dist(sleep_min, sleep_max); + const int64_t sleep_dur = rng_dist(rng_hw); + jau::sleep_for( sleep_dur * 1_ms ); BTDeviceRef connectedDevice_ = parent.getDevice(); - fprintf_td(stderr, "****** Server GATT::disconnectDevice(sessions [%d ok / %d total], left %d): client %s\n", - parent.servedProtocolSessionsSuccess.load(), parent.servedProtocolSessionsTotal.load(), parent.servingProtocolSessionsLeft.load(), - connectedDevice_->toString().c_str()); + fprintf_td(stderr, "****** Server i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, connectedDevice_->toString().c_str()); connectedDevice_->disconnect(); } @@ -452,8 +459,7 @@ class DBTServer01 : public DBTServerTest { fprintf_td(stderr, "****** Server GATT::mtuChanged(match %d, served %zu, left %zu): %d -> %d, %s\n", match, parent.servedProtocolSessionsTotal.load(), parent.servingProtocolSessionsLeft.load(), match ? (int)usedMTU_old : 0, (int)mtu, device->toString().c_str()); - if( onceDisconnect ) { - onceDisconnect = false; + if( parent.do_disconnect ) { std::thread disconnectThread(&MyGATTServerListener::disconnectDevice, this); disconnectThread.detach(); } @@ -574,22 +580,18 @@ class DBTServer01 : public DBTServerTest { public: - DBTServer01(const std::string& adapterName_, const jau::EUI48& useAdapter_, const BTMode btMode_, const bool use_SC_, const BTSecurityLevel adapterSecurityLevel_) { + DBTServer01(const std::string& adapterName_, const jau::EUI48& useAdapter_, const BTMode btMode_, + const bool use_SC_, const BTSecurityLevel adapterSecurityLevel_, const bool do_disconnect_) + { this->adapterName = adapterName_; this->useAdapter = useAdapter_; this->btMode = btMode_; this->use_SC = use_SC_; this->adapterSecurityLevel = adapterSecurityLevel_; + this->do_disconnect = do_disconnect_; dbGattServer->addListener( gattServerListener ); } - DBTServer01(const std::string& adapterName_, const jau::EUI48& useAdapter_, const BTSecurityLevel adapterSecurityLevel_) - : DBTServer01(adapterName_, useAdapter_, BTMode::DUAL, true /* SC */, adapterSecurityLevel_) - { } - - DBTServer01(const std::string& adapterName_, const BTSecurityLevel adapterSecurityLevel_) - : DBTServer01(adapterName_, EUI48::ALL_DEVICE, BTMode::DUAL, true /* SC */, adapterSecurityLevel_) - { } std::string getName() override { return adapterName; } diff --git a/trial/direct_bt/test_provoke_client_server_i470.cpp b/trial/direct_bt/test_provoke_client_server_i470.cpp index e393182f..ad10c837 100644 --- a/trial/direct_bt/test_provoke_client_server_i470.cpp +++ b/trial/direct_bt/test_provoke_client_server_i470.cpp @@ -50,22 +50,56 @@ static BaseDBTClientServer& base_test_framework = BaseDBTClientServer::get(); */ class TestDBTClientServer_i470 : public DBTClientServer1x { public: - void test_i470() { - base_test_framework.setupTest( 20_s ); + void test_i470_a() { + base_test_framework.setupTest( 10_s ); { const bool serverSC = true; - const std::string suffix = "i470"; - const int protocolSessionCount = 2; + const std::string suffix = "i470_a"; + const int protocolSessionCount = 10; + const int max_connections_per_session = 200; + const bool expSuccess = false; const bool server_client_order = true; const BTSecurityLevel secLevelServer = BTSecurityLevel::ENC_ONLY; const BTSecurityLevel secLevelClient = BTSecurityLevel::ENC_ONLY; const ExpectedPairing serverExpPairing = ExpectedPairing::DONT_CARE; const ExpectedPairing clientExpPairing = ExpectedPairing::DONT_CARE; + const bool client_do_disconnect = true; + const bool server_do_disconnect = false; - // std::shared_ptr<DBTServerTest> server = std::make_shared<DBTServer01>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer); - std::shared_ptr<DBTServerTest> server = std::make_shared<DBTServer00>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer); - std::shared_ptr<DBTClientTest> client = std::make_shared<DBTClient01>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL); - test8x_fullCycle(suffix, protocolSessionCount, server_client_order, + std::shared_ptr<DBTServerTest> server = std::make_shared<DBTServer01>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer, server_do_disconnect); + std::shared_ptr<DBTClientTest> client = std::make_shared<DBTClient01>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, client_do_disconnect); + + test8x_fullCycle(suffix, + protocolSessionCount, max_connections_per_session, expSuccess, + server_client_order, + server, secLevelServer, serverExpPairing, + client, secLevelClient, clientExpPairing); + } + base_test_framework.cleanupTest(); + } + + void test_i470_b() { + base_test_framework.setupTest( 10_s ); + { + const bool serverSC = true; + const std::string suffix = "i470_b"; + const int protocolSessionCount = 10; + const int max_connections_per_session = 200; + const bool expSuccess = false; + const bool server_client_order = true; + const BTSecurityLevel secLevelServer = BTSecurityLevel::ENC_ONLY; + const BTSecurityLevel secLevelClient = BTSecurityLevel::ENC_ONLY; + const ExpectedPairing serverExpPairing = ExpectedPairing::DONT_CARE; + const ExpectedPairing clientExpPairing = ExpectedPairing::DONT_CARE; + const bool client_do_disconnect = false; + const bool server_do_disconnect = true; + + std::shared_ptr<DBTServerTest> server = std::make_shared<DBTServer01>("S-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, serverSC, secLevelServer, server_do_disconnect); + std::shared_ptr<DBTClientTest> client = std::make_shared<DBTClient01>("C-"+suffix, EUI48::ALL_DEVICE, BTMode::DUAL, client_do_disconnect); + + test8x_fullCycle(suffix, + protocolSessionCount, max_connections_per_session, expSuccess, + server_client_order, server, secLevelServer, serverExpPairing, client, secLevelClient, clientExpPairing); } @@ -73,4 +107,5 @@ class TestDBTClientServer_i470 : public DBTClientServer1x { } }; -METHOD_AS_TEST_CASE( TestDBTClientServer_i470::test_i470, "ClientServer i470 Trial", "[trial][i470]"); +METHOD_AS_TEST_CASE( TestDBTClientServer_i470::test_i470_a, "ClientServer i470 Trial a", "[trial][i470]"); +METHOD_AS_TEST_CASE( TestDBTClientServer_i470::test_i470_b, "ClientServer i470 Trial b", "[trial][i470]"); |