/*
 * 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.flink.runtime.rpc;

import org.apache.flink.configuration.AkkaOptions;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.runtime.rpc.exceptions.RpcConnectionException;
import org.apache.flink.runtime.taskexecutor.TaskExecutorGateway;
import org.apache.flink.util.TestLogger;

import org.junit.Test;

import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

/**
 * This test validates that the RPC service gives a good message when it cannot connect to an
 * RpcEndpoint.
 */
public class RpcConnectionTest extends TestLogger {

    @Test
    public void testConnectFailure() throws Exception {
        // we start the RPC service with a very long timeout to ensure that the test
        // can only pass if the connection problem is not recognized merely via a timeout
        Configuration configuration = new Configuration();
        configuration.set(AkkaOptions.ASK_TIMEOUT_DURATION, Duration.ofSeconds(10000000));

        final RpcService rpcService =
                RpcSystem.load()
                        .localServiceBuilder(configuration)
                        .withBindAddress("localhost")
                        .withBindPort(0)
                        .createAndStart();
        try {
            CompletableFuture<TaskExecutorGateway> future =
                    rpcService.connect("foo.bar.com.test.invalid", TaskExecutorGateway.class);

            future.get(10000000, TimeUnit.SECONDS);
            fail("should never complete normally");
        } catch (TimeoutException e) {
            fail("should not fail with a generic timeout exception");
        } catch (ExecutionException e) {
            // that is what we want
            assertTrue(e.getCause() instanceof RpcConnectionException);
            assertTrue(
                    "wrong error message",
                    e.getCause().getMessage().contains("foo.bar.com.test.invalid"));
        } catch (Throwable t) {
            fail("wrong exception: " + t);
        } finally {
            rpcService.stopService().get();
        }
    }
}

@@ -1205,198 +1205,72 @@
 ent.
-CompletableFuture;%0Aimport java.util.concurrent.ExecutionException;%0Aimport java.util.concurrent.TimeUnit;%0Aimport java.util.concurrent.TimeoutException;%0A%0Aimport static org.junit
+TimeUnit;%0A%0Aimport static org.assertj.core.api
 .Assert
+ions
 .assertT
 rue;
@@ -1269,48 +1269,19 @@
 ertT
-rue;%0Aimport static org.junit.Assert.fail
+hatThrownBy
 ;%0A%0A/
@@ -1838,24 +1838,83 @@
 0000000));%0A%0A
+        try (RpcSystem rpcSystem = RpcSystem.load()) %7B%0A    
         fina
@@ -1955,25 +1955,29 @@
         
+   
-R
+ r
 pcSystem
 .load()%0A
@@ -1972,16 +1972,13 @@
 stem
-.load()%0A
+%0A    
     
@@ -1998,21 +1998,22 @@
        .
-local
+remote
 ServiceB
@@ -2032,18 +2032,41 @@
 guration
-)%0A
+, null, %228000-9000%22)%0A    
         
@@ -2127,32 +2127,36 @@
                 
+    
 .withBindPort(0)
@@ -2156,16 +2156,20 @@
 Port(0)%0A
+    
         
@@ -2203,24 +2203,25 @@
 tart();%0A
+%0A
         
 try %7B%0A  
@@ -2216,391 +2216,362 @@
     
-try %7B%0A            CompletableFuture%3CTaskExecutorGateway%3E future =%0A                    rpcService.connect(%22foo.bar.com.test.invalid%22, TaskExecutorGateway.class);%0A%0A            future.get(10000000, TimeUnit.SECONDS);%0A            fail(%22should never complete normally%22);%0A        %7D catch (TimeoutException e) %7B%0A            fail(%22should not fail with a generic timeout excep
+    final String invalidAddress =%0A                    rpcSystem.getRpcUrl(%0A                            rpcService.getAddress() + %22.invalid%22,%0A                            rpcService.getPort(),%0A                            %22foo%22,%0A                            AddressResolution.NO_ADDRESS_RESOLUTION,%0A                            new Configura
 tion
-%22
+()
 );%0A
+%0A
         
 %7D ca
@@ -2570,148 +2570,112 @@
     
-%7D catch (ExecutionException e) %7B%0A            // that is what we want%0A            assertTrue(e.getCause() instanceof RpcConnectionException);
+    assertThatThrownBy(%0A                            () -%3E%0A                                    rpcService
 %0A   
@@ -2687,20 +2687,20 @@
     
-assertTrue(%0A
+            
     
@@ -2719,210 +2719,289 @@
     
-%22wrong error message%22,%0A                    e.getCause().getMessage().contains(%22foo.bar.com.test.invalid%22));%0A        %7D catch (Throwable t) %7B%0A            fail(%22wrong exception: %22 + t);%0A        %7D f
+.connect(invalidAddress, TaskExecutorGateway.class)%0A                                            .get(10000000, TimeUnit.SECONDS))%0A                    .cause()%0A                    .isInstanceOf(RpcConnectionException.class)%0A                    .hasMessageContaining(
 in
+v
 al
-ly %7B
+idAddress);
 %0A   

Use proper RPC url