/*
 * Copyright 2022 LINE Corporation
 *
 * LINE Corporation 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:
 *
 *   https://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 com.linecorp.centraldogma.client.spring;

import static org.assertj.core.api.Assertions.assertThat;

import java.time.Duration;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.inject.Inject;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.Server;
import com.linecorp.centraldogma.client.CentralDogma;
import com.linecorp.centraldogma.client.spring.CentralDogmaInitializationTimeoutTest.TestConfiguration;
import com.linecorp.centraldogma.internal.api.v1.HttpApiV1Constants;

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = TestConfiguration.class)
@ActiveProfiles({ "local", "initTimeout" })
class CentralDogmaInitializationTimeoutTest {

    // TODO(ikhoon): Randomize the port number to avoid flakiness.
    private static final Lock lock = new ReentrantLock();
    private static final int TEST_SERVER_PORT = 56463;

    private static Server server;

    @SpringBootApplication
    static class TestConfiguration {}

    @Inject
    private CentralDogma client;

    @BeforeAll
    static void beforeAll() {
        lock.lock();
        server = Server.builder()
                       .http(TEST_SERVER_PORT)
                       .service(HttpApiV1Constants.HEALTH_CHECK_PATH,
                                (ctx, req) -> HttpResponse.delayed(HttpResponse.of("OK"),
                                                                   Duration.ofSeconds(5)))
                       .build();
        server.start().join();
    }

    @AfterAll
    static void afterAll() {
        try {
            // Immediately close the server to release the port quickly.
            server.close();
        } finally {
            lock.unlock();
        }
    }

    @Test
    void initializedEndpoints() {
        assertThat(client.whenEndpointReady()).isCompleted();
    }
}

@@ -760,24 +760,62 @@
 e.Duration;%0A
+import java.util.concurrent.TimeUnit;%0A
 import java.
@@ -842,16 +842,16 @@
 s.Lock;%0A
-
 import j
@@ -1031,24 +1031,62 @@
 r.api.Test;%0A
+import org.junit.jupiter.api.Timeout;%0A
 import org.j
@@ -1382,16 +1382,126 @@
 nsion;%0A%0A
+import com.google.common.util.concurrent.Uninterruptibles;%0A%0Aimport com.linecorp.armeria.client.retry.Backoff;%0A
 import c
@@ -2317,16 +2317,65 @@
 lient;%0A%0A
+    @Timeout(value = 5, unit = TimeUnit.MINUTES)%0A
     @Bef
@@ -2444,16 +2444,163 @@
     
-server =
+final int maxAttempts = 8;%0A        for (int i = 1; i %3C= maxAttempts; i++) %7B%0A            try %7B%0A                final Server server =%0A                       
  Ser
@@ -2613,16 +2613,23 @@
 ilder()%0A
+       
         
@@ -2690,16 +2690,23 @@
         
+  
+     
 .service
@@ -2776,16 +2776,23 @@
         
+     
+  
 (ctx, re
@@ -2908,16 +2908,23 @@
         
+       
 Duration
@@ -2962,16 +2962,23 @@
         
+       
 .build()
@@ -2983,24 +2983,32 @@
 ();%0A        
+     
+   
 server.start
@@ -3014,24 +3014,497 @@
 t().join();%0A
+                CentralDogmaInitializationTimeoutTest.server = server;%0A                break;%0A            %7D catch (Exception ex) %7B%0A                if (i %3C maxAttempts) %7B%0A                    // Ignore the exception silently apart from the last attempts.%0A                    final long sleep = Backoff.ofDefault().nextDelayMillis(maxAttempts);%0A                    Uninterruptibles.sleepUninterruptibly(sleep, TimeUnit.MILLISECONDS);%0A                %7D%0A            %7D%0A        %7D%0A
     %7D%0A%0A    @

Fix the test failure in `CentralDogmaInitializationTimeoutTest` (#726)