From 053bda5cbaa84961ecb3b559fed6ebad22b0acb9 Mon Sep 17 00:00:00 2001 From: Carsten Otto Date: Thu, 13 Jan 2022 19:15:35 +0100 Subject: [PATCH] add flow controller --- .../controller/FlowControllerIT.java | 85 +++++++++++++++++++ .../lndmanagej/controller/FlowController.java | 51 +++++++++++ .../controller/FlowControllerTest.java | 51 +++++++++++ 3 files changed, 187 insertions(+) create mode 100644 web/src/integrationTest/java/de/cotto/lndmanagej/controller/FlowControllerIT.java create mode 100644 web/src/main/java/de/cotto/lndmanagej/controller/FlowController.java create mode 100644 web/src/test/java/de/cotto/lndmanagej/controller/FlowControllerTest.java diff --git a/web/src/integrationTest/java/de/cotto/lndmanagej/controller/FlowControllerIT.java b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/FlowControllerIT.java new file mode 100644 index 00000000..26721283 --- /dev/null +++ b/web/src/integrationTest/java/de/cotto/lndmanagej/controller/FlowControllerIT.java @@ -0,0 +1,85 @@ +package de.cotto.lndmanagej.controller; + +import de.cotto.lndmanagej.model.ChannelIdResolver; +import de.cotto.lndmanagej.service.FlowService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.time.Duration; + +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.FlowReportFixtures.FLOW_REPORT; +import static de.cotto.lndmanagej.model.FlowReportFixtures.FLOW_REPORT_2; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static org.hamcrest.core.Is.is; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(controllers = FlowController.class) +class FlowControllerIT { + private static final String NODE_PREFIX = "/api/node/" + PUBKEY; + private static final String CHANNEL_PREFIX = "/api/channel/" + CHANNEL_ID.getShortChannelId(); + + @Autowired + private MockMvc mockMvc; + + @MockBean + private FlowService flowService; + + @MockBean + @SuppressWarnings("unused") + private ChannelIdResolver channelIdResolver; + + @Test + void getFlowReport_for_channel() throws Exception { + when(flowService.getFlowReportForChannel(CHANNEL_ID)).thenReturn(FLOW_REPORT_2); + mockMvc.perform(get(CHANNEL_PREFIX + "/flow-report")) + .andExpect(jsonPath("$.forwardedSent", is("1000"))) + .andExpect(jsonPath("$.forwardedReceived", is("2000"))) + .andExpect(jsonPath("$.forwardingFeesReceived", is("10"))) + .andExpect(jsonPath("$.rebalanceSent", is("60000"))) + .andExpect(jsonPath("$.rebalanceFeesSent", is("4"))) + .andExpect(jsonPath("$.rebalanceReceived", is("61000"))) + .andExpect(jsonPath("$.rebalanceSupportSent", is("9000"))) + .andExpect(jsonPath("$.rebalanceSupportFeesSent", is("2"))) + .andExpect(jsonPath("$.rebalanceSupportReceived", is("10"))) + .andExpect(jsonPath("$.totalSent", is("70006"))) + .andExpect(jsonPath("$.totalReceived", is("63020"))); + } + + @Test + void getFlowReport_for_channel_with_max_age() throws Exception { + when(flowService.getFlowReportForChannel(CHANNEL_ID, Duration.ofDays(1))).thenReturn(FLOW_REPORT); + mockMvc.perform(get(CHANNEL_PREFIX + "/flow-report/last-days/1")) + .andExpect(status().isOk()); + } + + @Test + void getFlowReport_for_peer() throws Exception { + when(flowService.getFlowReportForPeer(PUBKEY)).thenReturn(FLOW_REPORT); + mockMvc.perform(get(NODE_PREFIX + "/flow-report")) + .andExpect(jsonPath("$.forwardedSent", is("1050000"))) + .andExpect(jsonPath("$.forwardedReceived", is("9001000"))) + .andExpect(jsonPath("$.forwardingFeesReceived", is("1"))) + .andExpect(jsonPath("$.rebalanceSent", is("50000"))) + .andExpect(jsonPath("$.rebalanceFeesSent", is("5"))) + .andExpect(jsonPath("$.rebalanceReceived", is("51000"))) + .andExpect(jsonPath("$.rebalanceSupportSent", is("123"))) + .andExpect(jsonPath("$.rebalanceSupportFeesSent", is("1"))) + .andExpect(jsonPath("$.rebalanceSupportReceived", is("456"))) + .andExpect(jsonPath("$.totalSent", is("1100129"))) + .andExpect(jsonPath("$.totalReceived", is("9052457"))); + } + + @Test + void getFlowReport_for_peer_with_max_age() throws Exception { + when(flowService.getFlowReportForPeer(PUBKEY, Duration.ofDays(1))).thenReturn(FLOW_REPORT); + mockMvc.perform(get(NODE_PREFIX + "/flow-report/last-days/1")) + .andExpect(status().isOk()); + } +} \ No newline at end of file diff --git a/web/src/main/java/de/cotto/lndmanagej/controller/FlowController.java b/web/src/main/java/de/cotto/lndmanagej/controller/FlowController.java new file mode 100644 index 00000000..1d0e0fd1 --- /dev/null +++ b/web/src/main/java/de/cotto/lndmanagej/controller/FlowController.java @@ -0,0 +1,51 @@ +package de.cotto.lndmanagej.controller; + +import com.codahale.metrics.annotation.Timed; +import de.cotto.lndmanagej.controller.dto.FlowReportDto; +import de.cotto.lndmanagej.controller.dto.ObjectMapperConfiguration; +import de.cotto.lndmanagej.model.ChannelId; +import de.cotto.lndmanagej.model.Pubkey; +import de.cotto.lndmanagej.service.FlowService; +import org.springframework.context.annotation.Import; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.time.Duration; + +@RestController +@RequestMapping("/api") +@Import(ObjectMapperConfiguration.class) +public class FlowController { + + private final FlowService flowService; + + public FlowController(FlowService flowService) { + this.flowService = flowService; + } + + @Timed + @GetMapping("/channel/{channelId}/flow-report") + public FlowReportDto getFlowReportForChannel(@PathVariable ChannelId channelId) { + return FlowReportDto.createFromModel(flowService.getFlowReportForChannel(channelId)); + } + + @Timed + @GetMapping("/channel/{channelId}/flow-report/last-days/{lastDays}") + public FlowReportDto getFlowReportForChannel(@PathVariable ChannelId channelId, @PathVariable int lastDays) { + return FlowReportDto.createFromModel(flowService.getFlowReportForChannel(channelId, Duration.ofDays(lastDays))); + } + + @Timed + @GetMapping("/node/{pubkey}/flow-report") + public FlowReportDto getFlowReportForPeer(@PathVariable Pubkey pubkey) { + return FlowReportDto.createFromModel(flowService.getFlowReportForPeer(pubkey)); + } + + @Timed + @GetMapping("/node/{pubkey}/flow-report/last-days/{lastDays}") + public FlowReportDto getFlowReportForPeer(@PathVariable Pubkey pubkey, @PathVariable int lastDays) { + return FlowReportDto.createFromModel(flowService.getFlowReportForPeer(pubkey, Duration.ofDays(lastDays))); + } +} diff --git a/web/src/test/java/de/cotto/lndmanagej/controller/FlowControllerTest.java b/web/src/test/java/de/cotto/lndmanagej/controller/FlowControllerTest.java new file mode 100644 index 00000000..be1cb2fc --- /dev/null +++ b/web/src/test/java/de/cotto/lndmanagej/controller/FlowControllerTest.java @@ -0,0 +1,51 @@ +package de.cotto.lndmanagej.controller; + +import de.cotto.lndmanagej.controller.dto.FlowReportDto; +import de.cotto.lndmanagej.service.FlowService; +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.time.Duration; + +import static de.cotto.lndmanagej.model.ChannelIdFixtures.CHANNEL_ID; +import static de.cotto.lndmanagej.model.FlowReportFixtures.FLOW_REPORT; +import static de.cotto.lndmanagej.model.PubkeyFixtures.PUBKEY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class FlowControllerTest { + private static final FlowReportDto FLOW_REPORT_DTO = FlowReportDto.createFromModel(FLOW_REPORT); + @InjectMocks + private FlowController flowController; + + @Mock + private FlowService flowService; + + @Test + void getFlowReportForChannel() { + when(flowService.getFlowReportForChannel(CHANNEL_ID)).thenReturn(FLOW_REPORT); + assertThat(flowController.getFlowReportForChannel(CHANNEL_ID)).isEqualTo(FLOW_REPORT_DTO); + } + + @Test + void getFlowReportForChannel_with_max_age() { + when(flowService.getFlowReportForChannel(CHANNEL_ID, Duration.ofDays(123))).thenReturn(FLOW_REPORT); + assertThat(flowController.getFlowReportForChannel(CHANNEL_ID, 123)).isEqualTo(FLOW_REPORT_DTO); + } + + @Test + void getFlowReportForPeer() { + when(flowService.getFlowReportForPeer(PUBKEY)).thenReturn(FLOW_REPORT); + assertThat(flowController.getFlowReportForPeer(PUBKEY)).isEqualTo(FLOW_REPORT_DTO); + } + + @Test + void getFlowReportForPeer_with_max_age() { + when(flowService.getFlowReportForPeer(PUBKEY, Duration.ofDays(123))).thenReturn(FLOW_REPORT); + assertThat(flowController.getFlowReportForPeer(PUBKEY, 123)).isEqualTo(FLOW_REPORT_DTO); + } +} \ No newline at end of file