1//
2// MongoDBTest.cpp
3//
4// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "Poco/DateTime.h"
12#include "Poco/ObjectPool.h"
13#include "Poco/Environment.h"
14#include "Poco/MongoDB/InsertRequest.h"
15#include "Poco/MongoDB/QueryRequest.h"
16#include "Poco/MongoDB/DeleteRequest.h"
17#include "Poco/MongoDB/GetMoreRequest.h"
18#include "Poco/MongoDB/PoolableConnectionFactory.h"
19#include "Poco/MongoDB/Database.h"
20#include "Poco/MongoDB/Cursor.h"
21#include "Poco/MongoDB/ObjectId.h"
22#include "Poco/MongoDB/Binary.h"
23#include "Poco/MongoDB/Array.h"
24#include "Poco/Net/NetException.h"
25#include "Poco/UUIDGenerator.h"
26#include "Poco/CppUnit/TestCaller.h"
27#include "Poco/CppUnit/TestSuite.h"
28#include "MongoDBTest.h"
29#include <iostream>
30
31
32using namespace Poco::MongoDB;
33
34
35Poco::MongoDB::Connection::Ptr MongoDBTest::_mongo;
36
37namespace
38{
39 std::string getHost()
40 {
41#if POCO_OS == POCO_OS_ANDROID
42 return "10.0.2.2";
43#else
44 if(Poco::Environment::has("MONGODB_HOST"))
45 return Poco::Environment::get("MONGODB_HOST");
46 else
47 return "127.0.0.1";
48#endif
49 }
50}
51
52
53MongoDBTest::MongoDBTest(const std::string& name):
54 CppUnit::TestCase("MongoDB")
55{
56}
57
58
59MongoDBTest::~MongoDBTest()
60{
61}
62
63
64void MongoDBTest::setUp()
65{
66}
67
68
69void MongoDBTest::tearDown()
70{
71}
72
73
74void MongoDBTest::testInsertRequest()
75{
76 Poco::MongoDB::Document::Ptr player = new Poco::MongoDB::Document();
77 player->add("lastname", std::string("Braem"));
78 player->add("firstname", std::string("Franky"));
79
80 Poco::DateTime birthdate;
81 birthdate.assign(1969, 3, 9);
82 player->add("birthdate", birthdate.timestamp());
83
84 player->add("start", 1993);
85 player->add("active", false);
86
87 Poco::DateTime now;
88 player->add("lastupdated", now.timestamp());
89
90 player->add("unknown", NullValue());
91
92 Poco::MongoDB::Array::Ptr points = new Poco::MongoDB::Array();
93 points->add<Poco::Int32>("0", 0);
94 points->add<Poco::Int64>("1", 1);
95 points->add<double>("2", 2);
96 player->add("points", points);
97
98 Poco::MongoDB::InsertRequest request("team.players");
99 request.documents().push_back(player);
100 _mongo->sendRequest(request);
101}
102
103
104void MongoDBTest::testQueryRequest()
105{
106 Poco::MongoDB::QueryRequest request("team.players");
107 request.selector().add("lastname" , std::string("Braem"));
108 request.setNumberToReturn(1);
109
110 Poco::MongoDB::ResponseMessage response;
111
112 _mongo->sendRequest(request, response);
113
114 if ( response.documents().size() > 0 )
115 {
116 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
117
118 try
119 {
120 std::string lastname = doc->get<std::string>("lastname");
121 assertTrue (lastname.compare("Braem") == 0);
122 std::string firstname = doc->get<std::string>("firstname");
123 assertTrue (firstname.compare("Franky") == 0);
124 Poco::Timestamp birthDateTimestamp = doc->get<Poco::Timestamp>("birthdate");
125 Poco::DateTime birthDate(birthDateTimestamp);
126 assertTrue (birthDate.year() == 1969 && birthDate.month() == 3 && birthDate.day() == 9);
127 Poco::Timestamp lastupdatedTimestamp = doc->get<Poco::Timestamp>("lastupdated");
128 assertTrue (doc->isType<NullValue>("unknown"));
129 bool active = doc->get<bool>("active");
130 assertTrue (!active);
131 Poco::MongoDB::Array::Ptr points = doc->get<Poco::MongoDB::Array::Ptr>("points");
132 assertTrue (points->getInteger(0) == 0 && points->getInteger(1) == 1 && points->getInteger(2) == 2);
133
134 std::string id = doc->get("_id")->toString();
135 }
136 catch(Poco::NotFoundException& nfe)
137 {
138 fail(nfe.message() + " not found.");
139 }
140 }
141 else
142 {
143 fail("No document returned");
144 }
145}
146
147
148void MongoDBTest::testDBQueryRequest()
149{
150 Database db("team");
151 Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = db.createQueryRequest("players");
152 request->selector().add("lastname" , std::string("Braem"));
153
154 Poco::MongoDB::ResponseMessage response;
155 _mongo->sendRequest(*request, response);
156
157 if ( response.documents().size() > 0 )
158 {
159 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
160
161 try
162 {
163 std::string lastname = doc->get<std::string>("lastname");
164 assertTrue (lastname.compare("Braem") == 0);
165 std::string firstname = doc->get<std::string>("firstname");
166 assertTrue (firstname.compare("Franky") == 0);
167 Poco::Timestamp birthDateTimestamp = doc->get<Poco::Timestamp>("birthdate");
168 Poco::DateTime birthDate(birthDateTimestamp);
169 assertTrue (birthDate.year() == 1969 && birthDate.month() == 3 && birthDate.day() == 9);
170 Poco::Timestamp lastupdatedTimestamp = doc->get<Poco::Timestamp>("lastupdated");
171 assertTrue (doc->isType<NullValue>("unknown"));
172
173 std::string id = doc->get("_id")->toString();
174 }
175 catch(Poco::NotFoundException& nfe)
176 {
177 fail(nfe.message() + " not found.");
178 }
179 }
180 else
181 {
182 fail("No document returned");
183 }
184}
185
186
187void MongoDBTest::testCountCommand()
188{
189 Poco::MongoDB::QueryRequest request("team.$cmd");
190 request.setNumberToReturn(1);
191 request.selector().add("count", std::string("players"));
192
193 Poco::MongoDB::ResponseMessage response;
194
195 _mongo->sendRequest(request, response);
196
197 if ( response.documents().size() > 0 )
198 {
199 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
200 assertTrue (doc->getInteger("n") == 1);
201 }
202 else
203 {
204 fail("Didn't get a response from the count command");
205 }
206}
207
208
209void MongoDBTest::testDBCountCommand()
210{
211 Poco::MongoDB::Database db("team");
212 Poco::SharedPtr<Poco::MongoDB::QueryRequest> request = db.createCountRequest("players");
213
214 Poco::MongoDB::ResponseMessage response;
215 _mongo->sendRequest(*request, response);
216
217 if ( response.documents().size() > 0 )
218 {
219 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
220 assertTrue (doc->getInteger("n") == 1);
221 }
222 else
223 {
224 fail("Didn't get a response from the count command");
225 }
226}
227
228
229void MongoDBTest::testDBCount2Command()
230{
231 Poco::MongoDB::Database db("team");
232 Poco::Int64 count = db.count(*_mongo, "players");
233 assertTrue (count == 1);
234}
235
236
237void MongoDBTest::testDeleteRequest()
238{
239 Poco::MongoDB::DeleteRequest request("team.players");
240 request.selector().add("lastname", std::string("Braem"));
241
242 _mongo->sendRequest(request);
243}
244
245
246void MongoDBTest::testCursorRequest()
247{
248 Poco::MongoDB::Database db("team");
249
250 Poco::SharedPtr<Poco::MongoDB::DeleteRequest> deleteRequest = db.createDeleteRequest("numbers");
251 _mongo->sendRequest(*deleteRequest);
252
253 Poco::SharedPtr<Poco::MongoDB::InsertRequest> insertRequest = db.createInsertRequest("numbers");
254 for(int i = 0; i < 10000; ++i)
255 {
256 Document::Ptr doc = new Document();
257 doc->add("number", i);
258 insertRequest->documents().push_back(doc);
259 }
260 _mongo->sendRequest(*insertRequest);
261
262 Poco::Int64 count = db.count(*_mongo, "numbers");
263 assertTrue (count == 10000);
264
265 Poco::MongoDB::Cursor cursor("team", "numbers");
266
267 int n = 0;
268 Poco::MongoDB::ResponseMessage& response = cursor.next(*_mongo);
269 while(1)
270 {
271 n += static_cast<int>(response.documents().size());
272 if ( response.cursorID() == 0 )
273 break;
274 response = cursor.next(*_mongo);
275 }
276 assertTrue (n == 10000);
277
278 Poco::MongoDB::QueryRequest drop("team.$cmd");
279 drop.setNumberToReturn(1);
280 drop.selector().add("drop", std::string("numbers"));
281
282 Poco::MongoDB::ResponseMessage responseDrop;
283 _mongo->sendRequest(drop, responseDrop);
284}
285
286
287void MongoDBTest::testBuildInfo()
288{
289 Poco::MongoDB::QueryRequest request("team.$cmd");
290 request.setNumberToReturn(1);
291 request.selector().add("buildInfo", 1);
292
293 Poco::MongoDB::ResponseMessage response;
294
295 try
296 {
297 _mongo->sendRequest(request, response);
298 }
299 catch(Poco::NotImplementedException& nie)
300 {
301 std::cout << nie.message() << std::endl;
302 return;
303 }
304
305 if ( response.documents().size() > 0 )
306 {
307 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
308 std::cout << doc->toString(2);
309 }
310 else
311 {
312 fail("Didn't get a response from the buildinfo command");
313 }
314}
315
316
317void MongoDBTest::testConnectionPool()
318{
319 std::string host = getHost();
320 Poco::Net::SocketAddress sa(host, 27017);
321 Poco::PoolableObjectFactory<Poco::MongoDB::Connection, Poco::MongoDB::Connection::Ptr> factory(sa);
322 Poco::ObjectPool<Poco::MongoDB::Connection, Poco::MongoDB::Connection::Ptr> pool(factory, 10, 15);
323
324 Poco::MongoDB::PooledConnection pooledConnection(pool);
325
326 Poco::MongoDB::QueryRequest request("team.$cmd");
327 request.setNumberToReturn(1);
328 request.selector().add("count", std::string("players"));
329
330 Poco::MongoDB::ResponseMessage response;
331 ((Connection::Ptr) pooledConnection)->sendRequest(request, response);
332
333 if ( response.documents().size() > 0 )
334 {
335 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
336 assertTrue (doc->getInteger("n") == 1);
337 }
338 else
339 {
340 fail("Didn't get a response from the count command");
341 }
342}
343
344
345void MongoDBTest::testObjectID()
346{
347 ObjectId oid("536aeebba081de6815000002");
348 std::string str2 = oid.toString();
349 assertTrue (str2 == "536aeebba081de6815000002");
350}
351
352
353void MongoDBTest::testCommand() {
354 Poco::MongoDB::Database db("team");
355 Poco::SharedPtr<Poco::MongoDB::QueryRequest> command = db.createCommand();
356 command->selector().add("create", "fixCol")
357 .add("capped", true)
358 .add("max", 1024*1024)
359 .add("size", 1024);
360
361 Poco::MongoDB::ResponseMessage response;
362 _mongo->sendRequest(*command, response);
363 if ( response.documents().size() > 0 )
364 {
365 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
366 }
367 else
368 {
369 Poco::MongoDB::Document::Ptr lastError = db.getLastErrorDoc(*_mongo);
370 fail(lastError->toString(2));
371 }
372}
373
374
375void MongoDBTest::testUUID()
376{
377 Poco::MongoDB::Document::Ptr club = new Poco::MongoDB::Document();
378 club->add("name", std::string("Barcelona"));
379
380 Poco::UUIDGenerator generator;
381 Poco::UUID uuid = generator.create();
382 Poco::MongoDB::Binary::Ptr uuidBinary = new Poco::MongoDB::Binary(uuid);
383 club->add("uuid", uuidBinary);
384
385 Poco::MongoDB::InsertRequest request("team.club");
386 request.documents().push_back(club);
387
388 _mongo->sendRequest(request);
389
390 Poco::MongoDB::QueryRequest queryReq("team.club");
391 queryReq.selector().add("name" , std::string("Barcelona"));
392
393 Poco::MongoDB::ResponseMessage response;
394 _mongo->sendRequest(queryReq, response);
395
396 if ( response.documents().size() > 0 )
397 {
398 Poco::MongoDB::Document::Ptr doc = response.documents()[0];
399
400 try
401 {
402 std::string name = doc->get<std::string>("name");
403 assertTrue (name.compare("Barcelona") == 0);
404
405 Poco::MongoDB::Binary::Ptr uuidBinary = doc->get<Binary::Ptr>("uuid");
406 assertTrue (uuid == uuidBinary->uuid());
407 }
408 catch(Poco::NotFoundException& nfe)
409 {
410 fail(nfe.message() + " not found.");
411 }
412 }
413 else
414 {
415 fail("No document returned");
416 }
417
418 Poco::MongoDB::DeleteRequest delRequest("team.club");
419 delRequest.selector().add("name", std::string("Barcelona"));
420 _mongo->sendRequest(delRequest);
421}
422
423
424void MongoDBTest::testConnectURI()
425{
426 Poco::MongoDB::Connection conn;
427 Poco::MongoDB::Connection::SocketFactory sf;
428 std::string host = getHost();
429 conn.connect("mongodb://" + host, sf);
430 conn.disconnect();
431
432 try
433 {
434 conn.connect("http://" + host, sf);
435 fail("invalid URI scheme - must throw");
436 }
437 catch (Poco::UnknownURISchemeException&)
438 {
439 }
440
441 try
442 {
443 conn.connect("mongodb://" + host + "?ssl=true", sf);
444 fail("SSL not supported, must throw");
445 }
446 catch (Poco::NotImplementedException&)
447 {
448 }
449
450 conn.connect("mongodb://" + host + "/admin?ssl=false&connectTimeoutMS=10000&socketTimeoutMS=10000", sf);
451 conn.disconnect();
452
453 try
454 {
455 conn.connect("mongodb://" + host + "/admin?connectTimeoutMS=foo", sf);
456 fail("invalid parameter - must throw");
457 }
458 catch (Poco::Exception&)
459 {
460 }
461
462#ifdef MONGODB_TEST_AUTH
463 conn.connect("mongodb://admin:admin@127.0.0.1/admin", sf);
464 conn.disconnect();
465#endif
466}
467
468
469CppUnit::Test* MongoDBTest::suite()
470{
471 std::string host = getHost();
472 try
473 {
474 _mongo = new Poco::MongoDB::Connection(host, 27017);
475 std::cout << "Connected to [" << host << ":27017]" << std::endl;
476 }
477 catch (Poco::Net::ConnectionRefusedException& e)
478 {
479 std::cout << "Couldn't connect to " << e.message() << ". " << std::endl;
480 return 0;
481 }
482 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MongoDBTest");
483 CppUnit_addTest(pSuite, MongoDBTest, testBuildInfo);
484 CppUnit_addTest(pSuite, MongoDBTest, testInsertRequest);
485 CppUnit_addTest(pSuite, MongoDBTest, testQueryRequest);
486 CppUnit_addTest(pSuite, MongoDBTest, testDBQueryRequest);
487 CppUnit_addTest(pSuite, MongoDBTest, testCountCommand);
488 CppUnit_addTest(pSuite, MongoDBTest, testDBCountCommand);
489 CppUnit_addTest(pSuite, MongoDBTest, testDBCount2Command);
490 CppUnit_addTest(pSuite, MongoDBTest, testConnectionPool);
491 CppUnit_addTest(pSuite, MongoDBTest, testDeleteRequest);
492 CppUnit_addTest(pSuite, MongoDBTest, testCursorRequest);
493 CppUnit_addTest(pSuite, MongoDBTest, testObjectID);
494 CppUnit_addTest(pSuite, MongoDBTest, testCommand);
495 CppUnit_addTest(pSuite, MongoDBTest, testUUID);
496 CppUnit_addTest(pSuite, MongoDBTest, testConnectURI);
497 return pSuite;
498}
499