implement Milestone 17: Contacts interface with read/write permissions

This commit is contained in:
2026-01-18 16:29:07 +01:00
parent 00b9ceb467
commit 72a06f542b
6 changed files with 1230 additions and 1 deletions

View File

@@ -30,6 +30,7 @@ add_library(mosis-sandbox STATIC
../src/main/cpp/sandbox/location_interface.cpp
../src/main/cpp/sandbox/sensor_interface.cpp
../src/main/cpp/sandbox/bluetooth_interface.cpp
../src/main/cpp/sandbox/contacts_interface.cpp
)
target_include_directories(mosis-sandbox PUBLIC
../src/main/cpp/sandbox

View File

@@ -20,6 +20,7 @@
#include "location_interface.h"
#include "sensor_interface.h"
#include "bluetooth_interface.h"
#include "contacts_interface.h"
#include <filesystem>
#include <fstream>
#include <sstream>
@@ -2890,6 +2891,190 @@ bool Test_BluetoothLuaIntegration(std::string& error_msg) {
return true;
}
//=============================================================================
// Milestone 17: Contacts
//=============================================================================
bool Test_ContactsRequiresReadPermission(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
// No permission granted
std::string err;
auto results = contacts.Query({}, err);
EXPECT_TRUE(results.empty());
EXPECT_TRUE(err.find("permission") != std::string::npos);
return true;
}
bool Test_ContactsRequiresWritePermission(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
contacts.SetReadPermission(true); // Read OK, but not write
std::string err;
mosis::Contact contact;
contact.name = "John Doe";
contact.phone = "555-1234";
contact.email = "john@test.com";
int id = contacts.Add(contact, err);
EXPECT_TRUE(id == 0); // Failed
EXPECT_TRUE(err.find("permission") != std::string::npos);
return true;
}
bool Test_ContactsQueryWorks(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
contacts.SetReadPermission(true);
// Set mock contacts
std::vector<mosis::Contact> mockContacts = {
{1, "John Doe", "555-1234", "john@test.com"},
{2, "Jane Doe", "555-5678", "jane@test.com"},
{3, "Bob Smith", "555-9999", "bob@test.com"}
};
contacts.SetMockContacts(mockContacts);
std::string err;
mosis::QueryOptions opts;
opts.search = "Doe";
auto results = contacts.Query(opts, err);
EXPECT_TRUE(err.empty());
EXPECT_TRUE(results.size() == 2); // John and Jane
return true;
}
bool Test_ContactsQueryLimit(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
contacts.SetReadPermission(true);
// Set 50 mock contacts
std::vector<mosis::Contact> mockContacts;
for (int i = 0; i < 50; i++) {
mosis::Contact c;
c.id = i + 1;
c.name = "Contact " + std::to_string(i);
c.phone = "555-" + std::to_string(i);
mockContacts.push_back(c);
}
contacts.SetMockContacts(mockContacts);
std::string err;
// Query with limit
mosis::QueryOptions opts;
opts.limit = 10;
auto results = contacts.Query(opts, err);
EXPECT_TRUE(results.size() == 10);
// Query with excessive limit (gets all contacts < MAX_RESULTS)
opts.limit = 200;
results = contacts.Query(opts, err);
EXPECT_TRUE(results.size() == 50); // All contacts
return true;
}
bool Test_ContactsCRUD(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
contacts.SetReadPermission(true);
contacts.SetWritePermission(true);
std::string err;
// Add
mosis::Contact newContact;
newContact.name = "Test User";
newContact.phone = "555-1111";
newContact.email = "test@test.com";
int id = contacts.Add(newContact, err);
EXPECT_TRUE(id > 0);
EXPECT_TRUE(err.empty());
// Read back
auto contact = contacts.GetById(id, err);
EXPECT_TRUE(contact.has_value());
EXPECT_TRUE(contact->name == "Test User");
// Update
contact->name = "Updated User";
contact->phone = "555-2222";
bool updated = contacts.Update(*contact, err);
EXPECT_TRUE(updated);
// Verify update
contact = contacts.GetById(id, err);
EXPECT_TRUE(contact->name == "Updated User");
EXPECT_TRUE(contact->phone == "555-2222");
// Delete
bool deleted = contacts.Delete(id, err);
EXPECT_TRUE(deleted);
// Verify deleted
contact = contacts.GetById(id, err);
EXPECT_TRUE(!contact.has_value());
return true;
}
bool Test_ContactsDeleteNotFound(std::string& error_msg) {
mosis::ContactsInterface contacts("test.app");
contacts.SetWritePermission(true);
std::string err;
bool deleted = contacts.Delete(99999, err);
EXPECT_TRUE(!deleted);
EXPECT_TRUE(err.find("not found") != std::string::npos);
return true;
}
bool Test_ContactsLuaIntegration(std::string& error_msg) {
SandboxContext ctx = TestContext();
LuaSandbox sandbox(ctx);
mosis::ContactsInterface contacts("test.app");
mosis::RegisterContactsAPI(sandbox.GetState(), &contacts);
std::string script = R"lua(
-- Test that contacts global exists
if not contacts then
error("contacts global not found")
end
if not contacts.query then
error("contacts.query not found")
end
if not contacts.getById then
error("contacts.getById not found")
end
if not contacts.getCount then
error("contacts.getCount not found")
end
if not contacts.add then
error("contacts.add not found")
end
if not contacts.update then
error("contacts.update not found")
end
if not contacts.delete then
error("contacts.delete not found")
end
)lua";
bool ok = sandbox.LoadString(script, "contacts_test");
if (!ok) {
error_msg = "Lua test failed: " + sandbox.GetLastError();
return false;
}
return true;
}
//=============================================================================
// MAIN
//=============================================================================
@@ -3082,6 +3267,15 @@ int main(int argc, char* argv[]) {
harness.AddTest("BluetoothCleansUpOnShutdown", Test_BluetoothCleansUpOnShutdown);
harness.AddTest("BluetoothLuaIntegration", Test_BluetoothLuaIntegration);
// Milestone 17: Contacts
harness.AddTest("ContactsRequiresReadPermission", Test_ContactsRequiresReadPermission);
harness.AddTest("ContactsRequiresWritePermission", Test_ContactsRequiresWritePermission);
harness.AddTest("ContactsQueryWorks", Test_ContactsQueryWorks);
harness.AddTest("ContactsQueryLimit", Test_ContactsQueryLimit);
harness.AddTest("ContactsCRUD", Test_ContactsCRUD);
harness.AddTest("ContactsDeleteNotFound", Test_ContactsDeleteNotFound);
harness.AddTest("ContactsLuaIntegration", Test_ContactsLuaIntegration);
// Run tests
auto results = harness.Run(filter);