1 /* 2 * Copyright (C) 2017 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.tools.metalava 18 19 import com.android.tools.metalava.cli.common.ARG_HIDE 20 import com.android.tools.metalava.testing.java 21 import org.junit.Test 22 23 class KeepFileTest : DriverTest() { 24 @Test Generate Keep filenull25 fun `Generate Keep file`() { 26 check( 27 sourceFiles = 28 arrayOf( 29 java( 30 """ 31 package test.pkg; 32 @SuppressWarnings("ALL") 33 public interface MyInterface<T extends Object> 34 extends MyBaseInterface { 35 } 36 """ 37 ), 38 java( 39 """ 40 package a.b.c; 41 @SuppressWarnings("ALL") 42 public interface MyStream<T, S extends MyStream<T, S>> extends java.lang.AutoCloseable { 43 } 44 """ 45 ), 46 java( 47 """ 48 package test.pkg; 49 @SuppressWarnings("ALL") 50 public interface MyInterface2<T extends Number> 51 extends MyBaseInterface { 52 public class TtsSpan<C extends MyInterface<?>> { } 53 public abstract class Range<T extends Comparable<? super T>> { 54 protected String myString; 55 } 56 } 57 """ 58 ), 59 java( 60 """ 61 package test.pkg; 62 public interface MyBaseInterface { 63 void fun(int a, String b); 64 } 65 """ 66 ) 67 ), 68 proguard = 69 """ 70 -keep class a.b.c.MyStream { 71 } 72 -keep class test.pkg.MyBaseInterface { 73 public abstract void fun(int, java.lang.String); 74 } 75 -keep class test.pkg.MyInterface { 76 } 77 -keep class test.pkg.MyInterface2 { 78 } 79 -keep class test.pkg.MyInterface2${"$"}Range { 80 <init>(); 81 protected java.lang.String myString; 82 } 83 -keep class test.pkg.MyInterface2${"$"}TtsSpan { 84 <init>(); 85 } 86 """, 87 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 88 ) 89 } 90 91 @Test Primitive typesnull92 fun `Primitive types`() { 93 check( 94 sourceFiles = 95 arrayOf( 96 java( 97 """ 98 package test.pkg; 99 public class MyClass { 100 public int testMethodA(int a) {} 101 public boolean testMethodB(boolean a) {} 102 public float testMethodC(float a) {} 103 public double testMethodD(double a) {} 104 public byte testMethodE(byte a) {} 105 } 106 """ 107 ) 108 ), 109 proguard = 110 """ 111 -keep class test.pkg.MyClass { 112 <init>(); 113 public int testMethodA(int); 114 public boolean testMethodB(boolean); 115 public float testMethodC(float); 116 public double testMethodD(double); 117 public byte testMethodE(byte); 118 } 119 """, 120 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 121 ) 122 } 123 124 @Test Primitive array typesnull125 fun `Primitive array types`() { 126 check( 127 sourceFiles = 128 arrayOf( 129 java( 130 """ 131 package test.pkg; 132 public class MyClass { 133 public int[] testMethodA(int[] a) {} 134 public float[][] testMethodB(float[][] a) {} 135 public double[][][] testMethodC(double[][][] a) {} 136 public byte testMethodD(byte... a) {} 137 } 138 """ 139 ) 140 ), 141 proguard = 142 """ 143 -keep class test.pkg.MyClass { 144 <init>(); 145 public int[] testMethodA(int[]); 146 public float[][] testMethodB(float[][]); 147 public double[][][] testMethodC(double[][][]); 148 public byte testMethodD(byte[]); 149 } 150 """, 151 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 152 ) 153 } 154 155 @Test Object Array parametersnull156 fun `Object Array parameters`() { 157 check( 158 sourceFiles = 159 arrayOf( 160 java( 161 """ 162 package test.pkg; 163 public class MyClass { 164 public void testMethodA(String a) {} 165 public void testMethodB(Boolean[] a) {} 166 public void testMethodC(Integer... a) {} 167 } 168 """ 169 ) 170 ), 171 proguard = 172 """ 173 -keep class test.pkg.MyClass { 174 <init>(); 175 public void testMethodA(java.lang.String); 176 public void testMethodB(java.lang.Boolean[]); 177 public void testMethodC(java.lang.Integer[]); 178 } 179 """, 180 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 181 ) 182 } 183 184 @Test Arrays with Inner classnull185 fun `Arrays with Inner class`() { 186 check( 187 sourceFiles = 188 arrayOf( 189 java( 190 """ 191 package test.pkg; 192 public class MyClass { 193 public void testMethodA(InnerClass a) {} 194 public void testMethodB(InnerClass[] a) {} 195 public void testMethodC(InnerClass... a) {} 196 public class InnerClass {} 197 } 198 """ 199 ) 200 ), 201 proguard = 202 """ 203 -keep class test.pkg.MyClass { 204 <init>(); 205 public void testMethodA(test.pkg.MyClass${"$"}InnerClass); 206 public void testMethodB(test.pkg.MyClass${"$"}InnerClass[]); 207 public void testMethodC(test.pkg.MyClass${"$"}InnerClass[]); 208 } 209 -keep class test.pkg.MyClass${"$"}InnerClass { 210 <init>(); 211 } 212 """, 213 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 214 ) 215 } 216 217 @Test Conflicting Class Names in parametersnull218 fun `Conflicting Class Names in parameters`() { 219 check( 220 sourceFiles = 221 arrayOf( 222 java( 223 """ 224 package test.pkg; 225 public class String {} 226 """ 227 ), 228 java( 229 """ 230 package test.pkg; 231 public class MyClass { 232 public void testMethodA(String a, String b) {} 233 public void testMethodB(String a, test.pkg.String b) {} 234 public void testMethodC(String a, java.lang.String b) {} 235 public void testMethodD(java.lang.String a, test.pkg.String b) {} 236 } 237 """ 238 ), 239 java( 240 """ 241 package test.pkg; 242 public class MyClassArrays { 243 public void testMethodA(String[] a, String[] b) {} 244 public void testMethodB(String[] a, test.pkg.String[] b) {} 245 public void testMethodC(String[] a, java.lang.String[] b) {} 246 public void testMethodD(java.lang.String... a, test.pkg.String... b) {} 247 } 248 """ 249 ) 250 ), 251 proguard = 252 """ 253 -keep class test.pkg.MyClass { 254 <init>(); 255 public void testMethodA(test.pkg.String, test.pkg.String); 256 public void testMethodB(test.pkg.String, test.pkg.String); 257 public void testMethodC(test.pkg.String, java.lang.String); 258 public void testMethodD(java.lang.String, test.pkg.String); 259 } 260 -keep class test.pkg.MyClassArrays { 261 <init>(); 262 public void testMethodA(test.pkg.String[], test.pkg.String[]); 263 public void testMethodB(test.pkg.String[], test.pkg.String[]); 264 public void testMethodC(test.pkg.String[], java.lang.String[]); 265 public void testMethodD(java.lang.String[], test.pkg.String[]); 266 } 267 -keep class test.pkg.String { 268 <init>(); 269 } 270 """, 271 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 272 ) 273 } 274 275 @Test Multi dimensional arraysnull276 fun `Multi dimensional arrays`() { 277 check( 278 sourceFiles = 279 arrayOf( 280 java( 281 """ 282 package test.pkg; 283 public class String {} 284 """ 285 ), 286 java( 287 """ 288 package test.pkg; 289 public class MyClassArrays { 290 public void testMethodA(String[][] a, String[][] b) {} 291 public void testMethodB(String[][][] a, test.pkg.String[][][] b) {} 292 public void testMethodC(String[][] a, java.lang.String[][] b) {} 293 public class InnerClass {} 294 public void testMethodD(InnerClass[][] a) {} 295 } 296 """ 297 ) 298 ), 299 proguard = 300 """ 301 -keep class test.pkg.MyClassArrays { 302 <init>(); 303 public void testMethodA(test.pkg.String[][], test.pkg.String[][]); 304 public void testMethodB(test.pkg.String[][][], test.pkg.String[][][]); 305 public void testMethodC(test.pkg.String[][], java.lang.String[][]); 306 public void testMethodD(test.pkg.MyClassArrays${"$"}InnerClass[][]); 307 } 308 -keep class test.pkg.MyClassArrays${"$"}InnerClass { 309 <init>(); 310 } 311 -keep class test.pkg.String { 312 <init>(); 313 } 314 """, 315 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 316 ) 317 } 318 319 @Test Methods with arrays as the return typenull320 fun `Methods with arrays as the return type`() { 321 check( 322 sourceFiles = 323 arrayOf( 324 java( 325 """ 326 package test.pkg; 327 public class MyClass { 328 public String[] testMethodA() {} 329 public String[][] testMethodB() {} 330 public String[][][] testMethodC() {} 331 } 332 """ 333 ), 334 java( 335 """ 336 package test.pkg; 337 public class MyOtherClass { 338 public java.lang.String[] testMethodA() {} 339 public String[][] testMethodB() {} 340 public test.pkg.String[][][] testMethodC() {} 341 } 342 """ 343 ), 344 java( 345 """ 346 package test.pkg; 347 public class String {} 348 """ 349 ) 350 ), 351 proguard = 352 """ 353 -keep class test.pkg.MyClass { 354 <init>(); 355 public test.pkg.String[] testMethodA(); 356 public test.pkg.String[][] testMethodB(); 357 public test.pkg.String[][][] testMethodC(); 358 } 359 -keep class test.pkg.MyOtherClass { 360 <init>(); 361 public java.lang.String[] testMethodA(); 362 public test.pkg.String[][] testMethodB(); 363 public test.pkg.String[][][] testMethodC(); 364 } 365 -keep class test.pkg.String { 366 <init>(); 367 } 368 """, 369 extraArguments = arrayOf(ARG_HIDE, "KotlinKeyword") 370 ) 371 } 372 } 373