diff options
| author | 2021-02-02 22:45:03 +0000 | |
|---|---|---|
| committer | 2021-02-02 22:45:03 +0000 | |
| commit | 9d876e5dd6edcf280e9e800705c7f228f600a8ab (patch) | |
| tree | c5009ee58f2202138dfa38496b12ad4a499d775e | |
| parent | 898e9466ea15383ddbd19f084c56253228443fae (diff) | |
| parent | 0d46c77edcfe41ad21f7e0a964806ac18b6cd003 (diff) | |
Merge "Fix bug and migrate test." into sc-dev
| -rw-r--r-- | apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java | 45 | ||||
| -rw-r--r-- | services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java | 295 |
2 files changed, 225 insertions, 115 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index 223f3b04d4e6..6ab10518b557 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -791,15 +791,10 @@ class JobConcurrencyManager { mNumUnspecialized = mConfigMaxTotal; mNumUnspecialized -= mConfigNumReservedSlots.get(WORK_TYPE_TOP); mNumUnspecialized -= mConfigNumReservedSlots.get(WORK_TYPE_BG); - mNumUnspecialized -= mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP); - mNumUnspecialized -= mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG); - calculateUnspecializedRemaining(); - } - - private void calculateUnspecializedRemaining() { - mNumUnspecializedRemaining = mNumUnspecialized; + mNumUnspecializedRemaining = mConfigMaxTotal; for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) { - mNumUnspecializedRemaining -= mNumRunningJobs.valueAt(i); + mNumUnspecializedRemaining -= Math.max(mNumRunningJobs.valueAt(i), + mConfigNumReservedSlots.get(mNumRunningJobs.keyAt(i))); } } @@ -882,24 +877,42 @@ class JobConcurrencyManager { mNumUnspecialized = mConfigMaxTotal; final int numTop = mNumRunningJobs.get(WORK_TYPE_TOP) + mNumPendingJobs.get(WORK_TYPE_TOP); - final int resTop = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_TOP), numTop); + int resTop = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_TOP), numTop); mNumActuallyReservedSlots.put(WORK_TYPE_TOP, resTop); mNumUnspecialized -= resTop; final int numBg = mNumRunningJobs.get(WORK_TYPE_BG) + mNumPendingJobs.get(WORK_TYPE_BG); - final int resBg = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_BG), numBg); + int resBg = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_BG), numBg); mNumActuallyReservedSlots.put(WORK_TYPE_BG, resBg); mNumUnspecialized -= resBg; - calculateUnspecializedRemaining(); + + mNumUnspecializedRemaining = mNumUnspecialized; + // Account for already running jobs after we've assigned the minimum number of slots. + int unspecializedAssigned; + int extraRunning = (mNumRunningJobs.get(WORK_TYPE_TOP) - resTop); + if (extraRunning > 0) { + unspecializedAssigned = Math.max(0, + Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP) - resTop, + extraRunning)); + resTop += unspecializedAssigned; + mNumUnspecializedRemaining -= extraRunning; + } + extraRunning = (mNumRunningJobs.get(WORK_TYPE_BG) - resBg); + if (extraRunning > 0) { + unspecializedAssigned = Math.max(0, + Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG) - resBg, extraRunning)); + resBg += unspecializedAssigned; + mNumUnspecializedRemaining -= extraRunning; + } // Assign remaining unspecialized based on ranking. - int unspecializedAssigned = Math.max(0, - Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP), - Math.min(mNumUnspecializedRemaining, numTop - resTop))); + unspecializedAssigned = Math.max(0, + Math.min(mNumUnspecializedRemaining, + Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP), numTop) - resTop)); mNumActuallyReservedSlots.put(WORK_TYPE_TOP, resTop + unspecializedAssigned); mNumUnspecializedRemaining -= unspecializedAssigned; unspecializedAssigned = Math.max(0, - Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG), - Math.min(mNumUnspecializedRemaining, numBg - resBg))); + Math.min(mNumUnspecializedRemaining, + Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG), numBg) - resBg)); mNumActuallyReservedSlots.put(WORK_TYPE_BG, resBg + unspecializedAssigned); mNumUnspecializedRemaining -= unspecializedAssigned; } diff --git a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java index 15a9bcf59b28..62088015cbd5 100644 --- a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java @@ -21,9 +21,11 @@ import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; -import android.util.Log; +import android.annotation.NonNull; import android.util.Pair; +import android.util.SparseIntArray; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; @@ -58,106 +60,112 @@ public class WorkCountTrackerTest { * Represents running and pending jobs. */ class Jobs { - public int runningFg; - public int runningBg; - public int pendingFg; - public int pendingBg; + public final SparseIntArray running = new SparseIntArray(); + public final SparseIntArray pending = new SparseIntArray(); public void maybeEnqueueJobs(double startRatio, double fgJobRatio) { while (mRandom.nextDouble() < startRatio) { if (mRandom.nextDouble() < fgJobRatio) { - pendingFg++; + pending.put(WORK_TYPE_TOP, pending.get(WORK_TYPE_TOP) + 1); } else { - pendingBg++; + pending.put(WORK_TYPE_BG, pending.get(WORK_TYPE_BG) + 1); } } } public void maybeFinishJobs(double stopRatio) { - for (int i = runningBg; i > 0; i--) { + for (int i = running.get(WORK_TYPE_BG); i > 0; i--) { if (mRandom.nextDouble() < stopRatio) { - runningBg--; + running.put(WORK_TYPE_BG, running.get(WORK_TYPE_BG) - 1); } } - for (int i = runningFg; i > 0; i--) { + for (int i = running.get(WORK_TYPE_TOP); i > 0; i--) { if (mRandom.nextDouble() < stopRatio) { - runningFg--; + running.put(WORK_TYPE_TOP, running.get(WORK_TYPE_TOP) - 1); } } } } - private void startPendingJobs(Jobs jobs, int totalMax, int maxBg, int minBg) { - mWorkCountTracker.setConfig(new JobConcurrencyManager.WorkTypeConfig("critical", - totalMax, - // defaultMin - List.of(Pair.create(WORK_TYPE_TOP, totalMax - maxBg), - Pair.create(WORK_TYPE_BG, minBg)), - // defaultMax - List.of(Pair.create(WORK_TYPE_BG, maxBg)))); + private void startPendingJobs(Jobs jobs, int totalMax, + @NonNull List<Pair<Integer, Integer>> minLimits, + @NonNull List<Pair<Integer, Integer>> maxLimits) { + mWorkCountTracker.setConfig(new JobConcurrencyManager.WorkTypeConfig( + "test", totalMax, minLimits, maxLimits)); mWorkCountTracker.resetCounts(); - for (int i = 0; i < jobs.runningFg; i++) { - mWorkCountTracker.incrementRunningJobCount(WORK_TYPE_TOP); - } - for (int i = 0; i < jobs.runningBg; i++) { - mWorkCountTracker.incrementRunningJobCount(WORK_TYPE_BG); - } + for (int i = 0; i < jobs.running.size(); ++i) { + final int workType = jobs.running.keyAt(i); + final int count = jobs.running.valueAt(i); - for (int i = 0; i < jobs.pendingFg; i++) { - mWorkCountTracker.incrementPendingJobCount(WORK_TYPE_TOP); + for (int c = 0; c < count; ++c) { + mWorkCountTracker.incrementRunningJobCount(workType); + } } - for (int i = 0; i < jobs.pendingBg; i++) { - mWorkCountTracker.incrementPendingJobCount(WORK_TYPE_BG); + for (int i = 0; i < jobs.pending.size(); ++i) { + final int workType = jobs.pending.keyAt(i); + final int count = jobs.pending.valueAt(i); + + for (int c = 0; c < count; ++c) { + mWorkCountTracker.incrementPendingJobCount(workType); + } } mWorkCountTracker.onCountDone(); - while ((jobs.pendingFg > 0 + while ((jobs.pending.get(WORK_TYPE_TOP) > 0 && mWorkCountTracker.canJobStart(WORK_TYPE_TOP) != WORK_TYPE_NONE) - || (jobs.pendingBg > 0 + || (jobs.pending.get(WORK_TYPE_BG) > 0 && mWorkCountTracker.canJobStart(WORK_TYPE_BG) != WORK_TYPE_NONE)) { final boolean isStartingFg = mRandom.nextBoolean(); if (isStartingFg) { - if (jobs.pendingFg > 0 + if (jobs.pending.get(WORK_TYPE_TOP) > 0 && mWorkCountTracker.canJobStart(WORK_TYPE_TOP) != WORK_TYPE_NONE) { - jobs.pendingFg--; - jobs.runningFg++; + jobs.pending.put(WORK_TYPE_TOP, jobs.pending.get(WORK_TYPE_TOP) - 1); + jobs.running.put(WORK_TYPE_TOP, jobs.running.get(WORK_TYPE_TOP) + 1); mWorkCountTracker.stageJob(WORK_TYPE_TOP); mWorkCountTracker.onJobStarted(WORK_TYPE_TOP); } } else { - if (jobs.pendingBg > 0 + if (jobs.pending.get(WORK_TYPE_BG) > 0 && mWorkCountTracker.canJobStart(WORK_TYPE_BG) != WORK_TYPE_NONE) { - jobs.pendingBg--; - jobs.runningBg++; + jobs.pending.put(WORK_TYPE_BG, jobs.pending.get(WORK_TYPE_BG) - 1); + jobs.running.put(WORK_TYPE_BG, jobs.running.get(WORK_TYPE_BG) + 1); mWorkCountTracker.stageJob(WORK_TYPE_BG); mWorkCountTracker.onJobStarted(WORK_TYPE_BG); } } } - - Log.i(TAG, "" + mWorkCountTracker); } /** * Used by the following testRandom* tests. */ - private void checkRandom(Jobs jobs, int numTests, int totalMax, int maxBg, int minBg, + private void checkRandom(Jobs jobs, int numTests, int totalMax, + @NonNull List<Pair<Integer, Integer>> minLimits, + @NonNull List<Pair<Integer, Integer>> maxLimits, double startRatio, double fgJobRatio, double stopRatio) { for (int i = 0; i < numTests; i++) { - jobs.maybeFinishJobs(stopRatio); jobs.maybeEnqueueJobs(startRatio, fgJobRatio); - startPendingJobs(jobs, totalMax, maxBg, minBg); + startPendingJobs(jobs, totalMax, minLimits, maxLimits); - assertThat(jobs.runningFg).isAtMost(totalMax); - assertThat(jobs.runningBg).isAtMost(totalMax); - assertThat(jobs.runningFg + jobs.runningBg).isAtMost(totalMax); - assertThat(jobs.runningBg).isAtMost(maxBg); + int totalRunning = 0; + for (int r = 0; r < jobs.running.size(); ++r) { + final int numRunning = jobs.running.valueAt(r); + assertWithMessage( + "Work type " + jobs.running.keyAt(r) + " is running too many jobs") + .that(numRunning).isAtMost(totalMax); + totalRunning += numRunning; + } + assertThat(totalRunning).isAtMost(totalMax); + for (Pair<Integer, Integer> maxLimit : maxLimits) { + assertWithMessage("Work type " + maxLimit.first + " is running too many jobs") + .that(jobs.running.get(maxLimit.first)).isAtMost(maxLimit.second); + } } } @@ -170,13 +178,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 6; - final int maxBg = 4; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.1; final double fgJobRatio = 0.5; final double startRatio = 0.1; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio , stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -185,13 +194,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 2; - final int maxBg = 2; - final int minBg = 0; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); + final List<Pair<Integer, Integer>> minLimits = List.of(); final double stopRatio = 0.5; final double fgJobRatio = 0.5; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -200,13 +210,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 2; - final int maxBg = 2; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.5; final double fgJobRatio = 0.5; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -215,13 +226,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 10; - final int maxBg = 2; - final int minBg = 0; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); + final List<Pair<Integer, Integer>> minLimits = List.of(); final double stopRatio = 0.5; final double fgJobRatio = 0.5; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -230,13 +242,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 6; - final int maxBg = 4; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.5; final double fgJobRatio = 0.1; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -245,13 +258,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 6; - final int maxBg = 4; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.5; final double fgJobRatio = 0.9; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -260,13 +274,14 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 6; - final int maxBg = 4; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.4; final double fgJobRatio = 0.1; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } @Test @@ -275,53 +290,135 @@ public class WorkCountTrackerTest { final int numTests = 5000; final int totalMax = 6; - final int maxBg = 4; - final int minBg = 2; + final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4)); + final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2)); final double stopRatio = 0.4; final double fgJobRatio = 0.9; final double startRatio = 0.5; - checkRandom(jobs, numTests, totalMax, maxBg, minBg, startRatio, fgJobRatio, stopRatio); + checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, + startRatio, fgJobRatio, stopRatio); } /** Used by the following tests */ - private void checkSimple(int totalMax, int maxBg, int minBg, - int runningFg, int runningBg, int pendingFg, int pendingBg, - int resultRunningFg, int resultRunningBg, int resultPendingFg, int resultPendingBg) { + private void checkSimple(int totalMax, + @NonNull List<Pair<Integer, Integer>> minLimits, + @NonNull List<Pair<Integer, Integer>> maxLimits, + @NonNull List<Pair<Integer, Integer>> running, + @NonNull List<Pair<Integer, Integer>> pending, + @NonNull List<Pair<Integer, Integer>> resultRunning, + @NonNull List<Pair<Integer, Integer>> resultPending) { final Jobs jobs = new Jobs(); - jobs.runningFg = runningFg; - jobs.runningBg = runningBg; - jobs.pendingFg = pendingFg; - jobs.pendingBg = pendingBg; - - startPendingJobs(jobs, totalMax, maxBg, minBg); + for (Pair<Integer, Integer> run : running) { + jobs.running.put(run.first, run.second); + } + for (Pair<Integer, Integer> pend : pending) { + jobs.pending.put(pend.first, pend.second); + } -// fail(mWorkerCountTracker.toString()); - assertThat(jobs.runningFg).isEqualTo(resultRunningFg); - assertThat(jobs.runningBg).isEqualTo(resultRunningBg); + startPendingJobs(jobs, totalMax, minLimits, maxLimits); - assertThat(jobs.pendingFg).isEqualTo(resultPendingFg); - assertThat(jobs.pendingBg).isEqualTo(resultPendingBg); + for (Pair<Integer, Integer> run : resultRunning) { + assertWithMessage("Incorrect running result for work type " + run.first) + .that(jobs.running.get(run.first)).isEqualTo(run.second); + } + for (Pair<Integer, Integer> pend : resultPending) { + assertWithMessage("Incorrect pending result for work type " + pend.first) + .that(jobs.pending.get(pend.first)).isEqualTo(pend.second); + } } - @Test public void testBasic() { - // Args are: - // First 3: Total-max, bg-max, bg-min. - // Next 2: Running FG / BG - // Next 2: Pending FG / BG - // Next 4: Result running FG / BG, pending FG/BG. - checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 1, 0, /*res run/pen=*/ 1, 0, 0, 0); - - checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 0, /*res run/pen=*/ 6, 0, 4, 0); + checkSimple(6, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)), + /* run */ List.of(), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 1)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 1)), + /* resPen */ List.of()); + + checkSimple(6, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)), + /* run */ List.of(), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 4))); // When there are BG jobs pending, 2 (min-BG) jobs should run. - checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 1, /*res run/pen=*/ 5, 1, 5, 0); - checkSimple(6, 4, 2, /*run=*/ 0, 0, /*pen=*/ 10, 3, /*res run/pen=*/ 4, 2, 6, 1); - - checkSimple(8, 6, 2, /*run=*/ 0, 0, /*pen=*/ 0, 49, /*res run/pen=*/ 0, 6, 0, 43); - - checkSimple(6, 4, 2, /*run=*/ 6, 0, /*pen=*/ 10, 3, /*res run/pen=*/ 6, 0, 10, 3); + checkSimple(6, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)), + /* run */ List.of(), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 5))); + checkSimple(6, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)), + /* run */ List.of(), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 2)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 1))); + + checkSimple(8, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* run */ List.of(), + /* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)), + /* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_BG, 43))); + + checkSimple(8, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)), + /* pen */ List.of(Pair.create(WORK_TYPE_BG, 49)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_BG, 47))); + + checkSimple(8, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)), + /* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 4)), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 4)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49))); + + checkSimple(8, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 6)), + /* run */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 1)), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 48))); + + checkSimple(8, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 1)), + /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)), + /* run */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 49)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 8), Pair.create(WORK_TYPE_BG, 49))); + + checkSimple(6, + /* min */ List.of(Pair.create(WORK_TYPE_BG, 2)), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)), + /* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)), + /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3))); + + // This could happen if we lower the effective config due to higher memory pressure after + // we've already started running jobs. We shouldn't stop already running jobs, but also + // shouldn't start new ones. + checkSimple(5, + /* min */ List.of(), + /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)), + /* run */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)), + /* resRun */ List.of(Pair.create(WORK_TYPE_BG, 6)), + /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3))); } } |