From 393765c61d3b594d45c69f7aeaa24fdd867fe814 Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Tue, 17 May 2022 16:42:15 +0200 Subject: [PATCH 1/2] improve test --- .../test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java index 237bb461..74504dcc 100644 --- a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java +++ b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java @@ -28,6 +28,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) @@ -146,7 +148,11 @@ class GrpcGraphTest { @Test void resetCache() { - assertThatCode(() -> grpcGraph.resetCache()).doesNotThrowAnyException(); + when(grpcService.describeGraph()).thenReturn(Optional.of(ChannelGraph.getDefaultInstance())); + grpcGraph.getChannelEdges(); + grpcGraph.resetCache(); + grpcGraph.getChannelEdges(); + verify(grpcService, times(2)).describeGraph(); } private RoutingPolicy policy(int feeRate, int baseFee, boolean disabled, int timeLockDelta) { From 911e217aef53f0476174722a5896695fd1a68850 Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Tue, 17 May 2022 16:52:41 +0200 Subject: [PATCH 2/2] add graph service and "number of known channels" endpoint --- README.md | 1 + .../lndmanagej/service/GraphService.java | 23 ++++++++++ .../lndmanagej/service/GraphServiceTest.java | 42 +++++++++++++++++++ .../cotto/lndmanagej/grpc/GrpcGraphTest.java | 1 - web/build.gradle | 1 - .../ObjectMapperConfigurationIT.java | 5 +++ .../PickhardtPaymentsControllerIT.java | 4 +- .../controller/StatusControllerIT.java | 13 +++++- .../PickhardtPaymentsController.java | 10 ++--- .../controller/StatusController.java | 10 ++++- .../PickhardtPaymentsControllerTest.java | 6 +-- .../controller/StatusControllerTest.java | 12 +++++- 12 files changed, 113 insertions(+), 15 deletions(-) create mode 100644 backend/src/main/java/de/cotto/lndmanagej/service/GraphService.java create mode 100644 backend/src/test/java/de/cotto/lndmanagej/service/GraphServiceTest.java diff --git a/README.md b/README.md index 67903252..5e724f94 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ Status: `/api/status/` followed by... * `all-channels`: the channel IDs of all channels (open, closed, waiting close, ...) * "pending open channels" are not included, as these do not have an ID, yet! * `all-channels/pubkeys`: the pubkeys of all peers with at least one channel as defined above + * `known-channels`: the number of known channels in the whole network Channel specific: `/api/channel/{ID}/` (where `{ID}` is the channel ID) followed by... * (nothing): basic channel information (open height, remote pubkey, capacity, status, ...) diff --git a/backend/src/main/java/de/cotto/lndmanagej/service/GraphService.java b/backend/src/main/java/de/cotto/lndmanagej/service/GraphService.java new file mode 100644 index 00000000..ce9bfb72 --- /dev/null +++ b/backend/src/main/java/de/cotto/lndmanagej/service/GraphService.java @@ -0,0 +1,23 @@ +package de.cotto.lndmanagej.service; + +import de.cotto.lndmanagej.grpc.GrpcGraph; +import org.springframework.stereotype.Service; + +import java.util.Set; + +@Service +public class GraphService { + private final GrpcGraph grpcGraph; + + public GraphService(GrpcGraph grpcGraph) { + this.grpcGraph = grpcGraph; + } + + public int getNumberOfChannels() { + return grpcGraph.getChannelEdges().map(Set::size).orElse(0); + } + + public void resetCache() { + grpcGraph.resetCache(); + } +} diff --git a/backend/src/test/java/de/cotto/lndmanagej/service/GraphServiceTest.java b/backend/src/test/java/de/cotto/lndmanagej/service/GraphServiceTest.java new file mode 100644 index 00000000..21423852 --- /dev/null +++ b/backend/src/test/java/de/cotto/lndmanagej/service/GraphServiceTest.java @@ -0,0 +1,42 @@ +package de.cotto.lndmanagej.service; + +import de.cotto.lndmanagej.grpc.GrpcGraph; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; +import java.util.Set; + +import static de.cotto.lndmanagej.model.DirectedChannelEdgeFixtures.CHANNEL_EDGE_WITH_POLICY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class GraphServiceTest { + @InjectMocks + private GraphService graphService; + + @Mock + private GrpcGraph grpcGraph; + + @Test + void getNumberOfEdges_default() { + assertThat(graphService.getNumberOfChannels()).isEqualTo(0); + } + + @Test + void getNumberOfEdges() { + when(grpcGraph.getChannelEdges()).thenReturn(Optional.of(Set.of(CHANNEL_EDGE_WITH_POLICY))); + assertThat(graphService.getNumberOfChannels()).isEqualTo(1); + } + + @Test + void resetCache() { + graphService.resetCache(); + verify(grpcGraph).resetCache(); + } +} diff --git a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java index 74504dcc..de8a1468 100644 --- a/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java +++ b/grpc-adapter/src/test/java/de/cotto/lndmanagej/grpc/GrpcGraphTest.java @@ -25,7 +25,6 @@ import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_2; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_3; import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY_4; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.times; diff --git a/web/build.gradle b/web/build.gradle index d268e19e..23443617 100644 --- a/web/build.gradle +++ b/web/build.gradle @@ -6,7 +6,6 @@ dependencies { implementation('org.springframework.boot:spring-boot-starter-web') implementation project(':backend') implementation project(':pickhardt-payments') - implementation project(':grpc-adapter') implementation project(':model') testImplementation testFixtures(project(':model')) testImplementation testFixtures(project(':pickhardt-payments')) diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/ObjectMapperConfigurationIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/ObjectMapperConfigurationIT.java index 4c650931..6dfa209a 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/ObjectMapperConfigurationIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/ObjectMapperConfigurationIT.java @@ -3,6 +3,7 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration; import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.service.ChannelService; +import de.cotto.lndmanagej.service.GraphService; import de.cotto.lndmanagej.service.OwnNodeService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -37,6 +38,10 @@ class ObjectMapperConfigurationIT { @SuppressWarnings("unused") private OwnNodeService ownNodeService; + @MockBean + @SuppressWarnings("unused") + private GraphService graphService; + @Test void output_is_pretty_printed() throws Exception { when(channelService.getOpenChannels()).thenReturn(Set.of(LOCAL_OPEN_CHANNEL)); diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerIT.java index 0ff83c1f..cc5f82e4 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerIT.java @@ -1,13 +1,13 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration; -import de.cotto.lndmanagej.grpc.GrpcGraph; import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.HexString; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSender; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSplitter; import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus; +import de.cotto.lndmanagej.service.GraphService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -48,7 +48,7 @@ class PickhardtPaymentsControllerIT { @MockBean @SuppressWarnings("unused") - private GrpcGraph grpcGraph; + private GraphService graphService; @MockBean @SuppressWarnings("unused") diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java index 7964c7cc..63fa76a8 100644 --- a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/StatusControllerIT.java @@ -2,6 +2,7 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.model.ChannelIdResolver; import de.cotto.lndmanagej.service.ChannelService; +import de.cotto.lndmanagej.service.GraphService; import de.cotto.lndmanagej.service.OwnNodeService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -39,6 +40,9 @@ class StatusControllerIT { @MockBean private OwnNodeService ownNodeService; + @MockBean + private GraphService graphService; + @Test void isSyncedToChain() throws Exception { when(ownNodeService.isSyncedToChain()).thenReturn(true); @@ -96,4 +100,11 @@ class StatusControllerIT { mockMvc.perform(get(PREFIX + "/all-channels/pubkeys")) .andExpect(jsonPath("$.pubkeys", is(sortedPubkeys))); } -} \ No newline at end of file + + @Test + void getKnownChannels() throws Exception { + when(graphService.getNumberOfChannels()).thenReturn(123); + mockMvc.perform(get(PREFIX + "/known-channels")) + .andExpect(jsonPath("$", is(123))); + } +} diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/PickhardtPaymentsController.java b/web/src/main/java/de/cotto/lndmanagej/controller/PickhardtPaymentsController.java index 94e35585..a6ff2c40 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/PickhardtPaymentsController.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/PickhardtPaymentsController.java @@ -2,13 +2,13 @@ package de.cotto.lndmanagej.controller; import com.codahale.metrics.annotation.Timed; import de.cotto.lndmanagej.controller.dto.MultiPathPaymentDto; -import de.cotto.lndmanagej.grpc.GrpcGraph; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSender; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSplitter; import de.cotto.lndmanagej.pickhardtpayments.model.MultiPathPayment; import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus; +import de.cotto.lndmanagej.service.GraphService; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -25,18 +25,18 @@ public class PickhardtPaymentsController { private final MultiPathPaymentSplitter multiPathPaymentSplitter; private final MultiPathPaymentSender multiPathPaymentSender; private final PaymentStatusStream paymentStatusStream; - private final GrpcGraph grpcGraph; + private final GraphService graphService; public PickhardtPaymentsController( MultiPathPaymentSplitter multiPathPaymentSplitter, MultiPathPaymentSender multiPathPaymentSender, PaymentStatusStream paymentStatusStream, - GrpcGraph grpcGraph + GraphService graphService ) { this.multiPathPaymentSplitter = multiPathPaymentSplitter; this.multiPathPaymentSender = multiPathPaymentSender; this.paymentStatusStream = paymentStatusStream; - this.grpcGraph = grpcGraph; + this.graphService = graphService; } @Timed @@ -107,6 +107,6 @@ public class PickhardtPaymentsController { @Timed @GetMapping("/reset-graph-cache") public void resetGraph() { - grpcGraph.resetCache(); + graphService.resetCache(); } } diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java b/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java index 2a123fc9..e46fdddc 100644 --- a/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java +++ b/web/src/main/java/de/cotto/lndmanagej/controller/StatusController.java @@ -9,6 +9,7 @@ import de.cotto.lndmanagej.model.LocalChannel; import de.cotto.lndmanagej.model.LocalOpenChannel; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.service.ChannelService; +import de.cotto.lndmanagej.service.GraphService; import de.cotto.lndmanagej.service.OwnNodeService; import org.springframework.context.annotation.Import; import org.springframework.web.bind.annotation.GetMapping; @@ -23,10 +24,12 @@ import java.util.List; public class StatusController { private final OwnNodeService ownNodeService; private final ChannelService channelService; + private final GraphService graphService; - public StatusController(OwnNodeService ownNodeService, ChannelService channelService) { + public StatusController(OwnNodeService ownNodeService, ChannelService channelService, GraphService graphService) { this.ownNodeService = ownNodeService; this.channelService = channelService; + this.graphService = graphService; } @Timed @@ -85,4 +88,9 @@ public class StatusController { return new PubkeysDto(pubkeys); } + @Timed + @GetMapping("/known-channels") + public int getKnownChannels() { + return graphService.getNumberOfChannels(); + } } diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerTest.java index 5c03d719..638dc816 100644 --- a/web/src/test/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerTest.java +++ b/web/src/test/java/de/cotto/lndmanagej/controller/PickhardtPaymentsControllerTest.java @@ -1,12 +1,12 @@ package de.cotto.lndmanagej.controller; import de.cotto.lndmanagej.controller.dto.MultiPathPaymentDto; -import de.cotto.lndmanagej.grpc.GrpcGraph; import de.cotto.lndmanagej.model.Coins; import de.cotto.lndmanagej.model.HexString; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSender; import de.cotto.lndmanagej.pickhardtpayments.MultiPathPaymentSplitter; import de.cotto.lndmanagej.pickhardtpayments.model.PaymentStatus; +import de.cotto.lndmanagej.service.GraphService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -45,7 +45,7 @@ class PickhardtPaymentsControllerTest { private PaymentStatusStream paymentStatusStream; @Mock - private GrpcGraph grpcGraph; + private GraphService graphService; private final PaymentStatus paymentStatus = new PaymentStatus(HexString.EMPTY); @@ -115,6 +115,6 @@ class PickhardtPaymentsControllerTest { @Test void resetCache() { controller.resetGraph(); - verify(grpcGraph).resetCache(); + verify(graphService).resetCache(); } } diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java index edfa7ae6..da42c28a 100644 --- a/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java +++ b/web/src/test/java/de/cotto/lndmanagej/controller/StatusControllerTest.java @@ -5,6 +5,7 @@ import de.cotto.lndmanagej.controller.dto.PubkeysDto; import de.cotto.lndmanagej.model.ChannelId; import de.cotto.lndmanagej.model.Pubkey; import de.cotto.lndmanagej.service.ChannelService; +import de.cotto.lndmanagej.service.GraphService; import de.cotto.lndmanagej.service.OwnNodeService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -36,6 +37,9 @@ class StatusControllerTest { @Mock private ChannelService channelService; + @Mock + private GraphService graphService; + @Test void isSyncedToChain() { when(ownNodeService.isSyncedToChain()).thenReturn(true); @@ -98,4 +102,10 @@ class StatusControllerTest { when(ownNodeService.getBlockHeight()).thenReturn(123_456); assertThat(statusController.getBlockHeight()).isEqualTo(123_456); } -} \ No newline at end of file + + @Test + void getKnownChannels() { + when(graphService.getNumberOfChannels()).thenReturn(123); + assertThat(statusController.getKnownChannels()).isEqualTo(123); + } +}