| // Copyright (c) 2020, 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 com.android.tools.r8.utils.ConsumerUtils.emptyThrowingConsumer; |
| import static org.hamcrest.CoreMatchers.containsString; |
| import static org.hamcrest.CoreMatchers.is; |
| |
| import com.android.tools.r8.utils.StringUtils; |
| import com.android.tools.r8.utils.ThrowingConsumer; |
| import com.android.tools.r8.utils.codeinspector.CodeInspector; |
| import java.io.IOException; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.concurrent.ExecutionException; |
| import java.util.function.Function; |
| import org.hamcrest.Matcher; |
| |
| /** |
| * Abstract base for checking the result of executing (test) program(s). |
| * |
| * <p>All methods defined on this base must generalize to allow checking of multiple run results |
| * simultaneously. For methods on single runs see the SingleTestRunResult subclass. |
| */ |
| public abstract class TestRunResult<RR extends TestRunResult<RR>> { |
| |
| abstract RR self(); |
| |
| public abstract RR assertSuccess(); |
| |
| public abstract RR assertStdoutMatches(Matcher<String> matcher); |
| |
| public abstract RR assertFailure(); |
| |
| public abstract RR assertStderrMatches(Matcher<String> matcher); |
| |
| public abstract <E extends Throwable> RR inspect(ThrowingConsumer<CodeInspector, E> consumer) |
| throws IOException, ExecutionException, E; |
| |
| public abstract <E extends Throwable> RR inspectFailure( |
| ThrowingConsumer<CodeInspector, E> consumer) throws IOException, E; |
| |
| public abstract RR disassemble() throws IOException, ExecutionException; |
| |
| public <E extends Throwable> RR apply(ThrowingConsumer<RR, E> fn) throws E { |
| fn.accept(self()); |
| return self(); |
| } |
| |
| public <T extends Throwable> RR applyIf(boolean condition, ThrowingConsumer<RR, T> thenConsumer) |
| throws T { |
| return applyIf(condition, thenConsumer, emptyThrowingConsumer()); |
| } |
| |
| public <S extends Throwable, T extends Throwable> RR applyIf( |
| boolean condition, ThrowingConsumer<RR, S> thenConsumer, ThrowingConsumer<RR, T> elseConsumer) |
| throws S, T { |
| return applyIf( |
| condition, |
| thenConsumer, |
| true, |
| elseConsumer, |
| r -> { |
| assert false; |
| }); |
| } |
| |
| public <S extends Throwable, T extends Throwable, U extends Throwable> RR applyIf( |
| boolean condition1, |
| ThrowingConsumer<RR, S> thenConsumer1, |
| boolean condition2, |
| ThrowingConsumer<RR, T> thenConsumer2, |
| ThrowingConsumer<RR, U> elseConsumer) |
| throws S, T, U { |
| return applyIf( |
| condition1, |
| thenConsumer1, |
| condition2, |
| thenConsumer2, |
| true, |
| elseConsumer, |
| r -> { |
| assert false; |
| }); |
| } |
| |
| public <S extends Throwable, T extends Throwable, U extends Throwable, V extends Throwable> |
| RR applyIf( |
| boolean condition1, |
| ThrowingConsumer<RR, S> thenConsumer1, |
| boolean condition2, |
| ThrowingConsumer<RR, T> thenConsumer2, |
| boolean condition3, |
| ThrowingConsumer<RR, U> thenConsumer3, |
| ThrowingConsumer<RR, V> elseConsumer) |
| throws S, T, U, V { |
| if (condition1) { |
| thenConsumer1.accept(self()); |
| } else if (condition2) { |
| thenConsumer2.accept(self()); |
| } else if (condition3) { |
| thenConsumer3.accept(self()); |
| } else { |
| elseConsumer.accept(self()); |
| } |
| return self(); |
| } |
| |
| public <S> S map(Function<RR, S> fn) { |
| return fn.apply(self()); |
| } |
| |
| public RR assertSuccessWithOutputThatMatches(Matcher<String> matcher) { |
| assertStdoutMatches(matcher); |
| return assertSuccess(); |
| } |
| |
| public RR assertSuccessWithOutput(String expected) { |
| return assertSuccessWithOutputThatMatches(is(expected)); |
| } |
| |
| public RR assertSuccessWithOutputIf(boolean condition, String expected) { |
| if (condition) { |
| return assertSuccessWithOutput(expected); |
| } |
| return self(); |
| } |
| |
| public RR assertSuccessWithEmptyOutput() { |
| return assertSuccessWithOutput(""); |
| } |
| |
| public RR assertSuccessWithOutputLines(String... expected) { |
| return assertSuccessWithOutputLines(Arrays.asList(expected)); |
| } |
| |
| public RR assertSuccessWithOutputLinesIf(boolean condition, String... expected) { |
| return assertSuccessWithOutputLinesIf(condition, Arrays.asList(expected)); |
| } |
| |
| public RR assertSuccessWithOutputLinesIf(boolean condition, List<String> expected) { |
| if (condition) { |
| return assertSuccessWithOutputLines(expected); |
| } |
| return self(); |
| } |
| |
| public RR assertSuccessWithOutputLines(List<String> expected) { |
| return assertSuccessWithOutput(StringUtils.lines(expected)); |
| } |
| |
| public RR assertFailureWithErrorThatMatches(Matcher<String> matcher) { |
| assertStderrMatches(matcher); |
| return assertFailure(); |
| } |
| |
| public RR assertFailureWithErrorThatMatchesIf(boolean condition, Matcher<String> matcher) { |
| if (condition) { |
| assertStderrMatches(matcher); |
| return assertFailure(); |
| } |
| return self(); |
| } |
| |
| public RR assertFailureWithOutput(String expected) { |
| assertStdoutMatches(is(expected)); |
| return assertFailure(); |
| } |
| |
| public RR assertFailureWithErrorThatThrows(Class<? extends Throwable> expectedError) { |
| return assertFailureWithErrorThatMatches(containsString(expectedError.getName())); |
| } |
| |
| public RR assertFailureWithErrorThatThrowsIf( |
| boolean condition, Class<? extends Throwable> expectedError) { |
| if (condition) { |
| return assertFailureWithErrorThatThrows(expectedError); |
| } |
| return self(); |
| } |
| } |