Merge "New extra and helper methods to set screenlock to a specific complexity level"
This commit is contained in:
committed by
Android (Google) Code Review
commit
2288bdc9ab
@@ -6823,6 +6823,7 @@ package android.app.admin {
|
||||
field public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
|
||||
field public static final String EXTRA_DELEGATION_SCOPES = "android.app.extra.DELEGATION_SCOPES";
|
||||
field public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
|
||||
field @RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
|
||||
field public static final String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
|
||||
field public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
|
||||
field public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
|
||||
|
||||
@@ -1362,16 +1362,23 @@ public class DevicePolicyManager {
|
||||
public static final String EXTRA_RESTRICTION = "android.app.extra.RESTRICTION";
|
||||
|
||||
/**
|
||||
* Activity action: have the user enter a new password. This activity should
|
||||
* be launched after using {@link #setPasswordQuality(ComponentName, int)},
|
||||
* or {@link #setPasswordMinimumLength(ComponentName, int)} to have the user
|
||||
* enter a new password that meets the current requirements. You can use
|
||||
* {@link #isActivePasswordSufficient()} to determine whether you need to
|
||||
* have the user select a new password in order to meet the current
|
||||
* constraints. Upon being resumed from this activity, you can check the new
|
||||
* Activity action: have the user enter a new password.
|
||||
*
|
||||
* <p>For admin apps, this activity should be launched after using {@link
|
||||
* #setPasswordQuality(ComponentName, int)}, or {@link
|
||||
* #setPasswordMinimumLength(ComponentName, int)} to have the user enter a new password that
|
||||
* meets the current requirements. You can use {@link #isActivePasswordSufficient()} to
|
||||
* determine whether you need to have the user select a new password in order to meet the
|
||||
* current constraints. Upon being resumed from this activity, you can check the new
|
||||
* password characteristics to see if they are sufficient.
|
||||
*
|
||||
* If the intent is launched from within a managed profile with a profile
|
||||
* <p>Non-admin apps can use {@link #getPasswordComplexity()} to check the current screen lock
|
||||
* complexity, and use this activity with extra {@link #EXTRA_PASSWORD_COMPLEXITY} to suggest
|
||||
* to users how complex the app wants the new screen lock to be. Note that both {@link
|
||||
* #getPasswordComplexity()} and the extra {@link #EXTRA_PASSWORD_COMPLEXITY} require the
|
||||
* calling app to have the permission {@link permission#GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY}.
|
||||
*
|
||||
* <p>If the intent is launched from within a managed profile with a profile
|
||||
* owner built against {@link android.os.Build.VERSION_CODES#M} or before,
|
||||
* this will trigger entering a new password for the parent of the profile.
|
||||
* For all other cases it will trigger entering a new password for the user
|
||||
@@ -1383,6 +1390,24 @@ public class DevicePolicyManager {
|
||||
public static final String ACTION_SET_NEW_PASSWORD
|
||||
= "android.app.action.SET_NEW_PASSWORD";
|
||||
|
||||
/**
|
||||
* An integer indicating the complexity level of the new password an app would like the user to
|
||||
* set when launching the action {@link #ACTION_SET_NEW_PASSWORD}.
|
||||
*
|
||||
* <p>Must be one of
|
||||
* <ul>
|
||||
* <li>{@link #PASSWORD_COMPLEXITY_HIGH}
|
||||
* <li>{@link #PASSWORD_COMPLEXITY_MEDIUM}
|
||||
* <li>{@link #PASSWORD_COMPLEXITY_LOW}
|
||||
* <li>{@link #PASSWORD_COMPLEXITY_NONE}
|
||||
* </ul>
|
||||
*
|
||||
* <p>If an invalid value is used, it will be treated as {@link #PASSWORD_COMPLEXITY_NONE}.
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.GET_AND_REQUEST_SCREEN_LOCK_COMPLEXITY)
|
||||
public static final String EXTRA_PASSWORD_COMPLEXITY =
|
||||
"android.app.extra.PASSWORD_COMPLEXITY";
|
||||
|
||||
/**
|
||||
* Constant for {@link #getPasswordComplexity()}: no password.
|
||||
*
|
||||
|
||||
@@ -20,6 +20,11 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
@@ -27,6 +32,8 @@ import android.app.admin.DevicePolicyManager.PasswordComplexity;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@@ -85,6 +92,101 @@ public class PasswordMetrics implements Parcelable {
|
||||
nonLetter = in.readInt();
|
||||
}
|
||||
|
||||
/** Returns the min quality allowed by {@code complexityLevel}. */
|
||||
public static int complexityLevelToMinQuality(@PasswordComplexity int complexityLevel) {
|
||||
// this would be the quality of the first metrics since mMetrics is sorted in ascending
|
||||
// order of quality
|
||||
return PasswordComplexityBucket
|
||||
.complexityLevelToBucket(complexityLevel).mMetrics[0].quality;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a merged minimum {@link PasswordMetrics} requirements that a new password must meet
|
||||
* to fulfil {@code requestedQuality}, {@code requiresNumeric} and {@code
|
||||
* requiresLettersOrSymbols}, which are derived from {@link DevicePolicyManager} requirements,
|
||||
* and {@code complexityLevel}.
|
||||
*
|
||||
* <p>Note that we are taking {@code userEnteredPasswordQuality} into account because there are
|
||||
* more than one set of metrics to meet the minimum complexity requirement and inspecting what
|
||||
* the user has entered can help determine whether the alphabetic or alphanumeric set of metrics
|
||||
* should be used. For example, suppose minimum complexity requires either ALPHABETIC(8+), or
|
||||
* ALPHANUMERIC(6+). If the user has entered "a", the length requirement displayed on the UI
|
||||
* would be 8. Then the user appends "1" to make it "a1". We now know the user is entering
|
||||
* an alphanumeric password so we would update the min complexity required min length to 6.
|
||||
*/
|
||||
public static PasswordMetrics getMinimumMetrics(@PasswordComplexity int complexityLevel,
|
||||
int userEnteredPasswordQuality, int requestedQuality, boolean requiresNumeric,
|
||||
boolean requiresLettersOrSymbols) {
|
||||
int targetQuality = Math.max(
|
||||
userEnteredPasswordQuality,
|
||||
getActualRequiredQuality(
|
||||
requestedQuality, requiresNumeric, requiresLettersOrSymbols));
|
||||
return getTargetQualityMetrics(complexityLevel, targetQuality);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link PasswordMetrics} at {@code complexityLevel} which the metrics quality
|
||||
* is the same as {@code targetQuality}.
|
||||
*
|
||||
* <p>If {@code complexityLevel} does not allow {@code targetQuality}, returns the metrics
|
||||
* with the min quality at {@code complexityLevel}.
|
||||
*/
|
||||
// TODO(bernardchau): update tests to test getMinimumMetrics and change this to be private
|
||||
@VisibleForTesting
|
||||
public static PasswordMetrics getTargetQualityMetrics(
|
||||
@PasswordComplexity int complexityLevel, int targetQuality) {
|
||||
PasswordComplexityBucket targetBucket =
|
||||
PasswordComplexityBucket.complexityLevelToBucket(complexityLevel);
|
||||
for (PasswordMetrics metrics : targetBucket.mMetrics) {
|
||||
if (targetQuality == metrics.quality) {
|
||||
return metrics;
|
||||
}
|
||||
}
|
||||
// none of the metrics at complexityLevel has targetQuality, return metrics with min quality
|
||||
// see test case testGetMinimumMetrics_actualRequiredQualityStricter for an example, where
|
||||
// min complexity allows at least NUMERIC_COMPLEX, user has not entered anything yet, and
|
||||
// requested quality is NUMERIC
|
||||
return targetBucket.mMetrics[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds out the actual quality requirement based on whether quality is {@link
|
||||
* DevicePolicyManager#PASSWORD_QUALITY_COMPLEX} and whether digits, letters or symbols are
|
||||
* required.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
// TODO(bernardchau): update tests to test getMinimumMetrics and change this to be private
|
||||
public static int getActualRequiredQuality(
|
||||
int requestedQuality, boolean requiresNumeric, boolean requiresLettersOrSymbols) {
|
||||
if (requestedQuality != PASSWORD_QUALITY_COMPLEX) {
|
||||
return requestedQuality;
|
||||
}
|
||||
|
||||
// find out actual password quality from complex requirements
|
||||
if (requiresNumeric && requiresLettersOrSymbols) {
|
||||
return PASSWORD_QUALITY_ALPHANUMERIC;
|
||||
}
|
||||
if (requiresLettersOrSymbols) {
|
||||
return PASSWORD_QUALITY_ALPHABETIC;
|
||||
}
|
||||
if (requiresNumeric) {
|
||||
// cannot specify numeric complex using complex quality so this must be numeric
|
||||
return PASSWORD_QUALITY_NUMERIC;
|
||||
}
|
||||
|
||||
// reaching here means dpm sets quality to complex without specifying any requirements
|
||||
return PASSWORD_QUALITY_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code complexityLevel} or {@link DevicePolicyManager#PASSWORD_COMPLEXITY_NONE}
|
||||
* if {@code complexityLevel} is not valid.
|
||||
*/
|
||||
@PasswordComplexity
|
||||
public static int sanitizeComplexityLevel(@PasswordComplexity int complexityLevel) {
|
||||
return PasswordComplexityBucket.complexityLevelToBucket(complexityLevel).mComplexityLevel;
|
||||
}
|
||||
|
||||
public boolean isDefault() {
|
||||
return quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
|
||||
&& length == 0 && letters == 0 && upperCase == 0 && lowerCase == 0
|
||||
@@ -280,7 +382,7 @@ public class PasswordMetrics implements Parcelable {
|
||||
@PasswordComplexity
|
||||
public int determineComplexity() {
|
||||
for (PasswordComplexityBucket bucket : PasswordComplexityBucket.BUCKETS) {
|
||||
if (satisfiesBucket(bucket.getMetrics())) {
|
||||
if (satisfiesBucket(bucket.mMetrics)) {
|
||||
return bucket.mComplexityLevel;
|
||||
}
|
||||
}
|
||||
@@ -290,7 +392,7 @@ public class PasswordMetrics implements Parcelable {
|
||||
/**
|
||||
* Requirements in terms of {@link PasswordMetrics} for each {@link PasswordComplexity}.
|
||||
*/
|
||||
public static class PasswordComplexityBucket {
|
||||
private static class PasswordComplexityBucket {
|
||||
/**
|
||||
* Definition of {@link DevicePolicyManager#PASSWORD_COMPLEXITY_HIGH} in terms of
|
||||
* {@link PasswordMetrics}.
|
||||
@@ -299,12 +401,13 @@ public class PasswordMetrics implements Parcelable {
|
||||
new PasswordComplexityBucket(
|
||||
PASSWORD_COMPLEXITY_HIGH,
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */ 6),
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
|
||||
8),
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, /* length= */ 6),
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
|
||||
8));
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */
|
||||
6));
|
||||
|
||||
/**
|
||||
* Definition of {@link DevicePolicyManager#PASSWORD_COMPLEXITY_MEDIUM} in terms of
|
||||
@@ -314,11 +417,12 @@ public class PasswordMetrics implements Parcelable {
|
||||
new PasswordComplexityBucket(
|
||||
PASSWORD_COMPLEXITY_MEDIUM,
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */ 4),
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
|
||||
4),
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC, /* length= */ 4),
|
||||
new PasswordMetrics(
|
||||
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX, /* length= */
|
||||
DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC, /* length= */
|
||||
4));
|
||||
|
||||
/**
|
||||
@@ -328,11 +432,11 @@ public class PasswordMetrics implements Parcelable {
|
||||
private static final PasswordComplexityBucket LOW =
|
||||
new PasswordComplexityBucket(
|
||||
PASSWORD_COMPLEXITY_LOW,
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING));
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC));
|
||||
|
||||
/**
|
||||
* A special bucket to represent {@link DevicePolicyManager#PASSWORD_COMPLEXITY_NONE}.
|
||||
@@ -348,19 +452,27 @@ public class PasswordMetrics implements Parcelable {
|
||||
private final int mComplexityLevel;
|
||||
private final PasswordMetrics[] mMetrics;
|
||||
|
||||
/**
|
||||
* @param metricsArray must be sorted in ascending order of {@link #quality}.
|
||||
*/
|
||||
private PasswordComplexityBucket(@PasswordComplexity int complexityLevel,
|
||||
PasswordMetrics... metrics) {
|
||||
this.mComplexityLevel = complexityLevel;
|
||||
this.mMetrics = metrics;
|
||||
}
|
||||
PasswordMetrics... metricsArray) {
|
||||
int previousQuality = PASSWORD_QUALITY_UNSPECIFIED;
|
||||
for (PasswordMetrics metrics : metricsArray) {
|
||||
if (metrics.quality < previousQuality) {
|
||||
throw new IllegalArgumentException("metricsArray must be sorted in ascending"
|
||||
+ " order of quality");
|
||||
}
|
||||
previousQuality = metrics.quality;
|
||||
}
|
||||
|
||||
this.mMetrics = metricsArray;
|
||||
this.mComplexityLevel = complexityLevel;
|
||||
|
||||
/** Returns the {@link PasswordMetrics} that meet the min requirements of this bucket. */
|
||||
public PasswordMetrics[] getMetrics() {
|
||||
return mMetrics;
|
||||
}
|
||||
|
||||
/** Returns the bucket that {@code complexityLevel} represents. */
|
||||
public static PasswordComplexityBucket complexityLevelToBucket(
|
||||
private static PasswordComplexityBucket complexityLevelToBucket(
|
||||
@PasswordComplexity int complexityLevel) {
|
||||
for (PasswordComplexityBucket bucket : BUCKETS) {
|
||||
if (bucket.mComplexityLevel == complexityLevel) {
|
||||
|
||||
@@ -20,12 +20,23 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
|
||||
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
|
||||
import static android.app.admin.PasswordMetrics.complexityLevelToMinQuality;
|
||||
import static android.app.admin.PasswordMetrics.getActualRequiredQuality;
|
||||
import static android.app.admin.PasswordMetrics.getMinimumMetrics;
|
||||
import static android.app.admin.PasswordMetrics.getTargetQualityMetrics;
|
||||
import static android.app.admin.PasswordMetrics.sanitizeComplexityLevel;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.admin.PasswordMetrics.PasswordComplexityBucket;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -109,7 +120,7 @@ public class PasswordMetricsTest {
|
||||
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX,
|
||||
PasswordMetrics.computeForPassword("1").quality);
|
||||
// contains a long sequence so isn't complex
|
||||
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC,
|
||||
PasswordMetrics.computeForPassword("1234").quality);
|
||||
assertEquals(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
|
||||
PasswordMetrics.computeForPassword("").quality);
|
||||
@@ -145,7 +156,7 @@ public class PasswordMetricsTest {
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 5));
|
||||
|
||||
assertNotEquals(new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING, 4),
|
||||
new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX, 4));
|
||||
new PasswordMetrics(PASSWORD_QUALITY_COMPLEX, 4));
|
||||
|
||||
metrics0 = PasswordMetrics.computeForPassword("1234abcd,./");
|
||||
metrics1 = PasswordMetrics.computeForPassword("1234abcd,./");
|
||||
@@ -176,9 +187,9 @@ public class PasswordMetricsTest {
|
||||
@Test
|
||||
public void testConstructQuality() {
|
||||
PasswordMetrics expected = new PasswordMetrics();
|
||||
expected.quality = DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
|
||||
expected.quality = PASSWORD_QUALITY_COMPLEX;
|
||||
|
||||
PasswordMetrics actual = new PasswordMetrics(DevicePolicyManager.PASSWORD_QUALITY_COMPLEX);
|
||||
PasswordMetrics actual = new PasswordMetrics(PASSWORD_QUALITY_COMPLEX);
|
||||
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
@@ -256,42 +267,178 @@ public class PasswordMetricsTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToBucket_none() {
|
||||
PasswordMetrics[] bucket = PasswordComplexityBucket.complexityLevelToBucket(
|
||||
PASSWORD_COMPLEXITY_NONE).getMetrics();
|
||||
public void testSanitizeComplexityLevel_none() {
|
||||
assertEquals(PASSWORD_COMPLEXITY_NONE, sanitizeComplexityLevel(PASSWORD_COMPLEXITY_NONE));
|
||||
|
||||
for (PasswordMetrics metrics : bucket) {
|
||||
assertEquals(PASSWORD_COMPLEXITY_NONE, metrics.determineComplexity());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToBucket_low() {
|
||||
PasswordMetrics[] bucket = PasswordComplexityBucket.complexityLevelToBucket(
|
||||
PASSWORD_COMPLEXITY_LOW).getMetrics();
|
||||
|
||||
for (PasswordMetrics metrics : bucket) {
|
||||
assertEquals(PASSWORD_COMPLEXITY_LOW, metrics.determineComplexity());
|
||||
}
|
||||
public void testSanitizeComplexityLevel_low() {
|
||||
assertEquals(PASSWORD_COMPLEXITY_LOW, sanitizeComplexityLevel(PASSWORD_COMPLEXITY_LOW));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToBucket_medium() {
|
||||
PasswordMetrics[] bucket = PasswordComplexityBucket.complexityLevelToBucket(
|
||||
PASSWORD_COMPLEXITY_MEDIUM).getMetrics();
|
||||
|
||||
for (PasswordMetrics metrics : bucket) {
|
||||
assertEquals(PASSWORD_COMPLEXITY_MEDIUM, metrics.determineComplexity());
|
||||
}
|
||||
public void testSanitizeComplexityLevel_medium() {
|
||||
assertEquals(
|
||||
PASSWORD_COMPLEXITY_MEDIUM, sanitizeComplexityLevel(PASSWORD_COMPLEXITY_MEDIUM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToBucket_high() {
|
||||
PasswordMetrics[] bucket = PasswordComplexityBucket.complexityLevelToBucket(
|
||||
PASSWORD_COMPLEXITY_HIGH).getMetrics();
|
||||
public void testSanitizeComplexityLevel_high() {
|
||||
assertEquals(PASSWORD_COMPLEXITY_HIGH, sanitizeComplexityLevel(PASSWORD_COMPLEXITY_HIGH));
|
||||
}
|
||||
|
||||
for (PasswordMetrics metrics : bucket) {
|
||||
assertEquals(PASSWORD_COMPLEXITY_HIGH, metrics.determineComplexity());
|
||||
}
|
||||
@Test
|
||||
public void testSanitizeComplexityLevel_invalid() {
|
||||
assertEquals(PASSWORD_COMPLEXITY_NONE, sanitizeComplexityLevel(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToMinQuality_none() {
|
||||
assertEquals(PASSWORD_QUALITY_UNSPECIFIED,
|
||||
complexityLevelToMinQuality(PASSWORD_COMPLEXITY_NONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToMinQuality_low() {
|
||||
assertEquals(PASSWORD_QUALITY_SOMETHING,
|
||||
complexityLevelToMinQuality(PASSWORD_COMPLEXITY_LOW));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToMinQuality_medium() {
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX,
|
||||
complexityLevelToMinQuality(PASSWORD_COMPLEXITY_MEDIUM));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToMinQuality_high() {
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX,
|
||||
complexityLevelToMinQuality(PASSWORD_COMPLEXITY_HIGH));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComplexityLevelToMinQuality_invalid() {
|
||||
assertEquals(PASSWORD_QUALITY_UNSPECIFIED, complexityLevelToMinQuality(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetQualityMetrics_noneComplexityReturnsDefaultMetrics() {
|
||||
PasswordMetrics metrics =
|
||||
getTargetQualityMetrics(PASSWORD_COMPLEXITY_NONE, PASSWORD_QUALITY_ALPHANUMERIC);
|
||||
|
||||
assertTrue(metrics.isDefault());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetQualityMetrics_qualityNotAllowedReturnsMinQualityMetrics() {
|
||||
PasswordMetrics metrics =
|
||||
getTargetQualityMetrics(PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_NUMERIC);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
|
||||
assertEquals(/* expected= */ 4, metrics.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetQualityMetrics_highComplexityNumericComplex() {
|
||||
PasswordMetrics metrics = getTargetQualityMetrics(
|
||||
PASSWORD_COMPLEXITY_HIGH, PASSWORD_QUALITY_NUMERIC_COMPLEX);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
|
||||
assertEquals(/* expected= */ 8, metrics.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetQualityMetrics_mediumComplexityAlphabetic() {
|
||||
PasswordMetrics metrics = getTargetQualityMetrics(
|
||||
PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_ALPHABETIC);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_ALPHABETIC, metrics.quality);
|
||||
assertEquals(/* expected= */ 4, metrics.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTargetQualityMetrics_lowComplexityAlphanumeric() {
|
||||
PasswordMetrics metrics = getTargetQualityMetrics(
|
||||
PASSWORD_COMPLEXITY_MEDIUM, PASSWORD_QUALITY_ALPHANUMERIC);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, metrics.quality);
|
||||
assertEquals(/* expected= */ 4, metrics.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActualRequiredQuality_nonComplex() {
|
||||
int actual = getActualRequiredQuality(
|
||||
PASSWORD_QUALITY_NUMERIC_COMPLEX,
|
||||
/* requiresNumeric= */ false,
|
||||
/* requiresLettersOrSymbols= */ false);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActualRequiredQuality_complexRequiresNone() {
|
||||
int actual = getActualRequiredQuality(
|
||||
PASSWORD_QUALITY_COMPLEX,
|
||||
/* requiresNumeric= */ false,
|
||||
/* requiresLettersOrSymbols= */ false);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_UNSPECIFIED, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActualRequiredQuality_complexRequiresNumeric() {
|
||||
int actual = getActualRequiredQuality(
|
||||
PASSWORD_QUALITY_COMPLEX,
|
||||
/* requiresNumeric= */ true,
|
||||
/* requiresLettersOrSymbols= */ false);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActualRequiredQuality_complexRequiresLetters() {
|
||||
int actual = getActualRequiredQuality(
|
||||
PASSWORD_QUALITY_COMPLEX,
|
||||
/* requiresNumeric= */ false,
|
||||
/* requiresLettersOrSymbols= */ true);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_ALPHABETIC, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActualRequiredQuality_complexRequiresNumericAndLetters() {
|
||||
int actual = getActualRequiredQuality(
|
||||
PASSWORD_QUALITY_COMPLEX,
|
||||
/* requiresNumeric= */ true,
|
||||
/* requiresLettersOrSymbols= */ true);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMinimumMetrics_userInputStricter() {
|
||||
PasswordMetrics metrics = getMinimumMetrics(
|
||||
PASSWORD_COMPLEXITY_HIGH,
|
||||
PASSWORD_QUALITY_ALPHANUMERIC,
|
||||
PASSWORD_QUALITY_NUMERIC,
|
||||
/* requiresNumeric= */ false,
|
||||
/* requiresLettersOrSymbols= */ false);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_ALPHANUMERIC, metrics.quality);
|
||||
assertEquals(/* expected= */ 6, metrics.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMinimumMetrics_actualRequiredQualityStricter() {
|
||||
PasswordMetrics metrics = getMinimumMetrics(
|
||||
PASSWORD_COMPLEXITY_HIGH,
|
||||
PASSWORD_QUALITY_UNSPECIFIED,
|
||||
PASSWORD_QUALITY_NUMERIC,
|
||||
/* requiresNumeric= */ false,
|
||||
/* requiresLettersOrSymbols= */ false);
|
||||
|
||||
assertEquals(PASSWORD_QUALITY_NUMERIC_COMPLEX, metrics.quality);
|
||||
assertEquals(/* expected= */ 8, metrics.length);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user