Home | History | Annotate | Download | only in desugar
      1 // Copyright 2016 The Bazel Authors. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 package com.google.devtools.build.android.desugar;
     15 
     16 import static com.google.common.truth.Truth.assertThat;
     17 import static org.junit.Assert.fail;
     18 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
     19 
     20 import com.google.devtools.build.android.desugar.testdata.ClassCallingRequireNonNull;
     21 import java.io.IOException;
     22 import java.util.concurrent.atomic.AtomicInteger;
     23 import org.junit.Test;
     24 import org.junit.runner.RunWith;
     25 import org.junit.runners.JUnit4;
     26 import org.objectweb.asm.ClassReader;
     27 import org.objectweb.asm.ClassVisitor;
     28 import org.objectweb.asm.MethodVisitor;
     29 import org.objectweb.asm.Opcodes;
     30 
     31 /**
     32  * This test case tests the desugaring feature for Objects.requireNonNull. This feature replaces any
     33  * call to this method with o.getClass() to check whether 'o' is null.
     34  */
     35 @RunWith(JUnit4.class)
     36 public class DesugarObjectsRequireNonNullTest {
     37 
     38   @Test
     39   public void testClassCallingRequireNonNullHasNoReferenceToRequiresNonNull() {
     40     try {
     41       ClassReader reader = new ClassReader(ClassCallingRequireNonNull.class.getName());
     42 
     43       AtomicInteger counterForSingleArgument = new AtomicInteger(0);
     44       AtomicInteger counterForString = new AtomicInteger(0);
     45       AtomicInteger counterForSupplier = new AtomicInteger(0);
     46 
     47       reader.accept(
     48           new ClassVisitor(Opcodes.ASM5) {
     49             @Override
     50             public MethodVisitor visitMethod(
     51                 int access, String name, String desc, String signature, String[] exceptions) {
     52               return new MethodVisitor(api) {
     53                 @Override
     54                 public void visitMethodInsn(
     55                     int opcode, String owner, String name, String desc, boolean itf) {
     56                   if (opcode == INVOKESTATIC
     57                       && owner.equals("java/util/Objects")
     58                       && name.equals("requireNonNull")) {
     59                     switch (desc) {
     60                       case "(Ljava/lang/Object;)Ljava/lang/Object;":
     61                         counterForSingleArgument.incrementAndGet();
     62                         break;
     63                       case "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;":
     64                         counterForString.incrementAndGet();
     65                         break;
     66                       case "(Ljava/lang/Object;Ljava/util/function/Supplier;)Ljava/lang/Object;":
     67                         counterForSupplier.incrementAndGet();
     68                         break;
     69                       default:
     70                         fail("Unknown overloaded requireNonNull is found: " + desc);
     71                     }
     72                   }
     73                 }
     74               };
     75             }
     76           },
     77           0);
     78       assertThat(counterForSingleArgument.get()).isEqualTo(0);
     79       // we do not desugar requireNonNull(Object, String) or requireNonNull(Object, Supplier)
     80       assertThat(counterForString.get()).isEqualTo(1);
     81       assertThat(counterForSupplier.get()).isEqualTo(1);
     82     } catch (IOException e) {
     83       fail();
     84     }
     85   }
     86 
     87   @Test
     88   public void testInliningImplicitCallToObjectsRequireNonNull() {
     89     try {
     90       ClassCallingRequireNonNull.getStringLengthWithMethodReference(null);
     91       fail ("NullPointerException expected");
     92     } catch (NullPointerException e) {
     93       // Expected
     94     }
     95 
     96     assertThat(ClassCallingRequireNonNull.getStringLengthWithMethodReference("")).isEqualTo(0);
     97     assertThat(ClassCallingRequireNonNull.getStringLengthWithMethodReference("1")).isEqualTo(1);
     98 
     99     try {
    100       ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(null);
    101       fail ("NullPointerException expected");
    102     } catch (NullPointerException e) {
    103       // Expected
    104     }
    105 
    106     assertThat(
    107             ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(""))
    108         .isEqualTo(0);
    109     assertThat(
    110             ClassCallingRequireNonNull.getStringLengthWithLambdaAndExplicitCallToRequireNonNull(
    111                 "1"))
    112         .isEqualTo(1);
    113   }
    114 
    115   @Test
    116   public void testInliningExplicitCallToObjectsRequireNonNull() {
    117     try {
    118       ClassCallingRequireNonNull.getFirstCharVersionOne(null);
    119       fail ("NullPointerException expected");
    120     } catch (NullPointerException e) {
    121       // Expected
    122     }
    123 
    124     try {
    125       ClassCallingRequireNonNull.getFirstCharVersionTwo(null);
    126       fail ("NullPointerException expected");
    127     } catch (NullPointerException e) {
    128       // Expected
    129     }
    130 
    131     try {
    132       ClassCallingRequireNonNull.callRequireNonNullWithArgumentString(null);
    133       fail ("NullPointerException expected");
    134     } catch (NullPointerException e) {
    135       // Expected
    136     }
    137 
    138     try {
    139       ClassCallingRequireNonNull.callRequireNonNullWithArgumentSupplier(null);
    140       fail ("NullPointerException expected");
    141     } catch (NullPointerException e) {
    142       // Expected
    143     }
    144 
    145     assertThat(ClassCallingRequireNonNull.getFirstCharVersionOne("hello")).isEqualTo('h');
    146     assertThat(ClassCallingRequireNonNull.getFirstCharVersionTwo("hello")).isEqualTo('h');
    147 
    148     assertThat(ClassCallingRequireNonNull.callRequireNonNullWithArgumentString("hello"))
    149         .isEqualTo('h');
    150     assertThat(ClassCallingRequireNonNull.callRequireNonNullWithArgumentSupplier("hello"))
    151         .isEqualTo('h');
    152   }
    153 }
    154