Refactored EstimateIterationsResult and added tests

This commit is contained in:
Micah Silverman 2021-10-13 10:49:29 -04:00
parent 10f10d0963
commit e910ddad48
3 changed files with 80 additions and 24 deletions

View File

@ -1,44 +1,60 @@
package io.jsonwebtoken.security; package io.jsonwebtoken.security;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
public class EstimateIterationsResult { public class EstimateIterationsResult {
private int iterations; private int estimatedIterations;
private List<Integer> workFactors; private List<Result> results;
private List<Long> durations;
private boolean estimateSet;
public EstimateIterationsResult() { public EstimateIterationsResult() {
this.workFactors = new ArrayList<>(); this.results = new ArrayList<>();
this.durations = new ArrayList<>();
} }
public EstimateIterationsResult(int numSamples) { public EstimateIterationsResult(int numSamples) {
this.workFactors = new ArrayList<>(numSamples); this.results = new ArrayList<>(numSamples);
this.durations = new ArrayList<>(numSamples);
} }
public int getIterations() { public int getEstimatedIterations() {
return iterations; return estimatedIterations;
} }
public void setIterations(int iterations) { public synchronized void setEstimatedIterations(int estimatedIterations) {
this.iterations = iterations; if (estimateSet) {
throw new UnsupportedOperationException("Estimated iterations already set and can only be set once.");
}
estimateSet = true;
this.estimatedIterations = estimatedIterations;
} }
public List<Integer> getWorkFactors() { public void addResult(int workFactor, long duration) {
return workFactors; this.results.add(new Result(workFactor, duration));
} }
public void setWorkFactors(List<Integer> workFactors) { public List<Result> getResults() {
this.workFactors = workFactors; return Collections.unmodifiableList(results);
} }
public List<Long> getDurations() { public static final class Result {
return durations; private int workFactor;
} private long duration;
public void setDurations(List<Long> durations) { private Result(){}
this.durations = durations;
public Result(int workFactor, long duration) {
this.workFactor = workFactor;
this.duration = duration;
}
public int getWorkFactor() {
return workFactor;
}
public long getDuration() {
return duration;
}
} }
} }

View File

@ -0,0 +1,42 @@
package io.jsonwebtoken.security
import org.junit.Test
import org.junit.runner.RunWith
import static org.junit.Assert.*
import org.powermock.modules.junit4.PowerMockRunner
@RunWith(PowerMockRunner)
class EstimateIterationsResultTest {
// for coverage
@Test
void testConstructor() {
new EstimateIterationsResult()
new EstimateIterationsResult(10)
}
@Test
void testImmutable() {
EstimateIterationsResult r = new EstimateIterationsResult()
r.addResult(1, 1)
try {
def result = r.getResults()
result.add(new EstimateIterationsResult.Result(2, 2))
fail()
} catch (Exception e) {
assertTrue e instanceof UnsupportedOperationException
}
}
@Test
void testSetEstimateOnlyOnce() {
EstimateIterationsResult r = new EstimateIterationsResult()
r.setEstimatedIterations(1);
try {
r.setEstimatedIterations(1)
fail()
} catch (UnsupportedOperationException e) {
assertEquals "Estimated iterations already set and can only be set once.", e.message
}
}
}

View File

@ -188,9 +188,7 @@ public final class KeyAlgorithmsBridge {
if (collectSample) { if (collectSample) {
// For each attempt, the x axis is the workFactor, and the y axis is how long it took to compute: // For each attempt, the x axis is the workFactor, and the y axis is how long it took to compute:
points.add(new Point(workFactor, duration)); points.add(new Point(workFactor, duration));
ret.getDurations().add(duration); ret.addResult(workFactor, duration);
ret.getWorkFactors().add(workFactor);
//System.out.println("Collected point: workFactor=" + workFactor + ", duration=" + duration + " ms, %achieved=" + durationPercentAchieved);
} else { } else {
minWorkFactor = Math.max(minWorkFactor, workFactor); minWorkFactor = Math.max(minWorkFactor, workFactor);
//System.out.println(" Excluding sample: workFactor=" + workFactor + ", duration=" + duration + " ms, %achieved=" + durationPercentAchieved); //System.out.println(" Excluding sample: workFactor=" + workFactor + ", duration=" + duration + " ms, %achieved=" + durationPercentAchieved);
@ -232,7 +230,7 @@ public final class KeyAlgorithmsBridge {
} }
double average = sumX / points.size(); double average = sumX / points.size();
//ensure our average is at least as much as the smallest work factor that got us closest to desiredMillis: //ensure our average is at least as much as the smallest work factor that got us closest to desiredMillis:
ret.setIterations((int) Math.max(average, minWorkFactor)); ret.setEstimatedIterations((int) Math.max(average, minWorkFactor));
return ret; return ret;
} }