Loading tests/FlickerTests/AndroidManifest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Capture screen contents --> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <!-- Enable / Disable tracing !--> <uses-permission android:name="android.permission.DUMP" /> <!-- Run layers trace --> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <application> Loading tests/FlickerTests/AndroidTest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -25,5 +25,6 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="directory-keys" value="/sdcard/flicker" /> <option name="collect-on-run-ended-only" value="true" /> <option name="clean-up" value="false" /> </metrics_collector> </configuration> tests/FlickerTests/lib/Android.bpdeleted 100644 → 0 +0 −57 Original line number Diff line number Diff line // // Copyright (C) 2018 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // java_test { name: "flickerlib", platform_apis: true, srcs: ["src/**/*.java"], static_libs: [ "androidx.test.janktesthelper", "cts-wm-util", "platformprotosnano", "layersprotosnano", "truth-prebuilt", "sysui-helper", "launcher-helper-lib", ], } java_library { name: "flickerlib_without_helpers", platform_apis: true, srcs: ["src/**/*.java"], exclude_srcs: ["src/**/helpers/*.java"], static_libs: [ "cts-wm-util", "platformprotosnano", "layersprotosnano", "truth-prebuilt" ], } java_library { name: "flickerautomationhelperlib", sdk_version: "test_current", srcs: [ "src/com/android/server/wm/flicker/helpers/AutomationUtils.java", "src/com/android/server/wm/flicker/WindowUtils.java", ], static_libs: [ "sysui-helper", "launcher-helper-lib", "compatibility-device-util-axt", ], } tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.javadeleted 100644 → 0 +0 −134 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker; import java.util.concurrent.TimeUnit; import java.util.function.Function; /** * Collection of functional interfaces and classes representing assertions and their associated * results. Assertions are functions that are applied over a single trace entry and returns a * result which includes a detailed reason if the assertion fails. */ public class Assertions { /** * Checks assertion on a single trace entry. * * @param <T> trace entry type to perform the assertion on. */ @FunctionalInterface public interface TraceAssertion<T> extends Function<T, Result> { /** * Returns an assertion that represents the logical negation of this assertion. * * @return a assertion that represents the logical negation of this assertion */ default TraceAssertion<T> negate() { return (T t) -> apply(t).negate(); } } /** * Checks assertion on a single layers trace entry. */ @FunctionalInterface public interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> { } /** * Utility class to store assertions with an identifier to help generate more useful debug * data when dealing with multiple assertions. */ public static class NamedAssertion<T> { public final TraceAssertion<T> assertion; public final String name; public NamedAssertion(TraceAssertion<T> assertion, String name) { this.assertion = assertion; this.name = name; } } /** * Contains the result of an assertion including the reason for failed assertions. */ public static class Result { public static final String NEGATION_PREFIX = "!"; public final boolean success; public final long timestamp; public final String assertionName; public final String reason; public Result(boolean success, long timestamp, String assertionName, String reason) { this.success = success; this.timestamp = timestamp; this.assertionName = assertionName; this.reason = reason; } public Result(boolean success, String reason) { this.success = success; this.reason = reason; this.assertionName = ""; this.timestamp = 0; } /** * Returns the negated {@code Result} and adds a negation prefix to the assertion name. */ public Result negate() { String negatedAssertionName; if (this.assertionName.startsWith(NEGATION_PREFIX)) { negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1); } else { negatedAssertionName = NEGATION_PREFIX + this.assertionName; } return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason); } public boolean passed() { return this.success; } public boolean failed() { return !this.success; } @Override public String toString() { return "Timestamp: " + prettyTimestamp(timestamp) + "\nAssertion: " + assertionName + "\nReason: " + reason; } private String prettyTimestamp(long timestamp_ns) { StringBuilder prettyTimestamp = new StringBuilder(); TimeUnit[] timeUnits = {TimeUnit.HOURS, TimeUnit.MINUTES, TimeUnit.SECONDS, TimeUnit .MILLISECONDS}; String[] unitSuffixes = {"h", "m", "s", "ms"}; for (int i = 0; i < timeUnits.length; i++) { long convertedTime = timeUnits[i].convert(timestamp_ns, TimeUnit.NANOSECONDS); timestamp_ns -= TimeUnit.NANOSECONDS.convert(convertedTime, timeUnits[i]); prettyTimestamp.append(convertedTime).append(unitSuffixes[i]); } return prettyTimestamp.toString(); } } } tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.javadeleted 100644 → 0 +0 −183 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker; import com.android.server.wm.flicker.Assertions.NamedAssertion; import com.android.server.wm.flicker.Assertions.Result; import com.android.server.wm.flicker.Assertions.TraceAssertion; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; /** * Captures some of the common logic in {@link LayersTraceSubject} and {@link WmTraceSubject} * used to filter trace entries and combine multiple assertions. * * @param <T> trace entry type */ public class AssertionsChecker<T extends ITraceEntry> { private boolean mFilterEntriesByRange = false; private long mFilterStartTime = 0; private long mFilterEndTime = 0; private AssertionOption mOption = AssertionOption.NONE; private List<NamedAssertion<T>> mAssertions = new LinkedList<>(); public void add(Assertions.TraceAssertion<T> assertion, String name) { mAssertions.add(new NamedAssertion<>(assertion, name)); } public void filterByRange(long startTime, long endTime) { mFilterEntriesByRange = true; mFilterStartTime = startTime; mFilterEndTime = endTime; } private void setOption(AssertionOption option) { if (mOption != AssertionOption.NONE && option != mOption) { throw new IllegalArgumentException("Cannot use " + mOption + " option with " + option + " option."); } mOption = option; } public void checkFirstEntry() { setOption(AssertionOption.CHECK_FIRST_ENTRY); } public void checkLastEntry() { setOption(AssertionOption.CHECK_LAST_ENTRY); } public void checkChangingAssertions() { setOption(AssertionOption.CHECK_CHANGING_ASSERTIONS); } /** * Filters trace entries then runs assertions returning a list of failures. * * @param entries list of entries to perform assertions on * @return list of failed assertion results */ public List<Result> test(List<T> entries) { List<T> filteredEntries; List<Result> failures; if (mFilterEntriesByRange) { filteredEntries = entries.stream() .filter(e -> ((e.getTimestamp() >= mFilterStartTime) && (e.getTimestamp() <= mFilterEndTime))) .collect(Collectors.toList()); } else { filteredEntries = entries; } switch (mOption) { case CHECK_CHANGING_ASSERTIONS: return assertChanges(filteredEntries); case CHECK_FIRST_ENTRY: return assertEntry(filteredEntries.get(0)); case CHECK_LAST_ENTRY: return assertEntry(filteredEntries.get(filteredEntries.size() - 1)); } return assertAll(filteredEntries); } /** * Steps through each trace entry checking if provided assertions are true in the order they * are added. Each assertion must be true for at least a single trace entry. * * This can be used to check for asserting a change in property over a trace. Such as visibility * for a window changes from true to false or top-most window changes from A to Bb and back to A * again. */ private List<Result> assertChanges(List<T> entries) { List<Result> failures = new ArrayList<>(); int entryIndex = 0; int assertionIndex = 0; int lastPassedAssertionIndex = -1; if (mAssertions.size() == 0) { return failures; } while (assertionIndex < mAssertions.size() && entryIndex < entries.size()) { TraceAssertion<T> currentAssertion = mAssertions.get(assertionIndex).assertion; Result result = currentAssertion.apply(entries.get(entryIndex)); if (result.passed()) { lastPassedAssertionIndex = assertionIndex; entryIndex++; continue; } if (lastPassedAssertionIndex != assertionIndex) { failures.add(result); break; } assertionIndex++; if (assertionIndex == mAssertions.size()) { failures.add(result); break; } } if (failures.isEmpty()) { if (assertionIndex != mAssertions.size() - 1) { String reason = "\nAssertion " + mAssertions.get(assertionIndex).name + " never became false"; reason += "\nPassed assertions: " + mAssertions.stream().limit(assertionIndex) .map(assertion -> assertion.name).collect(Collectors.joining(",")); reason += "\nUntested assertions: " + mAssertions.stream().skip(assertionIndex + 1) .map(assertion -> assertion.name).collect(Collectors.joining(",")); Result result = new Result(false /* success */, 0 /* timestamp */, "assertChanges", "Not all assertions passed." + reason); failures.add(result); } } return failures; } private List<Result> assertEntry(T entry) { List<Result> failures = new ArrayList<>(); for (NamedAssertion<T> assertion : mAssertions) { Result result = assertion.assertion.apply(entry); if (result.failed()) { failures.add(result); } } return failures; } private List<Result> assertAll(List<T> entries) { return mAssertions.stream().flatMap( assertion -> entries.stream() .map(assertion.assertion) .filter(Result::failed)) .collect(Collectors.toList()); } private enum AssertionOption { NONE, CHECK_CHANGING_ASSERTIONS, CHECK_FIRST_ENTRY, CHECK_LAST_ENTRY, } } Loading
tests/FlickerTests/AndroidManifest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Capture screen contents --> <uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" /> <!-- Enable / Disable tracing !--> <uses-permission android:name="android.permission.DUMP" /> <!-- Run layers trace --> <uses-permission android:name="android.permission.HARDWARE_TEST"/> <application> Loading
tests/FlickerTests/AndroidTest.xml +1 −0 Original line number Diff line number Diff line Loading @@ -25,5 +25,6 @@ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> <option name="directory-keys" value="/sdcard/flicker" /> <option name="collect-on-run-ended-only" value="true" /> <option name="clean-up" value="false" /> </metrics_collector> </configuration>
tests/FlickerTests/lib/Android.bpdeleted 100644 → 0 +0 −57 Original line number Diff line number Diff line // // Copyright (C) 2018 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // java_test { name: "flickerlib", platform_apis: true, srcs: ["src/**/*.java"], static_libs: [ "androidx.test.janktesthelper", "cts-wm-util", "platformprotosnano", "layersprotosnano", "truth-prebuilt", "sysui-helper", "launcher-helper-lib", ], } java_library { name: "flickerlib_without_helpers", platform_apis: true, srcs: ["src/**/*.java"], exclude_srcs: ["src/**/helpers/*.java"], static_libs: [ "cts-wm-util", "platformprotosnano", "layersprotosnano", "truth-prebuilt" ], } java_library { name: "flickerautomationhelperlib", sdk_version: "test_current", srcs: [ "src/com/android/server/wm/flicker/helpers/AutomationUtils.java", "src/com/android/server/wm/flicker/WindowUtils.java", ], static_libs: [ "sysui-helper", "launcher-helper-lib", "compatibility-device-util-axt", ], }
tests/FlickerTests/lib/src/com/android/server/wm/flicker/Assertions.javadeleted 100644 → 0 +0 −134 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker; import java.util.concurrent.TimeUnit; import java.util.function.Function; /** * Collection of functional interfaces and classes representing assertions and their associated * results. Assertions are functions that are applied over a single trace entry and returns a * result which includes a detailed reason if the assertion fails. */ public class Assertions { /** * Checks assertion on a single trace entry. * * @param <T> trace entry type to perform the assertion on. */ @FunctionalInterface public interface TraceAssertion<T> extends Function<T, Result> { /** * Returns an assertion that represents the logical negation of this assertion. * * @return a assertion that represents the logical negation of this assertion */ default TraceAssertion<T> negate() { return (T t) -> apply(t).negate(); } } /** * Checks assertion on a single layers trace entry. */ @FunctionalInterface public interface LayersTraceAssertion extends TraceAssertion<LayersTrace.Entry> { } /** * Utility class to store assertions with an identifier to help generate more useful debug * data when dealing with multiple assertions. */ public static class NamedAssertion<T> { public final TraceAssertion<T> assertion; public final String name; public NamedAssertion(TraceAssertion<T> assertion, String name) { this.assertion = assertion; this.name = name; } } /** * Contains the result of an assertion including the reason for failed assertions. */ public static class Result { public static final String NEGATION_PREFIX = "!"; public final boolean success; public final long timestamp; public final String assertionName; public final String reason; public Result(boolean success, long timestamp, String assertionName, String reason) { this.success = success; this.timestamp = timestamp; this.assertionName = assertionName; this.reason = reason; } public Result(boolean success, String reason) { this.success = success; this.reason = reason; this.assertionName = ""; this.timestamp = 0; } /** * Returns the negated {@code Result} and adds a negation prefix to the assertion name. */ public Result negate() { String negatedAssertionName; if (this.assertionName.startsWith(NEGATION_PREFIX)) { negatedAssertionName = this.assertionName.substring(NEGATION_PREFIX.length() + 1); } else { negatedAssertionName = NEGATION_PREFIX + this.assertionName; } return new Result(!this.success, this.timestamp, negatedAssertionName, this.reason); } public boolean passed() { return this.success; } public boolean failed() { return !this.success; } @Override public String toString() { return "Timestamp: " + prettyTimestamp(timestamp) + "\nAssertion: " + assertionName + "\nReason: " + reason; } private String prettyTimestamp(long timestamp_ns) { StringBuilder prettyTimestamp = new StringBuilder(); TimeUnit[] timeUnits = {TimeUnit.HOURS, TimeUnit.MINUTES, TimeUnit.SECONDS, TimeUnit .MILLISECONDS}; String[] unitSuffixes = {"h", "m", "s", "ms"}; for (int i = 0; i < timeUnits.length; i++) { long convertedTime = timeUnits[i].convert(timestamp_ns, TimeUnit.NANOSECONDS); timestamp_ns -= TimeUnit.NANOSECONDS.convert(convertedTime, timeUnits[i]); prettyTimestamp.append(convertedTime).append(unitSuffixes[i]); } return prettyTimestamp.toString(); } } }
tests/FlickerTests/lib/src/com/android/server/wm/flicker/AssertionsChecker.javadeleted 100644 → 0 +0 −183 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm.flicker; import com.android.server.wm.flicker.Assertions.NamedAssertion; import com.android.server.wm.flicker.Assertions.Result; import com.android.server.wm.flicker.Assertions.TraceAssertion; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; /** * Captures some of the common logic in {@link LayersTraceSubject} and {@link WmTraceSubject} * used to filter trace entries and combine multiple assertions. * * @param <T> trace entry type */ public class AssertionsChecker<T extends ITraceEntry> { private boolean mFilterEntriesByRange = false; private long mFilterStartTime = 0; private long mFilterEndTime = 0; private AssertionOption mOption = AssertionOption.NONE; private List<NamedAssertion<T>> mAssertions = new LinkedList<>(); public void add(Assertions.TraceAssertion<T> assertion, String name) { mAssertions.add(new NamedAssertion<>(assertion, name)); } public void filterByRange(long startTime, long endTime) { mFilterEntriesByRange = true; mFilterStartTime = startTime; mFilterEndTime = endTime; } private void setOption(AssertionOption option) { if (mOption != AssertionOption.NONE && option != mOption) { throw new IllegalArgumentException("Cannot use " + mOption + " option with " + option + " option."); } mOption = option; } public void checkFirstEntry() { setOption(AssertionOption.CHECK_FIRST_ENTRY); } public void checkLastEntry() { setOption(AssertionOption.CHECK_LAST_ENTRY); } public void checkChangingAssertions() { setOption(AssertionOption.CHECK_CHANGING_ASSERTIONS); } /** * Filters trace entries then runs assertions returning a list of failures. * * @param entries list of entries to perform assertions on * @return list of failed assertion results */ public List<Result> test(List<T> entries) { List<T> filteredEntries; List<Result> failures; if (mFilterEntriesByRange) { filteredEntries = entries.stream() .filter(e -> ((e.getTimestamp() >= mFilterStartTime) && (e.getTimestamp() <= mFilterEndTime))) .collect(Collectors.toList()); } else { filteredEntries = entries; } switch (mOption) { case CHECK_CHANGING_ASSERTIONS: return assertChanges(filteredEntries); case CHECK_FIRST_ENTRY: return assertEntry(filteredEntries.get(0)); case CHECK_LAST_ENTRY: return assertEntry(filteredEntries.get(filteredEntries.size() - 1)); } return assertAll(filteredEntries); } /** * Steps through each trace entry checking if provided assertions are true in the order they * are added. Each assertion must be true for at least a single trace entry. * * This can be used to check for asserting a change in property over a trace. Such as visibility * for a window changes from true to false or top-most window changes from A to Bb and back to A * again. */ private List<Result> assertChanges(List<T> entries) { List<Result> failures = new ArrayList<>(); int entryIndex = 0; int assertionIndex = 0; int lastPassedAssertionIndex = -1; if (mAssertions.size() == 0) { return failures; } while (assertionIndex < mAssertions.size() && entryIndex < entries.size()) { TraceAssertion<T> currentAssertion = mAssertions.get(assertionIndex).assertion; Result result = currentAssertion.apply(entries.get(entryIndex)); if (result.passed()) { lastPassedAssertionIndex = assertionIndex; entryIndex++; continue; } if (lastPassedAssertionIndex != assertionIndex) { failures.add(result); break; } assertionIndex++; if (assertionIndex == mAssertions.size()) { failures.add(result); break; } } if (failures.isEmpty()) { if (assertionIndex != mAssertions.size() - 1) { String reason = "\nAssertion " + mAssertions.get(assertionIndex).name + " never became false"; reason += "\nPassed assertions: " + mAssertions.stream().limit(assertionIndex) .map(assertion -> assertion.name).collect(Collectors.joining(",")); reason += "\nUntested assertions: " + mAssertions.stream().skip(assertionIndex + 1) .map(assertion -> assertion.name).collect(Collectors.joining(",")); Result result = new Result(false /* success */, 0 /* timestamp */, "assertChanges", "Not all assertions passed." + reason); failures.add(result); } } return failures; } private List<Result> assertEntry(T entry) { List<Result> failures = new ArrayList<>(); for (NamedAssertion<T> assertion : mAssertions) { Result result = assertion.assertion.apply(entry); if (result.failed()) { failures.add(result); } } return failures; } private List<Result> assertAll(List<T> entries) { return mAssertions.stream().flatMap( assertion -> entries.stream() .map(assertion.assertion) .filter(Result::failed)) .collect(Collectors.toList()); } private enum AssertionOption { NONE, CHECK_CHANGING_ASSERTIONS, CHECK_FIRST_ENTRY, CHECK_LAST_ENTRY, } }