From 5e7f77e44cacc40da04ac9f744566de0710b12a1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Mon, 23 Feb 2015 07:14:54 +0100 Subject: [PATCH] Add uptime command --- .../java/net/pterodactylus/xdcc/core/Core.java | 14 +++- .../pterodactylus/xdcc/data/ConnectedNetwork.java | 9 ++- .../pterodactylus/xdcc/ui/stdin/CommandReader.java | 1 + .../pterodactylus/xdcc/ui/stdin/UptimeCommand.java | 71 ++++++++++++++++++++ .../xdcc/ui/stdin/StatsCommandTest.java | 5 ++ .../xdcc/ui/stdin/UptimeCommandTest.java | 77 ++++++++++++++++++++++ 6 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 src/main/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommand.java create mode 100644 src/test/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommandTest.java diff --git a/src/main/java/net/pterodactylus/xdcc/core/Core.java b/src/main/java/net/pterodactylus/xdcc/core/Core.java index bfad867..fab43ab 100644 --- a/src/main/java/net/pterodactylus/xdcc/core/Core.java +++ b/src/main/java/net/pterodactylus/xdcc/core/Core.java @@ -30,6 +30,8 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.time.Duration; +import java.time.Instant; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -110,6 +112,7 @@ public class Core extends AbstractExecutionThreadService { /** The logger. */ private static final Logger logger = Logger.getLogger(Core.class.getName()); + private final Instant startup = Instant.now(); private final Object syncObject = new Object(); /** The event bus. */ private final EventBus eventBus; @@ -196,8 +199,11 @@ public class Core extends AbstractExecutionThreadService { Network network = entry.getKey(); Collection bots = networkBots.row(network).values(); int packCount = bots.stream().mapToInt((bot) -> bot.packs().size()).reduce((a, b) -> a + b).orElse(0); - return new ConnectedNetwork(network, entry.getValue().hostname(), - entry.getValue().port(), entry.getValue().nickname(), + Connection connection = entry.getValue(); + return new ConnectedNetwork(network, connection.hostname(), + connection.port(), + connection.getUptime().get(), + connection.nickname(), channels.stream() .filter((channel) -> channel.network() .equals(network)) @@ -258,6 +264,10 @@ public class Core extends AbstractExecutionThreadService { return downloads.values(); } + public Duration getUptime() { + return Duration.between(startup, Instant.now()); + } + // // ACTIONS // diff --git a/src/main/java/net/pterodactylus/xdcc/data/ConnectedNetwork.java b/src/main/java/net/pterodactylus/xdcc/data/ConnectedNetwork.java index 183f1f3..49e2d5b 100644 --- a/src/main/java/net/pterodactylus/xdcc/data/ConnectedNetwork.java +++ b/src/main/java/net/pterodactylus/xdcc/data/ConnectedNetwork.java @@ -1,5 +1,6 @@ package net.pterodactylus.xdcc.data; +import java.time.Duration; import java.util.Collection; /** @@ -12,6 +13,7 @@ public class ConnectedNetwork { private final Network network; private final String hostname; private final int port; + private final Duration uptime; private final String nickname; private final Collection channels; private final Collection forcedChannels; @@ -19,11 +21,12 @@ public class ConnectedNetwork { private final int packCount; public ConnectedNetwork(Network network, String hostname, int port, - String nickname, Collection channels, + Duration uptime, String nickname, Collection channels, Collection forcedChannels, int botCount, int packCount) { this.network = network; this.hostname = hostname; this.port = port; + this.uptime = uptime; this.nickname = nickname; this.channels = channels; this.forcedChannels = forcedChannels; @@ -35,6 +38,10 @@ public class ConnectedNetwork { return network; } + public Duration getUptime() { + return uptime; + } + public String getHostname() { return hostname; } diff --git a/src/main/java/net/pterodactylus/xdcc/ui/stdin/CommandReader.java b/src/main/java/net/pterodactylus/xdcc/ui/stdin/CommandReader.java index 2d0a352..66447b0 100644 --- a/src/main/java/net/pterodactylus/xdcc/ui/stdin/CommandReader.java +++ b/src/main/java/net/pterodactylus/xdcc/ui/stdin/CommandReader.java @@ -93,6 +93,7 @@ public class CommandReader extends AbstractExecutionThreadService { commandBuilder.add(new FailedDownloadsCommand(failedDownloads)); commandBuilder.add(new RestartCommand(core, failedDownloads)); commandBuilder.add(new ResearchCommand(core)); + commandBuilder.add(new UptimeCommand(core)); commands = commandBuilder.build(); } diff --git a/src/main/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommand.java b/src/main/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommand.java new file mode 100644 index 0000000..56188ec --- /dev/null +++ b/src/main/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommand.java @@ -0,0 +1,71 @@ +package net.pterodactylus.xdcc.ui.stdin; + +import java.io.IOException; +import java.io.Writer; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import net.pterodactylus.xdcc.core.Core; +import net.pterodactylus.xdcc.data.ConnectedNetwork; + +/** + * {@link Command} that writes uptime information. + * + * @author David ‘Bombe’ Roden + */ +public class UptimeCommand implements Command { + + private final DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME; + private final Core core; + + public UptimeCommand(Core core) { + this.core = core; + } + + @Override + public String getName() { + return "uptime"; + } + + @Override + public Collection getAliases() { + return Collections.emptySet(); + } + + @Override + public State execute(State state, List parameters, Writer outputWriter) + throws IOException { + OffsetDateTime now = OffsetDateTime.now(); + outputWriter.write(String.format("Core running since %s, %s ago.\n", + formatter.format(core.getUptime().subtractFrom(now)), + formatTime(core.getUptime()))); + for (ConnectedNetwork network : core.connectedNetworks()) { + outputWriter.write(String.format("%s connected since %s, %s ago.\n", + network.getNetwork().name(), + formatter.format(network.getUptime().subtractFrom(now)), + formatTime(network.getUptime()))); + } + return state; + } + + private String formatTime(Duration uptime) { + long uptimeSeconds = uptime.getSeconds(); + long seconds = uptimeSeconds % 60; + long minutes = (uptimeSeconds / 60) % 60; + long hours = (uptimeSeconds / (60 * 60)) % 24; + long days = (uptimeSeconds / (60 * 60 * 24)) % 7; + long weeks = (uptimeSeconds / (60 * 60 * 24 * 7)); + String uptimeString = Stream + .of(weeks + "w", days + "d", hours + "h", minutes + "m", seconds + "s") + .filter(v -> !v.startsWith("0")) + .collect(Collectors.joining(" ")); + return uptimeString.isEmpty() ? "0s" : uptimeString; + } + +} diff --git a/src/test/java/net/pterodactylus/xdcc/ui/stdin/StatsCommandTest.java b/src/test/java/net/pterodactylus/xdcc/ui/stdin/StatsCommandTest.java index c1f0abc..efbdde3 100644 --- a/src/test/java/net/pterodactylus/xdcc/ui/stdin/StatsCommandTest.java +++ b/src/test/java/net/pterodactylus/xdcc/ui/stdin/StatsCommandTest.java @@ -10,6 +10,7 @@ import static org.mockito.Mockito.when; import java.io.IOException; import java.io.StringWriter; +import java.time.Duration; import net.pterodactylus.xdcc.core.Core; import net.pterodactylus.xdcc.data.ConnectedNetwork; @@ -34,6 +35,7 @@ public class StatsCommandTest { builder("TestNet").build(), "irc.test.net", 6667, + Duration.ofMinutes(1), "Nickname1", asList("#channel1", "#channel2"), emptyList(), @@ -44,6 +46,7 @@ public class StatsCommandTest { builder("DummyNet").build(), "irc.dummy.net", 6789, + Duration.ofMinutes(1), "Nickname2", asList("#dummy1", "#dummy2"), asList("#foo", "#bar"), @@ -54,6 +57,7 @@ public class StatsCommandTest { builder("FooNet").build(), "irc.foo.net", 7000, + Duration.ofMinutes(1), "Nickname3", emptyList(), emptyList(), @@ -64,6 +68,7 @@ public class StatsCommandTest { builder("BarNet").build(), "irc.bar.net", 7001, + Duration.ofMinutes(1), "Nickname4", emptyList(), asList("#foo", "#bar"), diff --git a/src/test/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommandTest.java b/src/test/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommandTest.java new file mode 100644 index 0000000..1f4b83a --- /dev/null +++ b/src/test/java/net/pterodactylus/xdcc/ui/stdin/UptimeCommandTest.java @@ -0,0 +1,77 @@ +package net.pterodactylus.xdcc.ui.stdin; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; + +import net.pterodactylus.xdcc.core.Core; +import net.pterodactylus.xdcc.data.ConnectedNetwork; +import net.pterodactylus.xdcc.data.Network; + +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; +import org.mockito.Mockito; + +/** + * Unit test for {@link UptimeCommand}. + * + * @author David ‘Bombe’ Roden + */ +public class UptimeCommandTest { + + private final Core core = Mockito.mock(Core.class); + private final UptimeCommand uptimeCommand = new UptimeCommand(core); + private final State state = Mockito.mock(State.class); + private final Writer writer = new StringWriter(); + + @Test + public void commandNameIsCorrect() { + MatcherAssert.assertThat(uptimeCommand.getName(), Matchers.is("uptime")); + } + + @Test + public void aliasesAreEmpty() { + MatcherAssert.assertThat(uptimeCommand.getAliases(), Matchers.empty()); + } + + @Test + public void connectionUptimeIsWritten() throws IOException { + Mockito.when(core.getUptime()).thenReturn(createDuration(1, 2, 3, 4, 5)); + uptimeCommand.execute(state, Collections.emptyList(), writer); + MatcherAssert.assertThat(writer.toString(), Matchers.containsString("1w 2d 3h 4m 5s")); + } + + @Test + public void connectionUptimeIsWrittenIfItIsZeroSeconds() throws IOException { + Mockito.when(core.getUptime()).thenReturn(createDuration(0, 0, 0, 0, 0)); + uptimeCommand.execute(state, Collections.emptyList(), writer); + MatcherAssert.assertThat(writer.toString(), Matchers.containsString("0s")); + } + + @Test + public void networkUptimeIsWritten() throws IOException { + Mockito.when(core.getUptime()).thenReturn(createDuration(1, 2, 3, 4, 5)); + ConnectedNetwork connectedNetwork = Mockito.mock(ConnectedNetwork.class); + Network network = Mockito.mock(Network.class); + Mockito.when(network.name()).thenReturn("Test"); + Mockito.when(connectedNetwork.getNetwork()).thenReturn(network); + Mockito.when(connectedNetwork.getUptime()).thenReturn(createDuration(2, 3, 4, 5, 6)); + Mockito.when(core.connectedNetworks()).thenReturn(Arrays.asList(connectedNetwork)); + uptimeCommand.execute(state, Collections.emptyList(), writer); + MatcherAssert.assertThat(writer.toString(), Matchers.containsString("2w 3d 4h 5m 6s")); + } + + private Duration createDuration(int weeks, int days, int hours, int minutes, int seconds) { + return Duration.ofSeconds( + weeks * (7 * 24 * 60 * 60) + + days * (24 * 60 * 60) + + hours * (60 * 60) + + minutes * 60 + + seconds); + } + +} -- 2.7.4