• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
testClassCallingRequireNonNullHasNoReferenceToRequiresNonNull()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
testInliningImplicitCallToObjectsRequireNonNull()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
testInliningExplicitCallToObjectsRequireNonNull()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