Restructuring and unit test

This commit is contained in:
Ryan Harg 2024-11-27 10:30:18 +01:00
parent d07b0aaed1
commit da402b0da9
4 changed files with 169 additions and 13 deletions

35
pom.xml
View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.rpr</groupId>
<artifactId>ddnsclient</artifactId>
@ -15,6 +16,8 @@
<quarkus.platform.version>3.16.4</quarkus.platform.version>
<skipITs>true</skipITs>
<surefire-plugin.version>3.5.0</surefire-plugin.version>
<mockito.version>5.14.1</mockito.version>
<assertj.version>3.26.3</assertj.version>
</properties>
<dependencyManagement>
@ -26,6 +29,12 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-bom</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
@ -56,6 +65,27 @@
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
<version>${assertj.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@ -106,7 +136,8 @@
</executions>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>

View file

@ -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();
}
}

View file

@ -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 {
}
});
}
}

View file

@ -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<String> hostnameCaptor = ArgumentCaptor.forClass(String.class);
verify(dnsResolver, times(2)).resolve(hostnameCaptor.capture());
List<String> 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")
);
}
}