2 * Copyright (c) 2010-2024 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.persistence.mongodb.internal;
15 import static org.junit.jupiter.api.Assertions.assertEquals;
16 import static org.junit.jupiter.api.Assertions.assertTrue;
18 import java.text.DateFormat;
19 import java.time.LocalDate;
20 import java.time.ZoneId;
21 import java.time.ZonedDateTime;
22 import java.time.temporal.ChronoUnit;
23 import java.util.ArrayList;
24 import java.util.Date;
25 import java.util.List;
28 import java.util.stream.Collectors;
30 import org.bson.Document;
31 import org.bson.types.ObjectId;
32 import org.junit.jupiter.api.Test;
33 import org.junit.jupiter.params.ParameterizedTest;
34 import org.junit.jupiter.params.provider.MethodSource;
35 import org.mockito.Mockito;
36 import org.openhab.core.items.GenericItem;
37 import org.openhab.core.items.ItemNotFoundException;
38 import org.openhab.core.library.items.ColorItem;
39 import org.openhab.core.library.items.DateTimeItem;
40 import org.openhab.core.library.items.ImageItem;
41 import org.openhab.core.library.items.NumberItem;
42 import org.openhab.core.library.items.StringItem;
43 import org.openhab.core.library.types.DateTimeType;
44 import org.openhab.core.library.types.DecimalType;
45 import org.openhab.core.library.types.HSBType;
46 import org.openhab.core.library.types.QuantityType;
47 import org.openhab.core.library.types.RawType;
48 import org.openhab.core.persistence.FilterCriteria;
49 import org.openhab.core.persistence.HistoricItem;
50 import org.osgi.framework.BundleContext;
52 import com.mongodb.client.MongoCollection;
53 import com.mongodb.client.MongoDatabase;
55 import ch.qos.logback.classic.Level;
56 import ch.qos.logback.classic.spi.ILoggingEvent;
57 import ch.qos.logback.core.read.ListAppender;
58 import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
61 * This is the implementation of the test for MongoDB {@link PersistenceService}.
63 * @author René Ulbricht - Initial contribution
65 public class MongoDBPersistenceServiceTest {
68 * Tests the activate method of MongoDBPersistenceService.
70 * This test checks if the activate method correctly logs the MongoDB URL, database, and collection.
71 * It uses different database backends provided by the provideDatabaseBackends method.
73 * @param dbContainer The container running the MongoDB instance.
76 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
77 public void testActivate(DatabaseTestContainer dbContainer) {
80 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
83 ListAppender<ILoggingEvent> listAppender = DataCreationHelper.setupLogger(MongoDBPersistenceService.class,
87 setupResult.service.activate(setupResult.bundleContext, setupResult.config);
90 List<ILoggingEvent> logsList = listAppender.list;
91 VerificationHelper.verifyLogMessage(logsList.get(0), "MongoDB URL " + dbContainer.getConnectionString(),
93 VerificationHelper.verifyLogMessage(logsList.get(1), "MongoDB database " + setupResult.dbname, Level.DEBUG);
94 VerificationHelper.verifyLogMessage(logsList.get(2), "MongoDB collection testCollection", Level.DEBUG);
101 * Tests the deactivate method of MongoDBPersistenceService.
103 * This test checks if the deactivate method correctly logs a message when the MongoDB persistence bundle is
105 * It uses different database backends provided by the provideDatabaseBackends method.
107 * @param dbContainer The container running the MongoDB instance.
110 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
111 public void testDeactivate(DatabaseTestContainer dbContainer) {
114 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
116 setupResult.service.activate(setupResult.bundleContext, setupResult.config);
119 ListAppender<ILoggingEvent> listAppender = DataCreationHelper.setupLogger(MongoDBPersistenceService.class,
123 setupResult.service.deactivate(1);
126 List<ILoggingEvent> logsList = listAppender.list;
127 VerificationHelper.verifyLogMessage(logsList.get(0),
128 "MongoDB persistence bundle stopping. Disconnecting from database.", Level.DEBUG);
135 * Tests the getId method of MongoDBPersistenceService.
137 * This test checks if the getId method correctly returns the ID of the MongoDBPersistenceService, which should be
141 public void testGetId() {
143 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
145 SetupResult setupResult = DataCreationHelper.setupMongoDB(null, dbContainer);
146 MongoDBPersistenceService service = setupResult.service;
149 String id = service.getId();
152 assertEquals("mongodb", id);
159 * Tests the getLabel method of MongoDBPersistenceService.
161 * This test checks if the getLabel method correctly returns the label of the MongoDBPersistenceService, which
162 * should be "MongoDB".
165 public void testGetLabel() {
167 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
169 SetupResult setupResult = DataCreationHelper.setupMongoDB(null, dbContainer);
170 MongoDBPersistenceService service = setupResult.service;
173 String label = service.getLabel(null);
176 assertEquals("MongoDB", label);
183 * Tests the store method of MongoDBPersistenceService with a NumberItem.
185 * This test checks if the store method correctly stores a NumberItem in the MongoDB database.
186 * It uses different database backends provided by the provideDatabaseBackends method.
188 * @param dbContainer The container running the MongoDB instance.
191 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
192 public void testStoreNumber(DatabaseTestContainer dbContainer) {
195 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
196 MongoDBPersistenceService service = setupResult.service;
197 MongoDatabase database = setupResult.database;
199 service.activate(setupResult.bundleContext, setupResult.config);
201 NumberItem item = DataCreationHelper.createNumberItem("TestItem", 10.1);
204 service.store(item, null);
207 MongoCollection<Document> collection = database.getCollection("testCollection");
208 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
210 assertEquals(1, documents.size()); // Assert that there is only one document
212 Document insertedDocument = documents.get(0); // Get the first (and only) document
214 VerificationHelper.verifyDocument(insertedDocument, "TestItem", 10.1);
221 * Tests the store method of MongoDBPersistenceService with a StringItem.
223 * This test checks if the store method correctly stores a StringItem in the MongoDB database.
224 * It uses different database backends provided by the provideDatabaseBackends method.
226 * @param dbContainer The container running the MongoDB instance.
229 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
230 public void testStoreString(DatabaseTestContainer dbContainer) {
233 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
234 MongoDBPersistenceService service = setupResult.service;
235 MongoDatabase database = setupResult.database;
237 service.activate(setupResult.bundleContext, setupResult.config);
239 StringItem item = DataCreationHelper.createStringItem("TestItem", "TestValue");
242 service.store(item, null);
245 MongoCollection<Document> collection = database.getCollection("testCollection");
246 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
248 assertEquals(1, documents.size()); // Assert that there is only one document
250 Document insertedDocument = documents.get(0); // Get the first (and only) document
252 VerificationHelper.verifyDocument(insertedDocument, "TestItem", "TestValue");
259 * Tests the store method of MongoDBPersistenceService with multiple items in a single collection.
261 * This test checks if the store method correctly stores multiple items in the same MongoDB collection.
262 * It uses different database backends provided by the provideDatabaseBackends method.
264 * @param dbContainer The container running the MongoDB instance.
267 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
268 public void testStoreSingleCollection(DatabaseTestContainer dbContainer) {
271 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
272 MongoDBPersistenceService service = setupResult.service;
273 MongoDatabase database = setupResult.database;
275 service.activate(setupResult.bundleContext, setupResult.config);
277 StringItem strItem1 = DataCreationHelper.createStringItem("TestItem", "TestValue");
278 StringItem strItem2 = DataCreationHelper.createStringItem("SecondTestItem", "SecondTestValue");
281 service.store(strItem1, null);
282 service.store(strItem2, null);
285 MongoCollection<Document> collection = database.getCollection("testCollection");
286 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
288 assertEquals(2, documents.size()); // Assert that there are two documents
290 Document insertedDocument1 = documents.get(0); // Get the first document
291 VerificationHelper.verifyDocument(insertedDocument1, "TestItem", "TestValue");
293 Document insertedDocument2 = documents.get(1); // Get the second document
294 VerificationHelper.verifyDocument(insertedDocument2, "SecondTestItem", "SecondTestValue");
301 * Tests the store method of MongoDBPersistenceService with multiple items.
303 * This test checks if the store method correctly stores multiple items in the same MongoDB collection.
304 * It uses different database backends provided by the provideDatabaseBackends method.
306 * @param dbContainer The container running the MongoDB instance.
309 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
310 public void testStoreMultipleItemsSingleCollection(DatabaseTestContainer dbContainer) {
313 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
314 MongoDBPersistenceService service = setupResult.service;
315 MongoDatabase database = setupResult.database;
317 service.activate(setupResult.bundleContext, setupResult.config);
319 StringItem strItem1 = DataCreationHelper.createStringItem("TestItem1", "TestValue1");
320 StringItem strItem2 = DataCreationHelper.createStringItem("TestItem2", "TestValue2");
323 service.store(strItem1, null);
324 service.store(strItem2, null);
327 MongoCollection<Document> collection = database.getCollection("testCollection");
328 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
330 assertEquals(2, documents.size()); // Assert that there are two documents
332 Document insertedDocument1 = documents.get(0); // Get the first document
333 VerificationHelper.verifyDocument(insertedDocument1, "TestItem1", "TestValue1");
335 Document insertedDocument2 = documents.get(1); // Get the second document
336 VerificationHelper.verifyDocument(insertedDocument2, "TestItem2", "TestValue2");
343 * Tests the store method of MongoDBPersistenceService with a StringItem and an alias.
345 * This test checks if the store method correctly stores a StringItem with an alias in the MongoDB database.
346 * It uses different database backends provided by the provideDatabaseBackends method.
348 * @param dbContainer The container running the MongoDB instance.
351 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
352 public void testStoreStringWithAlias(DatabaseTestContainer dbContainer) {
355 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
356 MongoDBPersistenceService service = setupResult.service;
357 MongoDatabase database = setupResult.database;
359 service.activate(setupResult.bundleContext, setupResult.config);
361 StringItem item = DataCreationHelper.createStringItem("TestItem", "TestValue");
364 service.store(item, "AliasName");
367 MongoCollection<Document> collection = database.getCollection("testCollection");
368 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
370 assertEquals(1, documents.size()); // Assert that there is only one document
372 Document insertedDocument = documents.get(0); // Get the first (and only) document
374 VerificationHelper.verifyDocumentWithAlias(insertedDocument, "AliasName", "TestItem", "TestValue");
381 * Tests the query method of MongoDBPersistenceService with NumberItems in a single collection.
383 * This test checks if the query method correctly retrieves NumberItems from a single MongoDB collection.
384 * It uses different database backends provided by the provideDatabaseBackends method.
386 * @param dbContainer The container running the MongoDB instance.
389 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
390 public void testQueryNumberItemsInOneCollection(DatabaseTestContainer dbContainer) {
393 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
394 MongoDBPersistenceService service = setupResult.service;
396 // Add items to the ItemRegistry
397 NumberItem itemReg1 = DataCreationHelper.createNumberItem("TestItem", 0);
398 NumberItem itemReg2 = DataCreationHelper.createNumberItem("TestItem2", 0);
400 Mockito.when(setupResult.itemRegistry.getItem("TestItem")).thenReturn(itemReg1);
401 Mockito.when(setupResult.itemRegistry.getItem("TestItem2")).thenReturn(itemReg2);
402 } catch (ItemNotFoundException e) {
405 service.activate(setupResult.bundleContext, setupResult.config);
408 for (int i = 0; i < 10; i++) {
409 NumberItem item1 = DataCreationHelper.createNumberItem("TestItem", i);
410 NumberItem item2 = DataCreationHelper.createNumberItem("TestItem2", i * 2);
411 service.store(item1, null);
412 service.store(item2, null);
416 FilterCriteria filter1 = DataCreationHelper.createFilterCriteria("TestItem");
417 Iterable<HistoricItem> result1 = service.query(filter1);
419 FilterCriteria filter2 = DataCreationHelper.createFilterCriteria("TestItem2");
420 Iterable<HistoricItem> result2 = service.query(filter2);
423 VerificationHelper.verifyQueryResult(result1, 0, 1, 10);
424 VerificationHelper.verifyQueryResult(result2, 0, 2, 10);
431 * Tests the query method of MongoDBPersistenceService with NumberItems in multiple collections.
433 * This test checks if the query method correctly retrieves NumberItems from multiple MongoDB collections.
434 * It uses different database backends provided by the provideDatabaseBackends method.
436 * @param dbContainer The container running the MongoDB instance.
439 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
440 public void testQueryNumberItemsInMultipleCollections(DatabaseTestContainer dbContainer) {
443 SetupResult setupResult = DataCreationHelper.setupMongoDB(null, dbContainer);
444 MongoDBPersistenceService service = setupResult.service;
445 BundleContext bundleContext = setupResult.bundleContext;
446 Map<String, Object> config = setupResult.config;
449 Mockito.when(setupResult.itemRegistry.getItem("TestItem"))
450 .thenReturn(DataCreationHelper.createNumberItem("TestItem", 0));
451 Mockito.when(setupResult.itemRegistry.getItem("TestItem2"))
452 .thenReturn(DataCreationHelper.createNumberItem("TestItem2", 0));
453 } catch (ItemNotFoundException e) {
456 service.activate(bundleContext, config);
459 for (int i = 0; i < 10; i++) {
460 NumberItem item1 = DataCreationHelper.createNumberItem("TestItem", i);
461 NumberItem item2 = DataCreationHelper.createNumberItem("TestItem2", i * 2);
462 service.store(item1, null);
463 service.store(item2, null);
467 FilterCriteria filter1 = DataCreationHelper.createFilterCriteria("TestItem");
468 Iterable<HistoricItem> result1 = service.query(filter1);
470 FilterCriteria filter2 = DataCreationHelper.createFilterCriteria("TestItem2");
471 Iterable<HistoricItem> result2 = service.query(filter2);
474 VerificationHelper.verifyQueryResult(result1, 0, 1, 10);
475 VerificationHelper.verifyQueryResult(result2, 0, 2, 10);
482 * Tests the query method of MongoDBPersistenceService with NumberItems in a single collection and a time range.
484 * This test checks if the query method correctly retrieves NumberItems from a single MongoDB collection within a
485 * specified time range.
486 * It uses different database backends provided by the provideDatabaseBackends method.
488 * @param dbContainer The container running the MongoDB instance.
491 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
492 public void testQueryNumberItemsInOneCollectionTimeRange(DatabaseTestContainer dbContainer) {
495 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
496 MongoDBPersistenceService service = setupResult.service;
497 MongoDatabase database = setupResult.database;
500 Mockito.when(setupResult.itemRegistry.getItem("TestItem"))
501 .thenReturn(DataCreationHelper.createNumberItem("TestItem", 0));
502 Mockito.when(setupResult.itemRegistry.getItem("TestItem2"))
503 .thenReturn(DataCreationHelper.createNumberItem("TestItem2", 0));
504 } catch (ItemNotFoundException e) {
507 service.activate(setupResult.bundleContext, setupResult.config);
509 // Get the collection
510 MongoCollection<Document> collection = database.getCollection("testCollection");
512 // Store items directly to the database with defined timestamps
513 for (int i = 0; i < 10; i++) {
514 Document obj = DataCreationHelper.createDocument("TestItem", i, LocalDate.now().minusDays(i));
515 collection.insertOne(obj);
517 Document obj2 = DataCreationHelper.createDocument("TestItem2", i * 2, LocalDate.now().minusDays(i));
518 collection.insertOne(obj2);
522 FilterCriteria filter1 = DataCreationHelper.createFilterCriteria("TestItem",
523 ZonedDateTime.now().minusDays(5), null);
524 Iterable<HistoricItem> result1 = service.query(filter1);
527 VerificationHelper.verifyQueryResult(result1, 4, -1, 5);
534 * Tests the query method of MongoDBPersistenceService with NumberItems in a single collection and a state equals
537 * This test checks if the query method correctly retrieves NumberItems from a single MongoDB collection that match
539 * It uses different database backends provided by the provideDatabaseBackends method.
541 * @param dbContainer The container running the MongoDB instance.
544 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideDatabaseBackends")
545 public void testQueryNumberItemsInOneCollectionStateEquals(DatabaseTestContainer dbContainer) {
548 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
549 MongoDBPersistenceService service = setupResult.service;
550 MongoDatabase database = setupResult.database;
553 Mockito.when(setupResult.itemRegistry.getItem("TestItem"))
554 .thenReturn(DataCreationHelper.createNumberItem("TestItem", 0));
555 } catch (ItemNotFoundException e) {
558 service.activate(setupResult.bundleContext, setupResult.config);
560 // Get the collection
561 MongoCollection<Document> collection = database.getCollection("testCollection");
563 // Store items directly to the database with defined timestamps
564 for (int i = 0; i < 10; i++) {
565 Document obj = DataCreationHelper.createDocument("TestItem", i, LocalDate.now().minusDays(i));
566 collection.insertOne(obj);
569 Document obj = DataCreationHelper.createDocument("TestItem", 4.0, LocalDate.now());
570 collection.insertOne(obj);
573 FilterCriteria filter1 = DataCreationHelper.createFilterCriteria("TestItem", null, null);
574 filter1.setState(new DecimalType(4.0));
575 filter1.setOperator(FilterCriteria.Operator.EQ);
577 Iterable<HistoricItem> result1 = service.query(filter1);
580 VerificationHelper.verifyQueryResult(result1, 4, 0, 2);
587 * Tests the store method of the MongoDBPersistenceService with all types of openHAB items.
588 * Each item is stored in the collection in the MongoDB database.
590 * @param item The item to store in the database.
593 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideOpenhabItemTypes")
594 public void testStoreAllOpenhabItemTypesSingleCollection(GenericItem item) {
596 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
598 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
599 MongoDBPersistenceService service = setupResult.service;
600 MongoDatabase database = setupResult.database;
602 service.activate(setupResult.bundleContext, setupResult.config);
605 service.store(item, null);
608 MongoCollection<Document> collection = database.getCollection("testCollection");
609 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
611 assertEquals(1, documents.size()); // Assert that there is only one document
613 Document insertedDocument = documents.get(0); // Get the first (and only) document
615 VerificationHelper.verifyDocument(insertedDocument, item.getName(), item.getState());
622 * Tests the store and query method for various image sizes of the MongoDBPersistenceService
623 * Each item is queried with the type from one collection in the MongoDB database.
625 * @param item The item to store in the database.
628 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideOpenhabImageItemsInDifferentSizes")
629 public void testStoreAndQueryyLargerImages(ImageItem item) {
631 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
633 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
634 MongoDBPersistenceService service = setupResult.service;
636 service.activate(setupResult.bundleContext, setupResult.config);
638 Mockito.when(setupResult.itemRegistry.getItem(item.getName())).thenReturn(item);
639 } catch (ItemNotFoundException e) {
642 service.store(item, null);
643 } catch (org.bson.BsonMaximumSizeExceededException e) {
644 if (item.getName().equals("ImageItem20MB")) {
653 FilterCriteria filter = DataCreationHelper.createFilterCriteria(item.getName());
654 Iterable<HistoricItem> result = service.query(filter);
657 VerificationHelper.verifyQueryResult(result, item.getState());
664 * Tests the old way of storing data and query method of the MongoDBPersistenceService with all types of openHAB
666 * Each item is queried with the type from one collection in the MongoDB database.
668 * @param item The item to store in the database.
671 @MethodSource("org.openhab.persistence.mongodb.internal.DataCreationHelper#provideOpenhabItemTypes")
672 public void testOldDataQueryAllOpenhabItemTypesSingleCollection(GenericItem item) {
674 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
676 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
677 MongoDBPersistenceService service = setupResult.service;
678 MongoDatabase database = setupResult.database;
680 service.activate(setupResult.bundleContext, setupResult.config);
682 Mockito.when(setupResult.itemRegistry.getItem(item.getName())).thenReturn(item);
683 } catch (ItemNotFoundException e) {
685 MongoCollection<Document> collection = database.getCollection("testCollection");
686 DataCreationHelper.storeOldData(collection, item.getName(), item.getState());
687 // after storing, we have to adjust the expected values for ImageItems, ColorItems as well as DateTimeItems
688 if (item instanceof ImageItem) {
689 item.setState(new RawType(new byte[0], "application/octet-stream"));
690 } else if (item instanceof ColorItem) {
691 item.setState(new HSBType("0,0,0"));
695 FilterCriteria filter = DataCreationHelper.createFilterCriteria(item.getName());
696 Iterable<HistoricItem> result = service.query(filter);
699 if (item instanceof DateTimeItem) {
700 // verify just the date part
701 assertEquals(((DateTimeType) item.getState()).getZonedDateTime().toLocalDate(),
702 ((DateTimeType) result.iterator().next().getState()).getZonedDateTime().toLocalDate());
704 VerificationHelper.verifyQueryResult(result, item.getState());
712 * Tests the writting of NumberItems including units
713 * Each item should be written to the database with the unit information
715 * @param item The item to store in the database.
718 public void testStoreNumberItemWithUnit() {
720 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
722 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
723 MongoDBPersistenceService service = setupResult.service;
724 MongoDatabase database = setupResult.database;
726 service.activate(setupResult.bundleContext, setupResult.config);
727 MongoCollection<Document> collection = database.getCollection("testCollection");
729 NumberItem item = DataCreationHelper.createNumberItem("Number:Energy", "TestItem",
730 new QuantityType<>("10.1 kWh"));
733 service.store(item, null);
736 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
738 assertEquals(1, documents.size()); // Assert that there is only one document
740 Document insertedDocument = documents.get(0); // Get the first (and only) document
742 assertEquals(10.1, insertedDocument.get(MongoDBFields.FIELD_VALUE));
743 assertEquals("kWh", insertedDocument.get(MongoDBFields.FIELD_UNIT));
750 * Tests the reading of NumberItems including units
751 * Each item should be written to the database with the unit information
753 * @param item The item to store in the database.
756 public void testQueryNumberItemWithUnit() {
758 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
760 SetupResult setupResult = DataCreationHelper.setupMongoDB("testCollection", dbContainer);
761 MongoDBPersistenceService service = setupResult.service;
762 MongoDatabase database = setupResult.database;
764 service.activate(setupResult.bundleContext, setupResult.config);
765 MongoCollection<Document> collection = database.getCollection("testCollection");
767 NumberItem item = DataCreationHelper.createNumberItem("Number:Energy", "TestItem",
768 new QuantityType<>("10.1 MWh"));
770 Mockito.when(setupResult.itemRegistry.getItem("TestItem")).thenReturn(item);
771 } catch (ItemNotFoundException e) {
774 Document obj = new Document();
775 obj.put(MongoDBFields.FIELD_ID, new ObjectId());
776 obj.put(MongoDBFields.FIELD_ITEM, "TestItem");
777 obj.put(MongoDBFields.FIELD_REALNAME, "TestItem");
778 obj.put(MongoDBFields.FIELD_TIMESTAMP, new Date());
779 obj.put(MongoDBFields.FIELD_VALUE, 201.5);
780 obj.put(MongoDBFields.FIELD_UNIT, "Wh");
781 collection.insertOne(obj);
784 FilterCriteria filter = DataCreationHelper.createFilterCriteria("TestItem");
785 Iterable<HistoricItem> result = service.query(filter);
786 VerificationHelper.verifyQueryResult(result, new QuantityType<>("201.5 Wh"));
793 * Tests the toString of a MongoDBItem
796 * @param item The item to store in the database.
799 public void testHistoricItemToString() {
801 ZonedDateTime now = ZonedDateTime.now();
802 HistoricItem item = new MongoDBItem("TestItem", new DecimalType(10.1), now);
805 String result = item.toString();
808 // Jan 29, 2024, 8:43:26 PM: TestItem -> 10.1
809 String expected = DateFormat.getDateTimeInstance().format(Date.from(now.toInstant())) + ": TestItem -> 10.1";
810 assertEquals(expected, result);
814 * Test the store method which stores a item state as well as a timestampe (ZonedDateTime) and check the result in
818 public void testStoreItemWithTimestamp() {
820 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
822 SetupResult setupResult = DataCreationHelper.setupMongoDB(null, dbContainer);
823 MongoDBPersistenceService service = setupResult.service;
824 MongoDatabase database = setupResult.database;
826 service.activate(setupResult.bundleContext, setupResult.config);
828 Mockito.when(setupResult.itemRegistry.getItem("TestItem"))
829 .thenReturn(DataCreationHelper.createNumberItem("TestItem", 0));
830 } catch (ItemNotFoundException e) {
834 NumberItem item = DataCreationHelper.createNumberItem("TestItem", 10.1);
835 DecimalType historicState = new DecimalType(11110.1);
836 ZonedDateTime now = ZonedDateTime.now();
837 service.store(item, now, historicState);
840 MongoCollection<Document> collection = database.getCollection("TestItem");
841 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
843 assertEquals(1, documents.size()); // Assert that there is only one document
845 Document insertedDocument = documents.get(0); // Get the first (and only) document
847 VerificationHelper.verifyDocument(insertedDocument, "TestItem", historicState);
848 assertEquals(Date.from(now.toInstant()), insertedDocument.get(MongoDBFields.FIELD_TIMESTAMP));
855 * Test the store method which stores a item state as well as a timestampe (ZonedDateTime) and check the result in
859 public void testStoreItemWithTimestampAndAlias() {
861 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
863 SetupResult setupResult = DataCreationHelper.setupMongoDB(null, dbContainer);
864 MongoDBPersistenceService service = setupResult.service;
865 MongoDatabase database = setupResult.database;
867 service.activate(setupResult.bundleContext, setupResult.config);
869 Mockito.when(setupResult.itemRegistry.getItem("TestItem"))
870 .thenReturn(DataCreationHelper.createNumberItem("TestItem", 0));
871 } catch (ItemNotFoundException e) {
875 NumberItem item = DataCreationHelper.createNumberItem("TestItem", 10.1);
876 DecimalType historicState = new DecimalType(11110.1);
877 ZonedDateTime now = ZonedDateTime.now();
878 service.store(item, now, historicState, "AliasName");
881 MongoCollection<Document> collection = database.getCollection("TestItem");
882 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
884 assertEquals(1, documents.size()); // Assert that there is only one document
886 Document insertedDocument = documents.get(0); // Get the first (and only) document
888 VerificationHelper.verifyDocumentWithAlias(insertedDocument, "AliasName", "TestItem", historicState);
889 assertEquals(Date.from(now.toInstant()), insertedDocument.get(MongoDBFields.FIELD_TIMESTAMP));
896 * Test the remove method to remove one item from the database
899 public void testremoveOneItem() {
901 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
903 SetupResult setupResult = DataCreationHelper.setupMongoDB("testcollection", dbContainer);
904 MongoDBPersistenceService service = setupResult.service;
905 MongoDatabase database = setupResult.database;
907 service.activate(setupResult.bundleContext, setupResult.config);
909 for (double i = 0; i < 10.00; i += 0.3) {
910 service.store(DataCreationHelper.createNumberItem("TestItem", i));
912 service.store(DataCreationHelper.createNumberItem("TestItemOther", 10.1));
915 service.remove(DataCreationHelper.createFilterCriteria("TestItem", null, null));
918 MongoCollection<Document> collection = database.getCollection("testcollection");
920 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
922 assertEquals(1, documents.size()); // Assert that there is the other document
924 VerificationHelper.verifyDocument(documents.get(0), "TestItemOther", 10.1);
931 * Test the remove method to remove values of a given timerange for one item
934 public void testremoveATimeRangeFromOneItem() {
936 DatabaseTestContainer dbContainer = new DatabaseTestContainer(new MemoryBackend());
938 SetupResult setupResult = DataCreationHelper.setupMongoDB("testcollection", dbContainer);
939 MongoDBPersistenceService service = setupResult.service;
940 MongoDatabase database = setupResult.database;
942 service.activate(setupResult.bundleContext, setupResult.config);
944 List<PersistenceTestItem> testDataList = DataCreationHelper.createTestData(service, "TestItem",
948 // Calculate the start and end dates
949 ZonedDateTime startDate = ZonedDateTime.now().plusDays(3).truncatedTo(ChronoUnit.DAYS);
950 ZonedDateTime endDate = ZonedDateTime.now().plusDays(17).truncatedTo(ChronoUnit.DAYS).plusDays(1)
953 // Create the filter and remove the data
954 service.remove(DataCreationHelper.createFilterCriteria("TestItem", startDate, endDate));
957 MongoCollection<Document> collection = database.getCollection("testcollection");
959 // Query the database for all data points
960 List<Document> documents = (ArrayList<Document>) collection.find().into(new ArrayList<>());
962 // Create a set of the returned data points
963 Set<PersistenceTestItem> returnedData = documents.stream()
964 .map(doc -> new PersistenceTestItem(doc.getString(MongoDBFields.FIELD_ITEM),
965 ZonedDateTime.ofInstant(doc.getDate(MongoDBFields.FIELD_TIMESTAMP).toInstant(),
966 ZoneId.systemDefault()),
967 doc.getDouble(MongoDBFields.FIELD_VALUE)))
968 .collect(Collectors.toSet());
970 // Create a set of the expected data points
971 Set<PersistenceTestItem> expectedData = testDataList
972 .stream().filter(testData -> !(testData.itemName.equals("TestItem")
973 && testData.date.isAfter(startDate) && testData.date.isBefore(endDate)))
974 .collect(Collectors.toSet());
976 for (PersistenceTestItem expectedItem : expectedData) {
977 // Assert that this item is in the returned data
978 assertTrue(returnedData.contains(expectedItem),
979 "Expected item not found in returned data: " + expectedItem);
982 // Iterate over the returned data
983 for (PersistenceTestItem returnedItem : returnedData) {
984 // Assert that this item is in the expected data
985 assertTrue(expectedData.contains(returnedItem),
986 "Unexpected item found in returned data: " + returnedItem);