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 | |
parent | 662486318a7509f2d610dbbcb39f1073d8b413c1 (diff) |
trial i470 test_provoke (C++) / TestDBTProvoke (Java) demonstrating C++ survives while Java crashes (known issue)
-rw-r--r-- | scripts/build.sh | 18 | ||||
-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 | ||||
-rw-r--r-- | trial/java/trial/org/direct_bt/DBTClient01.java | 164 | ||||
-rw-r--r-- | trial/java/trial/org/direct_bt/DBTClientServer1x.java | 160 | ||||
-rw-r--r-- | trial/java/trial/org/direct_bt/DBTServer01.java | 29 | ||||
-rw-r--r-- | trial/java/trial/org/direct_bt/TestDBTProvokeClientServer_i470.java | 45 |
9 files changed, 439 insertions, 390 deletions
diff --git a/scripts/build.sh b/scripts/build.sh index b5a99a53..fdd6e238 100644 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -43,16 +43,16 @@ buildit() { cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON .. # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DDEBUG=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DDEBUG=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DUSE_LIBUNWIND=OFF -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DUSE_LIBUNWIND=OFF -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DDEBUG=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DUSE_STRIP=OFF .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DUSE_STRIP=ON -DJAVAC_DEBUG_ARGS="none" .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DGPROF=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DPERF_ANALYSIS=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DDEBUG=ON -DINSTRUMENTATION=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DDEBUG=ON -DINSTRUMENTATION_UNDEFINED=ON .. - # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TESTING=ON -DDEBUG=ON -DINSTRUMENTATION_THREAD=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DUSE_STRIP=OFF .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DUSE_STRIP=ON -DJAVAC_DEBUG_ARGS="none" .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DGPROF=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DPERF_ANALYSIS=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DDEBUG=ON -DINSTRUMENTATION=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DDEBUG=ON -DINSTRUMENTATION_UNDEFINED=ON .. + # cmake $CLANG_ARGS -DCMAKE_INSTALL_PREFIX=$rootdir/dist-$archabi -DBUILDJAVA=ON -DBUILDEXAMPLES=ON -DBUILD_TRIAL=ON -DDEBUG=ON -DINSTRUMENTATION_THREAD=ON .. make -j $CPU_COUNT install if [ $? -eq 0 ] ; then 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]"); diff --git a/trial/java/trial/org/direct_bt/DBTClient01.java b/trial/java/trial/org/direct_bt/DBTClient01.java index 2f4d89b2..eca16ba8 100644 --- a/trial/java/trial/org/direct_bt/DBTClient01.java +++ b/trial/java/trial/org/direct_bt/DBTClient01.java @@ -68,8 +68,6 @@ public class DBTClient01 implements DBTClientTest { private final MyAdapterStatusListener myAdapterStatusListener = new MyAdapterStatusListener(); - private final byte cmd_arg = (byte)0x44; - private String adapterName = "TestDev2_Clt"; private EUI48 useAdapter = EUI48.ALL_DEVICE; private BTMode btMode = BTMode.DUAL; @@ -86,14 +84,16 @@ public class DBTClient01 implements DBTClientTest { private final AtomicInteger deviceReadyCount = new AtomicInteger(0); private final AtomicInteger notificationsReceived = new AtomicInteger(0); private final AtomicInteger indicationsReceived = new AtomicInteger(0); - private final AtomicInteger completedGATTCommands = new AtomicInteger(0); private final AtomicInteger completedMeasurementsTotal = new AtomicInteger(0); private final AtomicInteger completedMeasurementsSuccess = new AtomicInteger(0); - public DBTClient01(final String adapterName, final EUI48 useAdapter, final BTMode btMode) { + private final boolean do_disconnect; + + public DBTClient01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean do_disconnect) { this.adapterName = adapterName; this.useAdapter = useAdapter; this.btMode = btMode; + this.do_disconnect = do_disconnect; } @Override @@ -259,6 +259,19 @@ public class DBTClient01 implements DBTClientTest { } } + private void disconnectDevice(final BTDevice device) { + // sleep range: 100 - 1500 ms + final int sleep_min = 100; + final int sleep_max = 1500; + final int sleep_dur = (int) ( Math.random() * ( sleep_max - sleep_min + 1 ) + sleep_min ); + try { + Thread.sleep(sleep_dur); // wait a little (FIXME: Fast restart of advertising error) + } catch (final InterruptedException e) { } + + BTUtils.fprintf_td(System.err, "****** Client i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, device.toString()); + device.disconnect(); + } + @Override public void deviceReady(final BTDevice device, final long timestamp) { { @@ -271,8 +284,13 @@ public class DBTClient01 implements DBTClientTest { // Be nice to Test* case, allowing to reach its own listener.deviceReady() added later executeOffThread( () -> { processReadyDevice(device); }, - "DBT-Process-"+device.getAddressAndType(), true /* detach */); + "DBT-Process1-"+device.getAddressAndType(), true /* detach */); // processReadyDevice(device); // AdapterStatusListener::deviceReady() explicitly allows prolonged and complex code execution! + + if( do_disconnect ) { + executeOffThread( () -> { disconnectDevice(device); }, + "DBT-Disconnect-"+device.getAddressAndType(), true /* detach */); + } } } @@ -326,7 +344,6 @@ public class DBTClient01 implements DBTClientTest { } private void resetLastProcessingStats() { - completedGATTCommands.set(0); notificationsReceived.set(0); indicationsReceived.set(0); } @@ -432,95 +449,65 @@ public class DBTClient01 implements DBTClientTest { "PERF: get-gatt-services " + td35 + " ms,"+System.lineSeparator()); } - { - final BTGattCmd cmd = new BTGattCmd(device, "TestCmd", null /* service_uuid */, DBTConstants.CommandUUID, DBTConstants.ResponseUUID); - cmd.setVerbose(true); - final boolean cmd_resolved = cmd.isResolved(); - BTUtils.println(System.err, "Client Command test: "+cmd.toString()+", resolved "+cmd_resolved); - final byte[] cmd_data = { cmd_arg }; - final HCIStatusCode cmd_res = cmd.send(true /* prefNoAck */, cmd_data, 3000 /* timeoutMS */); - if( HCIStatusCode.SUCCESS == cmd_res ) { - final byte[] resp = cmd.getResponse(); - if( 1 == resp.length && resp[0] == cmd_arg ) { - BTUtils.fprintf_td(System.err, "Client Success: %s -> %s (echo response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */)); - completedGATTCommands.incrementAndGet(); - } else { - BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s (different response)\n", cmd.toString(), BTUtils.bytesHexString(resp, 0, resp.length, true /* lsb */)); - } - } else { - BTUtils.fprintf_td(System.err, "Client Failure: %s -> %s\n", cmd.toString(), cmd_res.toString()); - } - cmd.close(); - } - - try { - int i=0; - for(final Iterator<BTGattService> srvIter = primServices.iterator(); srvIter.hasNext(); i++) { - final BTGattService primService = srvIter.next(); - if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, " [%02d] Service UUID %s\n", i, primService.getUUID()); - BTUtils.fprintf_td(System.err, " [%02d] %s\n", i, primService.toString()); - } - int j=0; - final List<BTGattChar> serviceCharacteristics = primService.getChars(); - for(final Iterator<BTGattChar> charIter = serviceCharacteristics.iterator(); charIter.hasNext(); j++) { - final BTGattChar serviceChar = charIter.next(); + do { + try { + int i=0; + for(final Iterator<BTGattService> srvIter = primServices.iterator(); srvIter.hasNext(); i++) { + final BTGattService primService = srvIter.next(); if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic: UUID %s\n", i, j, serviceChar.getUUID()); - BTUtils.fprintf_td(System.err, " [%02d.%02d] %s\n", i, j, serviceChar.toString()); + BTUtils.fprintf_td(System.err, " [%02d] Service UUID %s\n", i, primService.getUUID()); + BTUtils.fprintf_td(System.err, " [%02d] %s\n", i, primService.toString()); } - final GattCharPropertySet properties = serviceChar.getProperties(); - if( properties.isSet(GattCharPropertySet.Type.Read) ) { - final byte[] value = serviceChar.readValue(); - final String svalue = BTUtils.decodeUTF8String(value, 0, value.length); + int j=0; + final List<BTGattChar> serviceCharacteristics = primService.getChars(); + for(final Iterator<BTGattChar> charIter = serviceCharacteristics.iterator(); charIter.hasNext(); j++) { + final BTGattChar serviceChar = charIter.next(); if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, " [%02d.%02d] value: %s ('%s')\n", i, j, BTUtils.bytesHexString(value, 0, -1, true), svalue); + BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic: UUID %s\n", i, j, serviceChar.getUUID()); + BTUtils.fprintf_td(System.err, " [%02d.%02d] %s\n", i, j, serviceChar.toString()); } - } - int k=0; - final List<BTGattDesc> charDescList = serviceChar.getDescriptors(); - for(final Iterator<BTGattDesc> descIter = charDescList.iterator(); descIter.hasNext(); k++) { - final BTGattDesc charDesc = descIter.next(); - if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] Descriptor: UUID %s\n", i, j, k, charDesc.getUUID()); - BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] %s\n", i, j, k, charDesc.toString()); + final GattCharPropertySet properties = serviceChar.getProperties(); + if( properties.isSet(GattCharPropertySet.Type.Read) ) { + final byte[] value = serviceChar.readValue(); + final String svalue = BTUtils.decodeUTF8String(value, 0, value.length); + if( GATT_VERBOSE ) { + BTUtils.fprintf_td(System.err, " [%02d.%02d] value: %s ('%s')\n", i, j, BTUtils.bytesHexString(value, 0, -1, true), svalue); + } } - } - final boolean cccdEnableResult[] = { false, false }; - if( serviceChar.enableNotificationOrIndication( cccdEnableResult ) ) { - // ClientCharConfigDescriptor (CCD) is available - final boolean clAdded = null != serviceChar.addCharListener( new MyGATTEventListener(i, j) ); - if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic-Listener: Notification(%b), Indication(%b): Added %b\n", - i, j, cccdEnableResult[0], cccdEnableResult[1], clAdded); - BTUtils.fprintf_td(System.err, "\n"); + int k=0; + final List<BTGattDesc> charDescList = serviceChar.getDescriptors(); + for(final Iterator<BTGattDesc> descIter = charDescList.iterator(); descIter.hasNext(); k++) { + final BTGattDesc charDesc = descIter.next(); + if( GATT_VERBOSE ) { + BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] Descriptor: UUID %s\n", i, j, k, charDesc.getUUID()); + BTUtils.fprintf_td(System.err, " [%02d.%02d.%02d] %s\n", i, j, k, charDesc.toString()); + } + } + final boolean cccdEnableResult[] = { false, false }; + if( serviceChar.enableNotificationOrIndication( cccdEnableResult ) ) { + // ClientCharConfigDescriptor (CCD) is available + final boolean clAdded = null != serviceChar.addCharListener( new MyGATTEventListener(i, j) ); + if( GATT_VERBOSE ) { + BTUtils.fprintf_td(System.err, " [%02d.%02d] Characteristic-Listener: Notification(%b), Indication(%b): Added %b\n", + i, j, cccdEnableResult[0], cccdEnableResult[1], clAdded); + BTUtils.fprintf_td(System.err, "\n"); + } } } - } - if( GATT_VERBOSE ) { - BTUtils.fprintf_td(System.err, "\n"); - } - } - } catch( final Exception ex) { - BTUtils.println(System.err, "****** Client Processing Ready Device: Exception.2 caught for " + device.toString() + ": "+ex.getMessage()); - ex.printStackTrace(); - } - - { - final long t0 = BTUtils.currentTimeMillis(); - boolean timeout = false; - do { - success = completedGATTCommands.get() >= 1 && ( notificationsReceived.get() >= 2 || indicationsReceived.get() >= 2 ); - if( !success ) { - timeout = 3000 < ( BTUtils.currentTimeMillis() - t0 ); // 3s timeout - if( !timeout ) { - try { Thread.sleep(17); } catch (final InterruptedException e) { } + if( GATT_VERBOSE ) { + BTUtils.fprintf_td(System.err, "\n"); } } - } while( !success && !timeout ); - } - { + success = notificationsReceived.get() >= 2 || indicationsReceived.get() >= 2; + + } catch( final Exception ex) { + BTUtils.println(System.err, "****** Client Processing Ready Device: Exception.2 caught for " + device.toString() + ": "+ex.getMessage()); + ex.printStackTrace(); + } + } while( !success && device.getConnected() ); + + if( device.getConnected() ) { // Tell server we have successfully completed the test. final BTGattCmd cmd = new BTGattCmd(device, "FinalHandshake", null /* service_uuid */, DBTConstants.CommandUUID, DBTConstants.ResponseUUID); cmd.setVerbose(true); @@ -569,15 +556,14 @@ public class DBTClient01 implements DBTClientTest { completedMeasurementsTotal.addAndGet(1); if( success ) { completedMeasurementsSuccess.addAndGet(1); - } - if( 0 < measurementsLeft.get() ) { - measurementsLeft.decrementAndGet(); + if( 0 < measurementsLeft.get() ) { + measurementsLeft.decrementAndGet(); + } } BTUtils.println(System.err, "****** Client Processing Ready Device: Success "+success+ "; Measurements completed "+completedMeasurementsSuccess.get()+ ", left "+measurementsLeft.get()+ "; Received notitifications "+notificationsReceived.get()+", indications "+indicationsReceived.get()+ - "; Completed GATT commands "+completedGATTCommands.get()+ ": "+device.getAddressAndType()); } diff --git a/trial/java/trial/org/direct_bt/DBTClientServer1x.java b/trial/java/trial/org/direct_bt/DBTClientServer1x.java index 460e6ece..efffbfb8 100644 --- a/trial/java/trial/org/direct_bt/DBTClientServer1x.java +++ b/trial/java/trial/org/direct_bt/DBTClientServer1x.java @@ -58,6 +58,9 @@ import org.junit.Assert; * - reuse server-adapter for client-mode discovery (just toggle on/off) */ public abstract class DBTClientServer1x extends BaseDBTClientServer { + // timeout check: timeout_value < test_duration + timeout_preempt_diff; // let's timeout here before our timeout timer + static final long timeout_preempt_diff = 500; + final Object mtx_sync = new Object(); BTDevice lastCompletedDevice = null; PairingMode lastCompletedDevicePairingMode = PairingMode.NONE; @@ -71,14 +74,16 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer { { final DBTServer00 server = new DBTServer00("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, secLevelServer); final DBTClient00 client = new DBTClient00("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL); - test8x_fullCycle(timeout_value, - suffix, protocolSessionCount, server_client_order, + test8x_fullCycle(timeout_value, suffix, + protocolSessionCount, DBTConstants.max_connections_per_session, true /* expSuccess */, + server_client_order, server, secLevelServer, serverExpPairing, client, secLevelClient, clientExpPairing); } - final void test8x_fullCycle(final long timeout_value, - final String suffix, final int protocolSessionCount, final boolean server_client_order, + final void test8x_fullCycle(final long timeout_value, final String suffix, + final int protocolSessionCount, final int max_connections_per_session, final boolean expSuccess, + final boolean server_client_order, final DBTServerTest server, final BTSecurityLevel secLevelServer, final ExpectedPairing serverExpPairing, final DBTClientTest client, final BTSecurityLevel secLevelClient, final ExpectedPairing clientExpPairing) { @@ -162,9 +167,9 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer { null == 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 = BTUtils.currentTimeMillis() - t0; - timeout = 0 < timeout_value && timeout_value <= test_duration + 500; // let's timeout here before our timeout timer + timeout = 0 < timeout_value && timeout_value <= test_duration + timeout_preempt_diff; // let's timeout here before our timeout timer if( !done && !max_connections_hit && !timeout ) { try { Thread.sleep(88); } catch (final InterruptedException e) { e.printStackTrace(); } } @@ -176,99 +181,104 @@ public abstract class DBTClientServer1x extends BaseDBTClientServer { test_duration, timeout, timeout_value, max_connections_hit); BTUtils.fprintf_td(System.err, " 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 )); BTUtils.fprintf_td(System.err, " 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 )); BTUtils.fprintf_td(System.err, "\n\n"); - Assert.assertFalse( max_connections_hit ); - Assert.assertFalse( timeout ); + if( expSuccess ) { + Assert.assertFalse( max_connections_hit ); + Assert.assertFalse( timeout ); - synchronized( mtx_sync ) { - Assert.assertTrue(protocolSessionCount <= server.getProtocolSessionsDoneTotal()); - Assert.assertEquals(protocolSessionCount, server.getProtocolSessionsDoneSuccess()); - Assert.assertTrue(protocolSessionCount <= client.getProtocolSessionsDoneTotal()); - Assert.assertEquals(protocolSessionCount, client.getProtocolSessionsDoneSuccess()); - Assert.assertNotNull(lastCompletedDevice); - Assert.assertNotNull(lastCompletedDeviceEIR); - Assert.assertFalse(lastCompletedDevice.getConnected()); - Assert.assertTrue( ( 1 * DBTConstants.max_connections_per_session ) > server.getDisconnectCount() ); + synchronized( mtx_sync ) { + Assert.assertTrue(protocolSessionCount <= server.getProtocolSessionsDoneTotal()); + Assert.assertEquals(protocolSessionCount, server.getProtocolSessionsDoneSuccess()); + Assert.assertTrue(protocolSessionCount <= client.getProtocolSessionsDoneTotal()); + Assert.assertEquals(protocolSessionCount, client.getProtocolSessionsDoneSuccess()); + Assert.assertNotNull(lastCompletedDevice); + Assert.assertNotNull(lastCompletedDeviceEIR); + Assert.assertFalse(lastCompletedDevice.getConnected()); + Assert.assertTrue( ( 1 * max_connections_per_session ) > server.getDisconnectCount() ); + } } // // Client stop // - DBTClientTest.stopDiscovery(client, true /* current_exp_discovering_state */, "test"+suffix+"_stopDiscovery"); + final boolean 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"); + final boolean 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 - // - final SMPKeyBin clientKeys = SMPKeyBin.read(DBTConstants.CLIENT_KEY_PATH, lastCompletedDevice, true /* verbose */); - Assert.assertTrue(clientKeys.isValid()); - final BTSecurityLevel clientKeysSecLevel = clientKeys.getSecLevel(); - Assert.assertEquals(secLevelClient, clientKeysSecLevel); - { - if( ExpectedPairing.PREPAIRED == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { - // Using encryption: pre-paired - Assert.assertEquals(PairingMode.PRE_PAIRED, lastCompletedDevicePairingMode); - Assert.assertEquals(BTSecurityLevel.ENC_ONLY, lastCompletedDeviceSecurityLevel); // pre-paired fixed level, no auth - } else if( ExpectedPairing.NEW_PAIRING == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { - // Using encryption: Newly paired - Assert.assertNotEquals(PairingMode.PRE_PAIRED, lastCompletedDevicePairingMode); - Assert.assertTrue("PairingMode client "+lastCompletedDevicePairingMode+" not > NONE", PairingMode.NONE.value < lastCompletedDevicePairingMode.value); - Assert.assertTrue("SecurityLevel client "+lastCompletedDeviceSecurityLevel+" not >= "+secLevelClient, secLevelClient.value <= lastCompletedDeviceSecurityLevel.value); - } else if( ExpectedPairing.DONT_CARE == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { - // Any encryption, any pairing - Assert.assertTrue("PairingMode client "+lastCompletedDevicePairingMode+" not > NONE", PairingMode.NONE.value < lastCompletedDevicePairingMode.value); - Assert.assertTrue("SecurityLevel client "+lastCompletedDeviceSecurityLevel+" not >= "+secLevelClient, secLevelClient.value <= lastCompletedDeviceSecurityLevel.value); - } else { - // No encryption: No pairing - Assert.assertEquals(PairingMode.NONE, lastCompletedDevicePairingMode); - Assert.assertEquals(BTSecurityLevel.NONE, lastCompletedDeviceSecurityLevel); - } - } - - // - // Validating EIR - // - synchronized( mtx_sync ) { - BTUtils.println(System.err, "lastCompletedDevice.connectedEIR: "+lastCompletedDeviceEIR.toString()); - Assert.assertNotEquals(0, lastCompletedDeviceEIR.getEIRDataMask().mask); - Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.FLAGS) ); - Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.SERVICE_UUID) ); - Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.NAME) ); - Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.CONN_IVAL) ); - Assert.assertEquals(serverName, lastCompletedDeviceEIR.getName()); + if( expSuccess ) { + // + // Validating Security Mode + // + final SMPKeyBin clientKeys = SMPKeyBin.read(DBTConstants.CLIENT_KEY_PATH, lastCompletedDevice, true /* verbose */); + Assert.assertTrue(clientKeys.isValid()); + final BTSecurityLevel clientKeysSecLevel = clientKeys.getSecLevel(); + Assert.assertEquals(secLevelClient, clientKeysSecLevel); { - final EInfoReport eir = lastCompletedDevice.getEIR().clone(); - BTUtils.println(System.err, "lastCompletedDevice.currentEIR: "+eir.toString()); - Assert.assertEquals(0, eir.getEIRDataMask().mask); - Assert.assertEquals(0, eir.getName().length()); + if( ExpectedPairing.PREPAIRED == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { + // Using encryption: pre-paired + Assert.assertEquals(PairingMode.PRE_PAIRED, lastCompletedDevicePairingMode); + Assert.assertEquals(BTSecurityLevel.ENC_ONLY, lastCompletedDeviceSecurityLevel); // pre-paired fixed level, no auth + } else if( ExpectedPairing.NEW_PAIRING == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { + // Using encryption: Newly paired + Assert.assertNotEquals(PairingMode.PRE_PAIRED, lastCompletedDevicePairingMode); + Assert.assertTrue("PairingMode client "+lastCompletedDevicePairingMode+" not > NONE", PairingMode.NONE.value < lastCompletedDevicePairingMode.value); + Assert.assertTrue("SecurityLevel client "+lastCompletedDeviceSecurityLevel+" not >= "+secLevelClient, secLevelClient.value <= lastCompletedDeviceSecurityLevel.value); + } else if( ExpectedPairing.DONT_CARE == clientExpPairing && BTSecurityLevel.NONE.value < secLevelClient.value ) { + // Any encryption, any pairing + Assert.assertTrue("PairingMode client "+lastCompletedDevicePairingMode+" not > NONE", PairingMode.NONE.value < lastCompletedDevicePairingMode.value); + Assert.assertTrue("SecurityLevel client "+lastCompletedDeviceSecurityLevel+" not >= "+secLevelClient, secLevelClient.value <= lastCompletedDeviceSecurityLevel.value); + } else { + // No encryption: No pairing + Assert.assertEquals(PairingMode.NONE, lastCompletedDevicePairingMode); + Assert.assertEquals(BTSecurityLevel.NONE, lastCompletedDeviceSecurityLevel); + } } - } - // - // Now reuse adapter for client mode -> Start discovery + Stop Discovery - // - { - final BTAdapter adapter = server.getAdapter(); - { // if( false ) { - adapter.removeAllStatusListener(); + // + // Validating EIR + // + synchronized( mtx_sync ) { + BTUtils.println(System.err, "lastCompletedDevice.connectedEIR: "+lastCompletedDeviceEIR.toString()); + Assert.assertNotEquals(0, lastCompletedDeviceEIR.getEIRDataMask().mask); + Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.FLAGS) ); + Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.SERVICE_UUID) ); + Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.NAME) ); + Assert.assertTrue( lastCompletedDeviceEIR.isSet(EIRDataTypeSet.DataType.CONN_IVAL) ); + Assert.assertEquals(serverName, lastCompletedDeviceEIR.getName()); + { + final EInfoReport eir = lastCompletedDevice.getEIR().clone(); + BTUtils.println(System.err, "lastCompletedDevice.currentEIR: "+eir.toString()); + Assert.assertEquals(0, eir.getEIRDataMask().mask); + Assert.assertEquals(0, eir.getName().length()); + } } - DBTEndpoint.startDiscovery(adapter, false /* current_exp_discovering_state */); + // + // Now reuse adapter for client mode -> Start discovery + Stop Discovery + // + { + final BTAdapter adapter = server.getAdapter(); + { // if( false ) { + adapter.removeAllStatusListener(); + } + + DBTEndpoint.startDiscovery(adapter, false /* current_exp_discovering_state */); - DBTEndpoint.stopDiscovery(adapter, true /* current_exp_discovering_state */); + DBTEndpoint.stopDiscovery(adapter, true /* current_exp_discovering_state */); + } } - final int count = manager.removeChangedAdapterSetListener(myChangedAdapterSetListener); BTUtils.println(System.err, "****** EOL Removed ChangedAdapterSetCallback " + count); } diff --git a/trial/java/trial/org/direct_bt/DBTServer01.java b/trial/java/trial/org/direct_bt/DBTServer01.java index 2134d55a..1183d8fa 100644 --- a/trial/java/trial/org/direct_bt/DBTServer01.java +++ b/trial/java/trial/org/direct_bt/DBTServer01.java @@ -60,9 +60,6 @@ import org.direct_bt.SMPPairingState; import org.direct_bt.ScanType; import org.jau.net.EUI48; -import trial.org.direct_bt.DBTServer00.MyAdapterStatusListener; -import trial.org.direct_bt.DBTServer00.MyGATTServerListener; - /** * This peripheral BTRole::Slave test participant works with DBTClient00. */ @@ -88,21 +85,18 @@ public class DBTServer01 implements DBTServerTest { private final AtomicInteger servedProtocolSessionsSuccess = new AtomicInteger(0); private final AtomicInteger servingProtocolSessionsLeft = new AtomicInteger(1); - public DBTServer01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean use_SC, final BTSecurityLevel adapterSecurityLevel) { + private final boolean do_disconnect; + + public DBTServer01(final String adapterName, final EUI48 useAdapter, final BTMode btMode, final boolean use_SC, final BTSecurityLevel adapterSecurityLevel, final boolean 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 ); } - public DBTServer01(final String adapterName, final EUI48 useAdapter, final BTSecurityLevel adapterSecurityLevel) { - this(adapterName, useAdapter, BTMode.DUAL, true /* SC */, adapterSecurityLevel); - } - public DBTServer01(final String adapterName, final BTSecurityLevel adapterSecurityLevel) { - this(adapterName, EUI48.ALL_DEVICE, BTMode.DUAL, true /* SC */, adapterSecurityLevel); - } @Override public String getName() { return adapterName; } @@ -470,17 +464,17 @@ public class DBTServer01 implements DBTServerTest { } } - boolean onceDisconnect = true; - private void disconnectDevice() { + // sleep range: 100 - 1500 ms + final int sleep_min = 100; + final int sleep_max = 1500; + final int sleep_dur = (int) ( Math.random() * ( sleep_max - sleep_min + 1 ) + sleep_min ); try { - Thread.sleep(300); + Thread.sleep(sleep_dur); // wait a little (FIXME: Fast restart of advertising error) } catch (final InterruptedException e) { } final BTDevice connectedDevice_ = getDevice(); - BTUtils.fprintf_td(System.err, "****** Server GATT::disconnectDevice(sessions [%d ok / %d total], left %d): client %s\n", - servedProtocolSessionsSuccess.get(), servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(), - connectedDevice_.toString()); + BTUtils.fprintf_td(System.err, "****** Server i470 disconnectDevice(delayed %d ms): client %s\n", sleep_dur, connectedDevice_.toString()); connectedDevice_.disconnect(); } @@ -533,8 +527,7 @@ public class DBTServer01 implements DBTServerTest { BTUtils.fprintf_td(System.err, "****** Server GATT::mtuChanged(match %b, served %d, left %d): %d -> %d, %s\n", match, servedProtocolSessionsTotal.get(), servingProtocolSessionsLeft.get(), match ? usedMTU_old : 0, mtu, device.toString()); - if( onceDisconnect ) { - onceDisconnect = false; + if( do_disconnect ) { executeOffThread( () -> { disconnectDevice(); }, "GattServer-DisconnectDevice", true /* detach */); } } diff --git a/trial/java/trial/org/direct_bt/TestDBTProvokeClientServer_i470.java b/trial/java/trial/org/direct_bt/TestDBTProvokeClientServer_i470.java index cb96610c..b2e8e1c8 100644 --- a/trial/java/trial/org/direct_bt/TestDBTProvokeClientServer_i470.java +++ b/trial/java/trial/org/direct_bt/TestDBTProvokeClientServer_i470.java @@ -44,21 +44,50 @@ import org.junit.runners.MethodSorters; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class TestDBTProvokeClientServer_i470 extends DBTClientServer1x { - @Test(timeout = 20000) - public final void test_i470() + @Test(timeout = 10000) + public final void test_i470_a() { final boolean serverSC = true; - final String suffix = "i470"; - final int protocolSessionCount = 2; + final String suffix = "i470_a"; + final int protocolSessionCount = 10; + final int max_connections_per_session = 200; + final boolean expSuccess = false; final boolean server_client_order = true; final ExpectedPairing serverExpPairing = ExpectedPairing.DONT_CARE; final ExpectedPairing clientExpPairing = ExpectedPairing.DONT_CARE; + final boolean client_do_disconnect = true; + final boolean server_do_disconnect = false; - // final DBTServerTest server = new DBTServer01("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, BTSecurityLevel.ENC_ONLY); - final DBTServerTest server = new DBTServer00("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, BTSecurityLevel.ENC_ONLY); - final DBTClientTest client = new DBTClient01("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL); + final DBTServerTest server = new DBTServer01("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, BTSecurityLevel.ENC_ONLY, server_do_disconnect); + final DBTClientTest client = new DBTClient01("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, client_do_disconnect); - test8x_fullCycle(20000, suffix, protocolSessionCount, server_client_order, + test8x_fullCycle(10000, suffix, + protocolSessionCount, max_connections_per_session, expSuccess, + server_client_order, + server, BTSecurityLevel.ENC_ONLY, serverExpPairing, + client, BTSecurityLevel.ENC_ONLY, clientExpPairing); + } + + @Test(timeout = 10000) + public final void test_i470_b() + { + final boolean serverSC = true; + final String suffix = "i470_b"; + final int protocolSessionCount = 10; + final int max_connections_per_session = 200; + final boolean expSuccess = false; + final boolean server_client_order = true; + final ExpectedPairing serverExpPairing = ExpectedPairing.DONT_CARE; + final ExpectedPairing clientExpPairing = ExpectedPairing.DONT_CARE; + final boolean client_do_disconnect = false; + final boolean server_do_disconnect = true; + + final DBTServerTest server = new DBTServer01("S-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, serverSC, BTSecurityLevel.ENC_ONLY, server_do_disconnect); + final DBTClientTest client = new DBTClient01("C-"+suffix, EUI48.ALL_DEVICE, BTMode.DUAL, client_do_disconnect); + + test8x_fullCycle(10000, suffix, + protocolSessionCount, max_connections_per_session, expSuccess, + server_client_order, server, BTSecurityLevel.ENC_ONLY, serverExpPairing, client, BTSecurityLevel.ENC_ONLY, clientExpPairing); } |