Skip to content

Commit

Permalink
Make resetState run all ShadowProvider packages even if others fail f…
Browse files Browse the repository at this point in the history
…irst.

Previously, a failure in a ShadowProvider's reset would cause any other
packages to not be called. This collects the failing ones and allows the
passing ones to run. In the  future, we may want to completely exit the
test if we find a resetter has an exception thrown as it could cascade
into other tests.

PiperOrigin-RevId: 644075842
  • Loading branch information
JuliaSullivanGoogle authored and Copybara-Service committed Jun 17, 2024
1 parent ecbba37 commit eaea7aa
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.annotation.Nonnull;
import javax.inject.Named;
Expand Down Expand Up @@ -659,8 +661,22 @@ private boolean hasUnexecutedRunnables() {
@Override
public void resetState() {
Locale.setDefault(initialLocale);
List<Throwable> exceptions = new ArrayList<>();
for (ShadowProvider provider : shadowProviders) {
provider.reset();
try {
provider.reset();
} catch (Throwable e) {
exceptions.add(e);
}
}

if (!exceptions.isEmpty()) {
RuntimeException runtimeException =
new RuntimeException("Some resetters failed. See suppressed exceptions.");
for (Throwable e : exceptions) {
runtimeException.addSuppressed(e);
}
throw runtimeException;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static android.os.Build.VERSION_CODES.O;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import static org.robolectric.annotation.ConscryptMode.Mode.OFF;
import static org.robolectric.annotation.ConscryptMode.Mode.ON;
Expand All @@ -23,13 +24,16 @@
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.ApkLoader;
import org.robolectric.BootstrapDeferringRobolectricTestRunner;
import org.robolectric.BootstrapDeferringRobolectricTestRunner.BootstrapWrapperI;
import org.robolectric.BootstrapDeferringRobolectricTestRunner.RoboInject;
Expand All @@ -42,9 +46,13 @@
import org.robolectric.annotation.LooperMode;
import org.robolectric.annotation.experimental.LazyApplication;
import org.robolectric.annotation.experimental.LazyApplication.LazyLoad;
import org.robolectric.internal.ResourcesMode;
import org.robolectric.internal.ShadowProvider;
import org.robolectric.manifest.AndroidManifest;
import org.robolectric.manifest.RoboNotFoundException;
import org.robolectric.pluginapi.TestEnvironmentLifecyclePlugin;
import org.robolectric.plugins.HierarchicalConfigurationStrategy.ConfigurationImpl;
import org.robolectric.plugins.StubSdk;
import org.robolectric.res.ResourceTable;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
Expand Down Expand Up @@ -355,4 +363,63 @@ public void systemResources_getDisplayMetrics_correctValues() {
assertThat(applicationInfo.dataDir).isNotNull();
assertThat(new File(applicationInfo.dataDir).isDirectory()).isTrue();
}

@LazyApplication(LazyLoad.ON)
@Test
public void testResetterFails_reportsFailureAndContinues() {
WorkingShadowProvider workingShadowProvider = new WorkingShadowProvider();
ShadowProvider[] shadowProviders = new ShadowProvider[2];
shadowProviders[0] = new ThrowingShadowProvider();
shadowProviders[1] = workingShadowProvider;

TestEnvironmentLifecyclePlugin[] telpArray = new TestEnvironmentLifecyclePlugin[0];
AndroidTestEnvironment androidTestEnvironment =
new AndroidTestEnvironment(
new StubSdk(RuntimeEnvironment.getApiLevel(), true),
new StubSdk(RuntimeEnvironment.getApiLevel(), true),
ResourcesMode.BINARY,
new ApkLoader(),
shadowProviders,
telpArray);
RuntimeException e =
assertThrows(RuntimeException.class, () -> androidTestEnvironment.resetState());
assertThat(e.getSuppressed()[0]).hasMessageThat().contains("Reset failed");
assertThat(workingShadowProvider.wasReset).isTrue();
}

private static class ThrowingShadowProvider implements ShadowProvider {
@Override
public void reset() {
throw new RuntimeException("Reset failed");
}

@Override
public String[] getProvidedPackageNames() {
return null;
}

@Override
public Collection<Entry<String, String>> getShadows() {
return new ArrayList<>();
}
}

private static class WorkingShadowProvider implements ShadowProvider {
public boolean wasReset = false;

@Override
public void reset() {
wasReset = true;
}

@Override
public String[] getProvidedPackageNames() {
return null;
}

@Override
public Collection<Entry<String, String>> getShadows() {
return new ArrayList<>();
}
}
}

0 comments on commit eaea7aa

Please sign in to comment.