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 | |
32 | using namespace Poco::MongoDB; |
33 | |
34 | |
35 | Poco::MongoDB::Connection::Ptr MongoDBTest::_mongo; |
36 | |
37 | namespace |
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 | |
53 | MongoDBTest::MongoDBTest(const std::string& name): |
54 | CppUnit::TestCase("MongoDB" ) |
55 | { |
56 | } |
57 | |
58 | |
59 | MongoDBTest::~MongoDBTest() |
60 | { |
61 | } |
62 | |
63 | |
64 | void MongoDBTest::setUp() |
65 | { |
66 | } |
67 | |
68 | |
69 | void MongoDBTest::tearDown() |
70 | { |
71 | } |
72 | |
73 | |
74 | void 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 | |
104 | void 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 | |
148 | void 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 | |
187 | void 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 | |
209 | void 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 | |
229 | void MongoDBTest::testDBCount2Command() |
230 | { |
231 | Poco::MongoDB::Database db("team" ); |
232 | Poco::Int64 count = db.count(*_mongo, "players" ); |
233 | assertTrue (count == 1); |
234 | } |
235 | |
236 | |
237 | void 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 | |
246 | void 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 | |
287 | void 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 | |
317 | void 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 | |
345 | void MongoDBTest::testObjectID() |
346 | { |
347 | ObjectId oid("536aeebba081de6815000002" ); |
348 | std::string str2 = oid.toString(); |
349 | assertTrue (str2 == "536aeebba081de6815000002" ); |
350 | } |
351 | |
352 | |
353 | void 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 | |
375 | void 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 | |
424 | void 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 | |
469 | CppUnit::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 | |