diff --git a/MasterPassword/Java/masterpassword-algorithm/pom.xml b/MasterPassword/Java/masterpassword-algorithm/pom.xml
index e3fcec4a..daee227c 100644
--- a/MasterPassword/Java/masterpassword-algorithm/pom.xml
+++ b/MasterPassword/Java/masterpassword-algorithm/pom.xml
@@ -39,18 +39,6 @@
1.4.0
-
-
- org.testng
- testng
- test
-
-
- ch.qos.logback
- logback-classic
- test
-
-
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java b/MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java
deleted file mode 100644
index 55978452..00000000
--- a/MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.lyndir.masterpassword;
-
-import static org.testng.Assert.*;
-
-import com.google.common.io.Resources;
-import com.lyndir.lhunath.opal.system.CodeUtils;
-import com.lyndir.lhunath.opal.system.logging.Logger;
-import com.lyndir.lhunath.opal.system.util.StringUtils;
-import java.net.URL;
-import javax.xml.bind.JAXBContext;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-
-public class MasterKeyTest {
-
- @SuppressWarnings("UnusedDeclaration")
- private static final Logger logger = Logger.get( MasterKeyTest.class );
-
- private MPWTests tests;
- private MPWTests.Case defaultCase;
-
- @BeforeMethod
- public void setUp()
- throws Exception {
-
- URL testCasesResource = Resources.getResource( "mpw_tests.xml" );
- tests = (MPWTests) JAXBContext.newInstance( MPWTests.class ).createUnmarshaller().unmarshal( testCasesResource );
- for (MPWTests.Case testCase : tests.getCases())
- testCase.initializeParentHierarchy( tests );
- defaultCase = tests.getCase( MPWTests.ID_DEFAULT );
- }
-
- @Test
- public void testEncode()
- throws Exception {
-
- for (MPWTests.Case testCase : tests.getCases()) {
- if (testCase.getResult().isEmpty())
- continue;
-
- logger.inf( "Running test case: %s [testEncode]", testCase.getIdentifier() );
- MasterKey masterKey = MasterKey.create( testCase.getAlgorithm(), testCase.getFullName(), testCase.getMasterPassword() );
- assertEquals(
- masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(), testCase.getSiteVariant(),
- testCase.getSiteContext() ), testCase.getResult(), "Failed test case: " + testCase );
- logger.inf( "passed!" );
- }
- }
-
- @Test
- public void testGetUserName()
- throws Exception {
-
- assertEquals( MasterKey.create( defaultCase.getFullName(), defaultCase.getMasterPassword() ).getFullName(),
- defaultCase.getFullName() );
- }
-
- @Test
- public void testGetKeyID()
- throws Exception {
-
- for (MPWTests.Case testCase : tests.getCases()) {
- if (testCase.getResult().isEmpty())
- continue;
-
- logger.inf( "Running test case: %s [testGetKeyID]", testCase.getIdentifier() );
- MasterKey masterKey = MasterKey.create( testCase.getFullName(), testCase.getMasterPassword() );
- assertEquals( CodeUtils.encodeHex( masterKey.getKeyID() ), testCase.getKeyID(), "Failed test case: " + testCase );
- logger.inf( "passed!" );
- }
- }
-
- @Test
- public void testInvalidate()
- throws Exception {
-
- try {
- MasterKey masterKey = MasterKey.create( defaultCase.getFullName(), defaultCase.getMasterPassword() );
- masterKey.invalidate();
- masterKey.encode( defaultCase.getSiteName(), defaultCase.getSiteType(), defaultCase.getSiteCounter(),
- defaultCase.getSiteVariant(), defaultCase.getSiteContext() );
- assertTrue( false, "Master key should have been invalidated, but was still usable." );
- }
- catch (IllegalStateException ignored) {
- }
- }
-}
diff --git a/MasterPassword/Java/masterpassword-tests/pom.xml b/MasterPassword/Java/masterpassword-tests/pom.xml
new file mode 100644
index 00000000..cba8d8b8
--- /dev/null
+++ b/MasterPassword/Java/masterpassword-tests/pom.xml
@@ -0,0 +1,43 @@
+
+
+
+ 4.0.0
+
+
+
+ com.lyndir.masterpassword
+ masterpassword
+ GIT-SNAPSHOT
+
+
+ Master Password Test Suite
+ The standard test suite to ensure the Master Password algorithm is operating as it should
+
+ masterpassword-tests
+ jar
+
+
+
+
+
+
+ com.lyndir.masterpassword
+ masterpassword-algorithm
+ GIT-SNAPSHOT
+
+
+
+
+ org.testng
+ testng
+ test
+
+
+ ch.qos.logback
+ logback-classic
+ test
+
+
+
+
+
diff --git a/MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java b/MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java
new file mode 100644
index 00000000..690195c1
--- /dev/null
+++ b/MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTestSuite.java
@@ -0,0 +1,82 @@
+package com.lyndir.masterpassword;
+
+import com.google.common.io.Resources;
+import com.lyndir.lhunath.opal.system.logging.Logger;
+import com.lyndir.lhunath.opal.system.util.NNFunctionNN;
+import java.net.URL;
+import javax.annotation.Nonnull;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+
+/**
+ * @author lhunath, 2015-12-22
+ */
+public class MPTestSuite {
+
+ @SuppressWarnings("UnusedDeclaration")
+ private static final Logger logger = Logger.get( MPTestSuite.class );
+ private static final String DEFAULT_RESOURCE_NAME = "mpw_tests.xml";
+
+ private MPTests tests;
+
+ public MPTestSuite()
+ throws UnavailableException {
+ this( DEFAULT_RESOURCE_NAME );
+ }
+
+ public MPTestSuite(String resourceName)
+ throws UnavailableException {
+ try {
+ URL testCasesResource = Resources.getResource( resourceName );
+ tests = (MPTests) JAXBContext.newInstance( MPTests.class ).createUnmarshaller().unmarshal( testCasesResource );
+
+ for (MPTests.Case testCase : tests.getCases())
+ testCase.initializeParentHierarchy( tests );
+ }
+ catch (IllegalArgumentException | JAXBException e) {
+ throw new UnavailableException( e );
+ }
+ }
+
+ public MPTests getTests() {
+ return tests;
+ }
+
+ public boolean forEach(String testName, NNFunctionNN testFunction) {
+ for (MPTests.Case testCase : tests.getCases()) {
+ if (testCase.getResult().isEmpty())
+ continue;
+
+ logger.inf( "[%s] on %s...", testName, testCase.getIdentifier() );
+ if (!testFunction.apply( testCase )) {
+ logger.err( "[%s] on %s: FAILED!", testName, testCase.getIdentifier() );
+ return false;
+ }
+ logger.inf( "[%s] on %s: passed!", testName, testCase.getIdentifier() );
+ }
+
+ return true;
+ }
+
+ public boolean run() {
+ return forEach( "mpw", new NNFunctionNN() {
+ @Nonnull
+ @Override
+ public Boolean apply(@Nonnull final MPTests.Case testCase) {
+ MasterKey masterKey = MasterKey.create( testCase.getAlgorithm(), testCase.getFullName(), testCase.getMasterPassword() );
+ String sitePassword = masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(),
+ testCase.getSiteVariant(), testCase.getSiteContext() );
+
+ return testCase.getResult().equals( sitePassword );
+ }
+ } );
+ }
+
+ public static class UnavailableException extends Exception {
+
+ public UnavailableException(final Throwable cause) {
+ super( cause );
+ }
+ }
+}
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MPWTests.java b/MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTests.java
similarity index 92%
rename from MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MPWTests.java
rename to MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTests.java
index 5673bda6..151d49f7 100644
--- a/MasterPassword/Java/masterpassword-algorithm/src/test/java/com/lyndir/masterpassword/MPWTests.java
+++ b/MasterPassword/Java/masterpassword-tests/src/main/java/com/lyndir/masterpassword/MPTests.java
@@ -15,12 +15,12 @@ import javax.xml.bind.annotation.*;
* @author lhunath, 14-12-05
*/
@XmlRootElement(name = "tests")
-public class MPWTests {
+public class MPTests {
- public static final String ID_DEFAULT = "default";
+ private static final String ID_DEFAULT = "default";
@SuppressWarnings("UnusedDeclaration")
- private static final Logger logger = Logger.get( MPWTests.class );
+ private static final Logger logger = Logger.get( MPTests.class );
@XmlElement(name = "case")
private List cases;
@@ -38,6 +38,15 @@ public class MPWTests {
throw new IllegalArgumentException( "No case for identifier: " + identifier );
}
+ public Case getDefaultCase() {
+ try {
+ return getCase( ID_DEFAULT );
+ }
+ catch (IllegalArgumentException e) {
+ throw new IllegalStateException( "Missing default case in test suite. Add a case with id: " + ID_DEFAULT, e );
+ }
+ }
+
@XmlRootElement(name = "case")
public static class Case {
@@ -68,7 +77,7 @@ public class MPWTests {
private transient Case parentCase;
- public void initializeParentHierarchy(MPWTests tests) {
+ public void initializeParentHierarchy(MPTests tests) {
if (parent != null) {
parentCase = tests.getCase( parent );
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/test/resources/mpw_tests.xml b/MasterPassword/Java/masterpassword-tests/src/main/resources/mpw_tests.xml
similarity index 100%
rename from MasterPassword/Java/masterpassword-algorithm/src/test/resources/mpw_tests.xml
rename to MasterPassword/Java/masterpassword-tests/src/main/resources/mpw_tests.xml
diff --git a/MasterPassword/Java/masterpassword-tests/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java b/MasterPassword/Java/masterpassword-tests/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java
new file mode 100644
index 00000000..89b5bea1
--- /dev/null
+++ b/MasterPassword/Java/masterpassword-tests/src/test/java/com/lyndir/masterpassword/MasterKeyTest.java
@@ -0,0 +1,96 @@
+package com.lyndir.masterpassword;
+
+import static org.testng.Assert.*;
+
+import com.google.common.io.Resources;
+import com.lyndir.lhunath.opal.system.CodeUtils;
+import com.lyndir.lhunath.opal.system.logging.Logger;
+import com.lyndir.lhunath.opal.system.util.NNFunctionNN;
+import com.lyndir.lhunath.opal.system.util.StringUtils;
+import java.net.URL;
+import javax.annotation.Nonnull;
+import javax.xml.bind.JAXBContext;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+public class MasterKeyTest {
+
+ @SuppressWarnings("UnusedDeclaration")
+ private static final Logger logger = Logger.get( MasterKeyTest.class );
+
+ private MPTestSuite testSuite;
+
+ @BeforeMethod
+ public void setUp()
+ throws Exception {
+
+ testSuite = new MPTestSuite();
+ }
+
+ @Test
+ public void testEncode()
+ throws Exception {
+
+ testSuite.forEach( "testEncode", new NNFunctionNN() {
+ @Nonnull
+ @Override
+ public Boolean apply(@Nonnull final MPTests.Case testCase) {
+ MasterKey masterKey = MasterKey.create( testCase.getAlgorithm(), testCase.getFullName(), testCase.getMasterPassword() );
+
+ assertEquals(
+ masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(),
+ testCase.getSiteVariant(), testCase.getSiteContext() ),
+ testCase.getResult(), "[testEncode] Failed test case: " + testCase );
+
+ return true;
+ }
+ } );
+ }
+
+ @Test
+ public void testGetUserName()
+ throws Exception {
+
+ MPTests.Case defaultCase = testSuite.getTests().getDefaultCase();
+
+ assertEquals( MasterKey.create( defaultCase.getFullName(), defaultCase.getMasterPassword() ).getFullName(),
+ defaultCase.getFullName(), "[testGetUserName] Failed test case: " + defaultCase );
+ }
+
+ @Test
+ public void testGetKeyID()
+ throws Exception {
+
+ testSuite.forEach( "testGetKeyID", new NNFunctionNN() {
+ @Nonnull
+ @Override
+ public Boolean apply(@Nonnull final MPTests.Case testCase) {
+ MasterKey masterKey = MasterKey.create( testCase.getFullName(), testCase.getMasterPassword() );
+
+ assertEquals( CodeUtils.encodeHex( masterKey.getKeyID() ),
+ testCase.getKeyID(), "[testGetKeyID] Failed test case: " + testCase );
+
+ return true;
+ }
+ } );
+ }
+
+ @Test
+ public void testInvalidate()
+ throws Exception {
+
+ try {
+ MPTests.Case defaultCase = testSuite.getTests().getDefaultCase();
+
+ MasterKey masterKey = MasterKey.create( defaultCase.getFullName(), defaultCase.getMasterPassword() );
+ masterKey.invalidate();
+ masterKey.encode( defaultCase.getSiteName(), defaultCase.getSiteType(), defaultCase.getSiteCounter(),
+ defaultCase.getSiteVariant(), defaultCase.getSiteContext() );
+
+ assertTrue( false, "[testInvalidate] Master key should have been invalidated, but was still usable." );
+ }
+ catch (IllegalStateException ignored) {
+ }
+ }
+}
diff --git a/MasterPassword/Java/masterpassword-algorithm/src/test/resources/logback.xml b/MasterPassword/Java/masterpassword-tests/src/test/resources/logback.xml
similarity index 100%
rename from MasterPassword/Java/masterpassword-algorithm/src/test/resources/logback.xml
rename to MasterPassword/Java/masterpassword-tests/src/test/resources/logback.xml
diff --git a/MasterPassword/Java/pom.xml b/MasterPassword/Java/pom.xml
index a1d99524..a4bbcf3e 100644
--- a/MasterPassword/Java/pom.xml
+++ b/MasterPassword/Java/pom.xml
@@ -19,6 +19,7 @@
pom
+ masterpassword-tests
masterpassword-algorithm
masterpassword-model
masterpassword-cli