davsclaus commented on code in PR #28037:
URL: https://github.com/apache/camel/pull/28037#discussion_r4306093807


##########
components/camel-web3j/src/test/java/org/apache/camel/component/web3j/Web3jConsumerResubscribeTest.java:
##########
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.web3j;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Flowable;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.methods.response.EthBlock;
+import org.web3j.protocol.core.methods.response.Log;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;

Review Comment:
   Needed for the `after(...)` suggestions below:
   ```suggestion
   import static org.mockito.Mockito.after;
   import static org.mockito.Mockito.mock;
   ```



##########
components/camel-web3j/src/test/java/org/apache/camel/component/web3j/Web3jConsumerResubscribeTest.java:
##########
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.web3j;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Flowable;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.methods.response.EthBlock;
+import org.web3j.protocol.core.methods.response.Log;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * A live subscription that ends with an error (such as a failed 
eth_getBlockByHash request inside web3j's
+ * blockFlowable) is subscribed again, instead of leaving a started consumer 
that receives nothing.
+ */
+class Web3jConsumerResubscribeTest extends CamelTestSupport {
+
+    private final Web3j web3j = mock(Web3j.class);
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @EndpointInject("mock:error")
+    private MockEndpoint error;
+
+    Web3jConsumerResubscribeTest() {
+        // the mocked client is stubbed before the context starts
+        testConfiguration().withUseAdviceWith(true);
+    }
+
+    @Override
+    protected void bindToRegistry(Registry registry) {
+        registry.bind("mockWeb3j", web3j);
+    }
+
+    private static EthBlock block(String number) {
+        EthBlock.Block block = new EthBlock.Block();
+        block.setNumber(number);
+        EthBlock ethBlock = new EthBlock();
+        ethBlock.setResult(block);
+        return ethBlock;
+    }
+
+    private void startRoute(String operation) throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                onException(Exception.class).handled(true).to("mock:error");
+                
from("web3j://http://127.0.0.1:8545?web3j=#mockWeb3j&operation="; + operation)
+                        .routeId("web3j").autoStartup(false)
+                        .to("mock:result");
+            }
+        });
+        context.start();
+        ((Web3jConsumer) 
context.getRoute("web3j").getConsumer()).setResubscribeDelay(10);
+        context.getRouteController().startRoute("web3j");
+    }
+
+    @Test
+    void blockSubscriptionEndedByAFailedRequestIsSubscribedAgain() throws 
Exception {
+        when(web3j.blockFlowable(anyBoolean())).thenReturn(
+                Flowable.concat(Flowable.just(block("0x1")), 
Flowable.error(new IOException("Connection reset"))),
+                Flowable.concat(Flowable.just(block("0x2")), 
Flowable.never()));
+        result.expectedMessageCount(2);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.BLOCK_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        assertEquals("0x2", 
result.getReceivedExchanges().get(1).getIn().getBody(EthBlock.Block.class).getNumberRaw());
+    }
+
+    @Test
+    void failuresWhileSubscribingAgainAreRoutedOnce() throws Exception {
+        // the node is unreachable for three attempts, then it answers again
+        IOException down = new IOException("Connection refused");
+        when(web3j.blockFlowable(anyBoolean())).thenReturn(
+                Flowable.error(down), Flowable.error(down), 
Flowable.error(down),
+                Flowable.concat(Flowable.just(block("0x1")), 
Flowable.never()));
+        result.expectedMessageCount(1);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.BLOCK_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        verify(web3j, times(4)).blockFlowable(anyBoolean());
+    }
+
+    @Test
+    void replayOfARangeIsNotSubscribedAgain() throws Exception {
+        // a replay of a block range would route the blocks of the range again
+        when(web3j.replayPastBlocksFlowable(any(), any(), anyBoolean()))
+                .thenReturn(Flowable.concat(Flowable.just(block("0x1")), 
Flowable.error(new IOException("Connection reset"))));
+        result.expectedMessageCount(1);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.REPLAY_BLOCKS_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        verify(web3j, times(1)).replayPastBlocksFlowable(any(), any(), 
anyBoolean());

Review Comment:
   This runs right after the error exchange arrives, before the 10 ms 
resubscribe delay has passed, so it would also pass without the 
`resubscribes()` guard. Waiting a few delay periods before verifying makes the 
test cover the guard:
   ```suggestion
           verify(web3j, after(200).times(1)).replayPastBlocksFlowable(any(), 
any(), anyBoolean());
   ```



##########
components/camel-web3j/src/test/java/org/apache/camel/component/web3j/Web3jConsumerResubscribeTest.java:
##########
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.web3j;
+
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import io.reactivex.Flowable;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+import org.web3j.protocol.Web3j;
+import org.web3j.protocol.core.methods.response.EthBlock;
+import org.web3j.protocol.core.methods.response.Log;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * A live subscription that ends with an error (such as a failed 
eth_getBlockByHash request inside web3j's
+ * blockFlowable) is subscribed again, instead of leaving a started consumer 
that receives nothing.
+ */
+class Web3jConsumerResubscribeTest extends CamelTestSupport {
+
+    private final Web3j web3j = mock(Web3j.class);
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @EndpointInject("mock:error")
+    private MockEndpoint error;
+
+    Web3jConsumerResubscribeTest() {
+        // the mocked client is stubbed before the context starts
+        testConfiguration().withUseAdviceWith(true);
+    }
+
+    @Override
+    protected void bindToRegistry(Registry registry) {
+        registry.bind("mockWeb3j", web3j);
+    }
+
+    private static EthBlock block(String number) {
+        EthBlock.Block block = new EthBlock.Block();
+        block.setNumber(number);
+        EthBlock ethBlock = new EthBlock();
+        ethBlock.setResult(block);
+        return ethBlock;
+    }
+
+    private void startRoute(String operation) throws Exception {
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() {
+                onException(Exception.class).handled(true).to("mock:error");
+                
from("web3j://http://127.0.0.1:8545?web3j=#mockWeb3j&operation="; + operation)
+                        .routeId("web3j").autoStartup(false)
+                        .to("mock:result");
+            }
+        });
+        context.start();
+        ((Web3jConsumer) 
context.getRoute("web3j").getConsumer()).setResubscribeDelay(10);
+        context.getRouteController().startRoute("web3j");
+    }
+
+    @Test
+    void blockSubscriptionEndedByAFailedRequestIsSubscribedAgain() throws 
Exception {
+        when(web3j.blockFlowable(anyBoolean())).thenReturn(
+                Flowable.concat(Flowable.just(block("0x1")), 
Flowable.error(new IOException("Connection reset"))),
+                Flowable.concat(Flowable.just(block("0x2")), 
Flowable.never()));
+        result.expectedMessageCount(2);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.BLOCK_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        assertEquals("0x2", 
result.getReceivedExchanges().get(1).getIn().getBody(EthBlock.Block.class).getNumberRaw());
+    }
+
+    @Test
+    void failuresWhileSubscribingAgainAreRoutedOnce() throws Exception {
+        // the node is unreachable for three attempts, then it answers again
+        IOException down = new IOException("Connection refused");
+        when(web3j.blockFlowable(anyBoolean())).thenReturn(
+                Flowable.error(down), Flowable.error(down), 
Flowable.error(down),
+                Flowable.concat(Flowable.just(block("0x1")), 
Flowable.never()));
+        result.expectedMessageCount(1);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.BLOCK_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        verify(web3j, times(4)).blockFlowable(anyBoolean());
+    }
+
+    @Test
+    void replayOfARangeIsNotSubscribedAgain() throws Exception {
+        // a replay of a block range would route the blocks of the range again
+        when(web3j.replayPastBlocksFlowable(any(), any(), anyBoolean()))
+                .thenReturn(Flowable.concat(Flowable.just(block("0x1")), 
Flowable.error(new IOException("Connection reset"))));
+        result.expectedMessageCount(1);
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.REPLAY_BLOCKS_OBSERVABLE);
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        verify(web3j, times(1)).replayPastBlocksFlowable(any(), any(), 
anyBoolean());
+    }
+
+    @Test
+    void logFilterFromAGivenBlockIsNotSubscribedAgain() throws Exception {
+        // a new filter from the same block would route the logs from that 
block again
+        when(web3j.ethLogFlowable(any())).thenReturn(Flowable.error(new 
IOException("Connection refused")));
+        error.expectedMessageCount(1);
+
+        startRoute(Web3jConstants.ETH_LOG_OBSERVABLE + "&fromBlock=16");
+
+        MockEndpoint.assertIsSatisfied(context, 5, TimeUnit.SECONDS);
+        verify(web3j, times(1)).ethLogFlowable(any());

Review Comment:
   Same as above:
   ```suggestion
           verify(web3j, after(200).times(1)).ethLogFlowable(any());
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to