#include "../service/src/views/projection.hpp" #include #include #include using smartbotic::database::applyProjection; void test_empty_projection_returns_document_unchanged() { nlohmann::json doc = {{"name", "Alice"}, {"age", 30}}; auto result = applyProjection(doc, {}, {}); assert(result == doc); std::cout << "PASS: empty projection returns document unchanged\n"; } void test_include_keeps_only_listed_fields() { nlohmann::json doc = {{"name", "Alice"}, {"email", "a@x.com"}, {"password", "secret"}}; auto result = applyProjection(doc, {"name", "email"}, {}); assert(result.contains("name")); assert(result.contains("email")); assert(!result.contains("password")); std::cout << "PASS: include keeps only listed fields\n"; } void test_exclude_removes_fields() { nlohmann::json doc = {{"name", "Alice"}, {"email", "a@x.com"}, {"password", "secret"}}; auto result = applyProjection(doc, {}, {"password"}); assert(result.contains("name")); assert(result.contains("email")); assert(!result.contains("password")); std::cout << "PASS: exclude removes fields\n"; } void test_include_takes_precedence_over_exclude() { nlohmann::json doc = {{"a", 1}, {"b", 2}, {"c", 3}}; auto result = applyProjection(doc, {"a"}, {"b", "c"}); assert(result.contains("a")); assert(!result.contains("b")); assert(!result.contains("c")); assert(result.size() == 1); std::cout << "PASS: include takes precedence over exclude\n"; } void test_nested_include_path() { nlohmann::json doc = { {"user", { {"profile", {{"name", "Alice"}, {"bio", "hi"}}}, {"private", {{"ssn", "123"}}} }} }; auto result = applyProjection(doc, {"user.profile.name"}, {}); assert(result["user"]["profile"]["name"] == "Alice"); assert(!result["user"]["profile"].contains("bio")); assert(!result["user"].contains("private")); std::cout << "PASS: nested include path\n"; } void test_nested_exclude_path() { nlohmann::json doc = { {"user", { {"name", "Alice"}, {"private", {{"ssn", "123"}, {"email", "a@x.com"}}} }} }; auto result = applyProjection(doc, {}, {"user.private.ssn"}); assert(result["user"]["name"] == "Alice"); assert(result["user"]["private"]["email"] == "a@x.com"); assert(!result["user"]["private"].contains("ssn")); std::cout << "PASS: nested exclude path\n"; } void test_metadata_always_preserved_with_include() { nlohmann::json doc = { {"_id", "doc-1"}, {"_version", 5}, {"name", "Alice"}, {"secret", "xyz"} }; auto result = applyProjection(doc, {"name"}, {}); assert(result.contains("_id")); assert(result.contains("_version")); assert(result.contains("name")); assert(!result.contains("secret")); std::cout << "PASS: metadata always preserved with include\n"; } void test_metadata_cannot_be_excluded() { nlohmann::json doc = {{"_id", "doc-1"}, {"_version", 5}, {"name", "Alice"}}; auto result = applyProjection(doc, {}, {"_id", "_version"}); assert(result.contains("_id")); assert(result.contains("_version")); std::cout << "PASS: metadata cannot be excluded\n"; } void test_missing_path_silently_skipped() { nlohmann::json doc = {{"name", "Alice"}}; auto result = applyProjection(doc, {"user.profile.name"}, {}); assert(!result.contains("user")); std::cout << "PASS: missing path silently skipped\n"; } int main() { test_empty_projection_returns_document_unchanged(); test_include_keeps_only_listed_fields(); test_exclude_removes_fields(); test_include_takes_precedence_over_exclude(); test_nested_include_path(); test_nested_exclude_path(); test_metadata_always_preserved_with_include(); test_metadata_cannot_be_excluded(); test_missing_path_silently_skipped(); std::cout << "\nAll view projection tests PASSED!\n"; return 0; }