Adding some utility test rules

> LasyActivityRule to be used by ActivityScenario
> Utility rule to easily override feature flags

Bug: 284202543
Test: Presubmit
flag: N/A
Change-Id: I95ae19bfb1d67a55941e7b8e5c47516a351b0d24
This commit is contained in:
Sunny Goyal
2023-06-06 08:56:07 -07:00
parent b6a32d1340
commit 2cf183d14c
2 changed files with 166 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2023 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.launcher3.util.rule;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import androidx.annotation.Nullable;
import androidx.test.core.app.ActivityScenario;
import com.android.launcher3.Launcher;
import org.junit.rules.ExternalResource;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Similar to {@code ActivityScenarioRule} but it creates the activity lazily when needed
*/
public class LazyActivityRule<A extends Activity> extends ExternalResource {
private final Supplier<ActivityScenario<A>> mScenarioSupplier;
@Nullable private ActivityScenario<A> mScenario;
/**
* Constructs LazyActivityScenarioRule for a given scenario provider.
*/
public LazyActivityRule(Supplier<ActivityScenario<A>> supplier) {
mScenarioSupplier = supplier;
}
/**
* Resets the rule, such that the activity is in closed state
*/
public synchronized void reset() {
if (mScenario != null) {
try {
mScenario.close();
} catch (AssertionError e) {
// Ignore errors during close
}
}
mScenario = null;
}
@Override
protected synchronized void after() {
reset();
}
/**
* Returns the scenario, creating one if it doesn't exist
*/
public synchronized ActivityScenario<A> getScenario() {
if (mScenario == null) {
mScenario = mScenarioSupplier.get();
}
return mScenario;
}
/**
* Executes the function {@code f} on the activities main thread and returns the result
*/
public <T> T getFromActivity(Function<A, T> f) {
AtomicReference<T> result = new AtomicReference<>();
getScenario().onActivity(a -> result.set(f.apply(a)));
return result.get();
}
/**
* Runs the provided function {@code f} on the activity if the scenario is already created
*/
public synchronized void runOnActivity(Consumer<A> f) {
if (mScenario != null) {
mScenario.onActivity(f::accept);
}
}
/**
* Returns a {@link LazyActivityRule} for the Launcher activity
*/
public static <T extends Launcher> LazyActivityRule<T> forLauncher() {
Context context = getInstrumentation().getTargetContext();
// Create the activity after the model setup is done.
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK
| FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | FLAG_ACTIVITY_NO_ANIMATION);
ResolveInfo ri = context.getPackageManager().resolveActivity(
new Intent(homeIntent).setPackage(context.getPackageName()), 0);
homeIntent.setComponent(ri.getComponentInfo().getComponentName());
return new LazyActivityRule<>(() -> ActivityScenario.launch(homeIntent));
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 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.launcher3.util.rule
import com.android.launcher3.config.FeatureFlags.BooleanFlag
import com.android.launcher3.config.FeatureFlags.IntFlag
import com.android.launcher3.util.SafeCloseable
import com.android.launcher3.util.TestUtil
import java.util.function.Supplier
import org.junit.rules.ExternalResource
/** Simple rule which wraps any SafeCloseable object */
class WrapperRule(private val overrideProvider: Supplier<SafeCloseable>) : ExternalResource() {
private lateinit var overrideClosable: SafeCloseable
override fun before() {
overrideClosable = overrideProvider.get()
}
override fun after() {
overrideClosable.close()
}
companion object {
fun BooleanFlag.overrideFlag(value: Boolean) = WrapperRule {
TestUtil.overrideFlag(this, value)
}
fun IntFlag.overrideFlag(value: Int) = WrapperRule { TestUtil.overrideFlag(this, value) }
}
}