From 7a237c2d1d68969a00bfad09e397da7e151a3b54 Mon Sep 17 00:00:00 2001 From: Vincent Boulaye Date: Sun, 16 Jun 2024 20:19:21 +0200 Subject: [PATCH 1/4] ignore UnsupportedOperationException thrown by jdk>18 when trying to setup the SystemExitSecurityManager (#1513) --- src/fitnesse/slim/instructions/SystemExitSecurityManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/fitnesse/slim/instructions/SystemExitSecurityManager.java b/src/fitnesse/slim/instructions/SystemExitSecurityManager.java index eeb1506d4..94871ee10 100644 --- a/src/fitnesse/slim/instructions/SystemExitSecurityManager.java +++ b/src/fitnesse/slim/instructions/SystemExitSecurityManager.java @@ -35,6 +35,10 @@ private static void tryUpdateSecurityManager(SecurityManager securityManager) { System.setSecurityManager(securityManager); } catch (SecurityException e) { System.err.println("Security manager could not be updated"); + } catch (UnsupportedOperationException e) { + System.err.println("Security manager could not be updated. If you are using a JDK version >=18, you need to set " + + "-Djava.security.manager=allow to allow this. Or use -Dprevent.system.exit=false to disable the FitNesse feature" + + " blocking System.exit() calls and prevent this message."); } } From a84b09f8e4f45036990cc608f7ebdcac755b4b80 Mon Sep 17 00:00:00 2001 From: Fried Hoeben Date: Sun, 16 Jun 2024 20:23:54 +0200 Subject: [PATCH 2/4] update release notes --- FitNesseRoot/FitNesse/ReleaseNotes/content.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/FitNesseRoot/FitNesse/ReleaseNotes/content.txt b/FitNesseRoot/FitNesse/ReleaseNotes/content.txt index 57a72375f..2b12c9ca2 100644 --- a/FitNesseRoot/FitNesse/ReleaseNotes/content.txt +++ b/FitNesseRoot/FitNesse/ReleaseNotes/content.txt @@ -1,4 +1,5 @@ !2 Pending Changes +* Allow usage of JDK > 18 ([[1513][https://github.com/unclebob/fitnesse/pull/1513]]). !2 20240219 * Added the defined values to the overview of all variables in scope. ([[1472][https://github.com/unclebob/fitnesse/pull/1472]]) From f2ad293ca70ed8dac26562959d043671b0178ecd Mon Sep 17 00:00:00 2001 From: AlexNetcare <135694182+AlexNetcare@users.noreply.github.com> Date: Sun, 7 Jul 2024 10:41:38 +0200 Subject: [PATCH 3/4] Fixed header overlapping content (#1517) --- .../resources/bootstrap/templates/skeleton.vm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/fitnesse/resources/bootstrap/templates/skeleton.vm b/src/fitnesse/resources/bootstrap/templates/skeleton.vm index 76bdff45d..c5312f74b 100644 --- a/src/fitnesse/resources/bootstrap/templates/skeleton.vm +++ b/src/fitnesse/resources/bootstrap/templates/skeleton.vm @@ -61,5 +61,20 @@ #end + + From a3c0ce3da9f811f2e3572bf1be8520c7c6b7638f Mon Sep 17 00:00:00 2001 From: AlexNetcare <135694182+AlexNetcare@users.noreply.github.com> Date: Sun, 7 Jul 2024 10:42:01 +0200 Subject: [PATCH 4/4] Feature/limit test histories (#1510) --- .../FitNesse/ReleaseNotes/content.txt | 1 + .../ConfigurationFile/content.txt | 1 + .../TestHistory/content.txt | 2 +- plugins.properties | 5 + src/fitnesse/ConfigurationParameter.java | 3 +- .../reporting/history/HistoryPurger.java | 55 ++++++++- .../history/SuiteHistoryFormatter.java | 10 ++ .../reporting/history/TestXmlFormatter.java | 10 ++ .../reporting/history/HistoryPurgerTest.java | 107 ++++++++++++++++++ 9 files changed, 186 insertions(+), 8 deletions(-) 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; + } }