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 // A map of non-api methods called by this method with the method signature as the key. 39 private final HashMap<String, MethodProfile> mCommonMethodCalls = new HashMap<>(); 40 41 // A map of api methods called by this method with the method signature as the key. 42 private final HashMap<String, MethodProfile> mApiMethodCalls = new HashMap<>(); 43 44 // A map of api constructors called by this method with the method signature as the key. 45 private final HashMap<String, MethodProfile> mApiConstructorCalls = new HashMap<>(); 46 47 // TODO(slotus): Add known patterns. 48 private static final Set<String> JUNIT4_ANNOTATION_PATTERNS = new HashSet<>(List.of()); 49 50 public enum MethodType { 51 JUNIT3(1), 52 JUNIT4(2), 53 /** A non-test method.*/ 54 COMMON(4), 55 // TODO(slotus): Solve the override case. 56 /** A method that is not extended from the super class. */ 57 DIRECT_MEMBER(8); 58 59 private final int mValue; 60 MethodType(int value)61 MethodType(int value) { 62 mValue = value; 63 } 64 getValue()65 public int getValue() { 66 return mValue; 67 } 68 } 69 MethodProfile( ClassProfile classProfile, String methodName, List<String> params)70 public MethodProfile( 71 ClassProfile classProfile, String methodName, List<String> params) { 72 mClass = classProfile; 73 mMethod = methodName; 74 mParams = params; 75 } 76 getMethodName()77 public String getMethodName() { 78 return mMethod; 79 } 80 getModuleName()81 public String getModuleName() { 82 return mClass.getModuleName(); 83 } 84 getPackageName()85 public String getPackageName() { 86 return mClass.getPackageName(); 87 } 88 getClassName()89 public String getClassName() { 90 return mClass.getClassName(); 91 } 92 getMethodParams()93 public List<String> getMethodParams() { 94 return mParams; 95 } 96 getApiMethodCalls()97 public Map<String, MethodProfile> getApiMethodCalls() { 98 return mApiMethodCalls; 99 } 100 getApiConstructorCalls()101 public Map<String, MethodProfile> getApiConstructorCalls() { 102 return mApiConstructorCalls; 103 } 104 getCommonMethodCalls()105 public Map<String, MethodProfile> getCommonMethodCalls() { 106 return mCommonMethodCalls; 107 } 108 getMethodSignatureWithClass()109 public String getMethodSignatureWithClass() { 110 return Utils.getMethodSignatureWithClass( 111 mClass.getPackageName(), mClass.getClassName(), mMethod, mParams); 112 } 113 114 /** Adds an API method called by the method. **/ addApiMethodCall(MethodProfile apiMethod)115 public void addApiMethodCall(MethodProfile apiMethod) { 116 mApiMethodCalls.putIfAbsent(apiMethod.getMethodSignatureWithClass(), apiMethod); 117 } 118 119 /** Adds an API constructor called by the method. **/ addApiConstructorCall(MethodProfile apiConstructor)120 public void addApiConstructorCall(MethodProfile apiConstructor) { 121 mApiConstructorCalls.putIfAbsent( 122 apiConstructor.getMethodSignatureWithClass(), apiConstructor); 123 } 124 125 /** Adds a non-API method called by the method. **/ addCommonMethodCall(MethodProfile method)126 public void addCommonMethodCall(MethodProfile method) { 127 mCommonMethodCalls.putIfAbsent(method.getMethodSignatureWithClass(), method); 128 } 129 130 /** Adds a method type for the method. */ addMethodType(MethodType methodType)131 public void addMethodType(MethodType methodType) { 132 mMethodType |= methodType.getValue(); 133 } 134 135 /** Returns true if it is decided that whether this is a test method or not. */ testMethodResolved()136 private boolean testMethodResolved() { 137 return matchAnyTypes( 138 MethodType.JUNIT3.getValue() 139 | MethodType.JUNIT4.getValue() 140 | MethodType.COMMON.getValue()); 141 } 142 143 /** Returns true if the method is a test method. */ isTestMethod()144 public boolean isTestMethod() { 145 if (!isJunit4Method() && !isJunit3Method()) { 146 addMethodType(MethodType.COMMON); 147 return false; 148 } 149 return true; 150 } 151 152 /** Returns true if the method is a JUnit3 test method. */ isJunit3Method()153 protected boolean isJunit3Method() { 154 if (testMethodResolved()) { 155 return matchAllTypes(MethodType.JUNIT3.getValue()); 156 } 157 if (mClass.isJunit3Class() && mMethod.startsWith("test")) { 158 addMethodType(MethodType.JUNIT3); 159 return true; 160 } 161 return false; 162 } 163 164 /** Returns true if the method is a JUnit4 test method. */ isJunit4Method()165 protected boolean isJunit4Method() { 166 if (testMethodResolved()) { 167 return matchAllTypes(MethodType.JUNIT4.getValue()); 168 } 169 for (ClassProfile annotation : annotationManagement.getAnnotations()) { 170 for (String pattern : JUNIT4_ANNOTATION_PATTERNS) { 171 if (annotation.getClassSignature().matches(pattern)) { 172 addMethodType(MethodType.JUNIT4); 173 return true; 174 } 175 } 176 } 177 return false; 178 } 179 matchAnyTypes(int typesValue)180 private boolean matchAnyTypes(int typesValue) { 181 return (mMethodType & typesValue) != 0; 182 } 183 matchAllTypes(int typesValue)184 private boolean matchAllTypes(int typesValue) { 185 return (mMethodType & typesValue) == typesValue; 186 } 187 } 188