|  | // Copyright (c) 2017, 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 com.android.tools.r8.R8RunArtTestsTest.CompilerUnderTest; | 
|  | import com.android.tools.r8.R8RunArtTestsTest.DexTool; | 
|  | import com.android.tools.r8.ToolHelper.DexVm; | 
|  | import com.android.tools.r8.errors.Unreachable; | 
|  | import com.google.common.collect.Sets; | 
|  | import java.util.ArrayList; | 
|  | import java.util.Arrays; | 
|  | import java.util.EnumSet; | 
|  | import java.util.List; | 
|  | import java.util.stream.Collectors; | 
|  |  | 
|  | public class TestCondition { | 
|  |  | 
|  | enum Runtime { | 
|  | ART_V4_0_4, | 
|  | ART_V4_4_4, | 
|  | ART_V5_1_1, | 
|  | ART_V6_0_1, | 
|  | ART_V7_0_0, | 
|  | ART_V8_1_0, | 
|  | ART_V9_0_0, | 
|  | ART_V10_0_0, | 
|  | ART_DEFAULT, | 
|  | JAVA; | 
|  |  | 
|  | static final Runtime LOWEST_ART_VERSION = ART_V4_0_4; | 
|  | static final Runtime HIGHEST_ART_VERSION = ART_DEFAULT; | 
|  |  | 
|  | static Runtime fromDexVmVersion(DexVm.Version version) { | 
|  | switch (version) { | 
|  | case V4_0_4: | 
|  | return ART_V4_0_4; | 
|  | case V4_4_4: | 
|  | return ART_V4_4_4; | 
|  | case V5_1_1: | 
|  | return ART_V5_1_1; | 
|  | case V6_0_1: | 
|  | return ART_V6_0_1; | 
|  | case V7_0_0: | 
|  | return ART_V7_0_0; | 
|  | case V8_1_0: | 
|  | return ART_V8_1_0; | 
|  | case V9_0_0: | 
|  | return ART_V9_0_0; | 
|  | case V10_0_0: | 
|  | return ART_V10_0_0; | 
|  | case DEFAULT: | 
|  | return ART_DEFAULT; | 
|  | default: | 
|  | throw new Unreachable(); | 
|  | } | 
|  | } | 
|  |  | 
|  | static boolean isArt(Runtime runtime) { | 
|  | return EnumSet.range(LOWEST_ART_VERSION, HIGHEST_ART_VERSION).contains(runtime); | 
|  | } | 
|  | } | 
|  |  | 
|  | static class ToolSet { | 
|  |  | 
|  | final EnumSet<DexTool> set; | 
|  |  | 
|  | public ToolSet(EnumSet<DexTool> set) { | 
|  | this.set = set; | 
|  | } | 
|  | } | 
|  |  | 
|  | static class CompilerSet { | 
|  |  | 
|  | final EnumSet<CompilerUnderTest> set; | 
|  |  | 
|  | public CompilerSet(EnumSet<CompilerUnderTest> set) { | 
|  | this.set = set; | 
|  | } | 
|  | } | 
|  |  | 
|  | static class RuntimeSet { | 
|  |  | 
|  | private EnumSet<Runtime> set; | 
|  |  | 
|  | public RuntimeSet(EnumSet<Runtime> set) { | 
|  | this.set = set; | 
|  | } | 
|  |  | 
|  | public static RuntimeSet fromDexVmVersionSet(EnumSet<DexVm.Version> dexVmSet) { | 
|  | List<Runtime> list = new ArrayList<>(dexVmSet.size()); | 
|  | for (DexVm.Version version : dexVmSet) { | 
|  | list.add(Runtime.fromDexVmVersion(version)); | 
|  | } | 
|  | return new RuntimeSet(EnumSet.copyOf(list)); | 
|  | } | 
|  |  | 
|  | boolean contains(Runtime runtime) { | 
|  | return set.contains(runtime); | 
|  | } | 
|  | } | 
|  |  | 
|  | static class CompilationModeSet { | 
|  |  | 
|  | final EnumSet<CompilationMode> set; | 
|  |  | 
|  | public CompilationModeSet(EnumSet<CompilationMode> set) { | 
|  | this.set = set; | 
|  | } | 
|  | } | 
|  |  | 
|  | public static final CompilerSet D8_COMPILER = | 
|  | compilers(CompilerUnderTest.D8, CompilerUnderTest.D8_AFTER_R8CF); | 
|  | public static final CompilerSet D8_NOT_AFTER_R8CF_COMPILER = compilers(CompilerUnderTest.D8); | 
|  | public static final CompilerSet D8_AFTER_R8CF_COMPILER = | 
|  | compilers(CompilerUnderTest.D8_AFTER_R8CF); | 
|  | // R8_COMPILER refers to R8 both in the standalone setting and after D8 | 
|  | // R8_NOT_AFTER_D8_COMPILER and R8_AFTER_D8_COMPILER refers to the standalone and the combined | 
|  | // settings, respectively | 
|  | public static final CompilerSet R8_COMPILER = | 
|  | compilers( | 
|  | CompilerUnderTest.R8, | 
|  | CompilerUnderTest.R8_AFTER_D8, | 
|  | CompilerUnderTest.D8_AFTER_R8CF, | 
|  | CompilerUnderTest.R8CF); | 
|  | public static final CompilerSet R8DEX_COMPILER = | 
|  | compilers(CompilerUnderTest.R8, CompilerUnderTest.R8_AFTER_D8); | 
|  | public static final CompilerSet R8_NOT_AFTER_D8_COMPILER = | 
|  | compilers(CompilerUnderTest.R8, CompilerUnderTest.D8_AFTER_R8CF, CompilerUnderTest.R8CF); | 
|  | public static final CompilerSet R8CF = compilers(CompilerUnderTest.R8CF); | 
|  |  | 
|  | public static final CompilationModeSet DEBUG_MODE = | 
|  | new CompilationModeSet(EnumSet.of(CompilationMode.DEBUG)); | 
|  | public static final CompilationModeSet RELEASE_MODE = | 
|  | new CompilationModeSet(EnumSet.of(CompilationMode.RELEASE)); | 
|  |  | 
|  | private static final ToolSet ANY_TOOL = new ToolSet(EnumSet.allOf(DexTool.class)); | 
|  | private static final CompilerSet ANY_COMPILER = | 
|  | new CompilerSet(EnumSet.allOf(CompilerUnderTest.class)); | 
|  | private static final RuntimeSet ANY_RUNTIME = new RuntimeSet(EnumSet.allOf(Runtime.class)); | 
|  | private static final RuntimeSet ANY_DEX_VM_RUNTIME = | 
|  | RuntimeSet.fromDexVmVersionSet(EnumSet.allOf(ToolHelper.DexVm.Version.class)); | 
|  | public static final RuntimeSet JAVA_RUNTIME = new RuntimeSet(EnumSet.of(Runtime.JAVA)); | 
|  | private static final CompilationModeSet ANY_MODE = | 
|  | new CompilationModeSet(EnumSet.allOf(CompilationMode.class)); | 
|  |  | 
|  | private final EnumSet<DexTool> dexTools; | 
|  | private final EnumSet<CompilerUnderTest> compilers; | 
|  | private final EnumSet<Runtime> runtimes; | 
|  | private final EnumSet<CompilationMode> compilationModes; | 
|  |  | 
|  | public TestCondition( | 
|  | EnumSet<DexTool> dexTools, | 
|  | EnumSet<CompilerUnderTest> compilers, | 
|  | EnumSet<Runtime> runtimes, | 
|  | EnumSet<CompilationMode> compilationModes) { | 
|  | this.dexTools = dexTools; | 
|  | this.compilers = compilers; | 
|  | this.runtimes = runtimes; | 
|  | this.compilationModes = compilationModes; | 
|  | } | 
|  |  | 
|  | public static ToolSet tools(DexTool... tools) { | 
|  | assert tools.length > 0; | 
|  | return new ToolSet(EnumSet.copyOf(Arrays.asList(tools))); | 
|  | } | 
|  |  | 
|  | public static CompilerSet compilers(CompilerUnderTest... compilers) { | 
|  | assert compilers.length > 0; | 
|  | return new CompilerSet(EnumSet.copyOf(Arrays.asList(compilers))); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet runtimes(DexVm.Version... runtimes) { | 
|  | assert runtimes.length > 0; | 
|  | return RuntimeSet.fromDexVmVersionSet(EnumSet.copyOf(Arrays.asList(runtimes))); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet runtimes(Runtime... runtimes) { | 
|  | assert runtimes.length > 0; | 
|  | return new RuntimeSet(EnumSet.copyOf(Arrays.asList(runtimes))); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet runtimesUpTo(DexVm.Version upto) { | 
|  | return RuntimeSet.fromDexVmVersionSet(EnumSet.range(DexVm.Version.first(), upto)); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet artRuntimesUpTo(Runtime upto) { | 
|  | assert Runtime.isArt(upto); | 
|  | return new RuntimeSet(EnumSet.range(Runtime.LOWEST_ART_VERSION, upto)); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet artRuntimesUpToAndJava(Runtime upto) { | 
|  | return runtimes( | 
|  | Sets.union(artRuntimesUpTo(upto).set, runtimes(Runtime.JAVA).set).toArray(new Runtime[0])); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet runtimesFrom(DexVm.Version start) { | 
|  | return RuntimeSet.fromDexVmVersionSet(EnumSet.range(start, DexVm.Version.last())); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet artRuntimesFrom(Runtime start) { | 
|  | assert Runtime.isArt(start); | 
|  | return new RuntimeSet(EnumSet.range(start, Runtime.HIGHEST_ART_VERSION)); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet artRuntimesFromAndJava(Runtime start) { | 
|  | return runtimes( | 
|  | Sets.union(artRuntimesFrom(start).set, runtimes(Runtime.JAVA).set).toArray(new Runtime[0])); | 
|  | } | 
|  |  | 
|  | public static RuntimeSet and(RuntimeSet... sets) { | 
|  | return new RuntimeSet( | 
|  | EnumSet.copyOf( | 
|  | Arrays.stream(sets) | 
|  | .flatMap(runtimeSet -> runtimeSet.set.stream()) | 
|  | .collect(Collectors.toSet()))); | 
|  | } | 
|  |  | 
|  | public static TestCondition or(TestCondition... conditions) { | 
|  | return new OrTestCondition(conditions); | 
|  | } | 
|  |  | 
|  | public static TestCondition match( | 
|  | ToolSet tools, | 
|  | CompilerSet compilers, | 
|  | RuntimeSet runtimes, | 
|  | CompilationModeSet compilationModes) { | 
|  | return new TestCondition(tools.set, compilers.set, runtimes.set, compilationModes.set); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(ToolSet tools, CompilerSet compilers, RuntimeSet runtimes) { | 
|  | return match(tools, compilers, runtimes, TestCondition.ANY_MODE); | 
|  | } | 
|  |  | 
|  | public static TestCondition any() { | 
|  | return match(TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, TestCondition.ANY_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition anyDexVm() { | 
|  | return match( | 
|  | TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, TestCondition.ANY_DEX_VM_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition cf() { | 
|  | return match(TestCondition.ANY_TOOL, R8CF, JAVA_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(ToolSet tools) { | 
|  | return match(tools, TestCondition.ANY_COMPILER, TestCondition.ANY_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(ToolSet tools, CompilerSet compilers) { | 
|  | return match(tools, compilers, TestCondition.ANY_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(ToolSet tools, RuntimeSet runtimes) { | 
|  | return match(tools, TestCondition.ANY_COMPILER, runtimes); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(CompilerSet compilers) { | 
|  | return match(TestCondition.ANY_TOOL, compilers, TestCondition.ANY_RUNTIME); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(CompilerSet compilers, CompilationModeSet compilationModes) { | 
|  | return match(TestCondition.ANY_TOOL, compilers, TestCondition.ANY_RUNTIME, compilationModes); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(CompilerSet compilers, RuntimeSet runtimes) { | 
|  | return match(TestCondition.ANY_TOOL, compilers, runtimes); | 
|  | } | 
|  |  | 
|  | public static TestCondition match(RuntimeSet runtimes) { | 
|  | return match(TestCondition.ANY_TOOL, TestCondition.ANY_COMPILER, runtimes); | 
|  | } | 
|  |  | 
|  | public boolean test( | 
|  | DexTool dexTool, | 
|  | CompilerUnderTest compilerUnderTest, | 
|  | Runtime runtime, | 
|  | CompilationMode compilationMode) { | 
|  | return dexTools.contains(dexTool) | 
|  | && compilers.contains(compilerUnderTest) | 
|  | && runtimes.contains(runtime) | 
|  | && compilationModes.contains(compilationMode); | 
|  | } | 
|  |  | 
|  | public boolean test( | 
|  | DexTool dexTool, | 
|  | CompilerUnderTest compilerUnderTest, | 
|  | DexVm.Version version, | 
|  | CompilationMode compilationMode) { | 
|  | return test(dexTool, compilerUnderTest, Runtime.fromDexVmVersion(version), compilationMode); | 
|  | } | 
|  |  | 
|  | public static class OrTestCondition extends TestCondition { | 
|  |  | 
|  | private final TestCondition[] conditions; | 
|  |  | 
|  | public OrTestCondition(TestCondition[] conditions) { | 
|  | super(null, null, null, null); | 
|  | this.conditions = conditions; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean test( | 
|  | DexTool dexTool, | 
|  | CompilerUnderTest compilerUnderTest, | 
|  | Runtime runtime, | 
|  | CompilationMode compilationMode) { | 
|  | for (TestCondition condition : conditions) { | 
|  | if (condition.test(dexTool, compilerUnderTest, runtime, compilationMode)) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean test( | 
|  | DexTool dexTool, | 
|  | CompilerUnderTest compilerUnderTest, | 
|  | DexVm.Version version, | 
|  | CompilationMode compilationMode) { | 
|  | for (TestCondition condition : conditions) { | 
|  | if (condition.test(dexTool, compilerUnderTest, version, compilationMode)) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  | } | 
|  | } |