Provide an API for during runtime tests.
[ADDED] masterpassword-tests provides an API for performing runtime tests of whether the master password algorithm performs as it should on the current platform.
This commit is contained in:
parent
acdb96cb6f
commit
188353d39b
@ -39,18 +39,6 @@
|
|||||||
<version>1.4.0</version>
|
<version>1.4.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- TESTING -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.testng</groupId>
|
|
||||||
<artifactId>testng</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>ch.qos.logback</groupId>
|
|
||||||
<artifactId>logback-classic</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -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) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
43
MasterPassword/Java/masterpassword-tests/pom.xml
Normal file
43
MasterPassword/Java/masterpassword-tests/pom.xml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!-- PROJECT METADATA -->
|
||||||
|
<parent>
|
||||||
|
<groupId>com.lyndir.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>Master Password Test Suite</name>
|
||||||
|
<description>The standard test suite to ensure the Master Password algorithm is operating as it should</description>
|
||||||
|
|
||||||
|
<artifactId>masterpassword-tests</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<!-- DEPENDENCY MANAGEMENT -->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!-- PROJECT REFERENCES -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.lyndir.masterpassword</groupId>
|
||||||
|
<artifactId>masterpassword-algorithm</artifactId>
|
||||||
|
<version>GIT-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- TESTING -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
@ -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<MPTests.Case, Boolean> 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<MPTests.Case, Boolean>() {
|
||||||
|
@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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,12 +15,12 @@ import javax.xml.bind.annotation.*;
|
|||||||
* @author lhunath, 14-12-05
|
* @author lhunath, 14-12-05
|
||||||
*/
|
*/
|
||||||
@XmlRootElement(name = "tests")
|
@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")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
private static final Logger logger = Logger.get( MPWTests.class );
|
private static final Logger logger = Logger.get( MPTests.class );
|
||||||
|
|
||||||
@XmlElement(name = "case")
|
@XmlElement(name = "case")
|
||||||
private List<Case> cases;
|
private List<Case> cases;
|
||||||
@ -38,6 +38,15 @@ public class MPWTests {
|
|||||||
throw new IllegalArgumentException( "No case for identifier: " + identifier );
|
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")
|
@XmlRootElement(name = "case")
|
||||||
public static class Case {
|
public static class Case {
|
||||||
|
|
||||||
@ -68,7 +77,7 @@ public class MPWTests {
|
|||||||
|
|
||||||
private transient Case parentCase;
|
private transient Case parentCase;
|
||||||
|
|
||||||
public void initializeParentHierarchy(MPWTests tests) {
|
public void initializeParentHierarchy(MPTests tests) {
|
||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parentCase = tests.getCase( parent );
|
parentCase = tests.getCase( parent );
|
@ -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<MPTests.Case, Boolean>() {
|
||||||
|
@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<MPTests.Case, Boolean>() {
|
||||||
|
@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) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@
|
|||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
<module>masterpassword-tests</module>
|
||||||
<module>masterpassword-algorithm</module>
|
<module>masterpassword-algorithm</module>
|
||||||
<module>masterpassword-model</module>
|
<module>masterpassword-model</module>
|
||||||
<module>masterpassword-cli</module>
|
<module>masterpassword-cli</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user