diff options
Diffstat (limited to 'robolectric/src/test/java/org/robolectric/shadows')
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); + } +} |