implement Milestone 16: Bluetooth interface with user consent
This commit is contained in:
@@ -29,6 +29,7 @@ add_library(mosis-sandbox STATIC
|
||||
../src/main/cpp/sandbox/audio_output.cpp
|
||||
../src/main/cpp/sandbox/location_interface.cpp
|
||||
../src/main/cpp/sandbox/sensor_interface.cpp
|
||||
../src/main/cpp/sandbox/bluetooth_interface.cpp
|
||||
)
|
||||
target_include_directories(mosis-sandbox PUBLIC
|
||||
../src/main/cpp/sandbox
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "audio_output.h"
|
||||
#include "location_interface.h"
|
||||
#include "sensor_interface.h"
|
||||
#include "bluetooth_interface.h"
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
@@ -2687,6 +2688,208 @@ bool Test_SensorLuaIntegration(std::string& error_msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Milestone 16: Bluetooth
|
||||
//=============================================================================
|
||||
|
||||
bool Test_BluetoothRequiresPermission(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
// No permission granted
|
||||
|
||||
std::string err;
|
||||
bool started = bluetooth.StartDiscovery(
|
||||
{},
|
||||
[](const std::vector<mosis::BluetoothDevice>&) {},
|
||||
[](mosis::BluetoothError, const std::string&) {},
|
||||
err
|
||||
);
|
||||
|
||||
EXPECT_TRUE(!started);
|
||||
EXPECT_TRUE(err.find("permission") != std::string::npos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothRequiresUserConsent(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
bluetooth.SetBluetoothPermission(true);
|
||||
// User consent NOT granted
|
||||
|
||||
std::string err;
|
||||
bool started = bluetooth.StartDiscovery(
|
||||
{},
|
||||
[](const std::vector<mosis::BluetoothDevice>&) {},
|
||||
[](mosis::BluetoothError, const std::string&) {},
|
||||
err
|
||||
);
|
||||
|
||||
EXPECT_TRUE(!started);
|
||||
EXPECT_TRUE(err.find("consent") != std::string::npos ||
|
||||
err.find("gesture") != std::string::npos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothDiscoveryWorks(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
bluetooth.SetBluetoothPermission(true);
|
||||
bluetooth.SetUserConsent(true);
|
||||
|
||||
// Set mock devices
|
||||
std::vector<mosis::BluetoothDevice> devices = {
|
||||
{"Device A", "AA:BB:CC:DD:EE:FF"},
|
||||
{"Device B", "11:22:33:44:55:66"}
|
||||
};
|
||||
bluetooth.SetMockDevices(devices);
|
||||
|
||||
std::vector<mosis::BluetoothDevice> discovered;
|
||||
bool got_devices = false;
|
||||
|
||||
std::string err;
|
||||
bool started = bluetooth.StartDiscovery(
|
||||
{},
|
||||
[&](const std::vector<mosis::BluetoothDevice>& devs) {
|
||||
got_devices = true;
|
||||
discovered = devs;
|
||||
},
|
||||
[](mosis::BluetoothError, const std::string&) {},
|
||||
err
|
||||
);
|
||||
|
||||
EXPECT_TRUE(started);
|
||||
EXPECT_TRUE(got_devices);
|
||||
EXPECT_TRUE(discovered.size() == 2);
|
||||
EXPECT_TRUE(discovered[0].name == "Device A");
|
||||
EXPECT_TRUE(discovered[0].address == "AA:BB:CC:DD:EE:FF");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothConnectionLimit(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
bluetooth.SetBluetoothPermission(true);
|
||||
|
||||
std::vector<std::shared_ptr<mosis::BluetoothConnection>> connections;
|
||||
std::string err;
|
||||
|
||||
// Create MAX_CONNECTIONS (5)
|
||||
for (int i = 0; i < 5; i++) {
|
||||
char addr[20];
|
||||
snprintf(addr, sizeof(addr), "AA:BB:CC:DD:EE:%02X", i);
|
||||
auto conn = bluetooth.Connect(addr, {}, err);
|
||||
EXPECT_TRUE(conn != nullptr);
|
||||
connections.push_back(conn);
|
||||
}
|
||||
|
||||
// 6th should fail
|
||||
auto extra = bluetooth.Connect("AA:BB:CC:DD:EE:FF", {}, err);
|
||||
EXPECT_TRUE(extra == nullptr);
|
||||
EXPECT_TRUE(err.find("limit") != std::string::npos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothSendReceive(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
bluetooth.SetBluetoothPermission(true);
|
||||
|
||||
std::string err;
|
||||
auto conn = bluetooth.Connect("AA:BB:CC:DD:EE:FF", {}, err);
|
||||
EXPECT_TRUE(conn != nullptr);
|
||||
EXPECT_TRUE(conn->IsConnected());
|
||||
|
||||
// Test send
|
||||
std::vector<uint8_t> data = {0x01, 0x02, 0x03};
|
||||
bool sent = conn->Send(data, err);
|
||||
EXPECT_TRUE(sent);
|
||||
|
||||
// Test receive via simulation
|
||||
std::vector<uint8_t> received;
|
||||
bool got_data = false;
|
||||
conn->SetOnData([&](const std::vector<uint8_t>& d) {
|
||||
got_data = true;
|
||||
received = d;
|
||||
});
|
||||
|
||||
std::vector<uint8_t> incoming = {0xAA, 0xBB};
|
||||
conn->SimulateData(incoming);
|
||||
|
||||
EXPECT_TRUE(got_data);
|
||||
EXPECT_TRUE(received.size() == 2);
|
||||
EXPECT_TRUE(received[0] == 0xAA);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothCleansUpOnShutdown(std::string& error_msg) {
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
bluetooth.SetBluetoothPermission(true);
|
||||
|
||||
std::string err;
|
||||
auto conn1 = bluetooth.Connect("AA:BB:CC:DD:EE:01", {}, err);
|
||||
auto conn2 = bluetooth.Connect("AA:BB:CC:DD:EE:02", {}, err);
|
||||
|
||||
EXPECT_TRUE(bluetooth.GetActiveConnectionCount() == 2);
|
||||
|
||||
bluetooth.Shutdown();
|
||||
|
||||
EXPECT_TRUE(bluetooth.GetActiveConnectionCount() == 0);
|
||||
EXPECT_TRUE(!conn1->IsConnected());
|
||||
EXPECT_TRUE(!conn2->IsConnected());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Test_BluetoothLuaIntegration(std::string& error_msg) {
|
||||
SandboxContext ctx = TestContext();
|
||||
LuaSandbox sandbox(ctx);
|
||||
|
||||
mosis::BluetoothInterface bluetooth("test.app");
|
||||
mosis::RegisterBluetoothAPI(sandbox.GetState(), &bluetooth);
|
||||
|
||||
std::string script = R"lua(
|
||||
-- Test that bluetooth global exists
|
||||
if not bluetooth then
|
||||
error("bluetooth global not found")
|
||||
end
|
||||
if not bluetooth.startDiscovery then
|
||||
error("bluetooth.startDiscovery not found")
|
||||
end
|
||||
if not bluetooth.stopDiscovery then
|
||||
error("bluetooth.stopDiscovery not found")
|
||||
end
|
||||
if not bluetooth.connect then
|
||||
error("bluetooth.connect not found")
|
||||
end
|
||||
if not bluetooth.disconnectAll then
|
||||
error("bluetooth.disconnectAll not found")
|
||||
end
|
||||
if not bluetooth.getConnectionCount then
|
||||
error("bluetooth.getConnectionCount not found")
|
||||
end
|
||||
if not bluetooth.isDiscovering then
|
||||
error("bluetooth.isDiscovering not found")
|
||||
end
|
||||
|
||||
-- Connection count should be 0 initially
|
||||
if bluetooth.getConnectionCount() ~= 0 then
|
||||
error("should have no active connections initially")
|
||||
end
|
||||
|
||||
-- Should not be discovering initially
|
||||
if bluetooth.isDiscovering() then
|
||||
error("should not be discovering initially")
|
||||
end
|
||||
)lua";
|
||||
|
||||
bool ok = sandbox.LoadString(script, "bluetooth_test");
|
||||
if (!ok) {
|
||||
error_msg = "Lua test failed: " + sandbox.GetLastError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// MAIN
|
||||
//=============================================================================
|
||||
@@ -2870,6 +3073,15 @@ int main(int argc, char* argv[]) {
|
||||
harness.AddTest("SensorCleansUpOnShutdown", Test_SensorCleansUpOnShutdown);
|
||||
harness.AddTest("SensorLuaIntegration", Test_SensorLuaIntegration);
|
||||
|
||||
// Milestone 16: Bluetooth
|
||||
harness.AddTest("BluetoothRequiresPermission", Test_BluetoothRequiresPermission);
|
||||
harness.AddTest("BluetoothRequiresUserConsent", Test_BluetoothRequiresUserConsent);
|
||||
harness.AddTest("BluetoothDiscoveryWorks", Test_BluetoothDiscoveryWorks);
|
||||
harness.AddTest("BluetoothConnectionLimit", Test_BluetoothConnectionLimit);
|
||||
harness.AddTest("BluetoothSendReceive", Test_BluetoothSendReceive);
|
||||
harness.AddTest("BluetoothCleansUpOnShutdown", Test_BluetoothCleansUpOnShutdown);
|
||||
harness.AddTest("BluetoothLuaIntegration", Test_BluetoothLuaIntegration);
|
||||
|
||||
// Run tests
|
||||
auto results = harness.Run(filter);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user