• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.class2nonsdklist;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.eq;
23 import static org.mockito.Mockito.atLeastOnce;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 
27 import static java.util.Collections.emptySet;
28 
29 import com.android.annotationvisitor.AnnotationHandler;
30 import com.android.annotationvisitor.AnnotationHandlerTestBase;
31 import com.android.annotationvisitor.AnnotationVisitor;
32 
33 import com.google.common.base.Joiner;
34 import com.google.common.collect.ImmutableMap;
35 import com.google.common.collect.ImmutableSet;
36 
37 import org.junit.Before;
38 import org.junit.Test;
39 
40 import java.io.IOException;
41 import java.util.Map;
42 
43 public class CovariantReturnTypeHandlerTest extends AnnotationHandlerTestBase {
44 
45     private static final String ANNOTATION = "Lannotation/Annotation;";
46     private static final String FLAG = "test-flag";
47 
48     @Before
setup()49     public void setup() throws IOException {
50         // To keep the test simpler and more concise, we don't use the real
51         // @CovariantReturnType annotation here, but use our own @Annotation.
52         // It doesn't have to match the real annotation, just have the same
53         // property (returnType).
54         mJavac.addSource("annotation.Annotation", Joiner.on('\n').join(
55                 "package annotation;",
56                 "import static java.lang.annotation.RetentionPolicy.CLASS;",
57                 "import java.lang.annotation.Retention;",
58                 "@Retention(CLASS)",
59                 "public @interface Annotation {",
60                 "  Class<?> returnType();",
61                 "}"));
62     }
63 
64     @Test
testReturnTypeWhitelisted()65     public void testReturnTypeWhitelisted() throws IOException {
66         mJavac.addSource("a.b.Class", Joiner.on('\n').join(
67                 "package a.b;",
68                 "import annotation.Annotation;",
69                 "public class Class {",
70                 "  @Annotation(returnType=Integer.class)",
71                 "  public String method() {return null;}",
72                 "}"));
73         mJavac.compile();
74 
75         Map<String, AnnotationHandler> handlerMap =
76                 ImmutableMap.of(ANNOTATION,
77                         new CovariantReturnTypeHandler(
78                                 mConsumer,
79                                 ImmutableSet.of("La/b/Class;->method()Ljava/lang/String;"),
80                                 FLAG));
81         new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
82 
83         assertNoErrors();
84         verify(mConsumer, times(1)).consume(
85                 eq("La/b/Class;->method()Ljava/lang/Integer;"), any(), eq(ImmutableSet.of(FLAG)));
86     }
87 
88     @Test
testAnnotatedMemberNotPublicApi()89     public void testAnnotatedMemberNotPublicApi() throws IOException {
90         mJavac.addSource("a.b.Class", Joiner.on('\n').join(
91                 "package a.b;",
92                 "import annotation.Annotation;",
93                 "public class Class {",
94                 "  @Annotation(returnType=Integer.class)",
95                 "  public String method() {return null;}",
96                 "}"));
97         mJavac.compile();
98 
99         Map<String, AnnotationHandler> handlerMap =
100                 ImmutableMap.of(ANNOTATION,
101                         new CovariantReturnTypeHandler(
102                                 mConsumer,
103                                 emptySet(),
104                                 FLAG));
105         new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
106 
107         verify(mStatus, atLeastOnce()).error(any(), any());
108     }
109 
110     @Test
testReturnTypeAlreadyWhitelisted()111     public void testReturnTypeAlreadyWhitelisted() throws IOException {
112         mJavac.addSource("a.b.Class", Joiner.on('\n').join(
113                 "package a.b;",
114                 "import annotation.Annotation;",
115                 "public class Class {",
116                 "  @Annotation(returnType=Integer.class)",
117                 "  public String method() {return null;}",
118                 "}"));
119         mJavac.compile();
120 
121         Map<String, AnnotationHandler> handlerMap =
122                 ImmutableMap.of(ANNOTATION,
123                         new CovariantReturnTypeHandler(
124                                 mConsumer,
125                                 ImmutableSet.of(
126                                         "La/b/Class;->method()Ljava/lang/String;",
127                                         "La/b/Class;->method()Ljava/lang/Integer;"
128                                 ),
129                                 FLAG));
130         new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
131 
132         verify(mStatus, atLeastOnce()).error(any(), any());
133     }
134 
135     @Test
testAnnotationOnField()136     public void testAnnotationOnField() throws IOException {
137         mJavac.addSource("a.b.Class", Joiner.on('\n').join(
138                 "package a.b;",
139                 "import annotation.Annotation;",
140                 "public class Class {",
141                 "  @Annotation(returnType=Integer.class)",
142                 "  public String field;",
143                 "}"));
144         mJavac.compile();
145 
146         Map<String, AnnotationHandler> handlerMap =
147                 ImmutableMap.of(ANNOTATION,
148                         new CovariantReturnTypeHandler(
149                                 mConsumer,
150                                 emptySet(),
151                                 FLAG));
152         new AnnotationVisitor(mJavac.getCompiledClass("a.b.Class"), mStatus, handlerMap).visit();
153 
154         verify(mStatus, atLeastOnce()).error(any(), any());
155     }
156 }
157