• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.cts.ctsprofiles;
18 
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 
25 /** Representation of a method included in the CTS package. */
26 public class MethodProfile {
27 
28     public final AnnotationManagement annotationManagement = new AnnotationManagement();
29 
30     private final String mMethod;
31 
32     private final ClassProfile mClass;
33 
34     private final List<String> mParams;
35 
36     private int mMethodType = 0;
37 
38     // Non-api methods called by this method.
39     private final HashMap<String, MethodProfile> mCommonMethodCalls = new HashMap<>();
40 
41     // Api methods called by this method.
42     private final HashMap<String, MethodProfile> mApiMethodCalls = new HashMap<>();
43 
44     // Api constructors called by this method.
45     private final HashMap<String, MethodProfile> mApiConstructorCalls = new HashMap<>();
46 
47     // Abstract api methods overridden by this method.
48     private final HashMap<String, MethodProfile> mOverriddenApiMethods = new HashMap<>();
49 
50     private static final Set<String> JUNIT4_ANNOTATION_PATTERNS = new HashSet<>(
51             List.of("org.junit.*")
52     );
53 
54     public enum MethodType {
55         JUNIT3(1),
56         JUNIT4(2),
57         /** A non-test method.*/
58         COMMON(4),
59         /** A method that is not extended from the super class. */
60         DIRECT_MEMBER(8),
61         ABSTRACT(16);
62 
63         private final int mValue;
64 
MethodType(int value)65         MethodType(int value) {
66             mValue = value;
67         }
68 
getValue()69         public int getValue() {
70             return mValue;
71         }
72     }
73 
MethodProfile( ClassProfile classProfile, String methodName, List<String> params)74     public MethodProfile(
75             ClassProfile classProfile, String methodName, List<String> params) {
76         mClass = classProfile;
77         mMethod = methodName;
78         mParams = params;
79     }
80 
getMethodName()81     public String getMethodName() {
82         return mMethod;
83     }
84 
getModuleName()85     public String getModuleName() {
86         return mClass.getModuleName();
87     }
88 
getPackageName()89     public String getPackageName() {
90         return mClass.getPackageName();
91     }
92 
getClassName()93     public String getClassName() {
94         return mClass.getClassName();
95     }
96 
getMethodParams()97     public List<String> getMethodParams() {
98         return mParams;
99     }
100 
isAbstract()101     public boolean isAbstract() {
102         return matchAllTypes(MethodType.ABSTRACT.getValue());
103     }
104 
getApiMethodCalls()105     public Map<String, MethodProfile> getApiMethodCalls() {
106         return mApiMethodCalls;
107     }
108 
getOverriddenApiMethods()109     public Map<String, MethodProfile> getOverriddenApiMethods() {
110         return mOverriddenApiMethods;
111     }
112 
getApiConstructorCalls()113     public Map<String, MethodProfile> getApiConstructorCalls() {
114         return mApiConstructorCalls;
115     }
116 
getCommonMethodCalls()117     public Map<String, MethodProfile> getCommonMethodCalls() {
118         return mCommonMethodCalls;
119     }
120 
121     /** Adds a called method. */
addMethodCall(MethodProfile methodCall)122     public void addMethodCall(MethodProfile methodCall) {
123         String methodSignature = methodCall.getMethodSignatureWithClass();
124         if (methodCall.isApiMethod()) {
125             if (methodCall.getMethodName().equals("<init>")) {
126                 mApiConstructorCalls.putIfAbsent(methodSignature, methodCall);
127             } else {
128                 mApiMethodCalls.putIfAbsent(methodSignature, methodCall);
129             }
130         } else {
131             mCommonMethodCalls.putIfAbsent(methodSignature, methodCall);
132         }
133     }
134 
135     /** Adds an API method overridden by this method. */
addOverriddenApiMethod(MethodProfile overriddenMethod)136     public void addOverriddenApiMethod(MethodProfile overriddenMethod) {
137         String methodSignature = overriddenMethod.getMethodSignatureWithClass();
138         mOverriddenApiMethods.putIfAbsent(methodSignature, overriddenMethod);
139     }
140 
getMethodSignatureWithClass()141     public String getMethodSignatureWithClass() {
142         return Utils.getMethodSignatureWithClass(
143                 mClass.getPackageName(), mClass.getClassName(), mMethod, mParams);
144     }
145 
146     /** Adds a method type for the method. */
addMethodType(MethodType methodType)147     public void addMethodType(MethodType methodType) {
148         mMethodType |= methodType.getValue();
149     }
150 
151     /** Returns true if it is decided that whether this is a test method or not. */
testMethodResolved()152     private boolean testMethodResolved() {
153         return matchAnyTypes(
154                 MethodType.JUNIT3.getValue()
155                         | MethodType.JUNIT4.getValue()
156                         | MethodType.COMMON.getValue());
157     }
158 
159     /** Returns true if the method is a test method. */
isTestMethod()160     public boolean isTestMethod() {
161         if (!isJunit4Method() && !isJunit3Method()) {
162             addMethodType(MethodType.COMMON);
163             return false;
164         }
165         return true;
166     }
167 
168     /** Returns true if the method is not extended from the super class. */
isDirectMember()169     public boolean isDirectMember() {
170         return matchAllTypes(MethodType.DIRECT_MEMBER.getValue());
171     }
172 
173     /** Returns true if the method is an API method. */
isApiMethod()174     public boolean isApiMethod() {
175         return mClass.isApiClass();
176     }
177 
178     /** Returns true if the method is a JUnit3 test method. */
isJunit3Method()179     protected boolean isJunit3Method() {
180         if (testMethodResolved()) {
181             return matchAllTypes(MethodType.JUNIT3.getValue());
182         }
183         if (mClass.isJunit3Class() && mMethod.startsWith("test")) {
184             addMethodType(MethodType.JUNIT3);
185             return true;
186         }
187         return false;
188     }
189 
190     /** Returns true if the method is a JUnit4 test method. */
isJunit4Method()191     protected boolean isJunit4Method() {
192         if (testMethodResolved()) {
193             return matchAllTypes(MethodType.JUNIT4.getValue());
194         }
195         for (ClassProfile annotation : annotationManagement.getAnnotations()) {
196             for (String pattern : JUNIT4_ANNOTATION_PATTERNS) {
197                 if (annotation.getClassSignature().matches(pattern)) {
198                     addMethodType(MethodType.JUNIT4);
199                     return true;
200                 }
201             }
202         }
203         return false;
204     }
205 
matchAnyTypes(int typesValue)206     private boolean matchAnyTypes(int typesValue) {
207         return (mMethodType & typesValue) != 0;
208     }
209 
matchAllTypes(int typesValue)210     private boolean matchAllTypes(int typesValue) {
211         return (mMethodType & typesValue) == typesValue;
212     }
213 }
214