aboutsummaryrefslogtreecommitdiff
path: root/robolectric/src/test/java/org/robolectric/shadows
diff options
context:
space:
mode:
Diffstat (limited to 'robolectric/src/test/java/org/robolectric/shadows')
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/AudioDeviceInfoBuilderTest.java25
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowClipboardManagerTest.java22
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowConnectivityManagerTest.java40
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowContentResolverTest.java7
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowGeocoderTest.java25
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowHardwareBufferTest.java3
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowLegacyLooperTest.java4
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowLinuxTest.java61
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowLocationManagerTest.java131
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowLooperResetterTest.java191
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowNfcAdapterTest.java3
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java80
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowSpeechRecognizerTest.java12
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowTelephonyManagerTest.java28
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowViewGroupTest.java83
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java33
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/SharedLibraryInfoBuilderTest.java49
17 files changed, 765 insertions, 32 deletions
diff --git a/robolectric/src/test/java/org/robolectric/shadows/AudioDeviceInfoBuilderTest.java b/robolectric/src/test/java/org/robolectric/shadows/AudioDeviceInfoBuilderTest.java
new file mode 100644
index 000000000..e1961877a
--- /dev/null
+++ b/robolectric/src/test/java/org/robolectric/shadows/AudioDeviceInfoBuilderTest.java
@@ -0,0 +1,25 @@
+package org.robolectric.shadows;
+
+import static android.media.AudioDeviceInfo.TYPE_BLUETOOTH_A2DP;
+import static android.os.Build.VERSION_CODES.M;
+import static com.google.common.truth.Truth.assertThat;
+
+import android.media.AudioDeviceInfo;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+/** Tests for {@link AudioDeviceInfoBuilder}. */
+@RunWith(AndroidJUnit4.class)
+@Config(minSdk = M)
+public class AudioDeviceInfoBuilderTest {
+
+ @Test
+ public void canCreateAudioDeviceInfoWithDesiredType() {
+ AudioDeviceInfo audioDeviceInfo =
+ AudioDeviceInfoBuilder.newBuilder().setType(TYPE_BLUETOOTH_A2DP).build();
+
+ assertThat(audioDeviceInfo.getType()).isEqualTo(TYPE_BLUETOOTH_A2DP);
+ }
+}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowClipboardManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowClipboardManagerTest.java
index 10f1fdb92..e718ab2fb 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowClipboardManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowClipboardManagerTest.java
@@ -1,6 +1,7 @@
package org.robolectric.shadows;
import static android.content.ClipboardManager.OnPrimaryClipChangedListener;
+import static android.os.Build.VERSION_CODES.P;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -14,6 +15,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
@RunWith(AndroidJUnit4.class)
public class ShadowClipboardManagerTest {
@@ -104,4 +106,24 @@ public class ShadowClipboardManagerTest {
clipboardManager.setPrimaryClip(ClipData.newPlainText(null, "BLARG?"));
verifyNoMoreInteractions(listener);
}
+
+ @Test
+ @Config(minSdk = P)
+ public void shouldClearPrimaryClip() {
+ clipboardManager.setPrimaryClip(ClipData.newPlainText(null, "BLARG?"));
+ clipboardManager.clearPrimaryClip();
+
+ assertThat(clipboardManager.hasText()).isFalse();
+ assertThat(clipboardManager.hasPrimaryClip()).isFalse();
+ }
+
+ @Test
+ @Config(minSdk = P)
+ public void shouldClearPrimaryClipAndFireListeners() {
+ OnPrimaryClipChangedListener listener = mock(OnPrimaryClipChangedListener.class);
+ clipboardManager.addPrimaryClipChangedListener(listener);
+ clipboardManager.clearPrimaryClip();
+
+ verify(listener).onPrimaryClipChanged();
+ }
}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowConnectivityManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowConnectivityManagerTest.java
index dd8da17b1..b224e4dfb 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowConnectivityManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowConnectivityManagerTest.java
@@ -10,12 +10,15 @@ import static android.os.Build.VERSION_CODES.N;
import static android.os.Build.VERSION_CODES.O;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
+import android.app.PendingIntent;
import android.content.Context;
+import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.LinkProperties;
import android.net.Network;
@@ -321,6 +324,10 @@ public class ShadowConnectivityManagerTest {
};
}
+ private static PendingIntent createSimplePendingIntent() {
+ return PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0);
+ }
+
@Test
@Config(minSdk = LOLLIPOP)
public void requestNetwork_shouldAddCallback() throws Exception {
@@ -339,6 +346,15 @@ public class ShadowConnectivityManagerTest {
}
@Test
+ @Config(minSdk = M)
+ public void registerCallback_withPendingIntent_shouldAddCallback() throws Exception {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ PendingIntent pendingIntent = createSimplePendingIntent();
+ connectivityManager.registerNetworkCallback(builder.build(), pendingIntent);
+ assertThat(shadowOf(connectivityManager).getNetworkCallbackPendingIntents()).hasSize(1);
+ }
+
+ @Test
@Config(minSdk = O)
public void requestNetwork_withTimeout_shouldAddCallback() throws Exception {
NetworkRequest.Builder builder = new NetworkRequest.Builder();
@@ -389,6 +405,21 @@ public class ShadowConnectivityManagerTest {
assertThat(shadowOf(connectivityManager).getNetworkCallbacks()).isEmpty();
}
+ @Test
+ @Config(minSdk = M)
+ public void unregisterCallback_withPendingIntent_shouldRemoveCallbacks() throws Exception {
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ // Add two pendingIntents, should treat them as equal based on Intent#filterEquals
+ PendingIntent pendingIntent1 = createSimplePendingIntent();
+ PendingIntent pendingIntent2 = createSimplePendingIntent();
+ connectivityManager.registerNetworkCallback(builder.build(), pendingIntent1);
+ connectivityManager.registerNetworkCallback(builder.build(), pendingIntent2);
+
+ assertThat(shadowOf(connectivityManager).getNetworkCallbackPendingIntents()).hasSize(1);
+ connectivityManager.unregisterNetworkCallback(pendingIntent2);
+ assertThat(shadowOf(connectivityManager).getNetworkCallbackPendingIntents()).isEmpty();
+ }
+
@Test(expected=IllegalArgumentException.class) @Config(minSdk = LOLLIPOP)
public void unregisterCallback_shouldNotAllowNullCallback() throws Exception {
// Verify that exception is thrown.
@@ -396,6 +427,15 @@ public class ShadowConnectivityManagerTest {
}
@Test
+ @Config(minSdk = M)
+ public void unregisterCallback_withPendingIntent_shouldNotAllowNullCallback() throws Exception {
+ // Verify that exception is thrown.
+ assertThrows(
+ IllegalArgumentException.class,
+ () -> connectivityManager.unregisterNetworkCallback((PendingIntent) null));
+ }
+
+ @Test
public void isActiveNetworkMetered_defaultsToTrue() {
assertThat(connectivityManager.isActiveNetworkMetered()).isTrue();
}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowContentResolverTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowContentResolverTest.java
index c77bb1e14..2c9452c96 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowContentResolverTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowContentResolverTest.java
@@ -1025,7 +1025,12 @@ public class ShadowContentResolverTest {
// unfortunately, there is no direct way of testing if authority is set or not
// however, it's checked in ContentProvider.Transport method calls (validateIncomingUri), so
// it's the closest we can test against
- provider.getIContentProvider().getType(uri); // should not throw
+ if (RuntimeEnvironment.getApiLevel() <= 28) {
+ provider.getIContentProvider().getType(uri); // should not throw
+ } else {
+ // just call validateIncomingUri directly
+ provider.validateIncomingUri(uri);
+ }
}
@Test
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowGeocoderTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowGeocoderTest.java
index d925a61d9..10cddde02 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowGeocoderTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowGeocoderTest.java
@@ -1,5 +1,6 @@
package org.robolectric.shadows;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.robolectric.Shadows.shadowOf;
@@ -7,6 +8,7 @@ import static org.robolectric.Shadows.shadowOf;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
+import android.location.Geocoder.GeocodeListener;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.IOException;
@@ -16,12 +18,14 @@ import java.util.Locale;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
/** Unit test for {@link ShadowGeocoder}. */
@RunWith(AndroidJUnit4.class)
public class ShadowGeocoderTest {
private Geocoder geocoder;
+ private List<Address> decodedAddresses;
@Before
public void setUp() throws Exception {
@@ -64,6 +68,27 @@ public class ShadowGeocoderTest {
}
@Test
+ @Config(minSdk = TIRAMISU)
+ public void getFromLocationSetsListenerWithTheOverwrittenListLimitingByMaxResults() {
+ ShadowGeocoder shadowGeocoder = shadowOf(geocoder);
+
+ List<Address> list =
+ Arrays.asList(new Address(Locale.getDefault()), new Address(Locale.CANADA));
+ shadowGeocoder.setFromLocation(list);
+
+ GeocodeListener geocodeListener = addresses -> decodedAddresses = addresses;
+
+ geocoder.getFromLocation(90.0, 90.0, 1, geocodeListener);
+ assertThat(decodedAddresses).containsExactly(list.get(0));
+
+ geocoder.getFromLocation(90.0, 90.0, 2, geocodeListener);
+ assertThat(decodedAddresses).containsExactly(list.get(0), list.get(1)).inOrder();
+
+ geocoder.getFromLocation(90.0, 90.0, 3, geocodeListener);
+ assertThat(decodedAddresses).containsExactly(list.get(0), list.get(1)).inOrder();
+ }
+
+ @Test
public void getFromLocation_throwsExceptionForInvalidLatitude() throws IOException {
try {
geocoder.getFromLocation(91.0, 90.0, 1);
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowHardwareBufferTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowHardwareBufferTest.java
index 35d16b692..fcede3f4e 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowHardwareBufferTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowHardwareBufferTest.java
@@ -2,6 +2,7 @@ package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Build.VERSION_CODES.P;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -86,7 +87,7 @@ public class ShadowHardwareBufferTest {
}
@Test
- @Config(minSdk = O)
+ @Config(minSdk = O, maxSdk = TIRAMISU /* framework no longer validates format in > T */)
public void createInvalidFormatThrows() {
try {
HardwareBuffer.create(
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowLegacyLooperTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowLegacyLooperTest.java
index eda3b1381..88fd2578e 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowLegacyLooperTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowLegacyLooperTest.java
@@ -267,7 +267,7 @@ public class ShadowLegacyLooperTest {
}
@Test
- public void resetThreadLoopers_fromNonMainThread_shouldThrowISE() throws InterruptedException {
+ public void resetThreadLoopers_fromNonMainThread_doesNotThrow() throws InterruptedException {
final AtomicReference<Throwable> ex = new AtomicReference<>();
Thread t =
new Thread() {
@@ -282,7 +282,7 @@ public class ShadowLegacyLooperTest {
};
t.start();
t.join();
- assertThat(ex.get()).isInstanceOf(IllegalStateException.class);
+ assertThat(ex.get()).isNull();
}
@Test
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowLinuxTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowLinuxTest.java
index bea5e63f5..366daf956 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowLinuxTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowLinuxTest.java
@@ -2,21 +2,29 @@ package org.robolectric.shadows;
import static android.os.Build.VERSION_CODES.O;
import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
import android.system.StructStat;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.time.Duration;
+import java.util.Arrays;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
-/** Unit tests for ShadowLinux to check values returned from stat() call. */
+/** Unit tests for {@code ShadowLinux}. */
@RunWith(AndroidJUnit4.class)
@Config(minSdk = O)
public final class ShadowLinuxTest {
+ @Rule public TemporaryFolder tempFolder = new TemporaryFolder();
+
private File file;
private String path;
private ShadowLinux shadowLinux;
@@ -24,10 +32,10 @@ public final class ShadowLinuxTest {
@Before
public void setUp() throws Exception {
shadowLinux = new ShadowLinux();
- file = File.createTempFile("ShadowLinuxTest", null);
+ file = tempFolder.newFile("ShadowLinuxTest");
path = file.getAbsolutePath();
try (FileOutputStream outputStream = new FileOutputStream(file)) {
- outputStream.write(1234);
+ outputStream.write("some UTF-8\u202Fcontent in a file".getBytes(UTF_8));
}
}
@@ -48,4 +56,51 @@ public final class ShadowLinuxTest {
StructStat stat = shadowLinux.stat(path);
assertThat(stat.st_mtime).isEqualTo(Duration.ofMillis(file.lastModified()).getSeconds());
}
+
+ @Test
+ public void pread_validateExtractsContentWithOffset() throws Exception {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ FileDescriptor fd = fis.getFD();
+ assertThat(fd.valid()).isTrue();
+
+ final int bytesCount = "content".length();
+ final int bytesOffset = 5;
+ final byte[] buffer = new byte[bytesCount + 2 * bytesOffset];
+ Arrays.fill(buffer, (byte) '-');
+
+ final int offsetInFile = "some UTF-8\u202F".getBytes(UTF_8).length;
+
+ assertThat(shadowLinux.pread(fd, buffer, bytesOffset, bytesCount, offsetInFile))
+ .isEqualTo(bytesCount);
+ assertThat(new String(buffer, UTF_8)).isEqualTo("-----content-----");
+ }
+ }
+
+ @Test
+ public void pread_handleFNF() throws Exception {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ FileDescriptor fd = fis.getFD();
+ assertThat(fd.valid()).isTrue();
+
+ // Delete the file under test.
+ fis.close();
+ assertThat(file.delete()).isTrue();
+
+ final byte[] buffer = new byte[10];
+ Arrays.fill(buffer, (byte) '-');
+ assertThat(shadowLinux.pread(fd, buffer, 0, 5, 0)).isEqualTo(-1);
+ }
+ }
+
+ @Test
+ public void pread_readPastEnd() throws Exception {
+ try (FileInputStream fis = new FileInputStream(file)) {
+ FileDescriptor fd = fis.getFD();
+ assertThat(fd.valid()).isTrue();
+
+ final byte[] buffer = new byte[10];
+ Arrays.fill(buffer, (byte) '-');
+ assertThat(shadowLinux.pread(fd, buffer, 0, 5, 500)).isEqualTo(-1);
+ }
+ }
}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowLocationManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowLocationManagerTest.java
index 5f46bbae6..5add1c81c 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowLocationManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowLocationManagerTest.java
@@ -28,6 +28,8 @@ import android.content.IntentFilter;
import android.location.Criteria;
import android.location.GnssAntennaInfo;
import android.location.GnssAntennaInfo.PhaseCenterOffset;
+import android.location.GnssMeasurementRequest;
+import android.location.GnssMeasurementsEvent;
import android.location.GnssStatus;
import android.location.GpsStatus;
import android.location.Location;
@@ -1161,6 +1163,65 @@ public class ShadowLocationManagerTest {
.inOrder();
}
+ @Config(minSdk = VERSION_CODES.S)
+ @Test
+ public void testRequestFlush_listener() {
+ TestLocationListener listener = new TestLocationListener();
+
+ try {
+ locationManager.requestFlush(GPS_PROVIDER, listener, 0);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(listener.flushes).isEmpty();
+ }
+
+ locationManager.requestLocationUpdates(GPS_PROVIDER, 0, 0, listener);
+ locationManager.requestFlush(GPS_PROVIDER, listener, 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertThat(listener.flushes).containsExactly(1);
+ }
+
+ @Config(minSdk = VERSION_CODES.S)
+ @Test
+ public void testRequestFlush_pendingIntent() {
+ TestLocationReceiver listener = new TestLocationReceiver(context);
+
+ try {
+ locationManager.requestFlush(GPS_PROVIDER, listener.pendingIntent, 0);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(listener.flushes).isEmpty();
+ }
+
+ locationManager.requestLocationUpdates(GPS_PROVIDER, 0, 0, listener.pendingIntent);
+ locationManager.requestFlush(GPS_PROVIDER, listener.pendingIntent, 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertThat(listener.flushes).containsExactly(1);
+ }
+
+ @Config(minSdk = VERSION_CODES.S)
+ @Test
+ public void testRequestFlush_pendingIntent_canceled() {
+ TestLocationReceiver listener = new TestLocationReceiver(context);
+
+ try {
+ locationManager.requestFlush(GPS_PROVIDER, listener.pendingIntent, 0);
+ fail();
+ } catch (IllegalArgumentException e) {
+ assertThat(listener.flushes).isEmpty();
+ }
+
+ locationManager.requestLocationUpdates(GPS_PROVIDER, 0, 0, listener.pendingIntent);
+ listener.pendingIntent.cancel();
+ locationManager.requestFlush(GPS_PROVIDER, listener.pendingIntent, 1);
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertThat(shadowLocationManager.getLocationRequests(GPS_PROVIDER)).isEmpty();
+ assertThat(listener.flushes).isEmpty();
+ }
+
@Test
public void testSimulateLocation_FastestInterval() {
Location loc1 = createLocation(MY_PROVIDER);
@@ -1206,6 +1267,26 @@ public class ShadowLocationManagerTest {
}
@Test
+ public void testSimulateLocation_Batch() {
+ Location loc1 = createLocation(MY_PROVIDER);
+ Location loc2 = createLocation(MY_PROVIDER);
+
+ TestLocationListener myListener = new TestLocationListener();
+
+ locationManager.requestLocationUpdates(MY_PROVIDER, 0, 0, myListener);
+ shadowLocationManager.simulateLocation(MY_PROVIDER, loc1, loc2);
+ locationManager.removeUpdates(myListener);
+
+ shadowOf(Looper.getMainLooper()).idle();
+
+ assertThat(myListener.locations)
+ .comparingElementsUsing(equality())
+ .containsExactly(loc1, loc2)
+ .inOrder();
+ assertThat(locationManager.getLastKnownLocation(MY_PROVIDER)).isEqualTo(loc2);
+ }
+
+ @Test
public void testLocationUpdates_NullListener() {
try {
locationManager.requestSingleUpdate(GPS_PROVIDER, null, null);
@@ -1330,6 +1411,14 @@ public class ShadowLocationManagerTest {
}
@Test
+ @Config(minSdk = VERSION_CODES.O)
+ public void testGetGnssBatchSize() {
+ assertThat(locationManager.getGnssBatchSize()).isEqualTo(0);
+ shadowLocationManager.setGnssBatchSize(5);
+ assertThat(locationManager.getGnssBatchSize()).isEqualTo(5);
+ }
+
+ @Test
@Config(minSdk = VERSION_CODES.P)
public void testGetGnssHardwareModelName() {
assertThat(locationManager.getGnssHardwareModelName()).isNull();
@@ -1442,6 +1531,38 @@ public class ShadowLocationManagerTest {
}
@Test
+ @Config(minSdk = VERSION_CODES.TIRAMISU)
+ public void testGnssMeasurementsCallback() {
+ GnssMeasurementsEvent.Callback listener1 = mock(GnssMeasurementsEvent.Callback.class);
+ GnssMeasurementsEvent.Callback listener2 = mock(GnssMeasurementsEvent.Callback.class);
+ InOrder inOrder1 = Mockito.inOrder(listener1);
+ InOrder inOrder2 = Mockito.inOrder(listener2);
+
+ GnssMeasurementsEvent events1 = new GnssMeasurementsEvent.Builder().build();
+ GnssMeasurementsEvent events2 = new GnssMeasurementsEvent.Builder().build();
+
+ locationManager.registerGnssMeasurementsCallback(Runnable::run, listener1);
+ locationManager.registerGnssMeasurementsCallback(
+ new GnssMeasurementRequest.Builder().build(), Runnable::run, listener2);
+
+ shadowLocationManager.simulateGnssMeasurementsEvent(events1);
+ inOrder1.verify(listener1).onGnssMeasurementsReceived(events1);
+ inOrder2.verify(listener2).onGnssMeasurementsReceived(events1);
+
+ locationManager.unregisterGnssMeasurementsCallback(listener2);
+
+ shadowLocationManager.simulateGnssMeasurementsEvent(events2);
+ inOrder1.verify(listener1).onGnssMeasurementsReceived(events2);
+ inOrder2.verify(listener2, never()).onGnssMeasurementsReceived(events2);
+
+ locationManager.unregisterGnssMeasurementsCallback(listener1);
+
+ shadowLocationManager.simulateGnssMeasurementsEvent(events1);
+ inOrder1.verify(listener1, never()).onGnssMeasurementsReceived(events1);
+ inOrder2.verify(listener2, never()).onGnssMeasurementsReceived(events1);
+ }
+
+ @Test
@Config(minSdk = VERSION_CODES.R)
public void testGnssAntennaInfoListener() {
GnssAntennaInfo.Listener listener1 = mock(GnssAntennaInfo.Listener.class);
@@ -1606,6 +1727,7 @@ public class ShadowLocationManagerTest {
private final PendingIntent pendingIntent;
private final ArrayList<Boolean> providerEnableds = new ArrayList<>();
private final ArrayList<Location> locations = new ArrayList<>();
+ private final ArrayList<Integer> flushes = new ArrayList<>();
private TestLocationReceiver(Context context) {
Intent intent = new Intent(Integer.toString(random.nextInt()));
@@ -1621,6 +1743,9 @@ public class ShadowLocationManagerTest {
if (intent.hasExtra(LocationManager.KEY_PROVIDER_ENABLED)) {
providerEnableds.add(intent.getBooleanExtra(LocationManager.KEY_PROVIDER_ENABLED, false));
}
+ if (intent.hasExtra(LocationManager.KEY_FLUSH_COMPLETE)) {
+ flushes.add(intent.getIntExtra(LocationManager.KEY_FLUSH_COMPLETE, -1));
+ }
}
}
@@ -1636,6 +1761,7 @@ public class ShadowLocationManagerTest {
private static class TestLocationListener implements LocationListener {
final ArrayList<Boolean> providerEnableds = new ArrayList<>();
final ArrayList<Location> locations = new ArrayList<>();
+ final ArrayList<Integer> flushes = new ArrayList<>();
@Override
public void onLocationChanged(Location location) {
@@ -1655,6 +1781,11 @@ public class ShadowLocationManagerTest {
public void onProviderDisabled(String s) {
providerEnableds.add(false);
}
+
+ @Override
+ public void onFlushComplete(int requestCode) {
+ flushes.add(requestCode);
+ }
}
private static class TestLocationListenerSelfRemoval extends TestLocationListener {
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowLooperResetterTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowLooperResetterTest.java
new file mode 100644
index 000000000..92e1643c5
--- /dev/null
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowLooperResetterTest.java
@@ -0,0 +1,191 @@
+package org.robolectric.shadows;
+
+import static android.os.Looper.getMainLooper;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.truth.Truth.assertThat;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import java.time.Duration;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.JUnit4;
+import org.junit.runners.model.InitializationError;
+import org.robolectric.RobolectricTestRunner;
+
+/** A specialized test for verifying that looper state is cleared properly between tests. */
+@RunWith(JUnit4.class)
+public class ShadowLooperResetterTest {
+ private final RunNotifier runNotifier = new RunNotifier();
+
+ @Before
+ public void setup() {
+ runNotifier.addListener(
+ new RunListener() {
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ throw new AssertionError("Unexpected test failure: " + failure, failure.getException());
+ }
+ });
+ }
+
+ /**
+ * Basic test class that interacts with Looper in two different tests, to ensure Looper remains
+ * functional after reset.
+ */
+ public static class BasicLooperTest {
+
+ private void doPostToLooperTest() {
+ checkNotNull(getMainLooper());
+
+ AtomicBoolean didRun = new AtomicBoolean(false);
+ new Handler(getMainLooper()).post(() -> didRun.set(true));
+
+ assertThat(didRun.get()).isFalse();
+ shadowOf(getMainLooper()).idle();
+ assertThat(didRun.get()).isTrue();
+ }
+
+ @Test
+ public void postToLooperTest() {
+ doPostToLooperTest();
+ }
+
+ @Test
+ public void anotherPostToLooperTest() {
+ doPostToLooperTest();
+ }
+ }
+
+ @Test
+ public void basicPostAndRun() throws InitializationError {
+ Runner runner = new RobolectricTestRunner(BasicLooperTest.class);
+
+ // run and assert no failures
+ runner.run(runNotifier);
+ }
+
+ /** Test that leaves an unexecuted runnable on Looper and verifies it is removed between tests. */
+ public static class PendingLooperTest {
+
+ private void doPostToLooperTest() {
+ checkState(shadowOf(getMainLooper()).isIdle());
+
+ AtomicBoolean didRun = new AtomicBoolean(false);
+ new Handler(getMainLooper()).post(() -> didRun.set(true));
+
+ assertThat(didRun.get()).isFalse();
+ assertThat(shadowOf(getMainLooper()).isIdle()).isFalse();
+ }
+
+ @Test
+ public void postToLooperTest() {
+ doPostToLooperTest();
+ }
+
+ @Test
+ public void anotherPostToLooperTest() {
+ doPostToLooperTest();
+ }
+ }
+
+ @Test
+ public void pendingTasksClearer() throws InitializationError {
+ Runner runner = new RobolectricTestRunner(PendingLooperTest.class);
+
+ // run and assert no failures
+ runner.run(runNotifier);
+ }
+
+ /** Test that uses delayed tasks */
+ public static class DelayedTaskTest {
+
+ private void doDelayedPostToLooperTest() {
+ checkState(shadowOf(getMainLooper()).isIdle());
+
+ AtomicBoolean didRun = new AtomicBoolean(false);
+ new Handler(getMainLooper()).postDelayed(() -> didRun.set(true), 100);
+ shadowOf(getMainLooper()).idle();
+ assertThat(didRun.get()).isFalse();
+ shadowOf(getMainLooper()).idleFor(Duration.ofMillis(100));
+ assertThat(didRun.get()).isTrue();
+ }
+
+ @Test
+ public void postToLooperTest() {
+ doDelayedPostToLooperTest();
+ }
+
+ @Test
+ public void anotherPostToLooperTest() {
+ doDelayedPostToLooperTest();
+ }
+ }
+
+ @Test
+ public void delayedTask() throws InitializationError {
+ Runner runner = new RobolectricTestRunner(DelayedTaskTest.class);
+
+ // run and assert no failures
+ runner.run(runNotifier);
+ }
+
+ /** Test that uses delayed tasks on a running looper */
+ public static class DelayedTaskRunningLooperTest {
+
+ // use a static thread so both tests share the same looper
+ static HandlerThread handlerThread;
+
+ @Before
+ public void init() {
+ if (handlerThread == null) {
+ handlerThread = new HandlerThread("DelayedTaskRunningLooperTest");
+ handlerThread.start();
+ }
+ }
+
+ @AfterClass
+ public static void shutDown() throws InterruptedException {
+ handlerThread.quit();
+ handlerThread.join();
+ }
+
+ private void doDelayedPostToLooperTest() {
+ checkNotNull(handlerThread.getLooper());
+
+ AtomicBoolean didRun = new AtomicBoolean(false);
+ new Handler(handlerThread.getLooper()).postDelayed(() -> didRun.set(true), 100);
+ shadowOf(handlerThread.getLooper()).idle();
+ assertThat(didRun.get()).isFalse();
+ shadowOf(handlerThread.getLooper()).idleFor(Duration.ofMillis(100));
+ assertThat(didRun.get()).isTrue();
+ }
+
+ @Test
+ public void postToLooperTest() {
+ doDelayedPostToLooperTest();
+ }
+
+ @Test
+ public void anotherPostToLooperTest() {
+ doDelayedPostToLooperTest();
+ }
+ }
+
+ @Test
+ public void delayedTaskRunningLooper() throws InitializationError {
+ Runner runner = new RobolectricTestRunner(DelayedTaskRunningLooperTest.class);
+
+ // run and assert no failures
+ runner.run(runNotifier);
+ }
+}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowNfcAdapterTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowNfcAdapterTest.java
index 5d43069b5..d913c9927 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowNfcAdapterTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowNfcAdapterTest.java
@@ -1,10 +1,12 @@
package org.robolectric.shadows;
+import static android.os.Build.VERSION_CODES.TIRAMISU;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
+import static org.robolectric.util.reflector.Reflector.reflector;
import android.app.Activity;
import android.app.Application;
@@ -24,6 +26,7 @@ import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.util.reflector.ForType;
@RunWith(AndroidJUnit4.class)
public class ShadowNfcAdapterTest {
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
index e3242fadd..12957335b 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowPackageManagerTest.java
@@ -963,7 +963,7 @@ public class ShadowPackageManagerTest {
}
@Test
- public void getApplicationInfo_ThisApplication() throws Exception {
+ public void getApplicationInfo_thisApplication() throws Exception {
ApplicationInfo info = packageManager.getApplicationInfo(context.getPackageName(), 0);
assertThat(info).isNotNull();
assertThat(info.packageName).isEqualTo(context.getPackageName());
@@ -971,6 +971,16 @@ public class ShadowPackageManagerTest {
}
@Test
+ @Config(minSdk = TIRAMISU)
+ public void getApplicationInfo_thisApplication_withApplicationInfoFlags() throws Exception {
+ ApplicationInfo info =
+ packageManager.getApplicationInfo(context.getPackageName(), ApplicationInfoFlags.of(0));
+ assertThat(info).isNotNull();
+ assertThat(info.packageName).isEqualTo(context.getPackageName());
+ assertThat(info.processName).isEqualTo(info.packageName);
+ }
+
+ @Test
public void getApplicationInfo_uninstalledApplication_includeUninstalled() throws Exception {
shadowOf(packageManager).deletePackage(context.getPackageName());
@@ -981,6 +991,20 @@ public class ShadowPackageManagerTest {
}
@Test
+ @Config(minSdk = TIRAMISU)
+ public void
+ getApplicationInfo_uninstalledApplication_includeUninstalled_withApplicationInfoFlags()
+ throws Exception {
+ shadowOf(packageManager).deletePackage(context.getPackageName());
+
+ ApplicationInfo info =
+ packageManager.getApplicationInfo(
+ context.getPackageName(), ApplicationInfoFlags.of(MATCH_UNINSTALLED_PACKAGES));
+ assertThat(info).isNotNull();
+ assertThat(info.packageName).isEqualTo(context.getPackageName());
+ }
+
+ @Test
public void getApplicationInfo_uninstalledApplication_dontIncludeUninstalled() {
shadowOf(packageManager).deletePackage(context.getPackageName());
@@ -992,6 +1016,20 @@ public class ShadowPackageManagerTest {
}
}
+ @Test
+ @Config(minSdk = TIRAMISU)
+ public void
+ getApplicationInfo_uninstalledApplication_dontIncludeUninstalled_withApplicationInfoFlags() {
+ shadowOf(packageManager).deletePackage(context.getPackageName());
+
+ try {
+ packageManager.getApplicationInfo(context.getPackageName(), ApplicationInfoFlags.of(0));
+ fail("PackageManager.NameNotFoundException not thrown");
+ } catch (PackageManager.NameNotFoundException e) {
+ // expected
+ }
+ }
+
@Test(expected = PackageManager.NameNotFoundException.class)
public void getApplicationInfo_whenUnknown_shouldThrowNameNotFoundException() throws Exception {
try {
@@ -1003,8 +1041,29 @@ public class ShadowPackageManagerTest {
}
}
+ @Test(expected = PackageManager.NameNotFoundException.class)
+ @Config(minSdk = TIRAMISU)
+ public void
+ getApplicationInfo_whenUnknown_shouldThrowNameNotFoundException_withApplicationInfoFlags()
+ throws Exception {
+ try {
+ packageManager.getApplicationInfo("unknown_package", ApplicationInfoFlags.of(0));
+ fail("should have thrown NameNotFoundException");
+ } catch (PackageManager.NameNotFoundException e) {
+ assertThat(e.getMessage()).contains("unknown_package");
+ throw e;
+ }
+ }
+
+ @Test
+ public void getApplicationInfo_nullPackage_shouldThrowNameNotFoundException() {
+ assertThrows(
+ PackageManager.NameNotFoundException.class,
+ () -> packageManager.getApplicationInfo(null, 0));
+ }
+
@Test
- public void getApplicationInfo_OtherApplication() throws Exception {
+ public void getApplicationInfo_otherApplication() throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = TEST_PACKAGE_NAME;
packageInfo.applicationInfo = new ApplicationInfo();
@@ -1019,6 +1078,23 @@ public class ShadowPackageManagerTest {
}
@Test
+ @Config(minSdk = TIRAMISU)
+ public void getApplicationInfo_otherApplication_withApplicationInfoFlags() throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = TEST_PACKAGE_NAME;
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.packageName = TEST_PACKAGE_NAME;
+ packageInfo.applicationInfo.name = TEST_PACKAGE_LABEL;
+ shadowOf(packageManager).installPackage(packageInfo);
+
+ ApplicationInfo info =
+ packageManager.getApplicationInfo(TEST_PACKAGE_NAME, ApplicationInfoFlags.of(0));
+ assertThat(info).isNotNull();
+ assertThat(info.packageName).isEqualTo(TEST_PACKAGE_NAME);
+ assertThat(packageManager.getApplicationLabel(info).toString()).isEqualTo(TEST_PACKAGE_LABEL);
+ }
+
+ @Test
public void getApplicationInfo_readsValuesFromSetPackageArchiveInfo() {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "some.package.name";
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowSpeechRecognizerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowSpeechRecognizerTest.java
index 062e73ab0..c0ff1622f 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowSpeechRecognizerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowSpeechRecognizerTest.java
@@ -121,6 +121,18 @@ public class ShadowSpeechRecognizerTest {
assertNoErrorLogs();
}
+ /** Verify that isDestroyed is corrected set by destroy and unset by startListening */
+ @Test
+ public void startListeningThenDestroyAndStartListening() {
+ startListening();
+ assertThat(shadowOf(speechRecognizer).isDestroyed()).isFalse();
+ speechRecognizer.destroy();
+ shadowOf(getMainLooper()).idle();
+ assertThat(shadowOf(speechRecognizer).isDestroyed()).isTrue();
+ startListening();
+ assertThat(shadowOf(speechRecognizer).isDestroyed()).isFalse();
+ }
+
/** Verify the startlistening flow works when using custom component name. */
@Test
public void startListeningWithCustomComponent() {
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowTelephonyManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowTelephonyManagerTest.java
index cb6359f8e..8571627a4 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowTelephonyManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowTelephonyManagerTest.java
@@ -45,6 +45,8 @@ import static org.robolectric.RuntimeEnvironment.getApplication;
import static org.robolectric.Shadows.shadowOf;
import static org.robolectric.shadows.ShadowTelephonyManager.createTelephonyDisplayInfo;
+import android.Manifest.permission;
+import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -101,6 +103,8 @@ public class ShadowTelephonyManagerTest {
public void setUp() throws Exception {
telephonyManager = (TelephonyManager) getApplication().getSystemService(TELEPHONY_SERVICE);
shadowTelephonyManager = Shadow.extract(telephonyManager);
+ shadowOf((Application) ApplicationProvider.getApplicationContext())
+ .grantPermissions(permission.READ_PRIVILEGED_PHONE_STATE);
}
@Test
@@ -1040,4 +1044,28 @@ public class ShadowTelephonyManagerTest {
assertThrows(IllegalStateException.class, () -> telephonyManager.isEmergencyNumber("911"));
}
+
+ @Test
+ @Config(minSdk = O)
+ public void
+ getEmergencyCallbackMode_noReadPrivilegedPhoneStatePermission_throwsSecurityException() {
+ shadowOf((Application) ApplicationProvider.getApplicationContext())
+ .denyPermissions(permission.READ_PRIVILEGED_PHONE_STATE);
+
+ assertThrows(SecurityException.class, () -> telephonyManager.getEmergencyCallbackMode());
+ }
+
+ @Test
+ @Config(minSdk = O)
+ public void getEmergencyCallback_wasSetToTrue_returnsTrue() {
+ shadowTelephonyManager.setEmergencyCallbackMode(true);
+
+ assertThat(telephonyManager.getEmergencyCallbackMode()).isTrue();
+ }
+
+ @Test
+ @Config(minSdk = O)
+ public void getEmergencyCallback_notSet_returnsFalse() {
+ assertThat(telephonyManager.getEmergencyCallbackMode()).isFalse();
+ }
}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowViewGroupTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowViewGroupTest.java
index 488b55e08..ad74bb4fc 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowViewGroupTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowViewGroupTest.java
@@ -14,8 +14,8 @@ import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
+import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -24,6 +24,7 @@ import android.view.animation.Animation.AnimationListener;
import android.view.animation.LayoutAnimationController;
import android.widget.FrameLayout;
import android.widget.TextView;
+import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.io.ByteArrayOutputStream;
@@ -34,6 +35,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.R;
import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
@RunWith(AndroidJUnit4.class)
public class ShadowViewGroupTest {
@@ -182,32 +184,71 @@ public class ShadowViewGroupTest {
}
@Test
+ @Config(minSdk = 17) // TODO: mysteriously fails on github CI on API 16
public void hasFocus_shouldReturnTrueIfAnyChildHasFocus() {
- makeFocusable(root, child1, child2, child3, child3a, child3b);
- assertFalse(root.hasFocus());
+ ContainerActivity containerActivity = Robolectric.setupActivity(ContainerActivity.class);
+ makeFocusable(
+ containerActivity.root,
+ containerActivity.child1,
+ containerActivity.child2,
+ containerActivity.child3,
+ containerActivity.child3a,
+ containerActivity.child3b);
- child1.requestFocus();
- assertTrue(root.hasFocus());
+ containerActivity.child1.requestFocus();
+ assertTrue(containerActivity.root.hasFocus());
- child1.clearFocus();
- assertFalse(child1.hasFocus());
- assertTrue(root.hasFocus());
+ containerActivity.child1.clearFocus();
+ assertFalse(containerActivity.child1.hasFocus());
+ assertTrue(containerActivity.root.hasFocus());
- child3b.requestFocus();
- assertTrue(root.hasFocus());
+ containerActivity.child3b.requestFocus();
+ assertTrue(containerActivity.root.hasFocus());
- child3b.clearFocus();
- assertFalse(child3b.hasFocus());
- assertFalse(child3.hasFocus());
- assertTrue(root.hasFocus());
+ containerActivity.child3b.clearFocus();
+ assertFalse(containerActivity.child3b.hasFocus());
+ assertFalse(containerActivity.child3.hasFocus());
+ assertTrue(containerActivity.root.hasFocus());
- child2.requestFocus();
- assertFalse(child3.hasFocus());
- assertTrue(child2.hasFocus());
- assertTrue(root.hasFocus());
+ containerActivity.child2.requestFocus();
+ assertFalse(containerActivity.child3.hasFocus());
+ assertTrue(containerActivity.child2.hasFocus());
+ assertTrue(containerActivity.root.hasFocus());
- root.requestFocus();
- assertTrue(root.hasFocus());
+ containerActivity.root.requestFocus();
+ assertTrue(containerActivity.root.hasFocus());
+ }
+
+ private static class ContainerActivity extends Activity {
+
+ ViewGroup root;
+ View child1;
+ View child2;
+ ViewGroup child3;
+ View child3a;
+ View child3b;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ root = new FrameLayout(this);
+
+ child1 = new View(this);
+ child2 = new View(this);
+ child3 = new FrameLayout(this);
+ child3a = new View(this);
+ child3b = new View(this);
+
+ root.addView(child1);
+ root.addView(child2);
+ root.addView(child3);
+
+ child3.addView(child3a);
+ child3.addView(child3b);
+
+ setContentView(root);
+ }
}
@Test
@@ -455,7 +496,7 @@ public class ShadowViewGroupTest {
DrawRecordView view = new DrawRecordView(context);
ViewGroup viewGroup = new FrameLayout(context);
viewGroup.addView(view);
- Bitmap bitmap = Bitmap.createBitmap(100, 100, Config.ARGB_8888);
+ Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
viewGroup.draw(canvas);
assertThat(view.wasDrawn).isTrue();
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java
index 299a85333..7a1bee691 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowWifiManagerTest.java
@@ -14,11 +14,15 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.robolectric.Shadows.shadowOf;
+import android.app.admin.DeviceAdminService;
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -226,11 +230,11 @@ public class ShadowWifiManagerTest {
assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(networkId);
// If we don't have permission to update, updateNetwork will return -1.
- shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission = */ false);
+ shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission= */ false);
assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(-1);
// Ensure updates can occur if permission is restored.
- shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission = */ true);
+ shadowOf(wifiManager).setUpdateNetworkPermission(networkId, /* hasPermission= */ true);
assertThat(wifiManager.updateNetwork(wifiConfiguration)).isEqualTo(networkId);
}
@@ -764,4 +768,29 @@ public class ShadowWifiManagerTest {
assertThat(shadowOf(wifiManager).getWifiApConfiguration().SSID).isEqualTo("foo");
}
+
+ @Test
+ @Config(minSdk = R)
+ public void shouldRecordTheLastSoftApConfiguration() {
+ SoftApConfiguration softApConfig =
+ new SoftApConfiguration.Builder()
+ .setSsid("foo")
+ .setPassphrase(null, SoftApConfiguration.SECURITY_TYPE_OPEN)
+ .build();
+
+ boolean status = wifiManager.setSoftApConfiguration(softApConfig);
+ assertThat(status).isTrue();
+
+ assertThat(shadowOf(wifiManager).getSoftApConfiguration().getSsid()).isEqualTo("foo");
+ }
+
+ private void setDeviceOwner() {
+ shadowOf(
+ (DevicePolicyManager)
+ ApplicationProvider.getApplicationContext()
+ .getSystemService(Context.DEVICE_POLICY_SERVICE))
+ .setDeviceOwner(
+ new ComponentName(
+ ApplicationProvider.getApplicationContext(), DeviceAdminService.class));
+ }
}
diff --git a/robolectric/src/test/java/org/robolectric/shadows/SharedLibraryInfoBuilderTest.java b/robolectric/src/test/java/org/robolectric/shadows/SharedLibraryInfoBuilderTest.java
new file mode 100644
index 000000000..2d5f0d6a5
--- /dev/null
+++ b/robolectric/src/test/java/org/robolectric/shadows/SharedLibraryInfoBuilderTest.java
@@ -0,0 +1,49 @@
+package org.robolectric.shadows;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.SharedLibraryInfo;
+import android.os.Build.VERSION_CODES;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+/** Tests for {@link SharedLibraryInfoBuilder}. */
+@RunWith(RobolectricTestRunner.class)
+@Config(minSdk = VERSION_CODES.O)
+public final class SharedLibraryInfoBuilderTest {
+
+ @Test
+ @Config(maxSdk = VERSION_CODES.P)
+ public void build_beforeVersionQ() {
+
+ SharedLibraryInfo sharedLibraryInfo =
+ SharedLibraryInfoBuilder.newBuilder()
+ .setName("trichromelibrary")
+ .setVersion(0)
+ .setType(SharedLibraryInfo.TYPE_STATIC)
+ .build();
+
+ assertThat(sharedLibraryInfo.getType()).isEqualTo(SharedLibraryInfo.TYPE_STATIC);
+ assertThat(sharedLibraryInfo.getName()).isEqualTo("trichromelibrary");
+ assertThat(sharedLibraryInfo.getVersion()).isEqualTo(0);
+ }
+
+ @Test
+ @Config(minSdk = VERSION_CODES.Q)
+ public void build_versionQ() {
+
+ SharedLibraryInfo sharedLibraryInfo =
+ SharedLibraryInfoBuilder.newBuilder()
+ .setName("com.google.android.trichromelibrary_535912833")
+ .setVersion(535912833)
+ .setType(SharedLibraryInfo.TYPE_STATIC)
+ .build();
+
+ assertThat(sharedLibraryInfo.getType()).isEqualTo(SharedLibraryInfo.TYPE_STATIC);
+ assertThat(sharedLibraryInfo.getName())
+ .isEqualTo("com.google.android.trichromelibrary_535912833");
+ assertThat(sharedLibraryInfo.getVersion()).isEqualTo(535912833);
+ }
+}