A full test script for various inputs and a Java TestNG implementation that tests it.
This commit is contained in:
parent
1a1e024178
commit
3d064fa68d
@ -122,6 +122,23 @@ public enum MPElementType {
|
||||
throw logger.bug( "No type for option: %s", option );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name The name of the type to look up. It is matched case insensitively.
|
||||
*
|
||||
* @return The type registered with the given name.
|
||||
*/
|
||||
public static MPElementType forName(final String name) {
|
||||
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
for (final MPElementType type : values())
|
||||
if (type.name().equalsIgnoreCase( name ))
|
||||
return type;
|
||||
|
||||
throw logger.bug( "No type for name: %s", name );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param typeClass The class for which we look up types.
|
||||
*
|
||||
|
@ -60,4 +60,21 @@ public enum MPElementVariant {
|
||||
|
||||
throw logger.bug( "No variant for option: %s", option );
|
||||
}
|
||||
/**
|
||||
* @param name The name of the variant to look up. It is matched case insensitively.
|
||||
*
|
||||
* @return The variant registered with the given name.
|
||||
*/
|
||||
public static MPElementVariant forName(final String name) {
|
||||
|
||||
if (name == null)
|
||||
return null;
|
||||
|
||||
for (final MPElementVariant type : values())
|
||||
if (type.name().equalsIgnoreCase( name ))
|
||||
return type;
|
||||
|
||||
throw logger.bug( "No variant for name: %s", name );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,189 @@
|
||||
package com.lyndir.masterpassword;
|
||||
|
||||
import static com.lyndir.lhunath.opal.system.util.ObjectUtils.*;
|
||||
|
||||
import com.google.common.base.Verify;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import com.lyndir.lhunath.opal.system.util.NFunctionNN;
|
||||
import com.lyndir.lhunath.opal.system.util.NNSupplier;
|
||||
import java.util.List;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.xml.bind.annotation.*;
|
||||
|
||||
|
||||
/**
|
||||
* @author lhunath, 14-12-05
|
||||
*/
|
||||
@XmlRootElement(name = "tests")
|
||||
public class MPWTests {
|
||||
|
||||
public static final String ID_DEFAULT = "default";
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
private static final Logger logger = Logger.get( MPWTests.class );
|
||||
|
||||
@XmlElement(name = "case")
|
||||
private List<Case> cases;
|
||||
|
||||
public List<Case> getCases() {
|
||||
return cases;
|
||||
}
|
||||
|
||||
public Case getCase(String identifier) {
|
||||
for (Case testCase : getCases())
|
||||
if (identifier.equals( testCase.getIdentifier() ))
|
||||
return testCase;
|
||||
|
||||
throw new IllegalArgumentException( "No case for identifier: " + identifier );
|
||||
}
|
||||
|
||||
@XmlRootElement(name = "case")
|
||||
public static class Case {
|
||||
|
||||
@XmlAttribute(name = "id")
|
||||
private String identifier;
|
||||
@XmlAttribute
|
||||
private String parent;
|
||||
@XmlElement
|
||||
private String fullName;
|
||||
@XmlElement
|
||||
private String masterPassword;
|
||||
@XmlElement
|
||||
private String keyID;
|
||||
@XmlElement
|
||||
private String siteName;
|
||||
@XmlElement
|
||||
private Integer siteCounter;
|
||||
@XmlElement
|
||||
private String siteType;
|
||||
@XmlElement
|
||||
private String siteVariant;
|
||||
@XmlElement
|
||||
private String siteContext;
|
||||
@XmlElement
|
||||
private String result;
|
||||
|
||||
private transient Case parentCase;
|
||||
|
||||
public void setTests(MPWTests tests) {
|
||||
|
||||
if (parent != null) {
|
||||
parentCase = tests.getCase( parent );
|
||||
fullName = ifNotNullElse( fullName, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getFullName();
|
||||
}
|
||||
} );
|
||||
masterPassword = ifNotNullElse( masterPassword, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getMasterPassword();
|
||||
}
|
||||
} );
|
||||
keyID = ifNotNullElse( keyID, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getKeyID();
|
||||
}
|
||||
} );
|
||||
siteName = ifNotNullElse( siteName, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getSiteName();
|
||||
}
|
||||
} );
|
||||
siteCounter = ifNotNullElse( siteCounter, new NNSupplier<Integer>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public Integer get() {
|
||||
return parentCase.getSiteCounter();
|
||||
}
|
||||
} );
|
||||
siteType = ifNotNullElse( siteType, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getSiteType().name();
|
||||
}
|
||||
} );
|
||||
siteVariant = ifNotNullElse( siteVariant, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getSiteVariant().name();
|
||||
}
|
||||
} );
|
||||
siteContext = ifNotNullElse( siteContext, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getSiteContext();
|
||||
}
|
||||
} );
|
||||
result = ifNotNullElse( result, new NNSupplier<String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String get() {
|
||||
return parentCase.getResult();
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Case getParentCase() {
|
||||
return parentCase;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public String getMasterPassword() {
|
||||
return masterPassword;
|
||||
}
|
||||
|
||||
public String getKeyID() {
|
||||
return keyID;
|
||||
}
|
||||
|
||||
public String getSiteName() {
|
||||
return siteName;
|
||||
}
|
||||
|
||||
public int getSiteCounter() {
|
||||
return siteCounter;
|
||||
}
|
||||
|
||||
public MPElementType getSiteType() {
|
||||
return MPElementType.forName( siteType );
|
||||
}
|
||||
|
||||
public MPElementVariant getSiteVariant() {
|
||||
return MPElementVariant.forName( siteVariant );
|
||||
}
|
||||
|
||||
public String getSiteContext() {
|
||||
return siteContext;
|
||||
}
|
||||
|
||||
public String getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,65 +2,62 @@ package com.lyndir.masterpassword;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import com.lyndir.lhunath.opal.system.logging.Logger;
|
||||
import java.net.URL;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
||||
public class MasterKeyTest {
|
||||
|
||||
private static final String FULL_NAME = "Robert Lee Mitchell";
|
||||
private static final String MASTER_PASSWORD = "banana colored duckling";
|
||||
private static final String SITE_NAME = "masterpasswordapp.com";
|
||||
@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.setTests( tests );
|
||||
defaultCase = tests.getCase( MPWTests.ID_DEFAULT );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncode()
|
||||
throws Exception {
|
||||
|
||||
MasterKey masterKey = new MasterKey( FULL_NAME, MASTER_PASSWORD );
|
||||
|
||||
assertEquals( masterKey.encode( SITE_NAME, MPElementType.GeneratedLong, 1, MPElementVariant.Password, null ), //
|
||||
"Jejr5[RepuSosp" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedMaximum, 1, MPElementVariant.Password, null ), //
|
||||
"bp7rJKc7kaXc4sxOwG0*" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedLong, 1, MPElementVariant.Password, null ), //
|
||||
"LiheCuwhSerz6)" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedMedium, 1, MPElementVariant.Password, null ), //
|
||||
"LihPih8+" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedBasic, 1, MPElementVariant.Password, null ), //
|
||||
"bpW62jmW" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedShort, 1, MPElementVariant.Password, null ), //
|
||||
"Lih6" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedPIN, 1, MPElementVariant.Password, null ), //
|
||||
"9216" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedName, 1, MPElementVariant.Password, null ), //
|
||||
"lihpihohi" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedPhrase, 1, MPElementVariant.Password, null ), //
|
||||
"li pihwe puz bemozno" );
|
||||
|
||||
assertEquals( masterKey.encode( "\u26C4", MPElementType.GeneratedMaximum, (int) 4294967295L, MPElementVariant.Password, null ),
|
||||
"r*)Ekr(FiduISCj*pg5-" );
|
||||
for (MPWTests.Case testCase : tests.getCases()) {
|
||||
MasterKey masterKey = new MasterKey( testCase.getFullName(), testCase.getMasterPassword() );
|
||||
assertEquals( masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(),
|
||||
testCase.getSiteVariant(), testCase.getSiteContext() ), testCase.getResult(),
|
||||
"Failed test case: " + testCase );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserName()
|
||||
throws Exception {
|
||||
|
||||
assertEquals( new MasterKey( FULL_NAME, "banana colored duckling" ).getUserName(), FULL_NAME );
|
||||
assertEquals( new MasterKey( defaultCase.getFullName(), defaultCase.getMasterPassword() ).getUserName(),
|
||||
defaultCase.getFullName() );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKeyID()
|
||||
throws Exception {
|
||||
|
||||
assertEquals( new MasterKey( FULL_NAME, "banana colored duckling" ).getKeyID(),
|
||||
"98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302" );
|
||||
for (MPWTests.Case testCase : tests.getCases()) {
|
||||
MasterKey masterKey = new MasterKey( testCase.getFullName(), testCase.getMasterPassword() );
|
||||
assertEquals( masterKey.getKeyID(), testCase.getKeyID(), "Failed test case: " + testCase );
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -68,10 +65,11 @@ public class MasterKeyTest {
|
||||
throws Exception {
|
||||
|
||||
try {
|
||||
MasterKey masterKey = new MasterKey( FULL_NAME, MASTER_PASSWORD );
|
||||
MasterKey masterKey = new MasterKey( defaultCase.getFullName(), defaultCase.getMasterPassword() );
|
||||
masterKey.invalidate();
|
||||
masterKey.encode( SITE_NAME, MPElementType.GeneratedLong, 1, MPElementVariant.Password, null );
|
||||
assertFalse( true, "Master key was not invalidated." );
|
||||
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) {
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
<configuration scan="false">
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<layout class="ch.qos.logback.classic.PatternLayout">
|
||||
<Pattern>%-8relative %22c{0} [%-5level] %msg%n</Pattern>
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="com.lyndir.masterpassword" level="${mp.log.level:-TRACE}" />
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
@ -0,0 +1,72 @@
|
||||
<tests>
|
||||
<case id="default">
|
||||
<fullName>Robert Lee Mitchell</fullName>
|
||||
<masterPassword>banana colored duckling</masterPassword>
|
||||
<keyID>98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302</keyID>
|
||||
<siteName>masterpasswordapp.com</siteName>
|
||||
<siteCounter>1</siteCounter>
|
||||
<siteType>GeneratedLong</siteType>
|
||||
<siteVariant>Password</siteVariant>
|
||||
<siteContext />
|
||||
<result>Jejr5[RepuSosp</result>
|
||||
</case>
|
||||
<case id="mb_fullName" parent="default">
|
||||
<fullName>⛄</fullName>
|
||||
<keyID>1717AA1F9BF5BA56CD0965CDA3D78E6D2E6A1EA8C067A8EA621F3DDAD4A87EB8</keyID>
|
||||
<result>NopaDajh8=Fene</result>
|
||||
</case>
|
||||
<case id="mb_masterPassword" parent="default">
|
||||
<masterPassword>⛄</masterPassword>
|
||||
<keyID>351432B8528A5ABECAB768CA95015097DE76FE14C41E10AF36C67DCFB8917E08</keyID>
|
||||
<result>QesuHirv5-Xepl</result>
|
||||
</case>
|
||||
<case id="mb_siteName" parent="default">
|
||||
<siteName>⛄</siteName>
|
||||
<result>LiheCuwhSerz6)</result>
|
||||
</case>
|
||||
<case id="loginName" parent="default">
|
||||
<siteVariant>Login</siteVariant>
|
||||
<result>WohzKifuDilo5,</result>
|
||||
</case>
|
||||
<case id="securityAnswer" parent="default">
|
||||
<siteVariant>Answer</siteVariant>
|
||||
<result>XineDiyj2)Tozz</result>
|
||||
</case>
|
||||
<case id="securityAnswer_context" parent="securityAnswer">
|
||||
<siteContext>question</siteContext>
|
||||
<result>XineDiyj2)Tozz</result>
|
||||
</case>
|
||||
<case id="type_maximum" parent="default">
|
||||
<siteType>GeneratedMaximum</siteType>
|
||||
<result>W6@692^B1#&@gVdSdLZ@</result>
|
||||
</case>
|
||||
<case id="type_medium" parent="default">
|
||||
<siteType>GeneratedMedium</siteType>
|
||||
<result>Jej2$Quv</result>
|
||||
</case>
|
||||
<case id="type_basic" parent="default">
|
||||
<siteType>GeneratedBasic</siteType>
|
||||
<result>WAo2xIg6</result>
|
||||
</case>
|
||||
<case id="type_short" parent="default">
|
||||
<siteType>GeneratedShort</siteType>
|
||||
<result>Jej2</result>
|
||||
</case>
|
||||
<case id="type_pin" parent="default">
|
||||
<siteType>GeneratedPIN</siteType>
|
||||
<result>7662</result>
|
||||
</case>
|
||||
<case id="type_name" parent="default">
|
||||
<siteType>GeneratedName</siteType>
|
||||
<result>jejraquvo</result>
|
||||
</case>
|
||||
<case id="type_phrase" parent="default">
|
||||
<siteType>GeneratedPhrase</siteType>
|
||||
<result>jejr quv cabsibu tam</result>
|
||||
</case>
|
||||
<case id="counter_ceiling" parent="default">
|
||||
<siteCounter>4294967295</siteCounter>
|
||||
<result>XambHoqo6[Peni</result>
|
||||
</case>
|
||||
</tests>
|
||||
|
Loading…
Reference in New Issue
Block a user