// Copyright 2016 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.android.desugar;

import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import static org.junit.Assert.fail;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;

import com.google.devtools.build.android.desugar.testdata.ClassCallingRequireNonNull;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

/**
 * This test case tests the desugaring feature for Objects.requireNonNull. This feature replaces any
 * call to this method with o.getClass() to check whether 'o' is null.
 */
@RunWith(JUnit4.class)
public class DesugarObjectsRequireNonNullTest {

  @Test
  public void testClassCallingRequireNonNullHasNoReferenceToRequiresNonNull() {
    try {
      ClassReader reader = new ClassReader(ClassCallingRequireNonNull.class.getName());

      AtomicInteger counterForSingleArgument = new AtomicInteger(0);
      AtomicInteger counterForString = new AtomicInteger(0);
      AtomicInteger counterForSupplier = new AtomicInteger(0);

      reader.accept(
          new ClassVisitor(Opcodes.ASM5) {
            @Override
            public MethodVisitor visitMethod(
                int access, String name, String desc, String signature, String[] exceptions) {
              return new MethodVisitor(api) {
                @Override
                public void visitMethodInsn(
                    int opcode, String owner, String name, String desc, boolean itf) {
                  if (opcode == INVOKESTATIC
                      && owner.equals("java/util/Objects")
                      && name.equals("requireNonNull")) {
                    switch (desc) {
                      case "(Ljava/lang/Object;)Ljava/lang/Object;":
                        counterForSingleArgument.incrementAndGet();
                        break;
                      case "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;":
                        counterForString.incrementAndGet();
                        break;
                      case "(Ljava/lang/Object;Ljava/util/function/Supplier;)Ljava/lang/Object;":
                        counterForSupplier.incrementAndGet();
                        break;
                      default:
                        fail("Unknown overloaded requireNonNull is found: " + desc);
                    }
                  }
                }
              };
            }
          },
          0);
      assertThat(counterForSingleArgument.get()).isEqualTo(0);
      // we do not desugar requireNonNull(Object, String) or requireNonNull(Object, Supplier)
      assertThat(counterForString.get()).isEqualTo(1);
      assertThat(counterForSupplier.get()).isEqualTo(1);
    } catch (IOException e) {
      fail();
    }
  }

  @Test
  public void testInliningImplicitCallToObjectsRequireNonNull() {
    assertThrows(
        NullPointerException.class,
        () -> ClassCallingRequireNonNull.getStringLengthWithMethodReference(null));

    assertThat(ClassCallingRequireNonNull.getStringLengthWithMethodReference("")).isEqualTo(0);
    assertThat(ClassCallingRequireNonNull.getStringLengthWithMethodReference("1")).isEqualTo(1);

    assertThrows(
        NullPointerException.class,
        () ->
            ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(
                null));

    assertThat(
            ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(""))
        .isEqualTo(0);
    assertThat(
            ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(
                "1"))
        .isEqualTo(1);
  }

  @Test
  public void testInliningExplicitCallToObjectsRequireNonNull() {
    assertThrows(
        NullPointerException.class, () -> ClassCallingRequireNonNull.getFirstCharVersionOne(null));

    assertThrows(
        NullPointerException.class, () -> ClassCallingRequireNonNull.getFirstCharVersionTwo(null));

    assertThrows(
        NullPointerException.class,
        () -> ClassCallingRequireNonNull.callRequireNonNullWithArgumentString(null));

    assertThrows(
        NullPointerException.class,
        () -> ClassCallingRequireNonNull.callRequireNonNullWithArgumentSupplier(null));

    assertThat(ClassCallingRequireNonNull.getFirstCharVersionOne("hello")).isEqualTo('h');
    assertThat(ClassCallingRequireNonNull.getFirstCharVersionTwo("hello")).isEqualTo('h');

    assertThat(ClassCallingRequireNonNull.callRequireNonNullWithArgumentString("hello"))
        .isEqualTo('h');
    assertThat(ClassCallingRequireNonNull.callRequireNonNullWithArgumentSupplier("hello"))
        .isEqualTo('h');
  }
}
