From da402b0da9f68aaa8b3e09063d52bb03e82c781d Mon Sep 17 00:00:00 2001 From: Ryan Harg Date: Wed, 27 Nov 2024 10:30:18 +0100 Subject: [PATCH] Restructuring and unit test --- pom.xml | 35 +++++- src/main/java/de/rpr/ddnsclient/Schedule.java | 26 +++++ .../{ScheduledUpdater.java => Updater.java} | 19 ++-- .../java/de/rpr/ddnsclient/UpdaterTest.java | 102 ++++++++++++++++++ 4 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 src/main/java/de/rpr/ddnsclient/Schedule.java rename src/main/java/de/rpr/ddnsclient/{ScheduledUpdater.java => Updater.java} (78%) create mode 100644 src/test/java/de/rpr/ddnsclient/UpdaterTest.java diff --git a/pom.xml b/pom.xml index ce4e097..5896501 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 de.rpr ddnsclient @@ -15,6 +16,8 @@ 3.16.4 true 3.5.0 + 5.14.1 + 3.26.3 @@ -26,6 +29,12 @@ pom import + + org.mockito + mockito-bom + ${mockito.version} + test + @@ -56,6 +65,27 @@ rest-assured test + + io.quarkus + quarkus-junit5-mockito + test + + + org.assertj + assertj-core + test + ${assertj.version} + + + org.mockito + mockito-junit-jupiter + test + + + org.mockito + mockito-core + test + @@ -106,7 +136,8 @@ - ${project.build.directory}/${project.build.finalName}-runner + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager ${maven.home} diff --git a/src/main/java/de/rpr/ddnsclient/Schedule.java b/src/main/java/de/rpr/ddnsclient/Schedule.java new file mode 100644 index 0000000..054fd68 --- /dev/null +++ b/src/main/java/de/rpr/ddnsclient/Schedule.java @@ -0,0 +1,26 @@ +package de.rpr.ddnsclient; + +import io.quarkus.scheduler.Scheduled; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.jboss.logging.Logger; + +@ApplicationScoped +public class Schedule { + + private static final Logger log = Logger.getLogger(Schedule.class); + + private final Updater updater; + + @Inject + public Schedule(Updater updater) { + this.updater = updater; + } + + @Scheduled(every = "${ddnsclient.interval:5m}") + void run() { + log.info("Starting run()"); + updater.run(); + } + +} diff --git a/src/main/java/de/rpr/ddnsclient/ScheduledUpdater.java b/src/main/java/de/rpr/ddnsclient/Updater.java similarity index 78% rename from src/main/java/de/rpr/ddnsclient/ScheduledUpdater.java rename to src/main/java/de/rpr/ddnsclient/Updater.java index a3b28a2..3bd003d 100644 --- a/src/main/java/de/rpr/ddnsclient/ScheduledUpdater.java +++ b/src/main/java/de/rpr/ddnsclient/Updater.java @@ -7,15 +7,14 @@ import de.rpr.ddnsclient.lookup.IpProvider; import de.rpr.ddnsclient.model.Config; import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.IPs; -import io.quarkus.scheduler.Scheduled; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import org.jboss.logging.Logger; @ApplicationScoped -public class ScheduledUpdater { +public class Updater { - private static final Logger log = Logger.getLogger(ScheduledUpdater.class); + private static final Logger log = Logger.getLogger(Updater.class); private final DynDnsRouter dynDnsRouter; private final IpProvider ipProvider; @@ -24,21 +23,19 @@ public class ScheduledUpdater { private final Config config; @Inject - public ScheduledUpdater( - DynDnsRouter dynDnsRouter, - IpProvider ipProvider, - DnsResolver dnsResolver, - Config config) { + public Updater(DynDnsRouter dynDnsRouter, IpProvider ipProvider, DnsResolver dnsResolver, Config config) { this.dynDnsRouter = dynDnsRouter; this.ipProvider = ipProvider; this.dnsResolver = dnsResolver; this.config = config; } - @Scheduled(every = "${ddnsclient.interval:5m}") void run() { + log.trace("Updater running."); - log.info("Starting run()"); + if(config.isEmpty()) { + throw new IllegalStateException("Missing configuration"); + } IPs publicIps = ipProvider.getPublicIps(); log.debugf("Public ips - v4: %s, v6: %s", publicIps.v4(), publicIps.v6()); @@ -51,6 +48,7 @@ public class ScheduledUpdater { log.debugf("Registered ips - v4: %s, v6: %s", registeredIps.v4(), registeredIps.v6()); if (!publicIps.equals(registeredIps)) { + log.tracef("IPs changed, updating..."); DynDns dynDns = dynDnsRouter.get(cfg.provider()); dynDns.update(cfg.hostname(), publicIps, new DyndnsAuth(null, null, cfg.token())); } else { @@ -58,5 +56,4 @@ public class ScheduledUpdater { } }); } - } diff --git a/src/test/java/de/rpr/ddnsclient/UpdaterTest.java b/src/test/java/de/rpr/ddnsclient/UpdaterTest.java new file mode 100644 index 0000000..7ac4e57 --- /dev/null +++ b/src/test/java/de/rpr/ddnsclient/UpdaterTest.java @@ -0,0 +1,102 @@ +package de.rpr.ddnsclient; + +import de.rpr.ddnsclient.dyndns.Ddnss; +import de.rpr.ddnsclient.dyndns.DynDns; +import de.rpr.ddnsclient.dyndns.DynDnsRouter; +import de.rpr.ddnsclient.lookup.DnsResolver; +import de.rpr.ddnsclient.lookup.IpProvider; +import de.rpr.ddnsclient.model.Config; +import de.rpr.ddnsclient.model.DyndnsAuth; +import de.rpr.ddnsclient.model.IPs; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class UpdaterTest { + + @Mock + DynDnsRouter dynDnsRouter; + @Mock + IpProvider ipProvider; + @Mock + DnsResolver dnsResolver; + + Config ddnssConfig = new Config() {{ + add(new Value("ddnss", "example.org", null, null, "token")); + }}; + + @Test + void should_throw_exception_if_config_is_empty() { + Config config = new Config(); + Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, config); + Assertions.assertThrows(IllegalStateException.class, updater::run); + } + + @Test + void should_process_all_config_entries() { + IPs ips = new IPs("ipv4", "ipv6"); + + when(ipProvider.getPublicIps()).thenReturn(ips); + when(dnsResolver.resolve(any())).thenReturn(ips); + + Config multipleConfigEntries = new Config() {{ + add(new Value("ddnss", "host1.example.org", null, null, "token")); + add(new Value("ddnss", "host2.example.org", null, null, "token")); + }}; + + Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, multipleConfigEntries); + updater.run(); + + ArgumentCaptor hostnameCaptor = ArgumentCaptor.forClass(String.class); + verify(dnsResolver, times(2)).resolve(hostnameCaptor.capture()); + + List capturedHostnames = hostnameCaptor.getAllValues(); + assertThat(capturedHostnames).containsExactly("host1.example.org", "host2.example.org"); + } + + @Test + void should_not_trigger_dyndns_update_if_ips_match() { + + IPs ips = new IPs("ipv4", "ipv6"); + + when(ipProvider.getPublicIps()).thenReturn(ips); + when(dnsResolver.resolve("example.org")).thenReturn(ips); + + Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig); + updater.run(); + + verify(dynDnsRouter, never()).get(any()); + } + + + @Test + void should_trigger_dyndns_update_if_ips_dont_match() { + + DynDns ddnss = mock(Ddnss.class); + + when(dynDnsRouter.get("ddnss")).thenReturn(ddnss); + + IPs publicIps = new IPs("ipv4", "ipv6"); + when(ipProvider.getPublicIps()).thenReturn(publicIps); + when(dnsResolver.resolve("example.org")).thenReturn(new IPs("registered_ipv4", "registered_ipv6")); + + Updater updater = new Updater(dynDnsRouter, ipProvider, dnsResolver, ddnssConfig); + updater.run(); + + verify(ddnss).update( + "example.org", + publicIps, + new DyndnsAuth(null, null, "token") + ); + } + +} \ No newline at end of file