// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed 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 com.google.devtools.build.lib.server;

import static com.google.common.truth.Truth.assertThat;

import com.google.devtools.build.lib.server.CommandManager.RunningCommand;
import com.google.devtools.build.lib.testutil.TestThread;
import com.google.devtools.build.lib.testutil.TestUtils;
import java.lang.Thread.State;
import java.util.UUID;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link CommandManager}. */
@RunWith(JUnit4.class)
public class CommandManagerTest {

  @Test
  public void testBasicOperationsOnSingleThread() {
    CommandManager underTest =
        new CommandManager(/*doIdleServerTasks=*/ false, "slow interrupt message suffix");
    assertThat(underTest.isEmpty()).isTrue();
    try (RunningCommand firstCommand = underTest.createCommand()) {
      assertThat(underTest.isEmpty()).isFalse();
      assertThat(isValidUuid(firstCommand.getId())).isTrue();
      try (RunningCommand secondCommand = underTest.createCommand()) {
        assertThat(underTest.isEmpty()).isFalse();
        assertThat(isValidUuid(secondCommand.getId())).isTrue();
        assertThat(firstCommand.getId()).isNotEqualTo(secondCommand.getId());
      }
      assertThat(underTest.isEmpty()).isFalse();
    }
    assertThat(underTest.isEmpty()).isTrue();
  }

  @Test
  public void testNotifiesOnBusyAndIdle() throws Exception {
    AtomicInteger notificationCounter = new AtomicInteger(0);
    CommandManager underTest =
        new CommandManager(/*doIdleServerTasks=*/ false, "slow interrupt message suffix");
    AtomicBoolean waiting = new AtomicBoolean(false);
    CyclicBarrier cyclicBarrier = new CyclicBarrier(2);

    TestThread thread =
        new TestThread(
            () -> {
              try {
                while (true) {
                  waiting.set(true);
                  underTest.waitForChange();
                  waiting.set(false);
                  notificationCounter.incrementAndGet();
                  cyclicBarrier.await();
                }
              } catch (InterruptedException e) {
                // Used to terminate the thread.
              }
            });
    thread.start();

    // We want to ensure at each step that we are actively awaiting notification.
    waitForThreadWaiting(waiting, thread);
    try (RunningCommand firstCommand = underTest.createCommand()) {
      cyclicBarrier.await();
      assertThat(notificationCounter.get()).isEqualTo(1);
      waitForThreadWaiting(waiting, thread);
      try (RunningCommand secondCommand = underTest.createCommand()) {
        cyclicBarrier.await();
        assertThat(notificationCounter.get()).isEqualTo(2);
        waitForThreadWaiting(waiting, thread);
      }
      cyclicBarrier.await();
      assertThat(notificationCounter.get()).isEqualTo(3);
      waitForThreadWaiting(waiting, thread);
    }
    cyclicBarrier.await();
    assertThat(notificationCounter.get()).isEqualTo(4);

    thread.interrupt();
    thread.joinAndAssertState(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
  }

  private static void waitForThreadWaiting(AtomicBoolean readyToWaitForChange, Thread thread)
      throws InterruptedException {
    while (!(readyToWaitForChange.get() && thread.getState() == State.WAITING)) {
      Thread.sleep(50);
    }
  }

  private static boolean isValidUuid(String uuidString) {
    try {
      UUID unused = UUID.fromString(uuidString);
      return true;
    } catch (IllegalArgumentException e) {
      return false;
    }
  }
}
