Repository: geode Updated Branches: refs/heads/feature/GEODE-2514 [created] d6ca901f7
GEODE-2514: add new tests for statistics archive rolling and removal * add MainWithChildrenRollingFileHandlerIntegrationTest * add StatArchiveHandlerIntegrationTest * expand DiskSpaceLimitIntegrationTest Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/d6ca901f Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/d6ca901f Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/d6ca901f Branch: refs/heads/feature/GEODE-2514 Commit: d6ca901f7f225c331e54c6ad7d300a9139a39ffb Parents: c6b941f Author: Kirk Lund <[email protected]> Authored: Tue Feb 21 13:09:24 2017 -0800 Committer: Kirk Lund <[email protected]> Committed: Tue Feb 21 13:40:50 2017 -0800 ---------------------------------------------------------------------- .../io/MainWithChildrenRollingFileHandler.java | 6 +- .../internal/statistics/StatArchiveHandler.java | 6 +- ...ildrenRollingFileHandlerIntegrationTest.java | 96 ++++++++ .../DiskSpaceLimitIntegrationTest.java | 245 ++++++++++++++++++- .../StatArchiveHandlerIntegrationTest.java | 243 ++++++++++++++++++ 5 files changed, 582 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/d6ca901f/geode-core/src/main/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandler.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandler.java b/geode-core/src/main/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandler.java index 20d1c4f..11d10af 100644 --- a/geode-core/src/main/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandler.java +++ b/geode-core/src/main/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandler.java @@ -206,7 +206,11 @@ public class MainWithChildrenRollingFileHandler implements RollingFileHandler { return tmp; } - private Pattern getFilePattern(String name) { + Pattern getFilePattern(String name) { + if (name == null || "".equals(name.trim())) { + throw new IllegalArgumentException("Name must not be empty"); + } + int extIdx = name.lastIndexOf('.'); String ext = ""; if (extIdx != -1) { http://git-wip-us.apache.org/repos/asf/geode/blob/d6ca901f/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveHandler.java ---------------------------------------------------------------------- diff --git a/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveHandler.java b/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveHandler.java index 3eb9730..03b0f89 100755 --- a/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveHandler.java +++ b/geode-core/src/main/java/org/apache/geode/internal/statistics/StatArchiveHandler.java @@ -446,7 +446,7 @@ public class StatArchiveHandler implements SampleHandler { * @return the modified archive file name to use; it is modified by applying mainArchiveId and * archiveId to the name for supporting file rolling */ - private File getRollingArchiveName(File archive, boolean archiveClosed) { + File getRollingArchiveName(File archive, boolean archiveClosed) { if (mainArchiveId != -1) { // leave mainArchiveId as is. Bump archiveId. } else { @@ -538,7 +538,7 @@ public class StatArchiveHandler implements SampleHandler { return result; } - private void initMainArchiveId(File archive) { + void initMainArchiveId(File archive) { if (mainArchiveId != -1) { // already initialized return; @@ -598,7 +598,7 @@ public class StatArchiveHandler implements SampleHandler { * @return the modified archive file name to use; it is modified by applying the next main id if * any files in the dir already have a main id in the file name */ - private File getRenameArchiveName(File archive) { + File getRenameArchiveName(File archive) { File dir = archive.getAbsoluteFile().getParentFile(); int previousMainId = this.rollingFileHandler.calcNextMainId(dir, false); if (previousMainId == 0) { http://git-wip-us.apache.org/repos/asf/geode/blob/d6ca901f/geode-core/src/test/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandlerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandlerIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandlerIntegrationTest.java new file mode 100644 index 0000000..5ea77c4 --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/io/MainWithChildrenRollingFileHandlerIntegrationTest.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.internal.io; + +import static org.assertj.core.api.Assertions.*; + +import java.util.regex.Pattern; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; + +import org.apache.geode.test.junit.categories.IntegrationTest; + +@Category(IntegrationTest.class) +public class MainWithChildrenRollingFileHandlerIntegrationTest { + + private String name; + private MainWithChildrenRollingFileHandler handler; + + @Rule + public TestName testName = new TestName(); + + @Before + public void before() throws Exception { + this.name = this.testName.getMethodName(); + this.handler = new MainWithChildrenRollingFileHandler(); + } + + @Test + public void getFilePattern_matchesFilesWithBothIds() throws Exception { + Pattern pattern = this.handler.getFilePattern(this.name); + + assertThat(pattern).isNotNull(); + assertThat(pattern.matcher(this.name).matches()).isFalse(); + assertThat(pattern.matcher(this.name + "-01-01").matches()).isTrue(); + assertThat(pattern.matcher(this.name + "-01-02").matches()).isTrue(); + assertThat(pattern.matcher(this.name + "-02-01").matches()).isTrue(); + assertThat(pattern.matcher(this.name + "-01").matches()).isFalse(); + assertThat(pattern.matcher(this.name + "0101").matches()).isFalse(); + assertThat(pattern.matcher(this.name + "--").matches()).isFalse(); + + // TODO: revisit these to determine if behavior should change + assertThat(pattern.matcher(this.name + "-01-01-01").matches()).isFalse(); + assertThat(pattern.matcher(this.name + ".01-01-01").matches()).isFalse(); + } + + @Test + public void getFilePattern_withNumbers_matchesFiles() throws Exception { + this.name = "a1s2d3f4_cache1_statistics"; + Pattern pattern = this.handler.getFilePattern(this.name); + + assertThat(pattern).isNotNull(); + assertThat(pattern.matcher(this.name + "-01-41").matches()).isTrue(); + } + + @Test + public void getFilePattern_withHyphens_matchesFiles() throws Exception { + this.name = "a1s2d3f4_cache1-statistics"; + Pattern pattern = this.handler.getFilePattern(this.name); + + assertThat(pattern).isNotNull(); + assertThat(pattern.matcher(this.name + "-01-41").matches()).isTrue(); + } + + @Test + public void getFilePattern_empty_throwsIllegalArgumentException() throws Exception { + this.name = ""; + + assertThatThrownBy(() -> this.handler.getFilePattern(this.name)) + .isInstanceOf(IllegalArgumentException.class); + } + + @Test + public void getFilePattern_null_throwsIllegalArgumentException() throws Exception { + this.name = null; + + assertThatThrownBy(() -> this.handler.getFilePattern(this.name)) + .isInstanceOf(IllegalArgumentException.class); + } + +} http://git-wip-us.apache.org/repos/asf/geode/blob/d6ca901f/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java index 1702d9a..5d94fa0 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java @@ -14,8 +14,10 @@ */ package org.apache.geode.internal.statistics; +import static java.lang.String.valueOf; import static java.util.concurrent.TimeUnit.MINUTES; -import static org.apache.commons.io.FileUtils.moveFileToDirectory; +import static org.apache.commons.io.FileUtils.*; +import static org.apache.commons.lang.StringUtils.leftPad; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -37,9 +39,14 @@ import org.junit.rules.TestName; import java.io.File; import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.TimeoutException; @Category(IntegrationTest.class) +@SuppressWarnings("unused") public class DiskSpaceLimitIntegrationTest { private static final long FILE_SIZE_LIMIT = 256; @@ -48,6 +55,8 @@ public class DiskSpaceLimitIntegrationTest { private File dir; private File dirOfDeletedFiles; + private String name; + private String archiveFileName; private LocalStatisticsFactory factory; @@ -55,9 +64,14 @@ public class DiskSpaceLimitIntegrationTest { private StatisticsType statisticsType; private Statistics statistics; + private RollingFileHandler testRollingFileHandler; + private MainWithChildrenRollingFileHandler mainWithChildrenRollingFileHandler; + private SampleCollector sampleCollector; private StatArchiveHandlerConfig config; + private long initTimeStamp; + private NanoTimer timer = new NanoTimer(); private long nanosTimeStamp; @@ -69,10 +83,10 @@ public class DiskSpaceLimitIntegrationTest { @Before public void setUp() throws Exception { this.dir = this.temporaryFolder.getRoot(); - this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted"); - this.archiveFileName = - new File(this.dir, this.testName.getMethodName() + ".gfs").getAbsolutePath(); + this.name = this.testName.getMethodName(); + + this.archiveFileName = new File(this.dir, this.name + ".gfs").getAbsolutePath(); this.factory = new LocalStatisticsFactory(null); this.statisticDescriptors = new StatisticDescriptor[] { @@ -93,11 +107,12 @@ public class DiskSpaceLimitIntegrationTest { .thenReturn(this.temporaryFolder.getRoot().getAbsolutePath()); when(this.config.getProductDescription()).thenReturn(this.testName.getMethodName()); - RollingFileHandler rollingFileHandler = new TestableRollingFileHandler(); + this.testRollingFileHandler = new TestableRollingFileHandler(); + this.mainWithChildrenRollingFileHandler = new MainWithChildrenRollingFileHandler(); this.sampleCollector = new SampleCollector(sampler); - this.sampleCollector.initialize(this.config, NanoTimer.getTime(), rollingFileHandler); + this.initTimeStamp = NanoTimer.getTime(); this.timer.reset(); this.nanosTimeStamp = this.timer.getLastResetTime() - getNanoRate(); } @@ -109,6 +124,9 @@ public class DiskSpaceLimitIntegrationTest { @Test public void zeroKeepsAllFiles() throws Exception { + this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted"); + this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler); + when(this.config.getArchiveDiskSpaceLimit()).thenReturn(0L); sampleUntilFileExists(archiveFile(1)); sampleUntilFileExists(archiveFile(2)); @@ -118,6 +136,9 @@ public class DiskSpaceLimitIntegrationTest { @Test public void aboveZeroDeletesOldestFile() throws Exception { + this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted"); + this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler); + when(this.config.getArchiveDiskSpaceLimit()).thenReturn(DISK_SPACE_LIMIT); sampleUntilFileExists(archiveFile(1)); sampleUntilFileExists(archiveFile(2)); @@ -138,6 +159,118 @@ public class DiskSpaceLimitIntegrationTest { assertThat(everExisted(archiveFile(1))).isTrue(); } + @Test + public void aboveZeroDeletesPreviousFiles() throws Exception { + assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(0); + + int oldMainId = 1; + int newMainId = 2; + + int numberOfPreviousFiles = 100; + int numberOfLines = 100; + createPreviousFiles(oldMainId, numberOfPreviousFiles, numberOfLines); + assertThat(numberOfFiles(this.dir)).as("Missing files: " + listFiles(this.dir)) + .isEqualTo(numberOfPreviousFiles); + + for (int childId = 1; childId <= numberOfPreviousFiles; childId++) { + assertThat(archiveFile(oldMainId, childId)).exists(); + } + + // current archive file does not exist yet + assertThat(archiveFile()).doesNotExist(); + + // rolling files for mainId 2 do not exist yet + assertThat(markerFile(newMainId)).doesNotExist(); + assertThat(archiveFile(newMainId, 1)).doesNotExist(); + + when(this.config.getArchiveDiskSpaceLimit()) + .thenReturn(sizeOfDirectory(this.dir) / numberOfPreviousFiles); + + this.sampleCollector.initialize(this.config, this.initTimeStamp, + this.mainWithChildrenRollingFileHandler); + + assertThat(archiveFile()).exists().hasParent(this.dir); + assertThat(markerFile(newMainId)).exists().hasParent(this.dir).hasBinaryContent(new byte[0]); + + assertThat(archiveFile(newMainId, 1)).doesNotExist(); + + sampleNumberOfTimes(1); + + sampleUntilFileExists(archiveFile(newMainId, 1)); + assertThat(archiveFile(newMainId, 1)).exists(); + + // this might be a brittle assertion... ok to delete if following for-block-assertion passes + assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(2); + + for (int childId = 1; childId <= numberOfPreviousFiles; childId++) { + assertThat(archiveFile(oldMainId, childId)).doesNotExist(); + } + } + + @Test + public void aboveZeroDeletesPreviousFiles_nameWithHyphen() throws Exception { + this.name = "psin8p724_cache1-statistics"; + this.archiveFileName = new File(this.dir, this.name + ".gfs").getAbsolutePath(); + when(this.config.getArchiveFileName()).thenReturn(new File(this.archiveFileName)); + + assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(0); + + int oldMainId = 1; + int newMainId = 2; + + int numberOfPreviousFiles = 100; + int numberOfLines = 100; + createPreviousFiles(oldMainId, numberOfPreviousFiles, numberOfLines); + assertThat(numberOfFiles(this.dir)).as("Missing files: " + listFiles(this.dir)) + .isEqualTo(numberOfPreviousFiles); + + for (int childId = 1; childId <= numberOfPreviousFiles; childId++) { + assertThat(archiveFile(oldMainId, childId)).exists(); + } + + // current archive file does not exist yet + assertThat(archiveFile()).doesNotExist(); + + // rolling files for mainId 2 do not exist yet + assertThat(markerFile(newMainId)).doesNotExist(); + assertThat(archiveFile(newMainId, 1)).doesNotExist(); + + when(this.config.getArchiveDiskSpaceLimit()) + .thenReturn(sizeOfDirectory(this.dir) / numberOfPreviousFiles); + + this.sampleCollector.initialize(this.config, this.initTimeStamp, + this.mainWithChildrenRollingFileHandler); + + assertThat(archiveFile()).exists().hasParent(this.dir); + assertThat(markerFile(newMainId)).exists().hasParent(this.dir).hasBinaryContent(new byte[0]); + + assertThat(archiveFile(newMainId, 1)).doesNotExist(); + + sampleNumberOfTimes(1); + + sampleUntilFileExists(archiveFile(newMainId, 1)); + assertThat(archiveFile(newMainId, 1)).exists(); + + // this might be a brittle assertion... ok to delete if following for-block-assertion passes + assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(2); + + for (int childId = 1; childId <= numberOfPreviousFiles; childId++) { + assertThat(archiveFile(oldMainId, childId)).doesNotExist(); + } + } + + private void sampleNumberOfTimes(final int value) throws InterruptedException { + long minutes = 1; + long timeout = System.nanoTime() + MINUTES.toNanos(minutes); + int count = 0; + do { + sample(advanceNanosTimeStamp()); + count++; + Thread.sleep(10); + } while (count < value && System.nanoTime() < timeout); + System.out.println("Sampled " + count + " times."); + } + private void sampleUntilFileExists(final File file) throws InterruptedException, TimeoutException { long minutes = 1; @@ -203,9 +336,102 @@ public class DiskSpaceLimitIntegrationTest { return 1000; // 1 second } - private File archiveFile(final int child) { - return new File(this.dir, - this.testName.getMethodName() + "-01-" + String.format("%02d", child) + ".gfs"); + private File archiveFile() { + return archiveFile(archiveName()); + } + + private String archiveName() { + return this.name; + } + + private File archiveFile(final String name) { + return new File(this.dir, name + ".gfs"); + } + + private File archiveFile(final int childId) { + return archiveFile(1, childId); + } + + private File archiveFile(final int mainId, final int childId) { + return archiveFile(archiveName(), mainId, childId); + } + + private File archiveFile(final String name, final int mainId, final int childId) { + return new File(this.dir, archiveName(name, mainId, childId) + ".gfs"); + } + + private String archiveName(final int mainId, final int childId) { + return archiveName(archiveName(), mainId, childId); + } + + private String archiveName(final String name, final int mainId, final int childId) { + return name + "-" + formatId(mainId) + "-" + formatId(childId); + } + + private File markerFile(final int mainId) { + return markerFile(archiveName(), mainId); + } + + private File markerFile(final String name, final int mainId) { + return new File(this.dir, markerName(name, mainId)); + } + + private String markerName(final int mainId) { + return markerName(archiveName(), mainId); + } + + private String markerName(final String name, final int mainId) { + return archiveName(name, mainId, 0) + ".marker"; + } + + private String formatId(final int id) { + return String.format("%02d", id); + } + + private List<File> listFiles(final File dir) { + return Arrays.asList(dir.listFiles()); + } + + private int numberOfFiles(final File dir) { + return dir.listFiles().length; + } + + private void createPreviousFiles(final int mainId, final int fileCount, final int lineCount) + throws IOException { + createPreviousFiles(this.name, mainId, fileCount, lineCount); + } + + private void createPreviousFiles(final String name, final int mainId, final int fileCount, + final int lineCount) throws IOException { + int childId = 1; + List<String> lines = lines(lineCount); + for (int i = 0; i < fileCount; i++) { + File file = createFile(name, mainId, childId); + writeFile(file, lines); + childId++; + } + } + + private File createFile(final String name, final int mainId, final int childId) { + File file = new File(this.dir, name + "-" + leftPad(valueOf(mainId), 2, "0") + "-" + + leftPad(valueOf(childId), 2, "0") + ".gfs"); + return file; + } + + private void writeFile(final File file, final List<String> lines) throws IOException { + PrintWriter writer = new PrintWriter(file, "UTF-8"); + for (String line : lines) { + writer.println(line); + } + writer.close(); + } + + private List<String> lines(final int lineCount) { + List<String> lines = new ArrayList<>(); + for (int i = 0; i < lineCount; i++) { + lines.add(this.testName.getMethodName()); + } + return lines; } /** @@ -222,5 +448,4 @@ public class DiskSpaceLimitIntegrationTest { } } } - } http://git-wip-us.apache.org/repos/asf/geode/blob/d6ca901f/geode-core/src/test/java/org/apache/geode/internal/statistics/StatArchiveHandlerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/statistics/StatArchiveHandlerIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/statistics/StatArchiveHandlerIntegrationTest.java new file mode 100644 index 0000000..ca5993c --- /dev/null +++ b/geode-core/src/test/java/org/apache/geode/internal/statistics/StatArchiveHandlerIntegrationTest.java @@ -0,0 +1,243 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for additional information regarding + * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. You may obtain a + * copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package org.apache.geode.internal.statistics; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.mock; + +import java.io.File; +import java.io.IOException; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestName; +import org.junit.runner.RunWith; + +import org.apache.geode.internal.io.MainWithChildrenRollingFileHandler; +import org.apache.geode.internal.io.RollingFileHandler; +import org.apache.geode.test.junit.categories.IntegrationTest; + +/** + * Tests behavior that interacts with file system. + */ +@Category(IntegrationTest.class) +@RunWith(JUnitParamsRunner.class) +public class StatArchiveHandlerIntegrationTest { + + private File dir; + private String ext; + private String name; + private File archive; + + private StatArchiveHandlerConfig mockConfig; + private SampleCollector mockCollector; + private RollingFileHandler rollingFileHandler; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Rule + public TestName testName = new TestName(); + + @Before + public void setUp() throws Exception { + this.dir = this.temporaryFolder.getRoot(); + + this.ext = ".gfs"; + this.name = this.testName.getMethodName(); + this.archive = new File(this.dir, this.name + this.ext); + + this.mockConfig = mock(StatArchiveHandlerConfig.class); + this.mockCollector = mock(SampleCollector.class); + this.rollingFileHandler = new MainWithChildrenRollingFileHandler(); + } + + @Test + @Parameters({"false,false,false", "false,false,true", "false,true,false", "false,true,true", + "true,false,false", "true,false,true", "true,true,false", "true,true,true"}) + public void getRollingArchiveName_withEmptyDir_createsFirstIds(final boolean archiveExists, + final boolean archiveClosed, final boolean initMainId) throws Exception { + if (archiveExists) { + this.archive.createNewFile(); + } + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + if (initMainId) { + handler.initMainArchiveId(this.archive); + } + + File file = handler.getRollingArchiveName(this.archive, archiveClosed); + + assertThat(file).hasParent(this.dir).hasName(this.name + formatIds(1, 1) + this.ext); + } + + @Test + @Parameters({"1,1,false,false", "1,1,false,true", "1,1,true,false", "1,1,true,true", + "1,10,false,false", "1,10,false,true", "1,10,true,false", "1,10,true,true", + "10,1,false,false", "10,1,false,true", "10,1,true,false", "10,1,true,true", + "10,10,false,false", "10,10,false,true", "10,10,true,false", "10,10,true,true"}) + public void getRollingArchiveName_withOldArchives_rollsChildId(final int mainCount, + final int childCount, final boolean archiveExists, final boolean archiveClosed) + throws Exception { + createEmptyArchiveFiles(this.dir, this.name, this.ext, mainCount, childCount); + if (archiveExists) { + this.archive.createNewFile(); + } + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + + File file = handler.getRollingArchiveName(this.archive, archiveClosed); + + assertThat(file).hasParent(this.dir) + .hasName(this.name + formatIds(mainCount, childCount + 1) + this.ext); + } + + @Test + public void initMainArchiveId_withEmptyDir_createsMainId_createsFirstMarker() throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + + handler.initMainArchiveId(this.archive); + + assertThat(new File(this.dir, this.name + formatIds(1, 0) + ".marker")).exists(); + } + + @Test + @Parameters({"1,1", "1,10", "10,1", "10,10"}) + public void initMainArchiveId_withOldArchives_rollsMainId_rollsMarker(final int mainCount, + final int childCount) throws Exception { + createEmptyArchiveFiles(this.dir, this.name, this.ext, mainCount, childCount); + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + + handler.initMainArchiveId(this.archive); + + assertThat(new File(this.dir, this.name + formatIds(mainCount + 1, 0) + ".marker")).exists(); + } + + @Test + public void getRenameArchiveName_withEmptyDir_createsFirstIds() throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).isNotNull().isEqualTo(new File(this.dir, this.name + "-01-01" + this.ext)); + } + + @Test + public void getRenameArchiveName_withExtraneousIds_withEmptyDir_appendsIds() throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + this.archive = new File(this.dir, this.name + "-01-01" + this.ext); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).hasParent(this.dir).hasName(this.name + "-01-01-01-01" + this.ext); + } + + @Test + public void getRenameArchiveName_withExtraneousDots_withEmptyDir_appendsIds() throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + this.archive = new File(this.dir, this.name + ".test.test" + this.ext); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).hasParent(this.dir).hasName(this.name + ".test.test-01-01" + this.ext); + } + + @Test + public void getRenameArchiveName_withExtraneousUnderscores_withEptyDir_appendsIds() + throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + this.archive = new File(this.dir, this.name + "_test_test" + this.ext); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).hasParent(this.dir).hasName(this.name + "_test_test-01-01" + this.ext); + } + + @Test + public void getRenameArchiveName_withExtraneousHyphens_withEmptyDir_appendsIds() + throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + this.archive = new File(this.dir, this.name + "-test-test" + this.ext); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).hasParent(this.dir).hasName(this.name + "-test-test-01-01" + this.ext); + } + + @Test + @Parameters({"1,1", "1,10", "10,1", "10,10"}) + public void getRenameArchiveName_withOldArchives_rollsMainId(final int mainCount, + final int childCount) throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + createEmptyArchiveFiles(this.dir, this.name, this.ext, mainCount, childCount); + + File renamed = handler.getRenameArchiveName(this.archive); + + assertThat(renamed).doesNotExist().hasParent(this.dir) + .hasName(this.name + formatIds(mainCount + 1, 1) + this.ext); + } + + @Test + public void getRenameArchiveName_withNullArchive_throwsNullPointerException() throws Exception { + StatArchiveHandler handler = + new StatArchiveHandler(this.mockConfig, this.mockCollector, this.rollingFileHandler); + File archive = null; + + assertThatThrownBy(() -> handler.getRenameArchiveName(archive)) + .isInstanceOf(NullPointerException.class); + } + + /** + * Returns mainId and childId formatted like "-01-01" + */ + private String formatIds(final int mainId, final int childId) { + return "-" + formatId(mainId) + "-" + formatId(childId); + } + + /** + * Returns id formatted like "01" + */ + private String formatId(final int id) { + return String.format("%02d", id); + } + + /** + * Creates empty archive files like dir/name-mainId-childId.ext. Returns greatest mainId. + */ + private int createEmptyArchiveFiles(final File dir, final String name, final String ext, + final int mainCount, final int childCount) throws IOException { + int mainId = 1; + for (; mainId <= mainCount; mainId++) { + for (int childId = 1; childId <= childCount; childId++) { + File existing = new File(dir, name + formatIds(mainId, childId) + ext); + existing.createNewFile(); + } + } + return mainId - 1; + } +}
