geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kl...@apache.org
Subject [4/5] geode git commit: GEODE-2514: add new tests for statistics archive rolling and removal
Date Wed, 22 Feb 2017 21:38:23 GMT
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/76fa7cc7
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/76fa7cc7
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/76fa7cc7

Branch: refs/heads/feature/GEODE-2460
Commit: 76fa7cc7300359afa83c5df30d3af4043b82da27
Parents: a63b830
Author: Kirk Lund <klund@apache.org>
Authored: Tue Feb 21 13:09:24 2017 -0800
Committer: Kirk Lund <klund@apache.org>
Committed: Wed Feb 22 12:47:10 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/76fa7cc7/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/76fa7cc7/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/76fa7cc7/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/76fa7cc7/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/76fa7cc7/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;
+  }
+}


Mime
View raw message