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 );
|
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.
|
* @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 );
|
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 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;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
|
||||||
public class MasterKeyTest {
|
public class MasterKeyTest {
|
||||||
|
|
||||||
private static final String FULL_NAME = "Robert Lee Mitchell";
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
private static final String MASTER_PASSWORD = "banana colored duckling";
|
private static final Logger logger = Logger.get( MasterKeyTest.class );
|
||||||
private static final String SITE_NAME = "masterpasswordapp.com";
|
|
||||||
|
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
|
@Test
|
||||||
public void testEncode()
|
public void testEncode()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
MasterKey masterKey = new MasterKey( FULL_NAME, MASTER_PASSWORD );
|
for (MPWTests.Case testCase : tests.getCases()) {
|
||||||
|
MasterKey masterKey = new MasterKey( testCase.getFullName(), testCase.getMasterPassword() );
|
||||||
assertEquals( masterKey.encode( SITE_NAME, MPElementType.GeneratedLong, 1, MPElementVariant.Password, null ), //
|
assertEquals( masterKey.encode( testCase.getSiteName(), testCase.getSiteType(), testCase.getSiteCounter(),
|
||||||
"Jejr5[RepuSosp" );
|
testCase.getSiteVariant(), testCase.getSiteContext() ), testCase.getResult(),
|
||||||
|
"Failed test case: " + testCase );
|
||||||
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-" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetUserName()
|
public void testGetUserName()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
assertEquals( new MasterKey( FULL_NAME, "banana colored duckling" ).getUserName(), FULL_NAME );
|
assertEquals( new MasterKey( defaultCase.getFullName(), defaultCase.getMasterPassword() ).getUserName(),
|
||||||
|
defaultCase.getFullName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetKeyID()
|
public void testGetKeyID()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
assertEquals( new MasterKey( FULL_NAME, "banana colored duckling" ).getKeyID(),
|
for (MPWTests.Case testCase : tests.getCases()) {
|
||||||
"98EEF4D1DF46D849574A82A03C3177056B15DFFCA29BB3899DE4628453675302" );
|
MasterKey masterKey = new MasterKey( testCase.getFullName(), testCase.getMasterPassword() );
|
||||||
|
assertEquals( masterKey.getKeyID(), testCase.getKeyID(), "Failed test case: " + testCase );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -68,10 +65,11 @@ public class MasterKeyTest {
|
|||||||
throws Exception {
|
throws Exception {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
MasterKey masterKey = new MasterKey( FULL_NAME, MASTER_PASSWORD );
|
MasterKey masterKey = new MasterKey( defaultCase.getFullName(), defaultCase.getMasterPassword() );
|
||||||
masterKey.invalidate();
|
masterKey.invalidate();
|
||||||
masterKey.encode( SITE_NAME, MPElementType.GeneratedLong, 1, MPElementVariant.Password, null );
|
masterKey.encode( defaultCase.getSiteName(), defaultCase.getSiteType(), defaultCase.getSiteCounter(),
|
||||||
assertFalse( true, "Master key was not invalidated." );
|
defaultCase.getSiteVariant(), defaultCase.getSiteContext() );
|
||||||
|
assertTrue( false, "Master key should have been invalidated, but was still usable." );
|
||||||
}
|
}
|
||||||
catch (IllegalStateException ignored) {
|
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