diff --git a/docs/STDO-124-plan.md b/docs/STDO-124-plan.md new file mode 100644 index 0000000..2ddf87b --- /dev/null +++ b/docs/STDO-124-plan.md @@ -0,0 +1,22 @@ +**RESUME STATE** *(top of the file; rewritten in place, never appended to; keep under 12 lines)* +- **Reconciled at**: this branch's HEAD, the P4 build-verification fix commit. +- **Authoritative**: `PLAN.md` in `lucidworks/tbe-pitches`, branch `STDO-124-bet`, for stage + sequencing, the done-condition, the stage graph and every measured claim. This file exists only + so `/team-studios:status` and the compaction resume hook have something to find in this repo. +- **Next**: this repo's release cut (an actual version tag) is a human action, not part of P4's + done-condition. + +**Decisions** *(append-only)* +- **This file is a pointer, not a fork of the plan.** Full decision log: `tbe-pitches`'s + `decision-log.md` on `STDO-124-bet`. +- **Two real defects fixed, not worked around**, to get a clean `mvn clean package` from an empty + local repository: a `NullPointerException` in `PropertiesLoader.readFolder` on a `null` + `listFiles()` result, and four test failures caused by a process-wide `Fig` singleton left + mutated by `FigUtilsTest` with no teardown. + +**Wiki candidates** *(append during the work, not at the end)* +- (empty) + +--- + +resume-state template r3-tamarind diff --git a/fig-core/src/main/java/twigkit/fig/loader/PropertiesLoader.java b/fig-core/src/main/java/twigkit/fig/loader/PropertiesLoader.java index 623622f..c2b4769 100644 --- a/fig-core/src/main/java/twigkit/fig/loader/PropertiesLoader.java +++ b/fig-core/src/main/java/twigkit/fig/loader/PropertiesLoader.java @@ -91,6 +91,10 @@ public boolean accept(File file, String s) { }; File[] files = folder.listFiles(filter); + if (files == null) { + logger.error("Unable to list files in folder (not a directory, or an I/O error occurred): {}", folder); + files = new File[0]; + } Arrays.sort(files, new Comparator() { public int compare(File file, File file1) { @@ -123,6 +127,9 @@ public boolean accept(File file) { }; File[] nestedFolders = folder.listFiles(folderFilter); + if (nestedFolders == null) { + nestedFolders = new File[0]; + } for (File nestedFolder : nestedFolders) { readFolder(fig, nestedFolder); } diff --git a/fig-core/src/test/java/twigkit.fig/util/FigUtilsTest.java b/fig-core/src/test/java/twigkit.fig/util/FigUtilsTest.java index be5709c..bb0c16e 100644 --- a/fig-core/src/test/java/twigkit.fig/util/FigUtilsTest.java +++ b/fig-core/src/test/java/twigkit.fig/util/FigUtilsTest.java @@ -1,5 +1,6 @@ package twigkit.fig.util; +import org.junit.After; import org.junit.Test; import twigkit.fig.Config; import twigkit.fig.Fig; @@ -13,9 +14,27 @@ */ public class FigUtilsTest { + /** + * {@link Fig#getInstance(twigkit.fig.loader.Loader...)} returns a process-wide singleton + * keyed on the loader(s) used. {@link FigUtils#merge(Fig, Fig)} mutates its first + * argument in place, so merging into the singleton for "confs" here would otherwise + * permanently leave that shared instance with merged-in data for the rest of the test + * run, corrupting unrelated tests (e.g. in {@code MergedPropertiesLoaderTest}) that + * expect to see the pristine "confs" configuration. Reloading after each test restores + * the singleton to its original, unmerged state. + */ + private Fig primary; + + @After + public void restoreSharedPrimaryFig() { + if (primary != null) { + primary.reload(); + } + } + @Test public void testExistingConfigPropertiesAreLeftUnchanged() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); String originalRoot1KeyValue = primary.find("root").value("root-1-key").as_string(); @@ -38,7 +57,7 @@ public void testExistingConfigPropertiesAreLeftUnchanged() { @Test public void testExistingConfigsAreUpdatedWithNewPropertyValues() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); FigUtils.merge(primary, secondary); @@ -55,7 +74,7 @@ public void testExistingConfigsAreUpdatedWithNewPropertyValues() { @Test public void testExistingConfigsAreUpdatedWithNewProperties() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); FigUtils.merge(primary, secondary); @@ -70,7 +89,7 @@ public void testExistingConfigsAreUpdatedWithNewProperties() { @Test public void testExistingConfigsAreUpdatedWithNewExtensions() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); FigUtils.merge(primary, secondary); @@ -81,7 +100,7 @@ public void testExistingConfigsAreUpdatedWithNewExtensions() { @Test public void testNewConfigsCanBeAdded() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); FigUtils.merge(primary, secondary); @@ -92,7 +111,7 @@ public void testNewConfigsCanBeAdded() { @Test public void testChildConfigPropertyValuesCanBeUpdated() { - Fig primary = Fig.getInstance(new PropertiesLoader("confs")); + primary = Fig.getInstance(new PropertiesLoader("confs")); Fig secondary = Fig.getInstance(new PropertiesLoader("confs_dev")); FigUtils.merge(primary, secondary);