### Question:
BatchingProgressLogger implements ProgressLogger { @Override public void logProgress(Supplier<String> msgFactory) { progressCounter.increment(); var localProgress = callCounter.get(); if (localProgress.longValue() < batchSize && (localProgress.incrementAndGet() >= batchSize)) { doLogPercentage(msgFactory); localProgress.setValue(0L); } } BatchingProgressLogger(Log log, long taskVolume, String task, int concurrency);  BatchingProgressLogger(Log log, long taskVolume, long batchSize, String task, int concurrency); @Override void logProgress(Supplier<String> msgFactory); @Override void logProgress(long progress, Supplier<String> msgFactory); @Override void logMessage(Supplier<String> msg); @Override long reset(long newTaskVolume); @Override Log getLog(); @Override void logProgress(double percentDone, Supplier<String> msg); static final long MAXIMUM_LOG_INTERVAL; }### Answer:
@Test void mustLogProgressOnlyAfterBatchSizeInvocations() { var log = new TestLog(); var taskVolume = 42; var batchSize = 8; var logger = new BatchingProgressLogger( log, taskVolume, batchSize, "foo", 0 ); for (int i = 0; i < taskVolume; i++) { int currentProgress = i; logger.logProgress(() -> String.valueOf(currentProgress)); } var threadName = Thread.currentThread().getName(); var messageTemplate = "[%s] foo %d%% %d"; var expectedMessages = List.of( formatWithLocale(messageTemplate, threadName, 1 * batchSize * 100 / taskVolume, 1 * batchSize - 1), formatWithLocale(messageTemplate, threadName, 2 * batchSize * 100 / taskVolume, 2 * batchSize - 1), formatWithLocale(messageTemplate, threadName, 3 * batchSize * 100 / taskVolume, 3 * batchSize - 1), formatWithLocale(messageTemplate, threadName, 4 * batchSize * 100 / taskVolume, 4 * batchSize - 1), formatWithLocale(messageTemplate, threadName, 5 * batchSize * 100 / taskVolume, 5 * batchSize - 1) ); var messages = log.getMessages("info"); assertEquals(expectedMessages, messages); }
@Test void mustLogProgressOnlyAfterHittingOrExceedingBatchSize() { var log = new TestLog(); var taskVolume = 1337; var progressStep = 5; var batchSize = 16; var logger = new BatchingProgressLogger( log, taskVolume, batchSize, "foo", 1 ); for (int i = 0; i < taskVolume; i += progressStep) { logger.logProgress(progressStep); } var threadName = Thread.currentThread().getName(); var messageTemplate = "[%s] foo %d%%"; var progressSteps = IntStream .iterate(0, i -> i < taskVolume, i -> i + progressStep) .boxed() .collect(Collectors.toList()); var loggedProgressSteps = ListIterate.distinctBy(progressSteps, i -> i / batchSize); var expectedMessages = loggedProgressSteps.stream() .skip(1) .map(i -> formatWithLocale(messageTemplate, threadName, i * 100 / taskVolume)) .collect(Collectors.toList()); var messages = log.getMessages("info"); assertEquals(expectedMessages, messages); }