diff --git a/FitNesseRoot/FitNesse/ReleaseNotes/content.txt b/FitNesseRoot/FitNesse/ReleaseNotes/content.txt index 2b12c9ca2..bfa84db90 100644 --- a/FitNesseRoot/FitNesse/ReleaseNotes/content.txt +++ b/FitNesseRoot/FitNesse/ReleaseNotes/content.txt @@ -1,5 +1,6 @@ !2 Pending Changes * Allow usage of JDK > 18 ([[1513][https://github.com/unclebob/fitnesse/pull/1513]]). +* Added a new configuration to limit the total amount of test histories per page. ([[1510][https://github.com/unclebob/fitnesse/pull/1510]]) !2 20240219 * Added the defined values to the overview of all variables in scope. ([[1472][https://github.com/unclebob/fitnesse/pull/1472]]) diff --git a/FitNesseRoot/FitNesse/UserGuide/AdministeringFitNesse/ConfigurationFile/content.txt b/FitNesseRoot/FitNesse/UserGuide/AdministeringFitNesse/ConfigurationFile/content.txt index 285502b6f..02a45aaef 100644 --- a/FitNesseRoot/FitNesse/UserGuide/AdministeringFitNesse/ConfigurationFile/content.txt +++ b/FitNesseRoot/FitNesse/UserGuide/AdministeringFitNesse/ConfigurationFile/content.txt @@ -178,6 +178,7 @@ There are more properties which can be used to tweak parts of FitNesse: * '''test.history.days''' - The number of days to keep test results around. Cleaned up after a new test run. * '''test.history.path''' - Location to store the test results. The default location is ''!-FitNesseRoot-!/files/testResults''. * '''TestHistory.purgeOptions''' - A comma separated list of the age, in number of days, to offer as purge options on the ''Test History'' page. + * '''TestHistory.maxCount''' - The number of histories to keep around per page. Cleaned up after a new test run. * Any variable that can be defined on a wiki page. The Slim test system has a set of [[custom properties][7 days'', or ''>30 days''. If you want to purge a different number of days, you can change the ''TestHistory.purgeOptions'' in the [[configuration file][ 0) { + // Sorting the files to have them in ascending order of creation + Arrays.sort(files, Comparator.comparing(file -> getDateFromPageHistoryFileName(file.getName()), Date::compareTo)); + File[] filesToDelete = new File[files.length - this.testhistoryCount]; + + System.arraycopy(files, 0, filesToDelete, 0, files.length - this.testhistoryCount); + for (File fileToDelete : filesToDelete) { + FileUtil.deleteFile(fileToDelete); + } + } + } + private Date getDateFromPageHistoryFileName(String name) { try { return tryExtractDateFromTestHistoryName(name); diff --git a/src/fitnesse/reporting/history/SuiteHistoryFormatter.java b/src/fitnesse/reporting/history/SuiteHistoryFormatter.java index 6330e15d9..4d1698d40 100644 --- a/src/fitnesse/reporting/history/SuiteHistoryFormatter.java +++ b/src/fitnesse/reporting/history/SuiteHistoryFormatter.java @@ -1,5 +1,6 @@ package fitnesse.reporting.history; +import fitnesse.ConfigurationParameter; import fitnesse.FitNesseContext; import fitnesse.reporting.BaseFormatter; import fitnesse.testrunner.WikiTestPageUtil; @@ -124,6 +125,15 @@ public void close() throws IOException { FileUtil.close(writer); } } + + String testhistoryMaxCount = context.getProperties() + .getProperty(ConfigurationParameter.TESTHISTORY_MAX_COUNT.getKey()); + // The given number of days (0) is irrelevant here since we purge the + // history by their amount + HistoryPurger historyPurger = new HistoryPurger( + context.getTestHistoryDirectory(), 0); + historyPurger.deleteTestHistoryByCount(getPage().getFullPath(), + testhistoryMaxCount); } @Override diff --git a/src/fitnesse/reporting/history/TestXmlFormatter.java b/src/fitnesse/reporting/history/TestXmlFormatter.java index d95493939..bd6de80fb 100755 --- a/src/fitnesse/reporting/history/TestXmlFormatter.java +++ b/src/fitnesse/reporting/history/TestXmlFormatter.java @@ -2,6 +2,7 @@ // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.reporting.history; +import fitnesse.ConfigurationParameter; import fitnesse.FitNesseContext; import fitnesse.reporting.BaseFormatter; import fitnesse.testrunner.WikiTestPageUtil; @@ -175,6 +176,15 @@ protected void setTotalRunTimeOnReport(TimeMeasurement totalTimeMeasurement) { protected void writeResults() throws IOException { writeResults(writerFactory.getWriter(context, getPage(), getPageCounts(), totalTimeMeasurement.startedAt())); + + String testhistoryMaxCount = context.getProperties() + .getProperty(ConfigurationParameter.TESTHISTORY_MAX_COUNT.getKey()); + // The given number of days (0) is irrelevant here since we purge the + // history by their amount + HistoryPurger historyPurger = new HistoryPurger( + context.getTestHistoryDirectory(), 0); + historyPurger.deleteTestHistoryByCount(getPage().getFullPath(), + testhistoryMaxCount); } @Override diff --git a/test/fitnesse/reporting/history/HistoryPurgerTest.java b/test/fitnesse/reporting/history/HistoryPurgerTest.java index a3c096bba..5463e9214 100644 --- a/test/fitnesse/reporting/history/HistoryPurgerTest.java +++ b/test/fitnesse/reporting/history/HistoryPurgerTest.java @@ -3,6 +3,8 @@ import fitnesse.util.Clock; import fitnesse.util.DateAlteringClock; import fitnesse.wiki.PathParser; +import fitnesse.wiki.WikiPagePath; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -12,6 +14,7 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; @@ -65,6 +68,70 @@ public void shouldBeAbleToDeleteSomeTestHistory() throws Exception { assertNotNull(pageHistory.get(makeDate("20090615000000"))); assertNull(pageHistory.get(makeDate("20090614000000"))); } + + @Test + public void shouldBeAbleToDeleteSomeTestHistoryByCount() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + generateTestResults(pageDirectory, new int[] {7, 5, 6, 4}); + + historyPurger.deleteTestHistoryByCount(new WikiPagePath(new String[] {"SomePage"}), "2"); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertEquals(2, pageHistory.size()); + assertNotNull(pageHistory.get(makeDate("20090616000000"))); + assertNull(pageHistory.get(makeDate("20090615000000"))); + } + + @Test + public void shouldBeAbleToDeleteAllTestHistoryByCount() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + generateTestResults(pageDirectory, new int[] {7, 5, 6, 4}); + + historyPurger.deleteTestHistoryByCount(new WikiPagePath(new String[] {"SomePage"}), "0"); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertNull(pageHistory); + } + + @Test + public void shouldNotDeleteAnyTestHistoryByCount() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + List testResults = generateTestResults(pageDirectory, new int[] {7, 5, 6, 4}); + + historyPurger.deleteTestHistoryByCount(new WikiPagePath(new String[] {"SomePage"}), String.valueOf(testResults.size() + 2)); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertEquals(testResults.size(), pageHistory.size()); + assertNotNull(pageHistory.get(makeDate("20090614000000"))); + assertNotNull(pageHistory.get(makeDate("20090617000000"))); + } + + @Test + public void shouldNotDeleteAnyTestHistoryByCountBecauseOfNullProperty() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + List testResults = generateTestResults(pageDirectory, new int[] {7, 5, 6, 4}); + + historyPurger.deleteTestHistoryByCount(new WikiPagePath(new String[] {"SomePage"}), null); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertEquals(testResults.size(), pageHistory.size()); + } + + @Test + public void shouldNotDeleteAnyTestHistoryByCountBecauseOfNotNumberProperty() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + List testResults = generateTestResults(pageDirectory, new int[] {7, 5, 6, 4}); + + historyPurger.deleteTestHistoryByCount(new WikiPagePath(new String[] {"SomePage"}), "NotANumber"); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertEquals(testResults.size(), pageHistory.size()); + } @Test public void shouldBeAbleToDeletePagesFromASuite() throws Exception { @@ -97,6 +164,38 @@ public void shouldBeAbleToDeletePagesFromASuite() throws Exception { assertNotNull(pageHistory.get(makeDate("20090615000000"))); assertNotNull(pageHistory.get(makeDate("20090614000000"))); } + + @Test + public void shouldBeAbleToDeletePagesFromASuiteByCount() throws Exception { + File pageDirectory = addPageDirectory("SomePage"); + addTestResult(pageDirectory, "20090614000000_1_0_0_0"); + addTestResult(pageDirectory, "20090615000000_1_0_0_0"); + + File subPageDirectory = addPageDirectory("SomePage.SubPage"); + addTestResult(subPageDirectory, "20090614000000_1_0_0_0"); + addTestResult(subPageDirectory, "20090615000000_1_0_0_0"); + + File otherPageDirectory = addPageDirectory("OtherPage"); + addTestResult(otherPageDirectory, "20090614000000_1_0_0_0"); + addTestResult(otherPageDirectory, "20090615000000_1_0_0_0"); + + historyPurger.deleteTestHistoryByCount(PathParser.parse("SomePage"), "1"); + + TestHistory history = new TestHistory(resultsDirectory); + PageHistory pageHistory = history.getPageHistory("SomePage"); + assertNotNull(pageHistory.get(makeDate("20090615000000"))); + assertNull(pageHistory.get(makeDate("20090614000000"))); + + pageHistory = history.getPageHistory("SomePage.SubPage"); + assertEquals(1, pageHistory.size()); + assertNotNull(pageHistory.get(makeDate("20090615000000"))); + assertNull(pageHistory.get(makeDate("20090614000000"))); + + pageHistory = history.getPageHistory("OtherPage"); + assertEquals(2, pageHistory.size()); + assertNotNull(pageHistory.get(makeDate("20090615000000"))); + assertNotNull(pageHistory.get(makeDate("20090614000000"))); + } @Test public void shouldDeletePageHistoryDirectoryIfEmptiedByPurge() throws Exception { @@ -161,4 +260,12 @@ private Date makeDate(String dateString) throws ParseException { return date; } + private List generateTestResults(File pageDirectory, int[] dayValues) + throws IOException { + List testResults = new ArrayList<>(); + for (int dayValue : dayValues) { + testResults.add(addTestResult(pageDirectory, "2009061" + dayValue + "000000_1_0_0_0")); + } + return testResults; + } }