| // Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | package com.android.tools.r8; | 
 |  | 
 | import static org.junit.Assert.assertEquals; | 
 | import static org.junit.Assert.assertFalse; | 
 | import static org.junit.Assert.assertNotNull; | 
 | import static org.junit.Assert.assertTrue; | 
 |  | 
 | import com.android.tools.r8.dex.Marker; | 
 | import com.android.tools.r8.naming.ProguardMapSupplier; | 
 | import com.android.tools.r8.utils.AndroidApiLevel; | 
 | import com.android.tools.r8.utils.VersionProperties; | 
 | import java.nio.file.Paths; | 
 | import java.util.Collection; | 
 | import java.util.HashSet; | 
 | import java.util.Set; | 
 | import org.junit.Test; | 
 |  | 
 | public class ProguardMapMarkerTest { | 
 |   private static final int EXPECTED_NUMBER_OF_KEYS_DEX = 5; | 
 |   private static final int EXPECTED_NUMBER_OF_KEYS_CF = 4; | 
 |   private static final String CLASS_FILE = | 
 |       ToolHelper.EXAMPLES_BUILD_DIR + "classes/trivial/Trivial.class"; | 
 |  | 
 |   @Test | 
 |   public void proguardMapMarkerTest24() throws CompilationFailedException { | 
 |     proguardMapMarkerTestDex(AndroidApiLevel.N); | 
 |   } | 
 |  | 
 |   @Test | 
 |   public void proguardMapMarkerTest26() throws CompilationFailedException { | 
 |     proguardMapMarkerTestDex(AndroidApiLevel.O); | 
 |   } | 
 |  | 
 |   private static class ProguardMapIds { | 
 |     String fromProgram = null; | 
 |     String fromMap = null; | 
 |   } | 
 |  | 
 |   private void proguardMapMarkerTestDex(AndroidApiLevel minApiLevel) | 
 |       throws CompilationFailedException { | 
 |     ProguardMapIds proguardMapIds = new ProguardMapIds(); | 
 |     R8.run( | 
 |         R8Command.builder() | 
 |             .addProgramFiles(Paths.get(CLASS_FILE)) | 
 |             .setDisableTreeShaking(true) | 
 |             .setProgramConsumer( | 
 |                 new DexIndexedConsumer.ForwardingConsumer(null) { | 
 |                   @Override | 
 |                   public void accept( | 
 |                       int fileIndex, | 
 |                       ByteDataView data, | 
 |                       Set<String> descriptors, | 
 |                       DiagnosticsHandler handler) { | 
 |                     Marker marker; | 
 |                     try { | 
 |                       Collection<Marker> markers = | 
 |                           ExtractMarker.extractMarkerFromDexProgramData(data.copyByteData()); | 
 |                       assertEquals(1, markers.size()); | 
 |                       marker = markers.iterator().next(); | 
 |                     } catch (Exception e) { | 
 |                       throw new RuntimeException(e); | 
 |                     } | 
 |                     proguardMapIds.fromProgram = marker.getPgMapId(); | 
 |                   } | 
 |                 }) | 
 |             .addLibraryFiles(ToolHelper.getAndroidJar(minApiLevel)) | 
 |             .setMinApiLevel(minApiLevel.getLevel()) | 
 |             .setProguardMapConsumer( | 
 |                 ToolHelper.consumeString( | 
 |                     proguardMap -> { | 
 |                       proguardMapIds.fromMap = | 
 |                           verifyMarkersGetPgMapId( | 
 |                               proguardMap, minApiLevel.getLevel(), EXPECTED_NUMBER_OF_KEYS_DEX); | 
 |                     })) | 
 |             .build()); | 
 |     verifyProguardMapIds(proguardMapIds); | 
 |   } | 
 |  | 
 |   private void verifyProguardMapIds(ProguardMapIds proguardMapIds) { | 
 |     assertTrue( | 
 |         proguardMapIds.fromProgram != null | 
 |             && proguardMapIds.fromProgram.length() == ProguardMapSupplier.PG_MAP_ID_LENGTH); | 
 |     assertTrue(proguardMapIds.fromMap != null); | 
 |     assertEquals(proguardMapIds.fromMap, proguardMapIds.fromProgram); | 
 |   } | 
 |  | 
 |   @Test | 
 |   public void proguardMapMarkerTestCf() throws CompilationFailedException { | 
 |     ProguardMapIds buildIds = new ProguardMapIds(); | 
 |     R8.run( | 
 |         R8Command.builder() | 
 |             .addProgramFiles(Paths.get(CLASS_FILE)) | 
 |             .setDisableTreeShaking(true) | 
 |             .setProgramConsumer( | 
 |                 new ClassFileConsumer.ForwardingConsumer(null) { | 
 |                   @Override | 
 |                   public void accept( | 
 |                       ByteDataView data, String descriptor, DiagnosticsHandler handler) { | 
 |                     Marker marker; | 
 |                     try { | 
 |                       Collection<Marker> markers = | 
 |                           ExtractMarker.extractMarkerFromClassProgramData(data.copyByteData()); | 
 |                       assertEquals(1, markers.size()); | 
 |                       marker = markers.iterator().next(); | 
 |                     } catch (Exception e) { | 
 |                       throw new RuntimeException(e); | 
 |                     } | 
 |                     buildIds.fromProgram = marker.getPgMapId(); | 
 |                   } | 
 |                 }) | 
 |             .addLibraryFiles(ToolHelper.getJava8RuntimeJar()) | 
 |             .setProguardMapConsumer( | 
 |                 ToolHelper.consumeString( | 
 |                     proguardMap -> { | 
 |                       buildIds.fromMap = | 
 |                           verifyMarkersGetPgMapId(proguardMap, null, EXPECTED_NUMBER_OF_KEYS_CF); | 
 |                     })) | 
 |             .build()); | 
 |     verifyProguardMapIds(buildIds); | 
 |   } | 
 |  | 
 |   private static String verifyMarkersGetPgMapId( | 
 |       String proguardMap, Integer minApiLevel, int expectedNumberOfKeys) { | 
 |     String[] lines = proguardMap.split("\n"); | 
 |     Set<String> keysFound = new HashSet<>(); | 
 |     String proguardMapId = null; | 
 |     for (String line : lines) { | 
 |       if (!line.startsWith("#")) { | 
 |         continue; | 
 |       } | 
 |       String comment = line.substring(1).trim(); | 
 |       int colonIndex = comment.indexOf(":"); | 
 |       if (colonIndex < 0) { | 
 |         continue; | 
 |       } | 
 |       String key = comment.substring(0, colonIndex).trim(); | 
 |       String value = comment.substring(colonIndex + 1).trim(); | 
 |       if (key.equals(ProguardMapSupplier.MARKER_KEY_COMPILER)) { | 
 |         assertEquals(ProguardMapSupplier.MARKER_VALUE_COMPILER, value); | 
 |       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_COMPILER_VERSION)) { | 
 |         assertEquals(Version.LABEL, value); | 
 |       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_MIN_API)) { | 
 |         assertNotNull(minApiLevel); | 
 |         assertEquals(minApiLevel.intValue(), Integer.parseInt(value)); | 
 |       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_COMPILER_HASH)) { | 
 |         assertEquals(VersionProperties.INSTANCE.getSha(), value); | 
 |       } else if (key.equals(ProguardMapSupplier.MARKER_KEY_PG_MAP_ID)) { | 
 |         proguardMapId = value; | 
 |       } else { | 
 |         continue; | 
 |       } | 
 |       assertFalse(keysFound.contains(key)); | 
 |       keysFound.add(key); | 
 |     } | 
 |     assertEquals(expectedNumberOfKeys, keysFound.size()); | 
 |     return proguardMapId; | 
 |   } | 
 | } |