diff --git a/li.strolch.testbase/.gitignore b/li.strolch.testbase/.gitignore
new file mode 100644
index 000000000..558680bb1
--- /dev/null
+++ b/li.strolch.testbase/.gitignore
@@ -0,0 +1,4 @@
+target/
+.project
+.classpath
+.settings
diff --git a/li.strolch.testbase/LICENSE b/li.strolch.testbase/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/li.strolch.testbase/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/li.strolch.testbase/README.md b/li.strolch.testbase/README.md
new file mode 100644
index 000000000..d774be67d
--- /dev/null
+++ b/li.strolch.testbase/README.md
@@ -0,0 +1,6 @@
+li.strolch.testbase
+===================
+
+[![Build Status](http://jenkins.eitchnet.ch/buildStatus/icon?job=li.strolch.testbase)](http://jenkins.eitchnet.ch/view/strolch/job/li.strolch.testbase/)
+
+Test base for the li.strolch.* projects
diff --git a/li.strolch.testbase/pom.xml b/li.strolch.testbase/pom.xml
new file mode 100644
index 000000000..ed13b0aae
--- /dev/null
+++ b/li.strolch.testbase/pom.xml
@@ -0,0 +1,73 @@
+
+ 4.0.0
+
+
+ li.strolch
+ li.strolch.parent
+ 1.0.0-SNAPSHOT
+ ../li.strolch.parent/pom.xml
+
+
+ li.strolch.testbase
+
+ li.strolch.testbase
+ runtime for Strolch
+
+ https://github.com/eitchnet/li.strolch.testbase
+
+ 2011
+
+
+ Github Issues
+ https://github.com/eitchnet/li.strolch.testbase/issues
+
+
+
+ scm:git:https://github.com/eitchnet/li.strolch.testbase.git
+ scm:git:git@github.com:eitch/li.strolch.testbase.git
+ https://github.com/eitchnet/li.strolch.testbase
+
+
+
+
+
+ li.strolch
+ li.strolch.model
+
+
+ li.strolch
+ li.strolch.agent
+
+
+ junit
+ junit
+ compile
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-eclipse-plugin
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ org.apache.maven.plugins
+ maven-site-plugin
+
+
+
+
\ No newline at end of file
diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AbstractModelTest.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AbstractModelTest.java
new file mode 100644
index 000000000..48217b11f
--- /dev/null
+++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AbstractModelTest.java
@@ -0,0 +1,87 @@
+package li.strolch.testbase.runtime;
+
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.runtime.StrolchConstants;
+import li.strolch.runtime.privilege.PrivilegeHandler;
+
+import org.junit.Test;
+
+import ch.eitchnet.privilege.model.Certificate;
+
+public abstract class AbstractModelTest {
+
+ protected abstract RuntimeMock getRuntimeMock();
+
+ protected String realmName = StrolchConstants.DEFAULT_REALM;
+
+ @Test
+ public void shouldStartContainer() {
+ PrivilegeHandler privilegeHandler = getRuntimeMock().getContainer().getPrivilegeHandler();
+ Certificate certificate = privilegeHandler.authenticate("test", "test".getBytes());
+ try (StrolchTransaction tx = getRuntimeMock().getRealm(this.realmName).openTx(certificate, "test")) {
+ tx.getOrderMap().getAllKeys(tx);
+ }
+ }
+
+ @Test
+ public void shouldCreateOrders() {
+
+ OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runCreateOrderTest();
+ }
+
+ @Test
+ public void shouldQueryOrderSizes() {
+
+ OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runQuerySizeTest();
+ }
+
+ @Test
+ public void shouldOrderCrud() {
+
+ OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runCrudTests();
+ }
+
+ @Test
+ public void shouldOrderPerformBulkOperations() {
+
+ OrderModelTestRunner testRunner = new OrderModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runBulkOperationTests();
+ }
+
+ @Test
+ public void shouldCreateResources() {
+
+ ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runCreateResourceTest();
+ }
+
+ @Test
+ public void shouldQueryResourceSizes() {
+
+ ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runQuerySizeTest();
+ }
+
+ @Test
+ public void shouldResourceCrud() {
+
+ ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runCrudTests();
+ }
+
+ @Test
+ public void shouldResourcePerformBulkOperations() {
+
+ ResourceModelTestRunner testRunner = new ResourceModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runBulkOperationTests();
+ }
+
+ @Test
+ public void shouldTestAudits() {
+ AuditModelTestRunner testRunner = new AuditModelTestRunner(getRuntimeMock(), this.realmName);
+ testRunner.runTestForAudits();
+ }
+}
diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AuditModelTestRunner.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AuditModelTestRunner.java
new file mode 100644
index 000000000..12d1bf5f4
--- /dev/null
+++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/AuditModelTestRunner.java
@@ -0,0 +1,319 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package li.strolch.testbase.runtime;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import li.strolch.agent.api.AuditTrail;
+import li.strolch.agent.api.StrolchRealm;
+import li.strolch.model.ModelGenerator;
+import li.strolch.model.audit.Audit;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.runtime.privilege.PrivilegeHandler;
+import ch.eitchnet.privilege.model.Certificate;
+import ch.eitchnet.utils.collections.DateRange;
+
+/**
+ * @author Robert von Burg
+ */
+public class AuditModelTestRunner {
+
+ private RuntimeMock runtimeMock;
+ private String realmName;
+ private Certificate certificate;
+
+ /**
+ * @param runtimeMock
+ * @param realmName
+ */
+ public AuditModelTestRunner(RuntimeMock runtimeMock, String realmName) {
+ this.runtimeMock = runtimeMock;
+ this.realmName = realmName;
+
+ PrivilegeHandler privilegeHandler = runtimeMock.getContainer().getPrivilegeHandler();
+ this.certificate = privilegeHandler.authenticate("test", "test".getBytes());
+ }
+
+ public void runTestForAudits() {
+
+ StrolchRealm realm = this.runtimeMock.getRealm(this.realmName);
+
+ Calendar cal = Calendar.getInstance();
+
+ cal.set(2000, 6, 1);
+ Date beforeCurrent = cal.getTime();
+ cal.set(2000, 6, 2);
+ Date current = cal.getTime();
+ cal.set(2000, 6, 3);
+ Date afterCurrent = cal.getTime();
+ cal.set(2000, 1, 1);
+ Date earlier = cal.getTime();
+ cal.set(2000, 11, 1);
+ Date later = cal.getTime();
+
+ DateRange earlierRange = new DateRange().from(earlier, true).to(beforeCurrent, true);
+ DateRange equalsRange = new DateRange().from(current, true).to(current, true);
+ DateRange laterRange = new DateRange().from(afterCurrent, true).to(later, true);
+ DateRange containsRange = new DateRange().from(earlier, true).to(later, true);
+
+ // first cleanup
+ cleanup(realm);
+
+ // single element actions
+ {
+ Audit audit = ModelGenerator.randomAudit();
+ audit.setDate(current);
+
+ // add
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.add(tx, audit);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ Set types = auditTrail.getTypes(tx);
+ assertEquals(1, types.size());
+ assertTrue(types.contains(audit.getElementType()));
+ }
+
+ // has
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertTrue(auditTrail.hasAudit(tx, audit.getElementType(), audit.getId()));
+
+ Audit dbAudit = auditTrail.getBy(tx, audit.getElementType(), audit.getId());
+ assertNotNull(dbAudit);
+ assertEquals(audit, dbAudit);
+
+ dbAudit = auditTrail.getBy(tx, "Foo", audit.getId());
+ assertNull(dbAudit);
+ }
+
+ // remove
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.remove(tx, audit);
+ }
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ Audit dbAudit = auditTrail.getBy(tx, audit.getElementType(), audit.getId());
+ assertNull(dbAudit);
+ }
+
+ // update
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.add(tx, audit);
+ }
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ Audit dbAudit = auditTrail.getBy(tx, audit.getElementType(), audit.getId());
+ dbAudit.setAction("Foo");
+ auditTrail.update(tx, dbAudit);
+ }
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ Audit dbAudit = auditTrail.getBy(tx, audit.getElementType(), audit.getId());
+ assertEquals("Foo", dbAudit.getAction());
+ }
+ }
+
+ // querying
+ {
+ Audit audit = ModelGenerator.randomAudit();
+ audit.setDate(current);
+
+ // querySize
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertEquals(1, auditTrail.querySize(tx, audit.getElementType(), equalsRange));
+ assertEquals(1, auditTrail.querySize(tx, audit.getElementType(), containsRange));
+ assertEquals(0, auditTrail.querySize(tx, audit.getElementType(), earlierRange));
+ assertEquals(0, auditTrail.querySize(tx, audit.getElementType(), laterRange));
+ }
+ }
+
+ // mass element actions
+ {
+ List audits = new ArrayList<>();
+ for (int i = 0; i < 100; i++) {
+ Audit randomAudit = ModelGenerator.randomAudit();
+ randomAudit.setElementType("FooBar");
+ randomAudit.setDate(current);
+ audits.add(randomAudit);
+ }
+ Collections.sort(audits, new AuditByIdComparator());
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.addAll(tx, audits);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertEquals(100, auditTrail.querySize(tx, "FooBar", containsRange));
+
+ List allElements = auditTrail.getAllElements(tx, "FooBar", containsRange);
+ Collections.sort(allElements, new AuditByIdComparator());
+ assertEquals(audits, allElements);
+
+ allElements = auditTrail.getAllElements(tx, "FooBar", earlierRange);
+ assertEquals(0, allElements.size());
+ allElements = auditTrail.getAllElements(tx, "FooBar", laterRange);
+ assertEquals(0, allElements.size());
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.removeAll(tx, audits);
+ assertEquals(0, auditTrail.querySize(tx, "FooBar", containsRange));
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertEquals(0, auditTrail.querySize(tx, "FooBar", containsRange));
+ }
+ }
+
+ // update all
+ {
+ List audits = new ArrayList<>();
+ for (int i = 0; i < 100; i++) {
+ Audit randomAudit = ModelGenerator.randomAudit();
+ randomAudit.setElementType("Bar");
+ randomAudit.setDate(current);
+ randomAudit.setAction("BarFoo");
+ audits.add(randomAudit);
+ }
+ Collections.sort(audits, new AuditByIdComparator());
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.addAll(tx, audits);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ List allElements = auditTrail.getAllElements(tx, "Bar", containsRange);
+ Collections.sort(allElements, new AuditByIdComparator());
+ assertEquals(audits, allElements);
+
+ for (Audit dbAudit : allElements) {
+ assertEquals("BarFoo", dbAudit.getAction());
+ }
+
+ for (Audit dbAudit : allElements) {
+ dbAudit.setAction("Foo");
+ }
+
+ auditTrail.updateAll(tx, allElements);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ List allElements = auditTrail.getAllElements(tx, "Bar", containsRange);
+ for (Audit dbAudit : allElements) {
+ assertEquals("Foo", dbAudit.getAction());
+ }
+ }
+ }
+
+ // remove all
+ {
+ // first cleanup
+ cleanup(realm);
+
+ List audits = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+ Audit randomAudit = ModelGenerator.randomAudit();
+ randomAudit.setDate(current);
+ randomAudit.setElementType("BarBarBar");
+ audits.add(randomAudit);
+ }
+ for (int i = 0; i < 5; i++) {
+ Audit randomAudit = ModelGenerator.randomAudit();
+ randomAudit.setDate(current);
+ randomAudit.setElementType("FooFooFoo");
+ audits.add(randomAudit);
+ }
+ for (int i = 0; i < 5; i++) {
+ Audit randomAudit = ModelGenerator.randomAudit();
+ randomAudit.setDate(current);
+ randomAudit.setElementType("BarFooBar");
+ audits.add(randomAudit);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ auditTrail.addAll(tx, audits);
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertEquals(15, auditTrail.querySize(tx, containsRange));
+ assertEquals(5, auditTrail.querySize(tx, "BarBarBar", containsRange));
+ assertEquals(5, auditTrail.querySize(tx, "FooFooFoo", containsRange));
+ assertEquals(5, auditTrail.querySize(tx, "BarFooBar", containsRange));
+ }
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ assertEquals(5, auditTrail.removeAll(tx, "BarBarBar", containsRange));
+ assertEquals(10, auditTrail.querySize(tx, containsRange));
+
+ assertEquals(5, auditTrail.removeAll(tx, "FooFooFoo", containsRange));
+ assertEquals(5, auditTrail.querySize(tx, containsRange));
+
+ assertEquals(5, auditTrail.removeAll(tx, "BarFooBar", containsRange));
+ assertEquals(0, auditTrail.querySize(tx, containsRange));
+ }
+ }
+ }
+
+ private void cleanup(StrolchRealm realm) {
+
+ DateRange dateRange = new DateRange().from(new Date(0), true).to(new Date((long) Math.pow(2, 50)), true);
+
+ try (StrolchTransaction tx = realm.openTx(this.certificate, "test")) {
+ AuditTrail auditTrail = tx.getAuditTrail();
+ Set types = auditTrail.getTypes(tx);
+ for (String type : types) {
+ auditTrail.removeAll(tx, type, dateRange);
+ }
+
+ assertEquals(0, auditTrail.querySize(tx, dateRange));
+ }
+ }
+
+ private final class AuditByIdComparator implements Comparator {
+ @Override
+ public int compare(Audit o1, Audit o2) {
+ return o1.getId().compareTo(o2.getId());
+ }
+ }
+}
diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java
new file mode 100644
index 000000000..59fc3f4f2
--- /dev/null
+++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/OrderModelTestRunner.java
@@ -0,0 +1,247 @@
+package li.strolch.testbase.runtime;
+
+import static li.strolch.model.ModelGenerator.BAG_ID;
+import static li.strolch.model.ModelGenerator.PARAM_STRING_ID;
+import static li.strolch.model.ModelGenerator.createOrder;
+import static li.strolch.model.ModelGenerator.createOrders;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import li.strolch.agent.api.OrderMap;
+import li.strolch.agent.impl.DataStoreMode;
+import li.strolch.model.Order;
+import li.strolch.model.parameter.Parameter;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.runtime.privilege.PrivilegeHandler;
+import ch.eitchnet.privilege.model.Certificate;
+
+@SuppressWarnings("nls")
+public class OrderModelTestRunner {
+
+ private static final String ID = "@testOrder";
+ private static final String NAME = "Test Order";
+ private static final String TYPE = "ToStock";
+
+ private RuntimeMock runtimeMock;
+ private String realmName;
+ private Certificate certificate;
+
+ public OrderModelTestRunner(RuntimeMock runtimeMock, String realmName) {
+ this.runtimeMock = runtimeMock;
+ this.realmName = realmName;
+
+ PrivilegeHandler privilegeHandler = runtimeMock.getContainer().getPrivilegeHandler();
+ this.certificate = privilegeHandler.authenticate("test", "test".getBytes());
+ }
+
+ public void runCreateOrderTest() {
+
+ // create
+ Order newOrder = createOrder("MyTestOrder", "Test Name", "TestType"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().add(tx, newOrder);
+ }
+ }
+
+ public void runQuerySizeTest() {
+
+ // remove all
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().removeAll(tx, tx.getOrderMap().getAllElements(tx));
+ }
+
+ // create three orders
+ Order order1 = createOrder("myTestOrder1", "Test Name", "QTestType1"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ Order order2 = createOrder("myTestOrder2", "Test Name", "QTestType2"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ Order order3 = createOrder("myTestOrder3", "Test Name", "QTestType3"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().add(tx, order1);
+ tx.getOrderMap().add(tx, order2);
+ tx.getOrderMap().add(tx, order3);
+ }
+
+ // query size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ long size = tx.getOrderMap().querySize(tx);
+ assertEquals("Should have three objects", 3, size);
+
+ size = tx.getOrderMap().querySize(tx, "QTestType1");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getOrderMap().querySize(tx, "QTestType2");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getOrderMap().querySize(tx, "QTestType3");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getOrderMap().querySize(tx, "NonExistingType");
+ assertEquals("Should have zero objects of type 'NonExistingType'", 0, size);
+ }
+ }
+
+ public void runCrudTests() {
+
+ // create
+ Order newOrder = createOrder(ID, NAME, TYPE);
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().add(tx, newOrder);
+ }
+
+ // read
+ Order readOrder = null;
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ readOrder = tx.getOrderMap().getBy(tx, TYPE, ID);
+ }
+ assertNotNull("Should read Order with id " + ID, readOrder);
+
+ // update
+ Parameter sParam = readOrder.getParameter(BAG_ID, PARAM_STRING_ID);
+ String newStringValue = "Giddiya!";
+ sParam.setValue(newStringValue);
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().update(tx, readOrder);
+ }
+
+ // read updated
+ Order updatedOrder = null;
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ updatedOrder = tx.getOrderMap().getBy(tx, TYPE, ID);
+ }
+ assertNotNull("Should read Order with id " + ID, updatedOrder);
+ if (this.runtimeMock.getRealm(this.realmName).getMode() != DataStoreMode.CACHED)
+ assertFalse("Objects can't be the same reference after re-reading!", readOrder == updatedOrder);
+ Parameter updatedParam = readOrder.getParameter(BAG_ID, PARAM_STRING_ID);
+ assertEquals(newStringValue, updatedParam.getValue());
+
+ // delete
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getOrderMap().remove(tx, readOrder);
+ }
+
+ // fail to re-read
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ Order order = tx.getOrderMap().getBy(tx, TYPE, ID);
+ assertNull("Should no read Order with id " + ID, order);
+ }
+ }
+
+ public void runBulkOperationTests() {
+
+ // create 15 orders
+ List orders = new ArrayList<>();
+ orders.addAll(createOrders(orders.size(), 5, "@", "My Order", "MyType1"));
+ orders.addAll(createOrders(orders.size(), 5, "@", "Other Order", "MyType2"));
+ orders.addAll(createOrders(orders.size(), 5, "@", "Further Order", "MyType3"));
+
+ // sort them so we know which order our objects are
+ Comparator comparator = new Comparator() {
+ @Override
+ public int compare(Order o1, Order o2) {
+ return o1.getId().compareTo(o2.getId());
+ }
+ };
+ Collections.sort(orders, comparator);
+
+ // first clear the map, so that we have a clean state
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+ orderMap.removeAll(tx, orderMap.getAllElements(tx));
+ }
+
+ {
+ // make sure it is empty
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+ assertEquals(0, orderMap.querySize(tx));
+ }
+
+ // now add some orders
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getOrderMap().addAll(tx, orders);
+ }
+
+ // make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+ assertEquals(orders.size(), orderMap.querySize(tx));
+ assertEquals(5, orderMap.querySize(tx, "MyType3"));
+ }
+
+ // now use the remove all by type
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getOrderMap().removeAllBy(tx, "MyType3");
+ }
+
+ // again make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+ assertEquals(orders.size() - 5, orderMap.querySize(tx));
+ assertEquals(0, orderMap.querySize(tx, "MyType3"));
+ }
+
+ // now use the remove all
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ long removed = tx.getOrderMap().removeAll(tx);
+ assertEquals(orders.size() - 5, removed);
+ }
+
+ // again make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+ assertEquals(0, orderMap.querySize(tx));
+ }
+ }
+
+ // now add all again
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getOrderMap().addAll(tx, orders);
+ }
+
+ Set expectedTypes = new HashSet<>();
+ expectedTypes.add("MyType1");
+ expectedTypes.add("MyType2");
+ expectedTypes.add("MyType3");
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ List allOrders = tx.getOrderMap().getAllElements(tx);
+ Collections.sort(allOrders, comparator);
+ assertEquals(orders, allOrders);
+ }
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ OrderMap orderMap = tx.getOrderMap();
+
+ Set types = orderMap.getTypes(tx);
+ assertEquals(expectedTypes, types);
+
+ Set keySet = orderMap.getAllKeys(tx);
+ assertEquals(15, keySet.size());
+
+ for (String type : types) {
+ Set idsByType = orderMap.getKeysBy(tx, type);
+ assertEquals(5, idsByType.size());
+
+ List ordersByType = orderMap.getElementsBy(tx, type);
+ assertEquals(5, ordersByType.size());
+ }
+ }
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ Order order = tx.getOrderMap().getBy(tx, "MyType1", "@00000001");
+ assertNotNull(order);
+ order = tx.getOrderMap().getBy(tx, "MyType2", "@00000006");
+ assertNotNull(order);
+ order = tx.getOrderMap().getBy(tx, "MyType3", "@00000011");
+ assertNotNull(order);
+ }
+ }
+}
diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/ResourceModelTestRunner.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/ResourceModelTestRunner.java
new file mode 100644
index 000000000..4725a53e7
--- /dev/null
+++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/ResourceModelTestRunner.java
@@ -0,0 +1,247 @@
+package li.strolch.testbase.runtime;
+
+import static li.strolch.model.ModelGenerator.BAG_ID;
+import static li.strolch.model.ModelGenerator.PARAM_STRING_ID;
+import static li.strolch.model.ModelGenerator.createResource;
+import static li.strolch.model.ModelGenerator.createResources;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import li.strolch.agent.api.ResourceMap;
+import li.strolch.agent.impl.DataStoreMode;
+import li.strolch.model.Resource;
+import li.strolch.model.parameter.Parameter;
+import li.strolch.persistence.api.StrolchTransaction;
+import li.strolch.runtime.privilege.PrivilegeHandler;
+import ch.eitchnet.privilege.model.Certificate;
+
+@SuppressWarnings("nls")
+public class ResourceModelTestRunner {
+
+ private static final String ID = "@testResource"; //$NON-NLS-1$
+ private static final String NAME = "Test Resource"; //$NON-NLS-1$
+ private static final String TYPE = "Box"; //$NON-NLS-1$
+
+ private RuntimeMock runtimeMock;
+ private String realmName;
+ private Certificate certificate;
+
+ public ResourceModelTestRunner(RuntimeMock runtimeMock, String realmName) {
+ this.runtimeMock = runtimeMock;
+ this.realmName = realmName;
+
+ PrivilegeHandler privilegeHandler = runtimeMock.getContainer().getPrivilegeHandler();
+ this.certificate = privilegeHandler.authenticate("test", "test".getBytes());
+ }
+
+ public void runCreateResourceTest() {
+
+ // create
+ Resource newResource = createResource("MyTestResource", "Test Name", "TestType"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().add(tx, newResource);
+ }
+ }
+
+ public void runQuerySizeTest() {
+
+ // remove all
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().removeAll(tx, tx.getResourceMap().getAllElements(tx));
+ }
+
+ // create three resources
+ Resource resource1 = createResource("myTestResource1", "Test Name", "QTestType1"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ Resource resource2 = createResource("myTestResource2", "Test Name", "QTestType2"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ Resource resource3 = createResource("myTestResource3", "Test Name", "QTestType3"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().add(tx, resource1);
+ tx.getResourceMap().add(tx, resource2);
+ tx.getResourceMap().add(tx, resource3);
+ }
+
+ // query size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ long size = tx.getResourceMap().querySize(tx);
+ assertEquals("Should have three objects", 3, size);
+
+ size = tx.getResourceMap().querySize(tx, "QTestType1");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getResourceMap().querySize(tx, "QTestType2");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getResourceMap().querySize(tx, "QTestType3");
+ assertEquals("Should have only one object of type 'QTestType1'", 1, size);
+
+ size = tx.getResourceMap().querySize(tx, "NonExistingType");
+ assertEquals("Should have zero objects of type 'NonExistingType'", 0, size);
+ }
+ }
+
+ public void runCrudTests() {
+
+ // create
+ Resource newResource = createResource(ID, NAME, TYPE);
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().add(tx, newResource);
+ }
+
+ // read
+ Resource readResource = null;
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ readResource = tx.getResourceMap().getBy(tx, TYPE, ID);
+ }
+ assertNotNull("Should read Resource with id " + ID, readResource); //$NON-NLS-1$
+
+ // update
+ Parameter sParam = readResource.getParameter(BAG_ID, PARAM_STRING_ID);
+ String newStringValue = "Giddiya!"; //$NON-NLS-1$
+ sParam.setValue(newStringValue);
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().update(tx, readResource);
+ }
+
+ // read updated
+ Resource updatedResource = null;
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ updatedResource = tx.getResourceMap().getBy(tx, TYPE, ID);
+ }
+ assertNotNull("Should read Resource with id " + ID, updatedResource); //$NON-NLS-1$
+ if (this.runtimeMock.getRealm(this.realmName).getMode() != DataStoreMode.CACHED)
+ assertFalse("Objects can't be the same reference after re-reading!", readResource == updatedResource); //$NON-NLS-1$
+ Parameter updatedParam = readResource.getParameter(BAG_ID, PARAM_STRING_ID);
+ assertEquals(newStringValue, updatedParam.getValue());
+
+ // delete
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ tx.getResourceMap().remove(tx, readResource);
+ }
+
+ // fail to re-read
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test");) {
+ Resource resource = tx.getResourceMap().getBy(tx, TYPE, ID);
+ assertNull("Should no read Resource with id " + ID, resource); //$NON-NLS-1$
+ }
+ }
+
+ public void runBulkOperationTests() {
+
+ // create 15 resources
+ List resources = new ArrayList<>();
+ resources.addAll(createResources(resources.size(), 5, "@", "My Resource", "MyType1"));
+ resources.addAll(createResources(resources.size(), 5, "@", "Other Resource", "MyType2"));
+ resources.addAll(createResources(resources.size(), 5, "@", "Further Resource", "MyType3"));
+
+ // sort them so we know which order our objects are
+ Comparator comparator = new Comparator() {
+ @Override
+ public int compare(Resource o1, Resource o2) {
+ return o1.getId().compareTo(o2.getId());
+ }
+ };
+ Collections.sort(resources, comparator);
+
+ // first clear the map, so that we have a clean state
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+ resourceMap.removeAll(tx, resourceMap.getAllElements(tx));
+ }
+
+ {
+ // make sure it is empty
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+ assertEquals(0, resourceMap.querySize(tx));
+ }
+
+ // now add some resources
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getResourceMap().addAll(tx, resources);
+ }
+
+ // make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+ assertEquals(resources.size(), resourceMap.querySize(tx));
+ assertEquals(5, resourceMap.querySize(tx, "MyType3"));
+ }
+
+ // now use the remove all by type
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getResourceMap().removeAllBy(tx, "MyType3");
+ }
+
+ // again make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+ assertEquals(resources.size() - 5, resourceMap.querySize(tx));
+ assertEquals(0, resourceMap.querySize(tx, "MyType3"));
+ }
+
+ // now use the remove all
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ long removed = tx.getResourceMap().removeAll(tx);
+ assertEquals(resources.size() - 5, removed);
+ }
+
+ // again make sure we have our expected size
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+ assertEquals(0, resourceMap.querySize(tx));
+ }
+ }
+
+ // now add all again
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ tx.getResourceMap().addAll(tx, resources);
+ }
+
+ Set expectedTypes = new HashSet<>();
+ expectedTypes.add("MyType1");
+ expectedTypes.add("MyType2");
+ expectedTypes.add("MyType3");
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ List allResources = tx.getResourceMap().getAllElements(tx);
+ Collections.sort(allResources, comparator);
+ assertEquals(resources, allResources);
+ }
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ ResourceMap resourceMap = tx.getResourceMap();
+
+ Set types = resourceMap.getTypes(tx);
+ assertEquals(expectedTypes, types);
+
+ Set keySet = resourceMap.getAllKeys(tx);
+ assertEquals(15, keySet.size());
+
+ for (String type : types) {
+ Set idsByType = resourceMap.getKeysBy(tx, type);
+ assertEquals(5, idsByType.size());
+
+ List resourcesByType = resourceMap.getElementsBy(tx, type);
+ assertEquals(5, resourcesByType.size());
+ }
+ }
+
+ try (StrolchTransaction tx = this.runtimeMock.getRealm(this.realmName).openTx(this.certificate, "test")) {
+ Resource resource = tx.getResourceMap().getBy(tx, "MyType1", "@00000001");
+ assertNotNull(resource);
+ resource = tx.getResourceMap().getBy(tx, "MyType2", "@00000006");
+ assertNotNull(resource);
+ resource = tx.getResourceMap().getBy(tx, "MyType3", "@00000011");
+ assertNotNull(resource);
+ }
+ }
+}
diff --git a/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java
new file mode 100644
index 000000000..757aa84f3
--- /dev/null
+++ b/li.strolch.testbase/src/main/java/li/strolch/testbase/runtime/RuntimeMock.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package li.strolch.testbase.runtime;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.text.MessageFormat;
+
+import li.strolch.agent.api.ComponentContainer;
+import li.strolch.agent.api.StrolchAgent;
+import li.strolch.agent.api.StrolchRealm;
+import li.strolch.runtime.configuration.RuntimeConfiguration;
+import li.strolch.runtime.privilege.PrivilegeHandler;
+import li.strolch.service.api.ServiceHandler;
+import li.strolch.service.api.ServiceResult;
+import li.strolch.service.api.ServiceResultState;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.eitchnet.utils.helper.FileHelper;
+import ch.eitchnet.utils.helper.StringHelper;
+
+public final class RuntimeMock {
+
+ private static final Logger logger = LoggerFactory.getLogger(RuntimeMock.class);
+ private static final String TARGET = "target"; //$NON-NLS-1$
+
+ private ComponentContainer container;
+ private StrolchAgent agent;
+ private File rootPath;
+ private File rootSrc;
+
+ public ComponentContainer getContainer() {
+ return this.container;
+ }
+
+ public StrolchAgent getAgent() {
+ return this.agent;
+ }
+
+ public PrivilegeHandler getPrivilegeHandler() {
+ return this.container.getPrivilegeHandler();
+ }
+
+ public ServiceHandler getServiceHandler() {
+ return this.container.getComponent(ServiceHandler.class);
+ }
+
+ public StrolchRealm getRealm(String realm) {
+ return this.container.getRealm(realm);
+ }
+
+ public void mockRuntime(File rootPath, File rootSrc) {
+
+ this.rootPath = rootPath;
+ this.rootSrc = rootSrc;
+
+ if (!this.rootPath.getParentFile().getName().equals(TARGET)) {
+ String msg = "Mocking path must be in a maven target: {0}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath());
+ throw new RuntimeException(msg);
+ }
+
+ File configSrc = new File(this.rootSrc, RuntimeConfiguration.PATH_CONFIG);
+
+ if (!configSrc.isDirectory() || !configSrc.canRead()) {
+ String msg = "Could not find config source in: {0}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, configSrc.getAbsolutePath());
+ throw new RuntimeException(msg);
+ }
+
+ if (this.rootPath.exists()) {
+ logger.info("Deleting all files in " + this.rootPath.getAbsolutePath()); //$NON-NLS-1$
+ if (!FileHelper.deleteFile(this.rootPath, true)) {
+ String msg = "Failed to delete {0}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath());
+ throw new RuntimeException(msg);
+ }
+ }
+
+ if (!this.rootPath.mkdirs()) {
+ String msg = "Failed to create {0}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, this.rootPath.getAbsolutePath());
+ throw new RuntimeException(msg);
+ }
+
+ logger.info(MessageFormat.format("Mocking runtime from {0} to {1}", this.rootSrc.getAbsolutePath(), //$NON-NLS-1$
+ this.rootPath.getAbsolutePath()));
+
+ if (!FileHelper.copy(this.rootSrc.listFiles(), this.rootPath, false)) {
+ String msg = "Failed to copy source files from {0} to {1}"; //$NON-NLS-1$
+ msg = MessageFormat.format(msg, this.rootSrc.getAbsolutePath(), this.rootPath.getAbsolutePath());
+ throw new RuntimeException(msg);
+ }
+ }
+
+ public void startContainer() {
+ startContainer("dev");
+ }
+
+ public void startContainer(String environment) {
+
+ try {
+ StrolchAgent agent = new StrolchAgent();
+ agent.setup(environment, this.rootPath);
+ agent.initialize();
+ agent.start();
+
+ this.agent = agent;
+ this.container = agent.getContainer();
+
+ } catch (Exception e) {
+ logger.error("Failed to start mocked container due to: " + e.getMessage(), e); //$NON-NLS-1$
+ destroyRuntime();
+ throw e;
+ }
+ }
+
+ public void destroyRuntime() {
+
+ if (this.agent == null)
+ return;
+
+ try {
+ this.agent.stop();
+ } catch (Exception e) {
+ logger.info("Failed to stop container: " + e.getMessage()); //$NON-NLS-1$
+ }
+
+ try {
+ this.agent.destroy();
+ } catch (Exception e) {
+ logger.info("Failed to destroy container: " + e.getMessage()); //$NON-NLS-1$
+ }
+ }
+
+ public static void assertServiceResult(ServiceResultState expectedState, Class> expectedResultType,
+ ServiceResult result) {
+ assertEquals("Expected service result of type " + expectedResultType + " but was " + result.getClass(),
+ expectedResultType, result.getClass());
+
+ if (!expectedState.equals(result.getState())) {
+ fail("Expected service result state " + expectedState + " but was " + result.getState() + ": Reason: "
+ + StringHelper.formatException(result.getThrowable()));
+ }
+ }
+}