From 116afffc4920705f8d0ce2b016700216a2a0cbb3 Mon Sep 17 00:00:00 2001 From: jonmv Date: Tue, 1 Nov 2022 22:11:07 +0100 Subject: No real changes --- .../com/yahoo/config/subscription/ConfigSet.java | 2 +- .../yahoo/config/subscription/ConfigSourceSet.java | 2 +- .../config/subscription/ConfigSubscriber.java | 11 +------- .../com/yahoo/config/subscription/ConfigURI.java | 4 +-- .../com/yahoo/config/subscription/DirSource.java | 2 +- .../subscription/impl/ConfigSetSubscription.java | 7 ++--- .../subscription/impl/ConfigSubscription.java | 32 +++++++--------------- .../subscription/impl/FileConfigSubscription.java | 8 +++--- .../yahoo/config/subscription/package-info.java | 5 ++-- .../yahoo/container/di/ConfigRetrieverTest.java | 9 ++---- .../java/com/yahoo/container/di/ContainerTest.java | 26 ++++++++++++++---- .../com/yahoo/container/di/ContainerTestBase.java | 6 ---- .../com/yahoo/container/di/DirConfigSource.java | 12 ++++---- .../container/jdisc/ContainerThreadFactory.java | 10 +------ .../container/jdisc/metric/MetricProvider.java | 9 +----- .../com/yahoo/jdisc/application/MetricImpl.java | 6 +--- 16 files changed, 57 insertions(+), 94 deletions(-) diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigSet.java b/config/src/main/java/com/yahoo/config/subscription/ConfigSet.java index 1b86db6b299..0fb0462e84e 100644 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigSet.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigSet.java @@ -23,7 +23,6 @@ public class ConfigSet implements ConfigSource { @SuppressWarnings({"unchecked", "rawtypes"}) public void addBuilder(String configId, ConfigInstance.Builder builder) { Class configClass = builder.getClass().getDeclaringClass(); - //System.out.println("Declaring class for builder " + builder + " is " + configClass); ConfigKey key = new ConfigKey(configClass, configId); configs.put(key, builder); } @@ -56,4 +55,5 @@ public class ConfigSet implements ConfigSource { } return sb.toString(); } + } diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigSourceSet.java b/config/src/main/java/com/yahoo/config/subscription/ConfigSourceSet.java index 81aeda52b54..597f83a605c 100755 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigSourceSet.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigSourceSet.java @@ -58,7 +58,7 @@ public class ConfigSourceSet implements ConfigSource { * @param address Connection endpoint on the format "tcp/host:port". */ public ConfigSourceSet(String address) { - this(new String[] {address}); + this(new String[] { address }); } /** diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java b/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java index 5d5ad1f1edc..e2b53879d92 100644 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigSubscriber.java @@ -275,7 +275,7 @@ public class ConfigSubscriber implements AutoCloseable { ConfigSubscription subscription = h.subscription(); log.log(Level.FINEST, () -> "Calling nextConfig for " + subscription.getKey()); if ( ! subscription.nextConfig(timeLeftMillis)) { - // This subscriber has no new state and we know it has exhausted all time + // This subscriber has no new state, and we know it has exhausted the timeout log.log(Level.FINEST, () -> "No new config for " + subscription.getKey()); return false; } @@ -407,15 +407,6 @@ public class ConfigSubscriber implements AutoCloseable { } } - /** - * The source used by this subscriber. - * - * @return the {@link ConfigSource} used by this subscriber - */ - public ConfigSource getSource() { - return source; - } - public boolean isClosed() { synchronized (monitor) { return state == State.CLOSED; diff --git a/config/src/main/java/com/yahoo/config/subscription/ConfigURI.java b/config/src/main/java/com/yahoo/config/subscription/ConfigURI.java index f0257457902..aa8a8c4a4c2 100644 --- a/config/src/main/java/com/yahoo/config/subscription/ConfigURI.java +++ b/config/src/main/java/com/yahoo/config/subscription/ConfigURI.java @@ -12,8 +12,8 @@ import java.io.File; */ public class ConfigURI { - private String configId; - private ConfigSource source; + private final String configId; + private final ConfigSource source; private ConfigURI(String configId, ConfigSource source) { this.configId = configId; diff --git a/config/src/main/java/com/yahoo/config/subscription/DirSource.java b/config/src/main/java/com/yahoo/config/subscription/DirSource.java index fbd65ccf597..9172048fe7b 100644 --- a/config/src/main/java/com/yahoo/config/subscription/DirSource.java +++ b/config/src/main/java/com/yahoo/config/subscription/DirSource.java @@ -11,7 +11,7 @@ public class DirSource implements ConfigSource { private final File dir; public DirSource(File dir) { - if (!dir.isDirectory()) throw new IllegalArgumentException("Not a directory: "+dir); + if (!dir.isDirectory()) throw new IllegalArgumentException("Not a directory: " + dir); this.dir = dir; } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java index 68f1dc2df17..15c6ce2441e 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java @@ -18,11 +18,10 @@ public class ConfigSetSubscription extends ConfigSubsc private final ConfigSet set; private final ConfigKey subKey; - ConfigSetSubscription(ConfigKey key, ConfigSource cset) { + ConfigSetSubscription(ConfigKey key, ConfigSet cset) { super(key); - if (!(cset instanceof ConfigSet)) throw new IllegalArgumentException("Source is not a ConfigSet: " + cset); - this.set = (ConfigSet) cset; - subKey = new ConfigKey<>(configClass, key.getConfigId()); + this.set = cset; + this.subKey = new ConfigKey<>(configClass, key.getConfigId()); if (!set.contains(subKey)) { throw new IllegalArgumentException("The given ConfigSet " + set + " does not contain a config for " + subKey); } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java index 5d720a74b15..2c5899df461 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java @@ -121,10 +121,9 @@ public abstract class ConfigSubscription { if (source instanceof FileSource || configId.startsWith("file:")) return getFileSub(key, source); if (source instanceof DirSource || configId.startsWith("dir:")) return getDirFileSub(key, source); if (source instanceof JarSource || configId.startsWith("jar:")) return getJarSub(key, source); - if (source instanceof ConfigSet) return new ConfigSetSubscription<>(key, source); - if (source instanceof ConfigSourceSet) { - JRTConfigRequester requester = requesters.getRequester((ConfigSourceSet) source, timingValues); - return new JRTConfigSubscription<>(key, requester, timingValues); + if (source instanceof ConfigSet cset) return new ConfigSetSubscription<>(key, cset); + if (source instanceof ConfigSourceSet csset) { + return new JRTConfigSubscription<>(key, requesters.getRequester(csset, timingValues), timingValues); } throw new IllegalArgumentException("Unknown source type: " + source); } @@ -132,21 +131,19 @@ public abstract class ConfigSubscription { private static JarConfigSubscription getJarSub(ConfigKey key, ConfigSource source) { String jarName; String path = "config/"; - if (source instanceof JarSource) { - JarSource js = (JarSource) source; + if (source instanceof JarSource js) { jarName = js.getJarFile().getName(); if (js.getPath() != null) path = js.getPath(); } else { - jarName = key.getConfigId().replace("jar:", "").replaceFirst("\\!/.*", ""); - if (key.getConfigId().contains("!/")) path = key.getConfigId().replaceFirst(".*\\!/", ""); + jarName = key.getConfigId().replace("jar:", "").replaceFirst("!/.*", ""); + if (key.getConfigId().contains("!/")) path = key.getConfigId().replaceFirst(".*!/", ""); } return new JarConfigSubscription<>(key, jarName, path); } private static ConfigSubscription getFileSub(ConfigKey key, ConfigSource source) { - File file = ((source instanceof FileSource)) - ? ((FileSource) source).getFile() - : new File(key.getConfigId().replace("file:", "")); + File file = source instanceof FileSource fileSource ? fileSource.getFile() + : new File(key.getConfigId().replace("file:", "")); return new FileConfigSubscription<>(key, file); } @@ -158,17 +155,8 @@ public abstract class ConfigSubscription { } private static ConfigSubscription getDirFileSub(ConfigKey key, ConfigSource source) { - String dir = key.getConfigId().replace("dir:", ""); - if (source instanceof DirSource) { - dir = ((DirSource) source).getDir().toString(); - } - if (!dir.endsWith(File.separator)) dir = dir + File.separator; - String name = getConfigFilename(key); - File file = new File(dir + name); - if (!file.exists()) { - throw new IllegalArgumentException("Could not find a config file for '" + key.getName() + "' in '" + dir + "'"); - } - return new FileConfigSubscription<>(key, file); + File dir = source instanceof DirSource dirSource ? dirSource.getDir() : new File(key.getConfigId().replace("dir:", "")); + return new FileConfigSubscription<>(key, new File(dir, getConfigFilename(key))); } @SuppressWarnings("unchecked") diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java index 5311b91c31f..47ac0dfbf85 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java @@ -11,6 +11,7 @@ import com.yahoo.vespa.config.ConfigPayload; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.Arrays; import static java.util.logging.Level.FINE; @@ -29,13 +30,12 @@ public class FileConfigSubscription extends ConfigSubs super(key); setGeneration(0L); file = f; - if (!file.exists() && !file.isFile()) - throw new IllegalArgumentException("Not a file: " + file); + if ( ! file.isFile()) throw new IllegalArgumentException("Not a file: " + file); } @Override public boolean nextConfig(long timeout) { - if (!file.exists() && !file.isFile()) throw new IllegalArgumentException("Not a file: " + file); + if ( ! file.isFile()) throw new IllegalArgumentException("Not a file: " + file); if (checkReloaded()) { log.log(FINE, () -> "User forced config reload at " + System.currentTimeMillis()); // User forced reload @@ -61,7 +61,7 @@ public class FileConfigSubscription extends ConfigSubs private T updateConfig() { ts = file.lastModified(); try { - ConfigPayload payload = new CfgConfigPayloadBuilder().deserialize(Arrays.asList(IOUtils.readFile(file).split("\n"))); + ConfigPayload payload = new CfgConfigPayloadBuilder().deserialize(Files.readAllLines(file.toPath())); return payload.toInstance(configClass, key.getConfigId()); } catch (IOException e) { throw new ConfigurationRuntimeException(e); diff --git a/config/src/main/java/com/yahoo/config/subscription/package-info.java b/config/src/main/java/com/yahoo/config/subscription/package-info.java index bda7649d184..58a47fa4249 100644 --- a/config/src/main/java/com/yahoo/config/subscription/package-info.java +++ b/config/src/main/java/com/yahoo/config/subscription/package-info.java @@ -1,8 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +/** Classes for subscribing to Vespa config. */ @ExportPackage -/** - * Classes for subscribing to Vespa config. - */ package com.yahoo.config.subscription; import com.yahoo.osgi.annotation.ExportPackage; diff --git a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java b/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java index 942555e391d..2bf33888569 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java +++ b/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java @@ -42,11 +42,6 @@ public class ConfigRetrieverTest { dirConfigSource = new DirConfigSource(tmpDir, "ConfigRetrieverTest-"); } - @AfterEach - public void cleanup() { - dirConfigSource.cleanup(); - } - @Test void require_that_bootstrap_configs_come_first() { writeConfigs(); @@ -54,6 +49,7 @@ public class ConfigRetrieverTest { ConfigSnapshot bootstrapConfigs = retriever.getConfigs(Collections.emptySet(), 0, true); assertTrue(bootstrapConfigs instanceof BootstrapConfigs); + retriever.shutdown(); } @Test @@ -71,12 +67,12 @@ public class ConfigRetrieverTest { } else { fail("ComponentsConfigs has unexpected type: " + componentsConfigs); } + retriever.shutdown(); } @Disabled @SuppressWarnings("unused") public void require_exception_upon_modified_components_keys_without_bootstrap() { - writeConfigs(); ConfigRetriever retriever = createConfigRetriever(); ConfigKey testConfigKey = new ConfigKey<>(TestConfig.class, dirConfigSource.configId()); @@ -99,6 +95,7 @@ public class ConfigRetrieverTest { ConfigRetriever retriever = createConfigRetriever(); assertTrue(retriever.getConfigs(Collections.emptySet(), 0, true) instanceof BootstrapConfigs); assertTrue(retriever.getConfigs(Collections.emptySet(), 0, true) instanceof ComponentsConfigs); + retriever.shutdown(); } public void writeConfigs() { diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java index c0d691c8a5a..6d95ba9c344 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java +++ b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java @@ -112,10 +112,8 @@ public class ContainerTest extends ContainerTestBase { // bundle-2 is installed, bundle-1 has been uninstalled assertEquals(1, osgi.getBundles().length); assertEquals("bundle-2", osgi.getBundles()[0].getSymbolicName()); - } - //@Test TODO - public void deconstructor_is_given_guice_components() { + container.shutdownConfigRetriever(); } @Test @@ -131,9 +129,11 @@ public class ContainerTest extends ContainerTestBase { container.reloadConfig(2); getNewComponentGraph(container, oldGraph); assertTrue(componentToDestruct.deconstructed); + + container.shutdownConfigRetriever(); } - @Disabled // because logAndDie is impossible(?) to verify programmatically + @Disabled("because logAndDie is impossible(?) to verify programmatically") @Test void manually_verify_what_happens_when_first_graph_contains_component_that_throws_exception_in_ctor() { writeBootstrapConfigs("thrower", ComponentThrowingExceptionInConstructor.class); @@ -144,6 +144,8 @@ public class ContainerTest extends ContainerTestBase { } catch (Throwable t) { fail("Expected to log and die"); } + + container.shutdownConfigRetriever(); } // Failure in component construction phase @@ -172,6 +174,8 @@ public class ContainerTest extends ContainerTestBase { assertEquals(3, currentGraph.generation()); assertSame(simpleComponent, currentGraph.getInstance(SimpleComponent.class)); assertNotNull(currentGraph.getInstance(ComponentTakingConfig.class)); + + container.shutdownConfigRetriever(); } @Test @@ -195,6 +199,8 @@ public class ContainerTest extends ContainerTestBase { // bundle-1 is kept, bundle-2 has been uninstalled assertEquals(1, osgi.getBundles().length); assertEquals("bundle-1", osgi.getBundles()[0].getSymbolicName()); + + container.shutdownConfigRetriever(); } // Failure in graph creation phase @@ -213,6 +219,8 @@ public class ContainerTest extends ContainerTestBase { container.reloadConfig(2); assertNewComponentGraphFails(container, currentGraph, IllegalArgumentException.class); assertEquals(1, currentGraph.generation()); + + container.shutdownConfigRetriever(); } @Test @@ -238,6 +246,8 @@ public class ContainerTest extends ContainerTestBase { // bundle-1 is kept, bundle-2 has been uninstalled assertEquals(1, osgi.getBundles().length); assertEquals("bundle-1", osgi.getBundles()[0].getSymbolicName()); + + container.shutdownConfigRetriever(); } private void assertNewComponentGraphFails(Container container, ComponentGraph currentGraph, Class exception) { @@ -261,7 +271,7 @@ public class ContainerTest extends ContainerTestBase { container.reloadConfig(2); assertThrows(IllegalArgumentException.class, - () -> getNewComponentGraph(container, currentGraph)); + () -> getNewComponentGraph(container, currentGraph)); ExecutorService exec = Executors.newFixedThreadPool(1); Future newGraph = exec.submit(() -> getNewComponentGraph(container, currentGraph)); @@ -277,10 +287,12 @@ public class ContainerTest extends ContainerTestBase { container.reloadConfig(3); assertNotNull(newGraph.get(5, TimeUnit.MINUTES)); + + container.shutdownConfigRetriever(); } @Test - void providers_are_destructed() { + void providers_are_destroyed() { writeBootstrapConfigs("id1", DestructableProvider.class); ComponentDeconstructor deconstructor = (generation, components, bundles) -> { @@ -304,6 +316,8 @@ public class ContainerTest extends ContainerTestBase { getNewComponentGraph(container, oldGraph); assertTrue(destructableEntity.deconstructed); + + container.shutdownConfigRetriever(); } @Test diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java index 7442eb2068d..54e5c54438b 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java +++ b/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java @@ -36,12 +36,6 @@ public class ContainerTestBase { osgi = new TestOsgi(BundleTestUtil.testBundles()); } - @AfterEach - public void cleanup() { - dirConfigSource.cleanup(); - } - - protected Container newContainer(DirConfigSource dirConfigSource, ComponentDeconstructor deconstructor) { return new Container(new CloudSubscriberFactory(dirConfigSource.configSource), diff --git a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java index db7e93f7c6e..39b50c66244 100644 --- a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java +++ b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java @@ -3,13 +3,17 @@ package com.yahoo.container.di; import com.yahoo.config.subscription.ConfigSource; import com.yahoo.config.subscription.ConfigSourceSet; +import org.junit.jupiter.api.Assertions; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.util.Random; +import static java.nio.charset.StandardCharsets.UTF_8; + /** * @author Tony Vaagenes * @author gjoranv @@ -18,7 +22,7 @@ import java.util.Random; public class DirConfigSource { private final File tempFolder; - public final ConfigSource configSource; + public final ConfigSource configSource; // TODO jonmv: remove, unused public DirConfigSource(File tmpDir, String testSourcePrefix) { this.tempFolder = tmpDir; @@ -46,13 +50,9 @@ public class DirConfigSource { return configSource; } - public void cleanup() { - tempFolder.delete(); - } - private static void printFile(File f, String content) { try (OutputStream out = new FileOutputStream(f)) { - out.write(content.getBytes("UTF-8")); + out.write(content.getBytes(UTF_8)); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/ContainerThreadFactory.java b/container-disc/src/main/java/com/yahoo/container/jdisc/ContainerThreadFactory.java index 92969ef9e97..b087c4e80b3 100644 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/ContainerThreadFactory.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/ContainerThreadFactory.java @@ -3,7 +3,6 @@ package com.yahoo.container.jdisc; import com.yahoo.container.jdisc.metric.MetricConsumerProvider; import com.yahoo.jdisc.application.ContainerThread; -import com.yahoo.jdisc.application.MetricConsumer; import java.util.concurrent.ThreadFactory; @@ -15,14 +14,7 @@ public class ContainerThreadFactory implements ThreadFactory { private final ThreadFactory delegate; public ContainerThreadFactory(MetricConsumerProvider metricConsumerProvider) { - metricConsumerProvider.getClass(); // throws NullPointerException - delegate = new ContainerThread.Factory(new com.google.inject.Provider() { - - @Override - public MetricConsumer get() { - return metricConsumerProvider.newInstance(); - } - }); + delegate = new ContainerThread.Factory(metricConsumerProvider::newInstance); } @Override diff --git a/container-disc/src/main/java/com/yahoo/container/jdisc/metric/MetricProvider.java b/container-disc/src/main/java/com/yahoo/container/jdisc/metric/MetricProvider.java index b547b3dd897..1afe152a420 100644 --- a/container-disc/src/main/java/com/yahoo/container/jdisc/metric/MetricProvider.java +++ b/container-disc/src/main/java/com/yahoo/container/jdisc/metric/MetricProvider.java @@ -3,7 +3,6 @@ package com.yahoo.container.jdisc.metric; import com.yahoo.container.di.componentgraph.Provider; import com.yahoo.jdisc.Metric; -import com.yahoo.jdisc.application.MetricConsumer; /** * An implementation of {@link Provider} component of Metric. Because this class depends on {@link @@ -17,13 +16,7 @@ public final class MetricProvider implements Provider { private final Metric metric; public MetricProvider(MetricConsumerProvider provider) { - metric = new com.yahoo.jdisc.application.MetricProvider(new com.google.inject.Provider() { - - @Override - public MetricConsumer get() { - return provider.newInstance(); - } - }).get(); + metric = new com.yahoo.jdisc.application.MetricProvider(provider::newInstance).get(); } @Override diff --git a/jdisc_core/src/main/java/com/yahoo/jdisc/application/MetricImpl.java b/jdisc_core/src/main/java/com/yahoo/jdisc/application/MetricImpl.java index 5a6a1f96bad..994bfc0fc3f 100644 --- a/jdisc_core/src/main/java/com/yahoo/jdisc/application/MetricImpl.java +++ b/jdisc_core/src/main/java/com/yahoo/jdisc/application/MetricImpl.java @@ -45,11 +45,7 @@ class MetricImpl implements Metric { } private MetricConsumer currentConsumer() { - Thread thread = Thread.currentThread(); - if (thread instanceof ContainerThread) { - return ((ContainerThread)thread).consumer(); - } - return consumer.get(); + return Thread.currentThread() instanceof ContainerThread thread ? thread.consumer() : consumer.get(); } private static class LocalConsumer extends ThreadLocal { -- cgit v1.2.3 From 2619a4060c8b0e5cbb653942762313394ec6c59e Mon Sep 17 00:00:00 2001 From: jonmv Date: Tue, 1 Nov 2022 23:39:22 +0100 Subject: Cleanup, no effective changes --- .../com/yahoo/config/subscription/DirSource.java | 2 +- .../subscription/impl/ConfigSetSubscription.java | 2 +- .../subscription/impl/ConfigSubscription.java | 8 +----- .../yahoo/container/di/ConfigRetrieverTest.java | 3 +-- .../java/com/yahoo/container/di/ContainerTest.java | 19 ++++++++++--- .../com/yahoo/container/di/ContainerTestBase.java | 5 ++-- .../com/yahoo/container/di/DirConfigSource.java | 31 +++++++--------------- .../com/yahoo/messagebus/ConfigAgentTestCase.java | 9 +++---- 8 files changed, 33 insertions(+), 46 deletions(-) diff --git a/config/src/main/java/com/yahoo/config/subscription/DirSource.java b/config/src/main/java/com/yahoo/config/subscription/DirSource.java index 9172048fe7b..5dfbd5f0bc4 100644 --- a/config/src/main/java/com/yahoo/config/subscription/DirSource.java +++ b/config/src/main/java/com/yahoo/config/subscription/DirSource.java @@ -11,7 +11,7 @@ public class DirSource implements ConfigSource { private final File dir; public DirSource(File dir) { - if (!dir.isDirectory()) throw new IllegalArgumentException("Not a directory: " + dir); + if ( ! dir.isDirectory()) throw new IllegalArgumentException("Not a directory: " + dir); this.dir = dir; } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java index 15c6ce2441e..41bab257248 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSetSubscription.java @@ -22,7 +22,7 @@ public class ConfigSetSubscription extends ConfigSubsc super(key); this.set = cset; this.subKey = new ConfigKey<>(configClass, key.getConfigId()); - if (!set.contains(subKey)) { + if ( ! set.contains(subKey)) { throw new IllegalArgumentException("The given ConfigSet " + set + " does not contain a config for " + subKey); } setGeneration(0L); diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java index 2c5899df461..c1a6740b6da 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java @@ -159,17 +159,11 @@ public abstract class ConfigSubscription { return new FileConfigSubscription<>(key, new File(dir, getConfigFilename(key))); } - @SuppressWarnings("unchecked") @Override public boolean equals(Object o) { - if (o instanceof ConfigSubscription) { - ConfigSubscription other = (ConfigSubscription) o; - return key.equals(other.key); - } - return false; + return o instanceof ConfigSubscription cs && key.equals(cs.key); } - /** * Called from {@link ConfigSubscriber} when the changed status of this config is propagated to the clients */ diff --git a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java b/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java index 2bf33888569..df92160550c 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java +++ b/container-core/src/test/java/com/yahoo/container/di/ConfigRetrieverTest.java @@ -9,7 +9,6 @@ import com.yahoo.container.di.ConfigRetriever.BootstrapConfigs; import com.yahoo.container.di.ConfigRetriever.ComponentsConfigs; import com.yahoo.container.di.ConfigRetriever.ConfigSnapshot; import com.yahoo.vespa.config.ConfigKey; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -39,7 +38,7 @@ public class ConfigRetrieverTest { @BeforeEach public void setup() { - dirConfigSource = new DirConfigSource(tmpDir, "ConfigRetrieverTest-"); + dirConfigSource = new DirConfigSource(tmpDir); } @Test diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java index 6d95ba9c344..6bb1af8258f 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java +++ b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java @@ -66,6 +66,7 @@ public class ContainerTest extends ContainerTestBase { assertEquals("reconfigured", component2.config.stringVal()); container.shutdownConfigRetriever(); + container.shutdown(newComponentGraph); } @Test @@ -90,6 +91,7 @@ public class ContainerTest extends ContainerTestBase { assertNotNull(ComponentGraph.getNode(newGraph, "id2")); container.shutdownConfigRetriever(); + container.shutdown(newGraph); } @Test @@ -107,13 +109,14 @@ public class ContainerTest extends ContainerTestBase { writeBootstrapConfigsWithBundles(List.of("bundle-2"), List.of(component2)); container.reloadConfig(2); - getNewComponentGraph(container, graph); + ComponentGraph newGraph = getNewComponentGraph(container, graph); // bundle-2 is installed, bundle-1 has been uninstalled assertEquals(1, osgi.getBundles().length); assertEquals("bundle-2", osgi.getBundles()[0].getSymbolicName()); container.shutdownConfigRetriever(); + container.shutdown(newGraph); } @Test @@ -127,10 +130,11 @@ public class ContainerTest extends ContainerTestBase { writeBootstrapConfigs("id2", DestructableComponent.class); container.reloadConfig(2); - getNewComponentGraph(container, oldGraph); + ComponentGraph newGraph = getNewComponentGraph(container, oldGraph); assertTrue(componentToDestruct.deconstructed); container.shutdownConfigRetriever(); + container.shutdown(newGraph); } @Disabled("because logAndDie is impossible(?) to verify programmatically") @@ -176,6 +180,7 @@ public class ContainerTest extends ContainerTestBase { assertNotNull(currentGraph.getInstance(ComponentTakingConfig.class)); container.shutdownConfigRetriever(); + container.shutdown(currentGraph); } @Test @@ -201,6 +206,7 @@ public class ContainerTest extends ContainerTestBase { assertEquals("bundle-1", osgi.getBundles()[0].getSymbolicName()); container.shutdownConfigRetriever(); + container.shutdown(currentGraph); } // Failure in graph creation phase @@ -221,6 +227,7 @@ public class ContainerTest extends ContainerTestBase { assertEquals(1, currentGraph.generation()); container.shutdownConfigRetriever(); + container.shutdown(currentGraph); } @Test @@ -248,6 +255,7 @@ public class ContainerTest extends ContainerTestBase { assertEquals("bundle-1", osgi.getBundles()[0].getSymbolicName()); container.shutdownConfigRetriever(); + container.shutdown(currentGraph); } private void assertNewComponentGraphFails(Container container, ComponentGraph currentGraph, Class exception) { @@ -286,9 +294,10 @@ public class ContainerTest extends ContainerTestBase { writeBootstrapConfigs("myId2", ComponentTakingConfig.class); container.reloadConfig(3); - assertNotNull(newGraph.get(5, TimeUnit.MINUTES)); + assertNotNull(newGraph.get(10, TimeUnit.SECONDS)); container.shutdownConfigRetriever(); + container.shutdown(newGraph.get()); } @Test @@ -313,11 +322,12 @@ public class ContainerTest extends ContainerTestBase { writeBootstrapConfigs("id2", DestructableProvider.class); container.reloadConfig(2); - getNewComponentGraph(container, oldGraph); + ComponentGraph graph = getNewComponentGraph(container, oldGraph); assertTrue(destructableEntity.deconstructed); container.shutdownConfigRetriever(); + container.shutdown(graph); } @Test @@ -327,6 +337,7 @@ public class ContainerTest extends ContainerTestBase { Container container = newContainer(dirConfigSource); ComponentGraph oldGraph = getNewComponentGraph(container); + container.shutdown(oldGraph); } static class DestructableEntity { diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java index 54e5c54438b..0ad376a13d8 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java +++ b/container-core/src/test/java/com/yahoo/container/di/ContainerTestBase.java @@ -6,7 +6,6 @@ import com.yahoo.container.core.config.BundleTestUtil; import com.yahoo.container.core.config.TestOsgi; import com.yahoo.container.di.ContainerTest.ComponentTakingConfig; import com.yahoo.container.di.componentgraph.core.ComponentGraph; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.io.TempDir; import org.osgi.framework.Bundle; @@ -31,14 +30,14 @@ public class ContainerTestBase { @BeforeEach public void setup() { - dirConfigSource = new DirConfigSource(tmpDir, "ContainerTest-"); + dirConfigSource = new DirConfigSource(tmpDir); componentGraph = new ComponentGraph(0); osgi = new TestOsgi(BundleTestUtil.testBundles()); } protected Container newContainer(DirConfigSource dirConfigSource, ComponentDeconstructor deconstructor) { - return new Container(new CloudSubscriberFactory(dirConfigSource.configSource), + return new Container(new CloudSubscriberFactory(dirConfigSource.configSource()), dirConfigSource.configId(), deconstructor, osgi); diff --git a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java index 39b50c66244..7704827311c 100644 --- a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java +++ b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java @@ -19,30 +19,24 @@ import static java.nio.charset.StandardCharsets.UTF_8; * @author gjoranv * @author ollivir */ -public class DirConfigSource { +class DirConfigSource { private final File tempFolder; - public final ConfigSource configSource; // TODO jonmv: remove, unused - public DirConfigSource(File tmpDir, String testSourcePrefix) { + DirConfigSource(File tmpDir) { this.tempFolder = tmpDir; - this.configSource = new ConfigSourceSet(testSourcePrefix + new Random().nextLong()); } - public void writeConfig(String name, String contents) { - File file = new File(tempFolder, name + ".cfg"); - if (!file.exists()) { - try { - file.createNewFile(); - } catch (IOException e) { - throw new RuntimeException(e); - } + void writeConfig(String name, String contents) { + try { + Files.writeString(tempFolder.toPath().resolve(name + ".cfg"), contents); + } + catch (IOException e) { + throw new UncheckedIOException(e); } - - printFile(file, contents + "\n"); } - public String configId() { + String configId() { return "dir:" + tempFolder.getPath(); } @@ -50,12 +44,5 @@ public class DirConfigSource { return configSource; } - private static void printFile(File f, String content) { - try (OutputStream out = new FileOutputStream(f)) { - out.write(content.getBytes(UTF_8)); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } diff --git a/messagebus/src/test/java/com/yahoo/messagebus/ConfigAgentTestCase.java b/messagebus/src/test/java/com/yahoo/messagebus/ConfigAgentTestCase.java index ad8e8a7c94e..f9185bfe0e0 100755 --- a/messagebus/src/test/java/com/yahoo/messagebus/ConfigAgentTestCase.java +++ b/messagebus/src/test/java/com/yahoo/messagebus/ConfigAgentTestCase.java @@ -5,21 +5,18 @@ import com.yahoo.config.subscription.ConfigSet; import com.yahoo.config.subscription.ConfigURI; import com.yahoo.messagebus.routing.RoutingSpec; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -import java.io.File; import java.util.concurrent.TimeUnit; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Simon Thoresen Hult */ public class ConfigAgentTestCase { - @TempDir - public File tmpFolder; - @Test void testRoutingConfig() throws InterruptedException { LocalHandler handler = new LocalHandler(); -- cgit v1.2.3 From 47eca27048399c3b1ccb317f0a66aef4ee43651c Mon Sep 17 00:00:00 2001 From: jonmv Date: Tue, 1 Nov 2022 23:46:29 +0100 Subject: Move file handling down into FileSource --- .../com/yahoo/config/subscription/DirSource.java | 4 ++-- .../com/yahoo/config/subscription/FileSource.java | 18 +++++++++++++++--- .../subscription/impl/ConfigSubscription.java | 9 +++++---- .../subscription/impl/FileConfigSubscription.java | 21 +++++++++------------ .../impl/FileConfigSubscriptionTest.java | 8 +++++--- .../com/yahoo/container/di/DirConfigSource.java | 22 +++++++++------------- 6 files changed, 45 insertions(+), 37 deletions(-) diff --git a/config/src/main/java/com/yahoo/config/subscription/DirSource.java b/config/src/main/java/com/yahoo/config/subscription/DirSource.java index 5dfbd5f0bc4..87bf51af26f 100644 --- a/config/src/main/java/com/yahoo/config/subscription/DirSource.java +++ b/config/src/main/java/com/yahoo/config/subscription/DirSource.java @@ -15,8 +15,8 @@ public class DirSource implements ConfigSource { this.dir = dir; } - public File getDir() { - return dir; + public FileSource getFile(String name) { + return new FileSource(new File(dir, name)); } } diff --git a/config/src/main/java/com/yahoo/config/subscription/FileSource.java b/config/src/main/java/com/yahoo/config/subscription/FileSource.java index 2178c64cca3..9d3c6041f4b 100644 --- a/config/src/main/java/com/yahoo/config/subscription/FileSource.java +++ b/config/src/main/java/com/yahoo/config/subscription/FileSource.java @@ -2,23 +2,35 @@ package com.yahoo.config.subscription; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.List; /** * Source specifying config from one local file * * @author Vegard Havdal + * @author jonmv */ public class FileSource implements ConfigSource { private final File file; public FileSource(File file) { - if ( ! file.isFile()) throw new IllegalArgumentException("Not an ordinary file: "+file); this.file = file; + validateFile(); } - public File getFile() { - return file; + public long getLastModified() { + return file.lastModified(); + } + + public List getContent() throws IOException { + return Files.readAllLines(file.toPath()); + } + + public void validateFile() { + if ( ! file.isFile()) throw new IllegalArgumentException("Not a file: " + file); } } diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java index c1a6740b6da..2c4e3d40250 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/ConfigSubscription.java @@ -142,8 +142,8 @@ public abstract class ConfigSubscription { } private static ConfigSubscription getFileSub(ConfigKey key, ConfigSource source) { - File file = source instanceof FileSource fileSource ? fileSource.getFile() - : new File(key.getConfigId().replace("file:", "")); + FileSource file = source instanceof FileSource fileSource ? fileSource + : new FileSource(new File(key.getConfigId().replace("file:", ""))); return new FileConfigSubscription<>(key, file); } @@ -155,8 +155,9 @@ public abstract class ConfigSubscription { } private static ConfigSubscription getDirFileSub(ConfigKey key, ConfigSource source) { - File dir = source instanceof DirSource dirSource ? dirSource.getDir() : new File(key.getConfigId().replace("dir:", "")); - return new FileConfigSubscription<>(key, new File(dir, getConfigFilename(key))); + DirSource dir = source instanceof DirSource dirSource ? dirSource + : new DirSource(new File(key.getConfigId().replace("dir:", ""))); + return new FileConfigSubscription<>(key, dir.getFile(getConfigFilename(key))); } @Override diff --git a/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java b/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java index 47ac0dfbf85..216657a6db3 100644 --- a/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java +++ b/config/src/main/java/com/yahoo/config/subscription/impl/FileConfigSubscription.java @@ -5,14 +5,11 @@ import com.yahoo.config.ConfigInstance; import com.yahoo.config.ConfigurationRuntimeException; import com.yahoo.config.subscription.CfgConfigPayloadBuilder; import com.yahoo.config.subscription.ConfigInterruptedException; -import com.yahoo.io.IOUtils; +import com.yahoo.config.subscription.FileSource; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.ConfigPayload; -import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.util.Arrays; import static java.util.logging.Level.FINE; @@ -23,19 +20,19 @@ import static java.util.logging.Level.FINE; */ public class FileConfigSubscription extends ConfigSubscription { - final File file; + final FileSource file; long ts; - FileConfigSubscription(ConfigKey key, File f) { + FileConfigSubscription(ConfigKey key, FileSource file) { super(key); + file.validateFile(); setGeneration(0L); - file = f; - if ( ! file.isFile()) throw new IllegalArgumentException("Not a file: " + file); + this.file = file; } @Override public boolean nextConfig(long timeout) { - if ( ! file.isFile()) throw new IllegalArgumentException("Not a file: " + file); + file.validateFile(); if (checkReloaded()) { log.log(FINE, () -> "User forced config reload at " + System.currentTimeMillis()); // User forced reload @@ -45,7 +42,7 @@ public class FileConfigSubscription extends ConfigSubs log.log(FINE, () -> "Config: " + configState.getConfig().toString()); return true; } - if (file.lastModified() != ts) { + if (file.getLastModified() != ts) { setConfigIncGen(updateConfig()); return true; } @@ -59,9 +56,9 @@ public class FileConfigSubscription extends ConfigSubs } private T updateConfig() { - ts = file.lastModified(); + ts = file.getLastModified(); try { - ConfigPayload payload = new CfgConfigPayloadBuilder().deserialize(Files.readAllLines(file.toPath())); + ConfigPayload payload = new CfgConfigPayloadBuilder().deserialize(file.getContent()); return payload.toInstance(configClass, key.getConfigId()); } catch (IOException e) { throw new ConfigurationRuntimeException(e); diff --git a/config/src/test/java/com/yahoo/config/subscription/impl/FileConfigSubscriptionTest.java b/config/src/test/java/com/yahoo/config/subscription/impl/FileConfigSubscriptionTest.java index e37a5d7b36b..aa948f2f0ae 100644 --- a/config/src/test/java/com/yahoo/config/subscription/impl/FileConfigSubscriptionTest.java +++ b/config/src/test/java/com/yahoo/config/subscription/impl/FileConfigSubscriptionTest.java @@ -2,6 +2,7 @@ package com.yahoo.config.subscription.impl; import com.yahoo.config.subscription.DirSource; +import com.yahoo.config.subscription.FileSource; import com.yahoo.foo.SimpletypesConfig; import com.yahoo.foo.TestReferenceConfig; import com.yahoo.vespa.config.ConfigKey; @@ -42,7 +43,7 @@ public class FileConfigSubscriptionTest { writeConfig("intval", "23"); ConfigSubscription sub = new FileConfigSubscription<>( new ConfigKey<>(SimpletypesConfig.class, ""), - TEST_TYPES_FILE); + new FileSource(TEST_TYPES_FILE)); assertTrue(sub.nextConfig(1000)); assertEquals(23, sub.getConfigState().getConfig().intval()); Thread.sleep(1000); @@ -56,7 +57,7 @@ public class FileConfigSubscriptionTest { writeConfig("intval", "23"); ConfigSubscription sub = new FileConfigSubscription<>( new ConfigKey<>(SimpletypesConfig.class, ""), - TEST_TYPES_FILE); + new FileSource(TEST_TYPES_FILE)); assertTrue(sub.nextConfig(1000)); assertEquals(23, sub.getConfigState().getConfig().intval()); writeConfig("intval", "33"); @@ -110,9 +111,10 @@ public class FileConfigSubscriptionTest { writeConfig("intval", "23"); ConfigSubscription sub = new FileConfigSubscription<>( new ConfigKey<>(SimpletypesConfig.class, ""), - TEST_TYPES_FILE); + new FileSource(TEST_TYPES_FILE)); sub.reload(1); Files.delete(TEST_TYPES_FILE.toPath()); // delete file so the below statement throws exception sub.nextConfig(0); } + } diff --git a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java index 7704827311c..071b4b17916 100644 --- a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java +++ b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java @@ -2,17 +2,14 @@ package com.yahoo.container.di; import com.yahoo.config.subscription.ConfigSource; -import com.yahoo.config.subscription.ConfigSourceSet; +import com.yahoo.config.subscription.DirSource; +import com.yahoo.config.subscription.FileSource; import org.junit.jupiter.api.Assertions; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.util.Random; - -import static java.nio.charset.StandardCharsets.UTF_8; +import java.io.UncheckedIOException; +import java.nio.file.Files; /** * @author Tony Vaagenes @@ -23,11 +20,11 @@ class DirConfigSource { private final File tempFolder; - DirConfigSource(File tmpDir) { + DirConfigSource(File tmpDir) { this.tempFolder = tmpDir; } - void writeConfig(String name, String contents) { + void writeConfig(String name, String contents) { try { Files.writeString(tempFolder.toPath().resolve(name + ".cfg"), contents); } @@ -36,13 +33,12 @@ class DirConfigSource { } } - String configId() { + String configId() { return "dir:" + tempFolder.getPath(); } - public ConfigSource configSource() { - return configSource; + ConfigSource configSource() { + return new DirSource(tempFolder); } - } -- cgit v1.2.3 From acd1c014cf612b5a370e78c9c7ab6e6cae3a8737 Mon Sep 17 00:00:00 2001 From: jonmv Date: Tue, 1 Nov 2022 23:47:16 +0100 Subject: Await subscriber exhausting configs list, in unit test --- .../java/com/yahoo/container/di/ContainerTest.java | 3 ++- .../com/yahoo/container/di/DirConfigSource.java | 31 +++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java index 6bb1af8258f..d869562cc19 100644 --- a/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java +++ b/container-core/src/test/java/com/yahoo/container/di/ContainerTest.java @@ -282,8 +282,9 @@ public class ContainerTest extends ContainerTestBase { () -> getNewComponentGraph(container, currentGraph)); ExecutorService exec = Executors.newFixedThreadPool(1); + dirConfigSource.clearCheckedConfigs(); Future newGraph = exec.submit(() -> getNewComponentGraph(container, currentGraph)); - + dirConfigSource.awaitConfigChecked(10_000); try { newGraph.get(1, TimeUnit.SECONDS); fail("Expected waiting for new config."); diff --git a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java index 071b4b17916..3d1d052b35b 100644 --- a/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java +++ b/container-core/src/test/java/com/yahoo/container/di/DirConfigSource.java @@ -10,6 +10,8 @@ import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Files; +import java.util.HashSet; +import java.util.Set; /** * @author Tony Vaagenes @@ -18,7 +20,9 @@ import java.nio.file.Files; */ class DirConfigSource { + private final Set checked = new HashSet<>(); private final File tempFolder; + private boolean doubleChecked; DirConfigSource(File tmpDir) { this.tempFolder = tmpDir; @@ -37,8 +41,33 @@ class DirConfigSource { return "dir:" + tempFolder.getPath(); } + synchronized void clearCheckedConfigs() { + checked.clear(); + doubleChecked = false; + } + + synchronized void awaitConfigChecked(long millis) throws InterruptedException { + long remaining, doom = System.currentTimeMillis() + millis; + while ( ! doubleChecked && (remaining = doom - System.currentTimeMillis()) > 0) wait(remaining); + Assertions.assertTrue(doubleChecked, "no config was checked more than once during " + millis + " millis"); + } + ConfigSource configSource() { - return new DirSource(tempFolder); + return new DirSource(tempFolder) { + @Override public FileSource getFile(String name) { + return new FileSource(new File(tempFolder, name)) { + @Override public long getLastModified() { + synchronized (DirConfigSource.this) { + if ( ! checked.add(name)) { + doubleChecked = true; + DirConfigSource.this.notifyAll(); + } + return super.getLastModified(); + } + } + }; + } + }; } } -- cgit v1.2.3