2
0

A full test script for various inputs and a Java TestNG implementation that tests it.

This commit is contained in:
Maarten Billemont 2014-12-05 02:17:28 -05:00
parent 1a1e024178
commit 3d064fa68d
6 changed files with 348 additions and 40 deletions

View File

@ -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.
* *

View File

@ -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 );
}
} }

View File

@ -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;
}
}
}

View File

@ -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) {
} }

View File

@ -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>

View File

@ -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#&amp;@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>