enh(MongoDB) More tests.

This commit is contained in:
Matej Kenda
2025-11-29 16:41:05 +01:00
parent 21db602f67
commit 20b3e4d770
9 changed files with 1423 additions and 124 deletions

View File

@@ -58,10 +58,13 @@ public:
Binary(const UUID& uuid);
/// Creates a Binary containing an UUID.
Binary(const char* data, unsigned char subtype = 0);
/// Creates a Binary with the contents of the given C-string and the given subtype.
Binary(const std::string& data, unsigned char subtype = 0);
/// Creates a Binary with the contents of the given string and the given subtype.
Binary(const void* data, Poco::Int32 size, unsigned char subtype = 0);
Binary(const void* data, Poco::Int32 size, unsigned char subtype);
/// Creates a Binary with the contents of the given buffer and the given subtype.
virtual ~Binary();

View File

@@ -49,6 +49,12 @@ Binary::Binary(const UUID& uuid):
}
Binary::Binary(const char* data, unsigned char subtype):
_buffer(reinterpret_cast<const unsigned char*>(data), std::strlen(data)),
_subtype(subtype)
{
}
Binary::Binary(const std::string& data, unsigned char subtype):
_buffer(reinterpret_cast<const unsigned char*>(data.data()), data.size()),

View File

@@ -14,7 +14,9 @@
#include "Poco/MongoDB/ObjectId.h"
#include "Poco/Format.h"
#include "Poco/Exception.h"
#include <cstring>
#include <cctype>
namespace Poco {
@@ -29,11 +31,18 @@ ObjectId::ObjectId()
ObjectId::ObjectId(const std::string& id)
{
poco_assert_dbg(id.size() == 24);
if (id.size() != 24)
throw Poco::InvalidArgumentException("ObjectId string must be exactly 24 hexadecimal characters");
const char* p = id.c_str();
for (std::size_t i = 0; i < 12; ++i)
{
// Validate that both characters are valid hex digits
if (!std::isxdigit(static_cast<unsigned char>(p[0])) ||
!std::isxdigit(static_cast<unsigned char>(p[1])))
{
throw Poco::InvalidArgumentException("ObjectId string contains invalid hexadecimal characters");
}
_id[i] = fromHex(p);
p += 2;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,94 @@
//
// BSONTest.h
//
// Definition of the BSONTest class.
//
// Copyright (c) 2004-2025, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef BSONTest_INCLUDED
#define BSONTest_INCLUDED
#include "Poco/MongoDB/MongoDB.h"
#include "CppUnit/TestCase.h"
class BSONTest: public CppUnit::TestCase
{
public:
BSONTest(const std::string& name);
virtual ~BSONTest();
void setUp();
void tearDown();
// Document tests
void testDocumentAddGet();
void testDocumentExists();
void testDocumentRemove();
void testDocumentClear();
void testDocumentSize();
void testDocumentElementNames();
void testNestedDocuments();
void testDuplicateDocumentMembers();
// Array tests
void testArray();
void testArrayIndexAccess();
void testArrayNested();
// Type tests
void testDouble();
void testString();
void testBool();
void testInt32();
void testInt64();
void testTimestamp();
void testNull();
void testBSONTimestamp();
// Binary tests
void testBinaryGeneric();
void testBinaryUUID();
void testBinarySubtypes();
// ObjectId tests
void testObjectID();
void testObjectIDTimestamp();
// RegularExpression tests
void testRegularExpression();
// JavaScriptCode tests
void testJavaScriptCode();
// Serialization/Deserialization tests
void testDocumentSerialization();
void testDocumentDeserialization();
void testArraySerialization();
void testComplexDocumentSerialization();
// toString tests
void testSimpleDocumentToString();
void testNestedDocumentToString();
void testDocumentWithArrayToString();
void testComplexDocumentToString();
void testToStringIndentation();
void testArrayToString();
// Failure/Error tests
void testGetNonExistent();
void testBadCast();
void testInvalidObjectID();
void testEmptyDocument();
static CppUnit::Test* suite();
};
#endif // BSONTest_INCLUDED

View File

@@ -27,6 +27,7 @@
using namespace Poco::MongoDB;
using namespace std::string_literals;
Poco::MongoDB::Connection::Ptr MongoDBTest::_mongo;
@@ -54,43 +55,6 @@ void MongoDBTest::tearDown()
}
void MongoDBTest::testArray()
{
Poco::MongoDB::Array::Ptr arr = new Poco::MongoDB::Array();
arr->add(std::string("First"));
Poco::DateTime birthdate;
birthdate.assign(1969, 3, 9);
arr->add(birthdate.timestamp());
arr->add(static_cast<Poco::Int32>(1993));
arr->add(false);
// Document-style interface
arr->add("4", "12.4E");
assertEqual(arr->size(), 5);
assertTrue(arr->exists("0"));
assertTrue(arr->exists("1"));
assertTrue(arr->exists("2"));
assertTrue(arr->exists("3"));
assertTrue(arr->exists("4"));
assertFalse(arr->exists("5"));
assertEqual(arr->get<std::string>(0), "First");
assertEqual(arr->get<Poco::Timestamp>(1).raw(), birthdate.timestamp().raw());
assertEqual(arr->get<Poco::Int32>(2), 1993);
assertEqual(arr->get<bool>(3), false);
assertEqual(arr->get<std::string>(4), "12.4E");
// Document-style interface
assertEqual(arr->get<Poco::Int32>("2"), 1993);
assertEqual(arr->get<std::string>("4"), "12.4E");
}
void MongoDBTest::testBuildInfo()
{
Poco::MongoDB::Database db("config");
@@ -187,8 +151,8 @@ void MongoDBTest::testDBCount()
request->setCommandName(OpMsgMessage::CMD_INSERT);
Document::Ptr player = new Document();
player->add("lastname", std::string("TestPlayer"));
player->add("firstname", std::string("Test"));
player->add("lastname"s, "TestPlayer"s);
player->add("firstname"s, "Test"s);
request->documents().push_back(player);
OpMsgMessage response;
@@ -203,7 +167,7 @@ void MongoDBTest::testDBCount()
request = db.createOpMsgMessage("players");
request->setCommandName(OpMsgMessage::CMD_DELETE);
Document::Ptr del = new Document();
del->add("limit", 0).addNewDocument("q").add("lastname" , std::string("TestPlayer"));
del->add("limit"s, 0).addNewDocument("q").add("lastname"s, "TestPlayer"s);
request->documents().push_back(del);
_mongo->sendRequest(*request, response);
}
@@ -235,7 +199,6 @@ CppUnit::Test* MongoDBTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MongoDBTest");
CppUnit_addTest(pSuite, MongoDBTest, testObjectID);
CppUnit_addTest(pSuite, MongoDBTest, testArray);
CppUnit_addTest(pSuite, MongoDBTest, testConnectURI);
CppUnit_addTest(pSuite, MongoDBTest, testHello);
CppUnit_addTest(pSuite, MongoDBTest, testBuildInfo);
@@ -258,8 +221,6 @@ CppUnit::Test* MongoDBTest::suite()
CppUnit_addTest(pSuite, MongoDBTest, testOpCmdCursorAggregate);
CppUnit_addTest(pSuite, MongoDBTest, testOpCmdKillCursor);
CppUnit_addTest(pSuite, MongoDBTest, testOpCmdCursorEmptyFirstBatch);
CppUnit_addTest(pSuite, MongoDBTest, testOpCmdUUID);
CppUnit_addTest(pSuite, MongoDBTest, testDBCount);

View File

@@ -30,13 +30,11 @@ public:
void tearDown();
void testObjectID();
void testArray();
void testBuildInfo();
void testHello();
void testConnectURI();
// OP_MSG wire protocol
void testOpCmdUUID();
void testOpCmdHello();
void testOpCmdWriteRead();
void testOpCmdInsert();

View File

@@ -23,60 +23,7 @@
using namespace Poco::MongoDB;
void MongoDBTest::testOpCmdUUID()
{
Database db("team");
Poco::SharedPtr<OpMsgMessage> request = db.createOpMsgMessage("club");
OpMsgMessage response;
request->setCommandName(OpMsgMessage::CMD_DROP);
_mongo->sendRequest(*request, response);
Document::Ptr club = new Document();
club->add("name", std::string("Barcelona"));
Poco::UUIDGenerator generator;
Poco::UUID uuid = generator.create();
Binary::Ptr uuidBinary = new Binary(uuid);
club->add("uuid", uuidBinary);
request->setCommandName(OpMsgMessage::CMD_INSERT);
request->documents().push_back(club);
_mongo->sendRequest(*request, response);
assertTrue(response.responseOk());
request->setCommandName(OpMsgMessage::CMD_FIND);
request->body().addNewDocument("filter").add("name", std::string("Barcelona"));
_mongo->sendRequest(*request, response);
assertTrue(response.responseOk());
if ( response.documents().size() > 0 )
{
Document::Ptr doc = response.documents()[0];
try
{
const auto& name = doc->get<std::string>("name");
assertEquals ("Barcelona", name );
Binary::Ptr uuidBinary = doc->get<Binary::Ptr>("uuid");
assertTrue (uuid == uuidBinary->uuid());
}
catch(Poco::NotFoundException& nfe)
{
fail(nfe.message() + " not found.");
}
}
else
{
fail("No document returned");
}
}
using namespace std::string_literals;
void MongoDBTest::testOpCmdHello()
@@ -110,11 +57,11 @@ void MongoDBTest::testOpCmdWriteRead()
request->setCommandName(OpMsgMessage::CMD_INSERT);
Document::Ptr doc = new Document();
doc->add("name", "John").add("number", -2);
doc->add("name"s, "John").add("number", -2);
request->documents().push_back(doc);
doc = new Document();
doc->add("name", "Franz").add("number", -2.8);
doc->add("name"s, "Franz").add("number", -2.8);
request->documents().push_back(doc);
try
@@ -142,20 +89,20 @@ void MongoDBTest::testOpCmdWriteRead()
void MongoDBTest::testOpCmdInsert()
{
Document::Ptr player = new Document();
player->add("lastname", std::string("Braem"));
player->add("firstname", std::string("Franky"));
player->add("lastname"s, "Braem"s);
player->add("firstname"s, "Franky"s);
Poco::DateTime birthdate;
birthdate.assign(1969, 3, 9);
player->add("birthdate", birthdate.timestamp());
player->add("birthdate"s, birthdate.timestamp());
player->add("start", 1993);
player->add("active", false);
player->add("start"s, 1993);
player->add("active"s, false);
Poco::DateTime now;
player->add("lastupdated", now.timestamp());
player->add("lastupdated"s, now.timestamp());
player->add("unknown", NullValue());
player->add("unknown"s, NullValue());
Database db("team");
Poco::SharedPtr<OpMsgMessage> request = db.createOpMsgMessage("players");
@@ -181,7 +128,7 @@ void MongoDBTest::testOpCmdFind()
Poco::SharedPtr<OpMsgMessage> request = db.createOpMsgMessage("players");
request->setCommandName(OpMsgMessage::CMD_FIND);
request->body().add("limit", 1).addNewDocument("filter").add("lastname" , std::string("Braem"));
request->body().add("limit"s, 1).addNewDocument("filter").add("lastname"s, "Braem"s);
OpMsgMessage response;
_mongo->sendRequest(*request, response);
@@ -223,20 +170,20 @@ void MongoDBTest::testOpCmdFind()
void MongoDBTest::testOpCmdUnaknowledgedInsert()
{
Document::Ptr player = new Document();
player->add("lastname", std::string("Braem"));
player->add("firstname", std::string("Franky"));
player->add("lastname"s, "Braem"s);
player->add("firstname"s, "Franky"s);
Poco::DateTime birthdate;
birthdate.assign(1969, 3, 9);
player->add("birthdate", birthdate.timestamp());
player->add("birthdate"s, birthdate.timestamp());
player->add("start", 1993);
player->add("active", false);
player->add("start"s, 1993);
player->add("active"s, false);
Poco::DateTime now;
player->add("lastupdated", now.timestamp());
player->add("lastupdated"s, now.timestamp());
player->add("unknown", NullValue());
player->add("unknown"s, NullValue());
Database db("team");
Poco::SharedPtr<OpMsgMessage> request = db.createOpMsgMessage("players");
@@ -269,7 +216,7 @@ void MongoDBTest::testOpCmdCursor()
for(int i = 0; i < 10000; ++i)
{
Document::Ptr doc = new Document();
doc->add("number", i);
doc->add("number"s, i);
request->documents().push_back(doc);
}
_mongo->sendRequest(*request, response);
@@ -309,7 +256,7 @@ void MongoDBTest::testOpCmdCursorAggregate()
for(int i = 0; i < 10000; ++i)
{
Document::Ptr doc = new Document();
doc->add("number", i);
doc->add("number"s, i);
request->documents().push_back(doc);
}
_mongo->sendRequest(*request, response);
@@ -356,7 +303,7 @@ void MongoDBTest::testOpCmdKillCursor()
for(int i = 0; i < 10000; ++i)
{
Document::Ptr doc = new Document();
doc->add("number", i);
doc->add("number"s, i);
request->documents().push_back(doc);
}
_mongo->sendRequest(*request, response);
@@ -413,7 +360,7 @@ void MongoDBTest::testOpCmdCursorEmptyFirstBatch()
for(int i = 0; i < 10000; ++i)
{
Document::Ptr doc = new Document();
doc->add("number", i);
doc->add("number"s, i);
request->documents().push_back(doc);
}
_mongo->sendRequest(*request, response);
@@ -453,7 +400,7 @@ void MongoDBTest::testOpCmdDelete()
request->setCommandName(OpMsgMessage::CMD_DELETE);
Document::Ptr del = new Document();
del->add("limit", 0).addNewDocument("q").add("lastname" , std::string("Braem"));
del->add("limit"s, 0).addNewDocument("q").add("lastname"s, "Braem"s);
request->documents().push_back(del);
OpMsgMessage response;

View File

@@ -10,13 +10,20 @@
#include "MongoDBTestSuite.h"
#include "MongoDBTest.h"
#include "BSONTest.h"
CppUnit::Test* MongoDBTestSuite::suite()
{
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MongoDBTestSuite");
pSuite->addTest(MongoDBTest::suite());
pSuite->addTest(BSONTest::suite());
CppUnit::Test* mongoTests = MongoDBTest::suite();
if (mongoTests != nullptr)
{
pSuite->addTest(mongoTests);
}
return pSuite;
}