// Copyright 2021 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.runtime;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.buildeventstream.BuildEventIdUtil;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.BuildEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos.TestStatus;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.config.BuildConfigurationKey;
import com.google.devtools.build.lib.view.test.TestStatus.BlazeTestStatus;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link TargetSummaryPublisher}. */
@RunWith(JUnit4.class)
public final class TargetSummaryEventTest {
  private static final String PATH = "package";
  private static final String TARGET_NAME = "name";

  private static final BuildConfigurationKey CONFIGURATION_KEY =
      BuildConfigurationKey.create(BuildOptions.builder().build());

  private static final String CHECKSUM = CONFIGURATION_KEY.getOptions().checksum();

  @Test
  public void testGetEventId() throws Exception {
    TargetSummaryEvent event =
        TargetSummaryEvent.create(target(PATH, TARGET_NAME, CONFIGURATION_KEY), false, false, null);
    assertThat(event.getEventId())
        .isEqualTo(
            BuildEventIdUtil.targetSummary(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.configurationId(CHECKSUM)));
  }

  @Test
  public void testGetEventId_nullConfig() throws Exception {
    TargetSummaryEvent event =
        TargetSummaryEvent.create(target(PATH, TARGET_NAME, null), false, false, null);
    assertThat(event.getEventId())
        .isEqualTo(
            BuildEventIdUtil.targetSummary(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.nullConfigurationId()));
  }

  @Test
  public void testPostedAfter_noTestSummary() throws Exception {
    TargetSummaryEvent event = TargetSummaryEvent.create(stubTarget(), false, false, null);
    assertThat(event.postedAfter())
        .containsExactly(
            BuildEventIdUtil.targetCompleted(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.configurationId(CHECKSUM)));
  }

  @Test
  public void testPostedAfter_expectTestSummary() throws Exception {
    TargetSummaryEvent event = TargetSummaryEvent.create(stubTarget(), false, true, null);
    assertThat(event.postedAfter())
        .containsExactly(
            BuildEventIdUtil.targetCompleted(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.configurationId(CHECKSUM)),
            BuildEventIdUtil.testSummary(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.configurationId(CHECKSUM)));
  }

  @Test
  public void testPostedAfter_nullConfig() throws Exception {
    TargetSummaryEvent event =
        TargetSummaryEvent.create(target(PATH, TARGET_NAME, null), false, true, null);
    assertThat(event.postedAfter())
        .containsExactly(
            BuildEventIdUtil.targetCompleted(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.nullConfigurationId()),
            BuildEventIdUtil.testSummary(
                Label.create(PATH, TARGET_NAME), BuildEventIdUtil.nullConfigurationId()));
  }

  @Test
  public void testAsStreamProto_forTest() throws Exception {
    TargetSummaryEvent event =
        TargetSummaryEvent.create(stubTarget(), true, true, BlazeTestStatus.FLAKY);
    BuildEvent proto = event.asStreamProto(null);
    assertThat(proto.getId()).isEqualTo(event.getEventId());
    assertThat(proto.getTargetSummary().getOverallBuildSuccess()).isTrue();
    assertThat(proto.getTargetSummary().getOverallTestStatus()).isEqualTo(TestStatus.FLAKY);
  }

  @Test
  public void testAsStreamProto_forBuildSuccess() throws Exception {
    TargetSummaryEvent event = TargetSummaryEvent.create(stubTarget(), true, false, null);
    BuildEvent proto = event.asStreamProto(null);
    assertThat(proto.getId()).isEqualTo(event.getEventId());
    assertThat(proto.getTargetSummary().getOverallBuildSuccess()).isTrue();
    assertThat(proto.getTargetSummary().getOverallTestStatus()).isEqualTo(TestStatus.NO_STATUS);
  }

  @Test
  public void testAsStreamProto_failedBuildIgnoresTestResult() throws Exception {
    TargetSummaryEvent event =
        TargetSummaryEvent.create(stubTarget(), false, true, BlazeTestStatus.PASSED);
    BuildEvent proto = event.asStreamProto(null);
    assertThat(proto.getId()).isEqualTo(event.getEventId());
    assertThat(proto.getTargetSummary().getOverallBuildSuccess()).isFalse();
    assertThat(proto.getTargetSummary().getOverallTestStatus()).isEqualTo(TestStatus.NO_STATUS);
  }

  private static ConfiguredTarget stubTarget() throws Exception {
    return target(PATH, TARGET_NAME, CONFIGURATION_KEY);
  }

  private static ConfiguredTarget target(
      String path, String targetName, BuildConfigurationKey configurationKey) throws Exception {
    ConfiguredTarget target = mock(ConfiguredTarget.class);
    when(target.getOriginalLabel()).thenReturn(Label.create(path, targetName));
    when(target.getConfigurationChecksum())
        .thenReturn(configurationKey == null ? null : configurationKey.getOptions().checksum());
    ConfiguredTargetKey key =
        ConfiguredTargetKey.builder()
            .setLabel(Label.create(path, targetName))
            .setConfigurationKey(configurationKey)
            .build();
    when(target.getLookupKey()).thenReturn(key);
    return target;
  }
}
