From f8e414a9dc83d753b8eb0a1bddedcefc492dc510 Mon Sep 17 00:00:00 2001 From: abebeos <149062843+abebeos@users.noreply.github.com> Date: Wed, 13 Dec 2023 00:13:37 +0200 Subject: [PATCH] convert java to kotlin (10 last files within 'AndroidSDK..test') (#1926) Co-authored-by: abebeos <129396476+abebeos@users.noreply.github.com> --- .../maplibre/android/MapLibreInjector.java | 36 --- .../org/maplibre/android/MapLibreInjector.kt | 32 +++ .../org/maplibre/android/MapLibreTest.java | 98 ------- .../java/org/maplibre/android/MapLibreTest.kt | 88 ++++++ .../engine/AndroidLocationEngineImplTest.java | 188 ------------ .../engine/AndroidLocationEngineImplTest.kt | 170 +++++++++++ .../engine/LocationEngineProxyTest.java | 105 ------- .../engine/LocationEngineProxyTest.kt | 88 ++++++ .../engine/LocationEngineRequestTest.java | 72 ----- .../engine/LocationEngineRequestTest.kt | 64 +++++ .../engine/LocationEngineResultTest.java | 133 --------- .../engine/LocationEngineResultTest.kt | 127 +++++++++ .../location/engine/LocationEngineTest.java | 143 ---------- .../location/engine/LocationEngineTest.kt | 127 +++++++++ ...usedLocationEngineImplAdditionalTest2.java | 153 ---------- ...eFusedLocationEngineImplAdditionalTest2.kt | 118 ++++++++ .../MapLibreFusedLocationEngineImplTest.java | 177 ------------ .../MapLibreFusedLocationEngineImplTest.kt | 166 +++++++++++ .../maplibre/android/utils/MockParcel.java | 268 ------------------ .../org/maplibre/android/utils/MockParcel.kt | 169 +++++++++++ 20 files changed, 1149 insertions(+), 1373 deletions(-) delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.kt delete mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.java create mode 100644 platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.kt diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.java deleted file mode 100644 index 94dbb8f40..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.maplibre.android; - -import android.content.Context; - -import androidx.annotation.NonNull; - -import org.maplibre.android.util.TileServerOptions; - -import java.lang.reflect.Field; - -public class MapLibreInjector { - - private static final String FIELD_INSTANCE = "INSTANCE"; - - public static void inject(@NonNull Context context, @NonNull String apiKey, - @NonNull TileServerOptions options) { - MapLibre maplibre = new MapLibre(context, apiKey, options); - try { - Field instance = MapLibre.class.getDeclaredField(FIELD_INSTANCE); - instance.setAccessible(true); - instance.set(maplibre, maplibre); - } catch (Exception exception) { - throw new AssertionError(); - } - } - - public static void clear() { - try { - Field field = MapLibre.class.getDeclaredField(FIELD_INSTANCE); - field.setAccessible(true); - field.set(field, null); - } catch (Exception exception) { - throw new AssertionError(); - } - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.kt new file mode 100644 index 000000000..037f48bef --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreInjector.kt @@ -0,0 +1,32 @@ +package org.maplibre.android + +import android.content.Context +import org.maplibre.android.MapLibre +import org.maplibre.android.util.TileServerOptions + +object MapLibreInjector { + private const val FIELD_INSTANCE = "INSTANCE" + @JvmStatic + fun inject(context: Context, apiKey: String, + options: TileServerOptions) { + val maplibre = MapLibre(context, apiKey, options) + try { + val instance = MapLibre::class.java.getDeclaredField(FIELD_INSTANCE) + instance.isAccessible = true + instance[maplibre] = maplibre + } catch (exception: Exception) { + throw AssertionError() + } + } + + @JvmStatic + fun clear() { + try { + val field = MapLibre::class.java.getDeclaredField(FIELD_INSTANCE) + field.isAccessible = true + field[field] = null + } catch (exception: Exception) { + throw AssertionError() + } + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.java deleted file mode 100644 index 2a7fe91a5..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package org.maplibre.android; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.DisplayMetrics; - -import org.maplibre.android.exceptions.MapLibreConfigurationException; -import org.maplibre.android.maps.MapView; -import org.maplibre.android.utils.ConfigUtils; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.nullable; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class MapLibreTest { - - private Context context; - private Context appContext; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void before() { - context = mock(Context.class); - appContext = mock(Context.class); - when(context.getApplicationContext()).thenReturn(appContext); - } - - @Test - public void testGetApiKey() { - final String apiKey = "pk.0000000001"; - MapLibreInjector.inject(context, apiKey, ConfigUtils.getMockedOptions()); - assertSame(apiKey, MapLibre.getApiKey()); - } - - @Test - public void testApplicationContext() { - MapLibreInjector.inject(context, "pk.0000000001", ConfigUtils.getMockedOptions()); - assertNotNull(MapLibre.getApplicationContext()); - assertNotEquals(context, appContext); - assertEquals(appContext, appContext); - } - - @Test - public void testPlainTokenValid() { - assertTrue(MapLibre.isApiKeyValid("apiKey")); - } - - @Test - public void testEmptyToken() { - assertFalse(MapLibre.isApiKeyValid("")); - } - - @Test - public void testNullToken() { - assertFalse(MapLibre.isApiKeyValid(null)); - } - - @Test - public void testNoInstance() { - DisplayMetrics displayMetrics = mock(DisplayMetrics.class); - Resources resources = mock(Resources.class); - when(resources.getDisplayMetrics()).thenReturn(displayMetrics); - when(context.getResources()).thenReturn(resources); - TypedArray typedArray = mock(TypedArray.class); - when(context.obtainStyledAttributes(nullable(AttributeSet.class), any(int[].class), anyInt(), anyInt())) - .thenReturn(typedArray); - - expectedException.expect(MapLibreConfigurationException.class); - expectedException.expectMessage( - "\nUsing MapView requires calling MapLibre.getInstance(Context context, String apiKey," - + " WellKnownTileServer wellKnownTileServer) before inflating or creating the view." - ); - new MapView(context); - } - - @After - public void after() { - MapLibreInjector.clear(); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.kt new file mode 100644 index 000000000..8dbe1f7e4 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/MapLibreTest.kt @@ -0,0 +1,88 @@ +package org.maplibre.android + +import android.content.Context +import android.content.res.Resources +import android.content.res.TypedArray +import android.util.AttributeSet +import android.util.DisplayMetrics +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.ExpectedException +import org.maplibre.android.MapLibreInjector.clear +import org.maplibre.android.MapLibreInjector.inject +import org.maplibre.android.exceptions.MapLibreConfigurationException +import org.maplibre.android.maps.MapView +import org.maplibre.android.utils.ConfigUtils.Companion.getMockedOptions +import org.mockito.ArgumentMatchers +import org.mockito.Mockito + +class MapLibreTest { + private var context: Context? = null + private var appContext: Context? = null + + @Rule + @JvmField // J2K: https://stackoverflow.com/a/33449455 + var expectedException = ExpectedException.none() + @Before + fun before() { + context = Mockito.mock(Context::class.java) + appContext = Mockito.mock(Context::class.java) + // J2K: https://www.baeldung.com/kotlin/smart-cast-to-type-is-impossible#2-using-the-safe-call-operator--and-a-scope-function + Mockito.`when`(context?.getApplicationContext()).thenReturn(appContext) + } + + @Test + fun testGetApiKey() { + val apiKey = "pk.0000000001" + inject(context!!, apiKey, getMockedOptions()) + Assert.assertSame(apiKey, MapLibre.getApiKey()) + } + + @Test + fun testApplicationContext() { + inject(context!!, "pk.0000000001", getMockedOptions()) + Assert.assertNotNull(MapLibre.getApplicationContext()) + Assert.assertNotEquals(context, appContext) + Assert.assertEquals(appContext, appContext) + } + + @Test + fun testPlainTokenValid() { + Assert.assertTrue(MapLibre.isApiKeyValid("apiKey")) + } + + @Test + fun testEmptyToken() { + Assert.assertFalse(MapLibre.isApiKeyValid("")) + } + + @Test + fun testNullToken() { + Assert.assertFalse(MapLibre.isApiKeyValid(null)) + } + + @Test + fun testNoInstance() { + val displayMetrics = Mockito.mock(DisplayMetrics::class.java) + val resources = Mockito.mock(Resources::class.java) + Mockito.`when`(resources.displayMetrics).thenReturn(displayMetrics) + Mockito.`when`(context!!.resources).thenReturn(resources) + val typedArray = Mockito.mock(TypedArray::class.java) + Mockito.`when`(context!!.obtainStyledAttributes(ArgumentMatchers.nullable(AttributeSet::class.java), ArgumentMatchers.any(IntArray::class.java), ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())) + .thenReturn(typedArray) + expectedException.expect(MapLibreConfigurationException::class.java) + expectedException.expectMessage(""" + + Using MapView requires calling MapLibre.getInstance(Context context, String apiKey, WellKnownTileServer wellKnownTileServer) before inflating or creating the view. + """.trimIndent()) + MapView(context!!) + } + + @After + fun after() { + clear() + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.java deleted file mode 100644 index beb5a4e72..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.app.PendingIntent; -import android.content.Context; -import android.location.Criteria; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.os.Looper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static junit.framework.TestCase.assertTrue; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class AndroidLocationEngineImplTest { - private static final double LATITUDE = 37.7749; - private static final double LONGITUDE = 122.4194; - - @Mock - private LocationManager locationManagerMock; - - private LocationEngine engine; - private AndroidLocationEngineImpl androidLocationEngineImpl; - - @Before - public void setUp() { - Context context = mock(Context.class); - when(context.getSystemService(Context.LOCATION_SERVICE)).thenReturn(locationManagerMock); - androidLocationEngineImpl = new AndroidLocationEngineImpl(context); - engine = new LocationEngineProxy<>(androidLocationEngineImpl); - } - - @Test - public void getLastLocation() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference resultRef = new AtomicReference<>(); - - LocationEngineCallback callback = getCallback(resultRef, latch); - final Location location = getMockLocation(LATITUDE, LONGITUDE); - final LocationEngineResult expectedResult = getMockEngineResult(location); - - when(locationManagerMock.getLastKnownLocation(anyString())).thenReturn(location); - - engine.getLastLocation(callback); - assertTrue(latch.await(5, SECONDS)); - - LocationEngineResult result = resultRef.get(); - assertThat(result.getLastLocation()).isEqualTo(expectedResult.getLastLocation()); - } - - @Test - public void createListener() { - LocationEngineCallback callback = mock(LocationEngineCallback.class); - LocationListener locationListener = androidLocationEngineImpl.createListener(callback); - Location mockLocation = getMockLocation(LATITUDE, LONGITUDE); - locationListener.onLocationChanged(mockLocation); - ArgumentCaptor argument = ArgumentCaptor.forClass(LocationEngineResult.class); - verify(callback).onSuccess(argument.capture()); - - LocationEngineResult result = argument.getValue(); - assertThat(result.getLastLocation()).isSameAs(mockLocation); - } - - @Test - public void requestLocationUpdatesWithNoPower() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_NO_POWER).build(); - LocationEngineCallback callback = mock(LocationEngineCallback.class); - Looper looper = mock(Looper.class); - Criteria criteria = mock(Criteria.class); - - engine.requestLocationUpdates(request, callback, looper); - verify(locationManagerMock, never()).getBestProvider(criteria, true); - } - - @Test - public void requestLocationUpdatesBestProviderNull() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - LocationEngineCallback callback = mock(LocationEngineCallback.class); - Looper looper = mock(Looper.class); - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn(null); - - engine.requestLocationUpdates(request, callback, looper); - assertThat(androidLocationEngineImpl.currentProvider).isEqualTo("passive"); - } - - @Test - public void requestLocationUpdatesWithPendingIntent() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - PendingIntent pendingIntent = mock(PendingIntent.class); - - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn(null); - - engine.requestLocationUpdates(request, pendingIntent); - assertThat(androidLocationEngineImpl.currentProvider).isEqualTo("passive"); - } - - @Test - public void removeLocationUpdatesForInvalidListener() { - LocationEngineCallback callback = mock(LocationEngineCallback.class); - engine.removeLocationUpdates(callback); - verify(locationManagerMock, never()).removeUpdates(any(LocationListener.class)); - } - - @Test - public void removeLocationUpdatesForPendingIntent() { - PendingIntent pendingIntent = mock(PendingIntent.class); - engine.removeLocationUpdates(pendingIntent); - verify(locationManagerMock, times(1)).removeUpdates(any(PendingIntent.class)); - } - - @Test - public void removeLocationUpdatesForValidListener() { - LocationEngineCallback callback = mock(LocationEngineCallback.class); - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - engine.requestLocationUpdates(request, callback, mock(Looper.class)); - engine.removeLocationUpdates(callback); - verify(locationManagerMock, times(1)).removeUpdates(any(LocationListener.class)); - } - - @Test(expected = NullPointerException.class) - public void getLastLocationNullCallback() { - engine.getLastLocation(null); - } - - @Test(expected = NullPointerException.class) - public void requestLocationUpdatesNullCallback() { - engine.requestLocationUpdates(null, null, null); - } - - @After - public void tearDown() { - reset(locationManagerMock); - engine = null; - } - - private static LocationEngineCallback getCallback( - final AtomicReference resultRef, - final CountDownLatch latch) { - return new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - resultRef.set(result); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - exception.printStackTrace(); - } - }; - } - - private static LocationEngineResult getMockEngineResult(Location location) { - return LocationEngineResult.create(location); - } - - private static Location getMockLocation(double lat, double lon) { - Location location = mock(Location.class); - location.setLatitude(lat); - location.setLongitude(lon); - return location; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.kt new file mode 100644 index 000000000..5d0f8e470 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/AndroidLocationEngineImplTest.kt @@ -0,0 +1,170 @@ +package org.maplibre.android.location.engine + +import android.app.PendingIntent +import android.content.Context +import android.location.Criteria +import android.location.Location +import android.location.LocationListener +import android.location.LocationManager +import android.os.Looper +import junit.framework.TestCase +import org.assertj.core.api.Assertions.* +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference + +@RunWith(MockitoJUnitRunner::class) +class AndroidLocationEngineImplTest { + @Mock + private val locationManagerMock: LocationManager? = null + private var engine: LocationEngine? = null + private var androidLocationEngineImpl: AndroidLocationEngineImpl? = null + @Before + fun setUp() { + val context = mock(Context::class.java) + `when`(context.getSystemService(Context.LOCATION_SERVICE)).thenReturn(locationManagerMock) + androidLocationEngineImpl = AndroidLocationEngineImpl(context) + engine = LocationEngineProxy(androidLocationEngineImpl) + } + + //@get:Throws(InterruptedException::class) + @Test + fun getLastLocation() { + val latch = CountDownLatch(1) + val resultRef = AtomicReference() + val callback = getCallback(resultRef, latch) + val location = getMockLocation(LATITUDE, LONGITUDE) + val expectedResult = getMockEngineResult(location) + `when`(locationManagerMock!!.getLastKnownLocation(anyString())).thenReturn(location) + engine!!.getLastLocation(callback) + TestCase.assertTrue(latch.await(5, TimeUnit.SECONDS)) + val result = resultRef.get() + assertThat(result.lastLocation).isEqualTo(expectedResult.lastLocation) + } + + @Test + fun createListener() { + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val locationListener = androidLocationEngineImpl!!.createListener(callback) + val mockLocation = getMockLocation(LATITUDE, LONGITUDE) + locationListener.onLocationChanged(mockLocation) + val argument = ArgumentCaptor.forClass(LocationEngineResult::class.java) + verify(callback).onSuccess(argument.capture()) + val result = argument.value + assertThat(result.lastLocation).isSameAs(mockLocation) + } + + @Test + fun requestLocationUpdatesWithNoPower() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_NO_POWER).build() + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val looper = mock(Looper::class.java) + val criteria = mock(Criteria::class.java) + engine!!.requestLocationUpdates(request, callback, looper) + verify(locationManagerMock, never())?.getBestProvider(criteria, true) + } + + @Test + fun requestLocationUpdatesBestProviderNull() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val looper = mock(Looper::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn(null) + engine!!.requestLocationUpdates(request, callback, looper) + assertThat(androidLocationEngineImpl!!.currentProvider).isEqualTo("passive") + } + + @Test + fun requestLocationUpdatesWithPendingIntent() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + val pendingIntent = mock(PendingIntent::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn(null) + engine!!.requestLocationUpdates(request, pendingIntent) + assertThat(androidLocationEngineImpl!!.currentProvider).isEqualTo("passive") + } + + @Test + fun removeLocationUpdatesForInvalidListener() { + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + engine!!.removeLocationUpdates(callback) + verify(locationManagerMock, never())?.removeUpdates(ArgumentMatchers.any(LocationListener::class.java)) + } + + @Test + fun removeLocationUpdatesForPendingIntent() { + val pendingIntent = mock(PendingIntent::class.java) + engine!!.removeLocationUpdates(pendingIntent) + verify(locationManagerMock, times(1))?.removeUpdates(ArgumentMatchers.any(PendingIntent::class.java)) + } + + @Test + fun removeLocationUpdatesForValidListener() { + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + engine!!.requestLocationUpdates(request, callback, mock(Looper::class.java)) + engine!!.removeLocationUpdates(callback) + verify(locationManagerMock, times(1))?.removeUpdates(ArgumentMatchers.any(LocationListener::class.java)) + } + + // J2K: removed "get". TODO: validate necessity of this test + @Test(expected = NullPointerException::class) + fun lastLocationNullCallback() { + engine!!.getLastLocation(null!!) + } + + // J2K: add "!!". TODO: validate necessity of this test + @Test(expected = NullPointerException::class) + fun requestLocationUpdatesNullCallback() { + engine!!.requestLocationUpdates(null!!, null!!, null!!) + } + + @After + fun tearDown() { + reset(locationManagerMock) + engine = null + } + + companion object { + private const val LATITUDE = 37.7749 + private const val LONGITUDE = 122.4194 + private fun getCallback( + resultRef: AtomicReference, + latch: CountDownLatch): LocationEngineCallback { + // J2K: remove "?" from LocationEngineResult? + return object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) { + resultRef.set(result) + latch.countDown() + } + + override fun onFailure(exception: Exception) { + exception.printStackTrace() + } + } + } + + private fun getMockEngineResult(location: Location): LocationEngineResult { + return LocationEngineResult.create(location) + } + + private fun getMockLocation(lat: Double, lon: Double): Location { + val location = mock(Location::class.java) + location.latitude = lat + location.longitude = lon + return location + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.java deleted file mode 100644 index bc4090644..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.location.LocationListener; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class LocationEngineProxyTest { - @Mock - private LocationEngineCallback callback; - - @Mock - private LocationEngineImpl engineImpl; - - private LocationEngineProxy locationEngineProxy; - - @Before - public void setUp() { - locationEngineProxy = new LocationEngineProxy<>(engineImpl); - } - - @Test - public void testAddListener() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - - LocationListener locationListener = locationEngineProxy.getListener(callback); - assertThat(locationListener).isSameAs(transport); - assertThat(locationEngineProxy.getListenersCount()).isEqualTo(1); - } - - @Test - public void testAddListenerTwice() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - - locationEngineProxy.getListener(callback); - locationEngineProxy.getListener(callback); - assertThat(locationEngineProxy.getListenersCount()).isEqualTo(1); - } - - @Test - public void testAddTwoListeners() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - locationEngineProxy.getListener(callback); - - LocationEngineCallback anotherCallback = mock(LocationEngineCallback.class); - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport anotherTransport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(anotherCallback); - when(engineImpl.createListener(anotherCallback)).thenReturn(anotherTransport); - locationEngineProxy.getListener(anotherCallback); - assertThat(locationEngineProxy.getListenersCount()).isEqualTo(2); - } - - @Test - public void testRemoveListener() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - locationEngineProxy.getListener(callback); - - locationEngineProxy.removeListener(callback); - assertThat(locationEngineProxy.getListenersCount()).isEqualTo(0); - } - - @Test - public void testCheckRemovedListener() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - locationEngineProxy.getListener(callback); - - LocationEngineCallback anotherCallback = mock(LocationEngineCallback.class); - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport anotherTransport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(anotherCallback); - when(engineImpl.createListener(anotherCallback)).thenReturn(anotherTransport); - locationEngineProxy.getListener(anotherCallback); - - assertThat(locationEngineProxy.removeListener(callback)).isSameAs(transport); - assertThat(locationEngineProxy.removeListener(anotherCallback)).isSameAs(anotherTransport); - } - - @Test - public void testRemoveListenerTwice() { - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(engineImpl.createListener(callback)).thenReturn(transport); - locationEngineProxy.getListener(callback); - - assertThat(locationEngineProxy.removeListener(callback)).isSameAs(transport); - assertThat(locationEngineProxy.removeListener(callback)).isNull(); - } -} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.kt new file mode 100644 index 000000000..1998177ce --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineProxyTest.kt @@ -0,0 +1,88 @@ +package org.maplibre.android.location.engine + +import android.location.LocationListener +import org.assertj.core.api.Assertions.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.maplibre.android.location.engine.AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner + +@RunWith(MockitoJUnitRunner::class) +class LocationEngineProxyTest { + @Mock + private val callback: LocationEngineCallback? = null + + @Mock + private val engineImpl: LocationEngineImpl? = null + private var locationEngineProxy: LocationEngineProxy? = null + @Before + fun setUp() { + locationEngineProxy = LocationEngineProxy(engineImpl) + } + + @Test + fun testAddListener() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + val locationListener = locationEngineProxy!!.getListener(callback!!) + assertThat(locationListener).isSameAs(transport) + assertThat(locationEngineProxy!!.listenersCount).isEqualTo(1) + } + + @Test + fun testAddListenerTwice() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + locationEngineProxy!!.getListener(callback!!) + locationEngineProxy!!.getListener(callback) + assertThat(locationEngineProxy!!.listenersCount).isEqualTo(1) + } + + @Test + fun testAddTwoListeners() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + locationEngineProxy!!.getListener(callback!!) + // J2K: using IDE suggestion "as LocationEngineCallback" + val anotherCallback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val anotherTransport = AndroidLocationEngineCallbackTransport(anotherCallback) + `when`(engineImpl.createListener(anotherCallback)).thenReturn(anotherTransport) + locationEngineProxy!!.getListener(anotherCallback) + assertThat(locationEngineProxy!!.listenersCount).isEqualTo(2) + } + + @Test + fun testRemoveListener() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + locationEngineProxy!!.getListener(callback!!) + locationEngineProxy!!.removeListener(callback) + assertThat(locationEngineProxy!!.listenersCount).isEqualTo(0) + } + + @Test + fun testCheckRemovedListener() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + locationEngineProxy!!.getListener(callback!!) + // J2K: using IDE suggestion "as LocationEngineCallback" + val anotherCallback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val anotherTransport = AndroidLocationEngineCallbackTransport(anotherCallback) + `when`(engineImpl.createListener(anotherCallback)).thenReturn(anotherTransport) + locationEngineProxy!!.getListener(anotherCallback) + assertThat(locationEngineProxy!!.removeListener(callback)).isSameAs(transport) + assertThat(locationEngineProxy!!.removeListener(anotherCallback)).isSameAs(anotherTransport) + } + + @Test + fun testRemoveListenerTwice() { + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(engineImpl!!.createListener(callback)).thenReturn(transport) + locationEngineProxy!!.getListener(callback!!) + assertThat(locationEngineProxy!!.removeListener(callback)).isSameAs(transport) + assertThat(locationEngineProxy!!.removeListener(callback)).isNull() + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.java deleted file mode 100644 index f8471e30b..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.java +++ /dev/null @@ -1,72 +0,0 @@ -package org.maplibre.android.location.engine; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -import static org.assertj.core.api.Assertions.assertThat; - -@RunWith(MockitoJUnitRunner.class) -public class LocationEngineRequestTest { - - @Test - public void checkDefaultValues() { - LocationEngineRequest request = new LocationEngineRequest.Builder(1000L).build(); - - assertThat(request.getInterval()).isEqualTo(1000L); - assertThat(request.getDisplacement()).isEqualTo(0.0f); - assertThat(request.getMaxWaitTime()).isEqualTo(0L); - assertThat(request.getFastestInterval()).isEqualTo(0L); - } - - @Test - public void checkBuilder() { - LocationEngineRequest request = new LocationEngineRequest.Builder(2000L) - .setDisplacement(100.0f) - .setMaxWaitTime(5000L) - .setFastestInterval(500L) - .build(); - - assertThat(request.getInterval()).isEqualTo(2000L); - assertThat(request.getDisplacement()).isEqualTo(100.0f); - assertThat(request.getMaxWaitTime()).isEqualTo(5000L); - assertThat(request.getFastestInterval()).isEqualTo(500L); - } - - @Test - public void checkRequestEqual() { - LocationEngineRequest request = new LocationEngineRequest.Builder(2000L).build(); - LocationEngineRequest otherRequest = new LocationEngineRequest.Builder(2000L).build(); - - assertThat(request).isEqualTo(otherRequest); - assertThat(request.hashCode()).isEqualTo(otherRequest.hashCode()); - } - - @Test - public void checkRequestsNotEqual() { - LocationEngineRequest request = new LocationEngineRequest.Builder(2000L).build(); - LocationEngineRequest otherRequest = new LocationEngineRequest.Builder(2000L) - .setFastestInterval(500L) - .build(); - - assertThat(request).isNotEqualTo(otherRequest); - } - - @Test - public void checkRequestsEqualHashCode() { - LocationEngineRequest request = new LocationEngineRequest.Builder(2000L).build(); - LocationEngineRequest otherRequest = new LocationEngineRequest.Builder(2000L).build(); - - assertThat(request.hashCode()).isEqualTo(otherRequest.hashCode()); - } - - @Test - public void checkRequestsNonEqualHashCode() { - LocationEngineRequest request = new LocationEngineRequest.Builder(2000L).build(); - LocationEngineRequest otherRequest = new LocationEngineRequest.Builder(2000L) - .setFastestInterval(500L) - .build(); - - assertThat(request.hashCode()).isNotEqualTo(otherRequest.hashCode()); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.kt new file mode 100644 index 000000000..123fd8e1f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineRequestTest.kt @@ -0,0 +1,64 @@ +package org.maplibre.android.location.engine + +import org.assertj.core.api.Assertions.* +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.junit.MockitoJUnitRunner + +@RunWith(MockitoJUnitRunner::class) +class LocationEngineRequestTest { + @Test + fun checkDefaultValues() { + val request = LocationEngineRequest.Builder(1000L).build() + assertThat(request.interval).isEqualTo(1000L) + assertThat(request.displacement).isEqualTo(0.0f) + assertThat(request.maxWaitTime).isEqualTo(0L) + assertThat(request.fastestInterval).isEqualTo(0L) + } + + @Test + fun checkBuilder() { + val request = LocationEngineRequest.Builder(2000L) + .setDisplacement(100.0f) + .setMaxWaitTime(5000L) + .setFastestInterval(500L) + .build() + assertThat(request.interval).isEqualTo(2000L) + assertThat(request.displacement).isEqualTo(100.0f) + assertThat(request.maxWaitTime).isEqualTo(5000L) + assertThat(request.fastestInterval).isEqualTo(500L) + } + + @Test + fun checkRequestEqual() { + val request = LocationEngineRequest.Builder(2000L).build() + val otherRequest = LocationEngineRequest.Builder(2000L).build() + assertThat(request).isEqualTo(otherRequest) + assertThat(request.hashCode()).isEqualTo(otherRequest.hashCode()) + } + + @Test + fun checkRequestsNotEqual() { + val request = LocationEngineRequest.Builder(2000L).build() + val otherRequest = LocationEngineRequest.Builder(2000L) + .setFastestInterval(500L) + .build() + assertThat(request).isNotEqualTo(otherRequest) + } + + @Test + fun checkRequestsEqualHashCode() { + val request = LocationEngineRequest.Builder(2000L).build() + val otherRequest = LocationEngineRequest.Builder(2000L).build() + assertThat(request.hashCode()).isEqualTo(otherRequest.hashCode()) + } + + @Test + fun checkRequestsNonEqualHashCode() { + val request = LocationEngineRequest.Builder(2000L).build() + val otherRequest = LocationEngineRequest.Builder(2000L) + .setFastestInterval(500L) + .build() + assertThat(request.hashCode()).isNotEqualTo(otherRequest.hashCode()) + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.java deleted file mode 100644 index 762c34ee7..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.java +++ /dev/null @@ -1,133 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.content.Intent; -import android.location.Location; -import android.location.LocationManager; -import android.os.Bundle; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class LocationEngineResultTest { - - private static final double TEST_LAT_LNG = 1.0; - - @Test - public void checkNullIntent() { - LocationEngineResult result = LocationEngineResult.extractResult(null); - assertThat(result).isNull(); - } - - @Test - public void passInvalidIntent() { - Intent intent = mock(Intent.class); - LocationEngineResult result = LocationEngineResult.extractResult(intent); - assertThat(result).isNull(); - } - - @Test - public void passValidIntent() { - Location location = mock(Location.class); - LocationEngineResult result = LocationEngineResult.extractResult(getValidIntent(location)); - assertThat(result).isNotNull(); - assertThat(result.getLastLocation()).isSameAs(location); - } - - @Test - public void passNullLocation() { - Location location = null; - LocationEngineResult result = LocationEngineResult.create(location); - assertForNullInput(result); - } - - @Test - public void passNullLocationList() { - List locations = null; - LocationEngineResult result = LocationEngineResult.create(locations); - assertForNullInput(result); - } - - @Test - public void passValidLocation() { - Location location = getValidLocation(); - LocationEngineResult result = LocationEngineResult.create(location); - assertForValidInput(result); - } - - @Test - public void passValidLocationList() { - List locations = Collections.singletonList(getValidLocation()); - LocationEngineResult result = LocationEngineResult.create(locations); - assertForValidInput(result); - } - - @Test - public void passMutableLocationListWithNulls() { - List locations = getLocationsWithNulls(); - LocationEngineResult result = LocationEngineResult.create(locations); - assertForValidInput(result); - } - - @Test - public void passImmutableLocationListWithNulls() { - List locations = Collections.unmodifiableList(getLocationsWithNulls()); - LocationEngineResult result = LocationEngineResult.create(locations); - assertForValidInput(result); - } - - @Test - public void passImmutableListWithNullLocation() { - List locations = Collections.singletonList(null); - LocationEngineResult result = LocationEngineResult.create(locations); - assertThat(result != null); - assertThat(result.getLocations().size() == 0); - } - - private static List getLocationsWithNulls() { - return new ArrayList() { - { - add(null); - add(getValidLocation()); - add(null); - } - }; - } - - private static Location getValidLocation() { - Location location = mock(Location.class); - when(location.getLatitude()).thenReturn(TEST_LAT_LNG); - when(location.getLongitude()).thenReturn(TEST_LAT_LNG); - return location; - } - - private static void assertForNullInput(LocationEngineResult result) { - assertThat(result).isNotNull(); - assertThat(result.getLocations()).isEmpty(); - } - - private static void assertForValidInput(LocationEngineResult result) { - assertThat(result.getLocations()).isNotNull(); - assertThat(result.getLocations().size()).isEqualTo(1); - assertThat(result.getLocations().get(0).getLatitude()).isEqualTo(TEST_LAT_LNG); - assertThat(result.getLocations().get(0).getLongitude()).isEqualTo(TEST_LAT_LNG); - } - - private static Intent getValidIntent(Location location) { - Intent intent = mock(Intent.class); - when(intent.hasExtra(LocationManager.KEY_LOCATION_CHANGED)).thenReturn(true); - Bundle bundle = mock(Bundle.class); - when(bundle.getParcelable(LocationManager.KEY_LOCATION_CHANGED)).thenReturn(location); - when(intent.getExtras()).thenReturn(bundle); - return intent; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.kt new file mode 100644 index 000000000..ec62e7460 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineResultTest.kt @@ -0,0 +1,127 @@ +package org.maplibre.android.location.engine + +import android.content.Intent +import android.location.Location +import android.location.LocationManager +import android.os.Bundle +import org.assertj.core.api.Assertions.* +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner +import java.util.Collections + +@RunWith(MockitoJUnitRunner::class) +class LocationEngineResultTest { + @Test + fun checkNullIntent() { + val result = LocationEngineResult.extractResult(null) + assertThat(result).isNull() + } + + @Test + fun passInvalidIntent() { + val intent = mock(Intent::class.java) + val result = LocationEngineResult.extractResult(intent) + assertThat(result).isNull() + } + + @Test + fun passValidIntent() { + val location = mock(Location::class.java) + val result = LocationEngineResult.extractResult(getValidIntent(location)) + assertThat(result).isNotNull() + assertThat(result!!.lastLocation).isSameAs(location) + } + + @Test + fun passNullLocation() { + val location: Location? = null + val result = LocationEngineResult.create(location) + assertForNullInput(result) + } + + @Test + fun passNullLocationList() { + val locations: List? = null + val result = LocationEngineResult.create(locations) + assertForNullInput(result) + } + + @Test + fun passValidLocation() { + val location = validLocation + val result = LocationEngineResult.create(location) + assertForValidInput(result) + } + + @Test + fun passValidLocationList() { + val locations = listOf(validLocation) + val result = LocationEngineResult.create(locations) + assertForValidInput(result) + } + + @Test + fun passMutableLocationListWithNulls() { + val locations = locationsWithNulls + val result = LocationEngineResult.create(locations) + assertForValidInput(result) + } + + @Test + fun passImmutableLocationListWithNulls() { + val locations = Collections.unmodifiableList(locationsWithNulls) + val result = LocationEngineResult.create(locations) + assertForValidInput(result) + } + + @Test + fun passImmutableListWithNullLocation() { + val locations = listOf(null) + val result = LocationEngineResult.create(locations) + assertThat(result != null) + assertThat(result.locations.size == 0) + } + + companion object { + private const val TEST_LAT_LNG = 1.0 + // J2K: IDE suggestion to use ArrayList + private val locationsWithNulls: ArrayList + private get() = object : ArrayList() { + init { + add(null) + add(validLocation) + add(null) + } + } + private val validLocation: Location + private get() { + val location = mock(Location::class.java) + `when`(location.latitude).thenReturn(TEST_LAT_LNG) + `when`(location.longitude).thenReturn(TEST_LAT_LNG) + return location + } + + private fun assertForNullInput(result: LocationEngineResult) { + assertThat(result).isNotNull() + assertThat(result.locations).isEmpty() + } + + private fun assertForValidInput(result: LocationEngineResult) { + assertThat(result.locations).isNotNull() + assertThat(result.locations.size).isEqualTo(1) + assertThat(result.locations[0].latitude).isEqualTo(TEST_LAT_LNG) + assertThat(result.locations[0].longitude).isEqualTo(TEST_LAT_LNG) + } + + private fun getValidIntent(location: Location): Intent { + val intent = mock(Intent::class.java) + `when`(intent.hasExtra(LocationManager.KEY_LOCATION_CHANGED)).thenReturn(true) + val bundle = mock(Bundle::class.java) + `when`(bundle.getParcelable(LocationManager.KEY_LOCATION_CHANGED)).thenReturn(location) + `when`(intent.extras).thenReturn(bundle) + return intent + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.java deleted file mode 100644 index d2f9ba7d3..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.location.Location; -import android.location.LocationListener; -import android.os.Looper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; -import org.mockito.stubbing.Stubber; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class LocationEngineTest { - private static final double LATITUDE = 37.7749; - private static final double LONGITUDE = 122.4194; - private static final long INTERVAL = 1000L; - - @Mock - private LocationEngineImpl locationEngineImpl; - - private LocationEngine engine; - - @Before - public void setUp() { - engine = new LocationEngineProxy<>(locationEngineImpl); - } - - @Test - public void getLastLocation() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference resultRef = new AtomicReference<>(); - - LocationEngineCallback callback = getCallback(resultRef, latch); - final Location location = getMockLocation(LATITUDE, LONGITUDE); - final LocationEngineResult expectedResult = getMockEngineResult(location); - - setupDoAnswer(expectedResult).when(locationEngineImpl).getLastLocation(callback); - - engine.getLastLocation(callback); - assertTrue(latch.await(5, SECONDS)); - - LocationEngineResult result = resultRef.get(); - assertThat(result).isSameAs(expectedResult); - assertThat(result.getLastLocation()).isEqualTo(expectedResult.getLastLocation()); - } - - @Test(expected = NullPointerException.class) - public void getLastLocationNullCallback() { - engine.getLastLocation(null); - } - - @Test - public void requestLocationUpdates() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference resultRef = new AtomicReference<>(); - - LocationEngineCallback callback = getCallback(resultRef, latch); - final Location location = getMockLocation(LATITUDE, LONGITUDE); - final LocationEngineResult expectedResult = getMockEngineResult(location); - Looper looper = mock(Looper.class); - - AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport transport = - new AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport(callback); - when(locationEngineImpl.createListener(callback)).thenReturn(transport); - - engine.requestLocationUpdates(getRequest(INTERVAL), callback, looper); - transport.onLocationChanged(location); - assertTrue(latch.await(5, SECONDS)); - - LocationEngineResult result = resultRef.get(); - assertThat(result.getLastLocation()).isEqualTo(expectedResult.getLastLocation()); - } - - @Test(expected = NullPointerException.class) - public void requestLocationUpdatesNullCallback() { - engine.requestLocationUpdates(null, null, null); - } - - @After - public void tearDown() { - reset(locationEngineImpl); - engine = null; - } - - private static Stubber setupDoAnswer(final LocationEngineResult expectedResult) { - return doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) { - LocationEngineCallback callback = invocation.getArgument(0); - callback.onSuccess(expectedResult); - return null; - } - }); - } - - private static LocationEngineRequest getRequest(long interval) { - return new LocationEngineRequest.Builder(interval).build(); - } - - private static LocationEngineCallback getCallback( - final AtomicReference resultRef, - final CountDownLatch latch) { - return new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - resultRef.set(result); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - exception.printStackTrace(); - } - }; - } - - private static LocationEngineResult getMockEngineResult(Location location) { - return LocationEngineResult.create(location); - } - - private static Location getMockLocation(double lat, double lon) { - Location location = mock(Location.class); - location.setLatitude(lat); - location.setLongitude(lon); - return location; - } -} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.kt new file mode 100644 index 000000000..f66e2f716 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/LocationEngineTest.kt @@ -0,0 +1,127 @@ +package org.maplibre.android.location.engine + +import android.location.Location +import android.location.LocationListener +import android.os.Looper +import org.assertj.core.api.Assertions.* +import org.junit.After +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.maplibre.android.location.engine.AndroidLocationEngineImpl.AndroidLocationEngineCallbackTransport +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner +import org.mockito.stubbing.Stubber +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference + +@RunWith(MockitoJUnitRunner::class) +class LocationEngineTest { + @Mock + private val locationEngineImpl: LocationEngineImpl? = null + private var engine: LocationEngine? = null + @Before + fun setUp() { + engine = LocationEngineProxy(locationEngineImpl) + } + + //@get:Throws(InterruptedException::class) + @Test + fun getLastLocation () + { + val latch = CountDownLatch(1) + val resultRef = AtomicReference() + val callback = getCallback(resultRef, latch) + val location = getMockLocation(LATITUDE, LONGITUDE) + val expectedResult = getMockEngineResult(location) + setupDoAnswer(expectedResult).`when`(locationEngineImpl)?.getLastLocation(callback) + engine!!.getLastLocation(callback) + assertTrue(latch.await(5, TimeUnit.SECONDS)) + val result = resultRef.get() + assertThat(result).isSameAs(expectedResult) + assertThat(result.lastLocation).isEqualTo(expectedResult.lastLocation) + } + + // J2K: // TODO: this becomes unreachable, validate necessity of test + @Test(expected = NullPointerException::class) + fun getLastLocationNullCallback () { + engine!!.getLastLocation(null!!) + } + + @Test + @Throws(InterruptedException::class) + fun requestLocationUpdates() { + val latch = CountDownLatch(1) + val resultRef = AtomicReference() + val callback = getCallback(resultRef, latch) + val location = getMockLocation(LATITUDE, LONGITUDE) + val expectedResult = getMockEngineResult(location) + val looper = mock(Looper::class.java) + val transport = AndroidLocationEngineCallbackTransport(callback) + `when`(locationEngineImpl!!.createListener(callback)).thenReturn(transport) + engine!!.requestLocationUpdates(getRequest(INTERVAL), callback, looper) + transport.onLocationChanged(location) + assertTrue(latch.await(5, TimeUnit.SECONDS)) + val result = resultRef.get() + assertThat(result.lastLocation).isEqualTo(expectedResult.lastLocation) + } + + // J2K: // TODO: this becomes unreachable, validate necessity of test + @Test(expected = NullPointerException::class) + fun requestLocationUpdatesNullCallback() { + engine!!.requestLocationUpdates(null!!, null!!, null!!) + } + + @After + fun tearDown() { + reset(locationEngineImpl) + engine = null + } + + companion object { + private const val LATITUDE = 37.7749 + private const val LONGITUDE = 122.4194 + private const val INTERVAL = 1000L + private fun setupDoAnswer(expectedResult: LocationEngineResult): Stubber { + return doAnswer { invocation -> + val callback = invocation.getArgument>(0) + callback.onSuccess(expectedResult) + null + } + } + + private fun getRequest(interval: Long): LocationEngineRequest { + return LocationEngineRequest.Builder(interval).build() + } + + private fun getCallback( + resultRef: AtomicReference, + latch: CountDownLatch): LocationEngineCallback { + // J2K: remove ? + return object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) { + resultRef.set(result) + latch.countDown() + } + + override fun onFailure(exception: Exception) { + exception.printStackTrace() + } + } + } + + private fun getMockEngineResult(location: Location): LocationEngineResult { + return LocationEngineResult.create(location) + } + + private fun getMockLocation(lat: Double, lon: Double): Location { + val location = mock(Location::class.java) + location.latitude = lat + location.longitude = lon + return location + } + } +} \ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.java deleted file mode 100644 index 64970a7e4..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.content.Context; -import android.location.Criteria; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.location.LocationProvider; -import android.os.Looper; - -import androidx.annotation.NonNull; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.junit.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class MapLibreFusedLocationEngineImplAdditionalTest2 { - private static final long INTERVAL = 1000L; - private static final String PROVIDER = "test_provider"; - private ArrayList engines = new ArrayList<>(); - private LocationManager mockLocationManager; - private Location location = new Location(PROVIDER); - - @Before - public void setUp() { - location = mock(Location.class); - when(location.getLatitude()).thenReturn(1.0); - when(location.getLongitude()).thenReturn(2.0); - Context mockContext = mock(Context.class); - mockLocationManager = mock(LocationManager.class); - when(mockContext.getSystemService(anyString())).thenReturn(mockLocationManager); - List providers = new ArrayList<>(); - providers.add(PROVIDER); - when(mockLocationManager.getAllProviders()).thenReturn(providers); - when(mockLocationManager.getBestProvider(any(Criteria.class), anyBoolean())) - .thenReturn(LocationManager.GPS_PROVIDER); - doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) { - LocationListener listener = (LocationListener) invocation.getArguments()[3]; - listener.onProviderEnabled(PROVIDER); - listener.onStatusChanged(PROVIDER, LocationProvider.AVAILABLE, null); - listener.onLocationChanged(location); - listener.onProviderDisabled(PROVIDER); - return null; - } - }).when(mockLocationManager) - .requestLocationUpdates(anyString(), anyLong(), anyFloat(), any(LocationListener.class), any(Looper.class)); - engines.add(new LocationEngineProxy<>(new MapLibreFusedLocationEngineImpl(mockContext))); - engines.add(new LocationEngineProxy<>(new AndroidLocationEngineImpl(mockContext))); - } - - @Test - public void checkGetLastLocation() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(engines.size()); - - for (LocationEngineProxy engineProxy : engines) { - engineProxy.getLastLocation(new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - } - - @Override - public void onFailure(@NonNull Exception exception) { - assertEquals("Last location unavailable", exception.getLocalizedMessage()); - latch.countDown(); - } - }); - } - assertTrue(latch.await(1, TimeUnit.SECONDS)); - - when(mockLocationManager.getLastKnownLocation(anyString())).thenReturn(location); - final CountDownLatch latch1 = new CountDownLatch(engines.size()); - - for (LocationEngineProxy engineProxy : engines) { - engineProxy.getLastLocation(new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - List list = result.getLocations(); - assertEquals(1, list.size()); - assertEquals(1.0, list.get(0).getLatitude(), 0); - assertEquals(2.0, list.get(0).getLongitude(), 0); - latch1.countDown(); - } - - @Override - public void onFailure(@NonNull Exception exception) { - - } - }); - - } - assertTrue(latch1.await(1, TimeUnit.SECONDS)); - - } - - @Test - public void checkRequestAndRemoveLocationUpdates() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(engines.size()); - - LocationEngineCallback engineCallback = new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - List list = result.getLocations(); - assertEquals(1, list.size()); - assertEquals(1.0, list.get(0).getLatitude(), 0); - assertEquals(2.0, list.get(0).getLongitude(), 0); - latch.countDown(); - } - - @Override - public void onFailure(@NonNull Exception exception) { - - } - }; - - - for (LocationEngineProxy engineProxy : engines) { - engineProxy.requestLocationUpdates(getRequest(INTERVAL, LocationEngineRequest.PRIORITY_HIGH_ACCURACY), - engineCallback, mock(Looper.class)); - - assertTrue(latch.await(1, TimeUnit.SECONDS)); - - assertNotNull(engineProxy.removeListener(engineCallback)); - } - - } - - private static LocationEngineRequest getRequest(long interval, int priority) { - return new LocationEngineRequest.Builder(interval).setPriority(priority).build(); - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.kt new file mode 100644 index 000000000..84a77514f --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplAdditionalTest2.kt @@ -0,0 +1,118 @@ +package org.maplibre.android.location.engine + +import android.content.Context +import android.location.Criteria +import android.location.Location +import android.location.LocationListener +import android.location.LocationManager +import android.location.LocationProvider +import android.os.Looper +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentMatchers +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +@RunWith(MockitoJUnitRunner::class) +class MapLibreFusedLocationEngineImplAdditionalTest2 { + private val engines = ArrayList>() + private var mockLocationManager: LocationManager? = null + private var location = Location(PROVIDER) + @Before + fun setUp() { + location = mock(Location::class.java) + `when`(location.latitude).thenReturn(1.0) + `when`(location.longitude).thenReturn(2.0) + val mockContext = mock(Context::class.java) + mockLocationManager = mock(LocationManager::class.java) + `when`(mockContext.getSystemService(anyString())).thenReturn(mockLocationManager) + val providers: MutableList = ArrayList() + providers.add(PROVIDER) + // J2K: add ? + `when`(mockLocationManager?.getAllProviders()).thenReturn(providers) + `when`(mockLocationManager?.getBestProvider(any(Criteria::class.java), anyBoolean())) + .thenReturn(LocationManager.GPS_PROVIDER) + doAnswer { invocation -> + val listener = invocation.arguments[3] as LocationListener + listener.onProviderEnabled(PROVIDER) + listener.onStatusChanged(PROVIDER, LocationProvider.AVAILABLE, null) + listener.onLocationChanged(location) + listener.onProviderDisabled(PROVIDER) + null + }.`when`(mockLocationManager) + // J2K: add ? + ?.requestLocationUpdates(ArgumentMatchers.anyString(), ArgumentMatchers.anyLong(), ArgumentMatchers.anyFloat(), ArgumentMatchers.any(LocationListener::class.java), ArgumentMatchers.any(Looper::class.java)) + engines.add(LocationEngineProxy(MapLibreFusedLocationEngineImpl(mockContext))) + engines.add(LocationEngineProxy(AndroidLocationEngineImpl(mockContext))) + } + + @Test + @Throws(InterruptedException::class) + fun checkGetLastLocation() { + val latch = CountDownLatch(engines.size) + for (engineProxy in engines) { + // J2K: remove ? from LocationEngineResult + engineProxy.getLastLocation(object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) {} + override fun onFailure(exception: Exception) { + assertEquals("Last location unavailable", exception.localizedMessage) + latch.countDown() + } + }) + } + assertTrue(latch.await(1, TimeUnit.SECONDS)) + `when`(mockLocationManager!!.getLastKnownLocation(anyString())).thenReturn(location) + val latch1 = CountDownLatch(engines.size) + for (engineProxy in engines) { + // J2K: remove ? from LocationEngineResult + engineProxy.getLastLocation(object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) { + val list = result.locations + assertEquals(1, list.size.toLong()) + assertEquals(1.0, list[0].latitude, 0.0) + assertEquals(2.0, list[0].longitude, 0.0) + latch1.countDown() + } + + override fun onFailure(exception: Exception) {} + }) + } + assertTrue(latch1.await(1, TimeUnit.SECONDS)) + } + + @Test + @Throws(InterruptedException::class) + fun checkRequestAndRemoveLocationUpdates() { + val latch = CountDownLatch(engines.size) + // J2K: remove ? from LocationEngineResult + val engineCallback: LocationEngineCallback = object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) { + val list = result.locations + assertEquals(1, list.size.toLong()) + assertEquals(1.0, list[0].latitude, 0.0) + assertEquals(2.0, list[0].longitude, 0.0) + latch.countDown() + } + + override fun onFailure(exception: Exception) {} + } + for (engineProxy in engines) { + engineProxy.requestLocationUpdates(getRequest(INTERVAL, LocationEngineRequest.PRIORITY_HIGH_ACCURACY), + engineCallback, mock(Looper::class.java)) + assertTrue(latch.await(1, TimeUnit.SECONDS)) + assertNotNull(engineProxy.removeListener(engineCallback)) + } + } + + companion object { + private const val INTERVAL = 1000L + private const val PROVIDER = "test_provider" + private fun getRequest(interval: Long, priority: Int): LocationEngineRequest { + return LocationEngineRequest.Builder(interval).setPriority(priority).build() + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.java deleted file mode 100644 index a526ccdbb..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.java +++ /dev/null @@ -1,177 +0,0 @@ -package org.maplibre.android.location.engine; - -import android.app.PendingIntent; -import android.content.Context; -import android.location.Criteria; -import android.location.Location; -import android.location.LocationListener; -import android.location.LocationManager; -import android.os.Looper; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; - -import java.util.Arrays; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static junit.framework.TestCase.assertTrue; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.anyBoolean; -import static org.mockito.Mockito.anyFloat; -import static org.mockito.Mockito.anyLong; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@RunWith(MockitoJUnitRunner.class) -public class MapLibreFusedLocationEngineImplTest { - private static final double LATITUDE = 37.7749; - private static final double LONGITUDE = 122.4194; - - @Mock - private LocationManager locationManagerMock; - - private LocationEngine engine; - private MapLibreFusedLocationEngineImpl maplibreFusedLocationEngineImpl; - - @Before - public void setUp() { - Context context = mock(Context.class); - when(context.getSystemService(Context.LOCATION_SERVICE)).thenReturn(locationManagerMock); - maplibreFusedLocationEngineImpl = new MapLibreFusedLocationEngineImpl(context); - engine = new LocationEngineProxy<>(maplibreFusedLocationEngineImpl); - } - - @Test - public void getLastLocation() throws InterruptedException { - final CountDownLatch latch = new CountDownLatch(1); - final AtomicReference resultRef = new AtomicReference<>(); - - LocationEngineCallback callback = getCallback(resultRef, latch); - final Location location = getMockLocation(LATITUDE, LONGITUDE); - final LocationEngineResult expectedResult = getMockEngineResult(location); - - when(locationManagerMock.getAllProviders()).thenReturn(Arrays.asList("gps", "network")); - when(locationManagerMock.getLastKnownLocation(anyString())).thenReturn(location); - - engine.getLastLocation(callback); - assertTrue(latch.await(5, SECONDS)); - - LocationEngineResult result = resultRef.get(); - assertThat(result.getLastLocation()).isEqualTo(expectedResult.getLastLocation()); - } - - @Test - public void createListener() { - LocationEngineCallback callback = mock(LocationEngineCallback.class); - LocationListener locationListener = maplibreFusedLocationEngineImpl.createListener(callback); - Location mockLocation = getMockLocation(LATITUDE, LONGITUDE); - locationListener.onLocationChanged(mockLocation); - ArgumentCaptor argument = ArgumentCaptor.forClass(LocationEngineResult.class); - verify(callback).onSuccess(argument.capture()); - - LocationEngineResult result = argument.getValue(); - assertThat(result.getLastLocation()).isSameAs(mockLocation); - } - - @Test - public void requestLocationUpdatesOutdoors() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - LocationEngineCallback callback = mock(LocationEngineCallback.class); - Looper looper = mock(Looper.class); - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn("gps"); - engine.requestLocationUpdates(request, callback, looper); - verify(locationManagerMock, times(2)).requestLocationUpdates(anyString(), - anyLong(), anyFloat(), any(LocationListener.class), any(Looper.class)); - } - - @Test - public void requestLocationUpdatesIndoors() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - LocationEngineCallback callback = mock(LocationEngineCallback.class); - Looper looper = mock(Looper.class); - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn("network"); - engine.requestLocationUpdates(request, callback, looper); - verify(locationManagerMock, times(1)).requestLocationUpdates(anyString(), - anyLong(), anyFloat(), any(LocationListener.class), any(Looper.class)); - } - - @Test - public void requestLocationUpdatesOutdoorsWithPendingIntent() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - PendingIntent pendingIntent = mock(PendingIntent.class); - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn("gps"); - engine.requestLocationUpdates(request, pendingIntent); - verify(locationManagerMock, times(2)).requestLocationUpdates(anyString(), - anyLong(), anyFloat(), any(PendingIntent.class)); - } - - @Test - public void requestLocationUpdatesIndoorsWithPendingIntent() { - LocationEngineRequest request = new LocationEngineRequest.Builder(10) - .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build(); - PendingIntent pendingIntent = mock(PendingIntent.class); - when(locationManagerMock.getBestProvider(any(Criteria.class), anyBoolean())).thenReturn("network"); - engine.requestLocationUpdates(request, pendingIntent); - verify(locationManagerMock, times(1)).requestLocationUpdates(anyString(), - anyLong(), anyFloat(), any(PendingIntent.class)); - } - - @Test(expected = NullPointerException.class) - public void getLastLocationNullCallback() { - engine.getLastLocation(null); - } - - @Test(expected = NullPointerException.class) - public void requestLocationUpdatesNullCallback() { - engine.requestLocationUpdates(null, null, null); - } - - @After - public void tearDown() { - reset(locationManagerMock); - engine = null; - } - - private static LocationEngineCallback getCallback( - final AtomicReference resultRef, - final CountDownLatch latch) { - return new LocationEngineCallback() { - @Override - public void onSuccess(LocationEngineResult result) { - resultRef.set(result); - latch.countDown(); - } - - @Override - public void onFailure(Exception exception) { - exception.printStackTrace(); - } - }; - } - - private static LocationEngineResult getMockEngineResult(Location location) { - return LocationEngineResult.create(location); - } - - private static Location getMockLocation(double lat, double lon) { - Location location = mock(Location.class); - location.setLatitude(lat); - location.setLongitude(lon); - return location; - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.kt new file mode 100644 index 000000000..f7383e5f9 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/location/engine/MapLibreFusedLocationEngineImplTest.kt @@ -0,0 +1,166 @@ +package org.maplibre.android.location.engine + +import android.app.PendingIntent +import android.content.Context +import android.location.Criteria +import android.location.Location +import android.location.LocationListener +import android.location.LocationManager +import android.os.Looper +import junit.framework.TestCase.* +import org.assertj.core.api.Assertions.* +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.ArgumentMatchers.* +import org.mockito.Mock +import org.mockito.Mockito.* +import org.mockito.junit.MockitoJUnitRunner +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference + +@RunWith(MockitoJUnitRunner::class) +class MapLibreFusedLocationEngineImplTest { + @Mock + private val locationManagerMock: LocationManager? = null + private var engine: LocationEngine? = null + private var maplibreFusedLocationEngineImpl: MapLibreFusedLocationEngineImpl? = null + @Before + fun setUp() { + val context = mock(Context::class.java) + `when`(context.getSystemService(Context.LOCATION_SERVICE)).thenReturn(locationManagerMock) + maplibreFusedLocationEngineImpl = MapLibreFusedLocationEngineImpl(context) + engine = LocationEngineProxy(maplibreFusedLocationEngineImpl) + } + + // J2K: rewrite test to not use "@get" + @Test + fun getLastLocation() { + val latch = CountDownLatch(1) + val resultRef = AtomicReference() + val callback = getCallback(resultRef, latch) + val location = getMockLocation(LATITUDE, LONGITUDE) + val expectedResult = getMockEngineResult(location) + `when`(locationManagerMock!!.allProviders).thenReturn(mutableListOf("gps", "network")) + `when`(locationManagerMock.getLastKnownLocation(anyString())).thenReturn(location) + engine!!.getLastLocation(callback) + assertTrue(latch.await(5, TimeUnit.SECONDS)) + val result = resultRef.get() + assertThat(result.lastLocation).isEqualTo(expectedResult.lastLocation) + } + + @Test + fun createListener() { + // J2K: IDE suggestion "as LocationEngineCallback" + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val locationListener = maplibreFusedLocationEngineImpl!!.createListener(callback) + val mockLocation = getMockLocation(LATITUDE, LONGITUDE) + locationListener.onLocationChanged(mockLocation) + val argument = ArgumentCaptor.forClass(LocationEngineResult::class.java) + verify(callback).onSuccess(argument.capture()) + val result = argument.value + assertThat(result.lastLocation).isSameAs(mockLocation) + } + + @Test + fun requestLocationUpdatesOutdoors() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + // J2K: IDE suggestion "as LocationEngineCallback" + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val looper = mock(Looper::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn("gps") + engine!!.requestLocationUpdates(request, callback, looper) + verify(locationManagerMock, times(2)).requestLocationUpdates(anyString(), + anyLong(), anyFloat(), any(LocationListener::class.java), any(Looper::class.java)) + } + + @Test + fun requestLocationUpdatesIndoors() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + // J2K: IDE suggestion "as LocationEngineCallback" + val callback: LocationEngineCallback = mock(LocationEngineCallback::class.java) as LocationEngineCallback + val looper = mock(Looper::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn("network") + engine!!.requestLocationUpdates(request, callback, looper) + verify(locationManagerMock, times(1)).requestLocationUpdates(anyString(), + anyLong(), anyFloat(), any(LocationListener::class.java), any(Looper::class.java)) + } + + @Test + fun requestLocationUpdatesOutdoorsWithPendingIntent() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + val pendingIntent = mock(PendingIntent::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn("gps") + engine!!.requestLocationUpdates(request, pendingIntent) + verify(locationManagerMock, times(2)).requestLocationUpdates(anyString(), + anyLong(), anyFloat(), any(PendingIntent::class.java)) + } + + @Test + fun requestLocationUpdatesIndoorsWithPendingIntent() { + val request = LocationEngineRequest.Builder(10) + .setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY).build() + val pendingIntent = mock(PendingIntent::class.java) + `when`(locationManagerMock!!.getBestProvider(any(Criteria::class.java), anyBoolean())).thenReturn("network") + engine!!.requestLocationUpdates(request, pendingIntent) + verify(locationManagerMock, times(1)).requestLocationUpdates(anyString(), + anyLong(), anyFloat(), any(PendingIntent::class.java)) + } + +// J2k: // TODO: see https://github.com/maplibre/maplibre-native/issues/1949 +/* + // J2K: rewrite test to not use "@get", rename to "getLastLocationNull" + @Test(expected = NullPointerException::class) + fun getLastLocationNull() { + engine!!.getLastLocation(null!!) + } + + // J2K: changed "null" to "null!!" + @Test(expected = NullPointerException::class) + fun requestLocationUpdatesNullCallback() { + engine!!.requestLocationUpdates(null!!, null!!, null!!) + } +*/ + @After + fun tearDown() { + reset(locationManagerMock) + engine = null + } + + companion object { + private const val LATITUDE = 37.7749 + private const val LONGITUDE = 122.4194 + private fun getCallback( + resultRef: AtomicReference, + latch: CountDownLatch): LocationEngineCallback { + // J2K: remove '?' from LocationEngineResult? + return object : LocationEngineCallback { + override fun onSuccess(result: LocationEngineResult) { + resultRef.set(result) + latch.countDown() + } + + override fun onFailure(exception: Exception) { + exception.printStackTrace() + } + } + } + + private fun getMockEngineResult(location: Location): LocationEngineResult { + return LocationEngineResult.create(location) + } + + private fun getMockLocation(lat: Double, lon: Double): Location { + val location = mock(Location::class.java) + location.latitude = lat + location.longitude = lon + return location + } + } +} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.java b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.java deleted file mode 100644 index 8d1c72199..000000000 --- a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.java +++ /dev/null @@ -1,268 +0,0 @@ -package org.maplibre.android.utils; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyByte; -import static org.mockito.ArgumentMatchers.anyDouble; -import static org.mockito.ArgumentMatchers.anyFloat; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class MockParcel { - - @Nullable - public static Parcelable obtain(@NonNull Parcelable object) { - return obtain(object, 0); - } - - @Nullable - public static Parcelable obtain(@NonNull Parcelable object, int describeContentsValue) { - testDescribeContents(object, describeContentsValue); - testParcelableArray(object); - return testParcelable(object); - } - - public static Parcelable testParcelable(@NonNull Parcelable object) { - Parcel parcel = ParcelMocker.obtain(object); - object.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - - try { - Field field = object.getClass().getDeclaredField("CREATOR"); - field.setAccessible(true); - Class creatorClass = field.getType(); - Object fieldValue = field.get(object); - Method myMethod = creatorClass.getDeclaredMethod("createFromParcel", Parcel.class); - return (Parcelable) myMethod.invoke(fieldValue, parcel); - } catch (Exception exception) { - return null; - } - } - - public static void testParcelableArray(@NonNull Parcelable object) { - Parcelable[] objects = new Parcelable[] {object}; - Parcel parcel = ParcelMocker.obtain(objects); - parcel.writeParcelableArray(objects, 0); - parcel.setDataPosition(0); - Parcelable[] parcelableArray = parcel.readParcelableArray(object.getClass().getClassLoader()); - assertArrayEquals("parcel should match initial object", objects, parcelableArray); - } - - public static void testDescribeContents(@NonNull Parcelable object, int describeContentsValue) { - if (describeContentsValue == 0) { - assertEquals("\nExpecting a describeContents() value of 0 for a " + object.getClass().getSimpleName() - + " instance." + "\nYou can provide a different value for describeContentValue through the obtain method.", - 0, - object.describeContents()); - } else { - assertEquals("Expecting a describeContents() value of " + describeContentsValue, - describeContentsValue, - object.describeContents()); - } - } - - private static class ParcelMocker { - - public static Parcel obtain(@NonNull Parcelable target) { - Parcel parcel = new ParcelMocker(target).getMockedParcel(); - target.writeToParcel(parcel, 0); - parcel.setDataPosition(0); - return parcel; - } - - public static Parcel obtain(@NonNull Parcelable[] targets) { - if (targets.length == 0) { - throw new IllegalArgumentException("The passed argument may not be empty"); - } - Parcel parcel = new ParcelMocker(targets[0]).getMockedParcel(); - parcel.writeParcelableArray(targets, 0); - parcel.setDataPosition(0); - return parcel; - } - - private List objects; - private Object object; - private Parcel mockedParcel; - private int position; - - private ParcelMocker(Object o) { - this.object = o; - mockedParcel = mock(Parcel.class); - objects = new ArrayList<>(); - setupMock(); - } - - private Parcel getMockedParcel() { - return mockedParcel; - } - - private void setupMock() { - setupWrites(); - setupReads(); - setupOthers(); - } - - private void setupWrites() { - Answer writeValueAnswer = new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Object parameter = invocation.getArguments()[0]; - objects.add(parameter); - return null; - } - }; - Answer writeArrayAnswer = new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - Object[] parameters = (Object[]) invocation.getArguments()[0]; - objects.add(parameters.length); - for (Object o : parameters) { - objects.add(o); - } - return null; - } - }; - Answer writeIntArrayAnswer = new Answer() { - @Override - public Void answer(InvocationOnMock invocation) throws Throwable { - int[] parameters = (int[]) invocation.getArguments()[0]; - if (parameters != null) { - objects.add(parameters.length); - for (Object o : parameters) { - objects.add(o); - } - } else { - objects.add(-1); - } - return null; - } - }; - doAnswer(writeValueAnswer).when(mockedParcel).writeByte(anyByte()); - doAnswer(writeValueAnswer).when(mockedParcel).writeLong(anyLong()); - doAnswer(writeValueAnswer).when(mockedParcel).writeString(anyString()); - doAnswer(writeValueAnswer).when(mockedParcel).writeInt(anyInt()); - doAnswer(writeIntArrayAnswer).when(mockedParcel).writeIntArray(any(int[].class)); - doAnswer(writeValueAnswer).when(mockedParcel).writeDouble(anyDouble()); - doAnswer(writeValueAnswer).when(mockedParcel).writeFloat(anyFloat()); - doAnswer(writeValueAnswer).when(mockedParcel).writeParcelable(any(Parcelable.class), eq(0)); - doAnswer(writeArrayAnswer).when(mockedParcel).writeParcelableArray(any(Parcelable[].class), eq(0)); - } - - private void setupReads() { - when(mockedParcel.readInt()).then(new Answer() { - @NonNull - @Override - public Integer answer(InvocationOnMock invocation) throws Throwable { - return (Integer) objects.get(position++); - } - }); - when(mockedParcel.readByte()).thenAnswer(new Answer() { - @NonNull - @Override - public Byte answer(InvocationOnMock invocation) throws Throwable { - return (Byte) objects.get(position++); - } - }); - when(mockedParcel.readLong()).thenAnswer(new Answer() { - @NonNull - @Override - public Long answer(InvocationOnMock invocation) throws Throwable { - return (Long) objects.get(position++); - } - }); - when(mockedParcel.readString()).thenAnswer(new Answer() { - @NonNull - @Override - public String answer(InvocationOnMock invocation) throws Throwable { - return (String) objects.get(position++); - } - }); - when(mockedParcel.readDouble()).thenAnswer(new Answer() { - @NonNull - @Override - public Double answer(InvocationOnMock invocation) throws Throwable { - return (Double) objects.get(position++); - } - }); - when(mockedParcel.readFloat()).thenAnswer(new Answer() { - @NonNull - @Override - public Float answer(InvocationOnMock invocation) throws Throwable { - return (Float) objects.get(position++); - } - }); - when(mockedParcel.readParcelable(Parcelable.class.getClassLoader())).thenAnswer(new Answer() { - @NonNull - @Override - public Parcelable answer(InvocationOnMock invocation) throws Throwable { - return (Parcelable) objects.get(position++); - } - }); - when(mockedParcel.readParcelableArray(Parcelable.class.getClassLoader())).thenAnswer(new Answer() { - @NonNull - @Override - public Object[] answer(InvocationOnMock invocation) throws Throwable { - int size = (Integer) objects.get(position++); - Field field = object.getClass().getDeclaredField("CREATOR"); - field.setAccessible(true); - Class creatorClass = field.getType(); - Object fieldValue = field.get(object); - Method myMethod = creatorClass.getDeclaredMethod("newArray", int.class); - Object[] array = (Object[]) myMethod.invoke(fieldValue, size); - for (int i = 0; i < size; i++) { - array[i] = objects.get(position++); - } - return array; - } - }); - when(mockedParcel.createIntArray()).then(new Answer() { - @Nullable - @Override - public int[] answer(InvocationOnMock invocation) throws Throwable { - int size = (Integer) objects.get(position++); - if (size == -1) { - return null; - } - - int[] array = new int[size]; - for (int i = 0; i < size; i++) { - array[i] = (Integer) objects.get(position++); - } - - return array; - } - }); - } - - private void setupOthers() { - doAnswer(new Answer() { - @Nullable - @Override - public Void answer(@NonNull InvocationOnMock invocation) throws Throwable { - position = ((Integer) invocation.getArguments()[0]); - return null; - } - }).when(mockedParcel).setDataPosition(anyInt()); - } - } -} diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.kt b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.kt new file mode 100644 index 000000000..5be793633 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDK/src/test/java/org/maplibre/android/utils/MockParcel.kt @@ -0,0 +1,169 @@ +package org.maplibre.android.utils + +import android.os.Parcel +import android.os.Parcelable +import org.junit.Assert.* +import org.mockito.ArgumentMatchers +import org.mockito.Mockito.* +import org.mockito.stubbing.Answer + +object MockParcel { + @JvmOverloads + fun obtain(`object`: Parcelable, describeContentsValue: Int = 0): Parcelable? { + testDescribeContents(`object`, describeContentsValue) + testParcelableArray(`object`) + return testParcelable(`object`) + } + + fun testParcelable(`object`: Parcelable): Parcelable? { + val parcel = ParcelMocker.obtain(`object`) + `object`.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + return try { + val field = `object`.javaClass.getDeclaredField("CREATOR") + field.isAccessible = true + val creatorClass = field.type + val fieldValue = field[`object`] + val myMethod = creatorClass.getDeclaredMethod("createFromParcel", Parcel::class.java) + myMethod.invoke(fieldValue, parcel) as Parcelable + } catch (exception: Exception) { + null + } + } + + fun testParcelableArray(`object`: Parcelable) { + val objects = arrayOf(`object`) + val parcel = ParcelMocker.obtain(objects) + parcel.writeParcelableArray(objects, 0) + parcel.setDataPosition(0) + val parcelableArray = parcel.readParcelableArray(`object`.javaClass.classLoader) + assertArrayEquals("parcel should match initial object", objects, parcelableArray) + } + + fun testDescribeContents(`object`: Parcelable, describeContentsValue: Int) { + if (describeContentsValue == 0) { + assertEquals(""" +Expecting a describeContents() value of 0 for a ${`object`.javaClass.simpleName} instance. +You can provide a different value for describeContentValue through the obtain method.""", + 0, + `object`.describeContents().toLong()) + } else { + assertEquals("Expecting a describeContents() value of $describeContentsValue", + describeContentsValue.toLong(), + `object`.describeContents().toLong()) + } + } + + private class ParcelMocker private constructor(private val `object`: Any) { + private val objects: MutableList + private val mockedParcel: Parcel + private var position = 0 + + init { + mockedParcel = mock(Parcel::class.java) + objects = ArrayList() + setupMock() + } + + private fun setupMock() { + setupWrites() + setupReads() + setupOthers() + } + + private fun setupWrites() { + val writeValueAnswer: Answer = Answer { invocation -> + val parameter = invocation.arguments[0] + objects.add(parameter) + null + } + val writeArrayAnswer: Answer = Answer { invocation -> + val parameters = invocation.arguments[0] as Array + objects.add(parameters.size) + for (o in parameters) { + objects.add(o) + } + null + } + val writeIntArrayAnswer: Answer = Answer { invocation -> + val parameters = invocation.arguments[0] as IntArray + if (parameters != null) { + objects.add(parameters.size) + for (o in parameters) { + objects.add(o) + } + } else { + objects.add(-1) + } + null + } + doAnswer(writeValueAnswer).`when`(mockedParcel).writeByte(ArgumentMatchers.anyByte()) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeLong(ArgumentMatchers.anyLong()) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeString(ArgumentMatchers.anyString()) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeInt(ArgumentMatchers.anyInt()) + doAnswer(writeIntArrayAnswer).`when`(mockedParcel).writeIntArray(ArgumentMatchers.any(IntArray::class.java)) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeDouble(ArgumentMatchers.anyDouble()) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeFloat(ArgumentMatchers.anyFloat()) + doAnswer(writeValueAnswer).`when`(mockedParcel).writeParcelable(ArgumentMatchers.any(Parcelable::class.java), ArgumentMatchers.eq(0)) + doAnswer(writeArrayAnswer).`when`(mockedParcel).writeParcelableArray(ArgumentMatchers.any(Array::class.java), ArgumentMatchers.eq(0)) + } + + private fun setupReads() { + `when`(mockedParcel.readInt()).then { objects[position++] as Int } + `when`(mockedParcel.readByte()).thenAnswer { objects[position++] as Byte } + `when`(mockedParcel.readLong()).thenAnswer { objects[position++] as Long } + `when`(mockedParcel.readString()).thenAnswer { objects[position++] as String } + `when`(mockedParcel.readDouble()).thenAnswer { objects[position++] as Double } + `when`(mockedParcel.readFloat()).thenAnswer { objects[position++] as Float } + `when`(mockedParcel.readParcelable(Parcelable::class.java.classLoader)).thenAnswer { objects[position++] as Parcelable } + `when`(mockedParcel.readParcelableArray(Parcelable::class.java.classLoader)).thenAnswer { + val size = objects[position++] as Int + val field = `object`.javaClass.getDeclaredField("CREATOR") + field.isAccessible = true + val creatorClass = field.type + val fieldValue = field[`object`] + val myMethod = creatorClass.getDeclaredMethod("newArray", Int::class.javaPrimitiveType) + val array = myMethod.invoke(fieldValue, size) as Array + for (i in 0 until size) { + array[i] = objects[position++] + } + array + } + `when`(mockedParcel.createIntArray()).then(Answer { + val size = objects[position++] as Int + if (size == -1) { + return@Answer null + } + val array = IntArray(size) + for (i in 0 until size) { + array[i] = objects[position++] as Int + } + array + }) + } + + private fun setupOthers() { + doAnswer { invocation -> + position = invocation.arguments[0] as Int + null + }.`when`(mockedParcel).setDataPosition(ArgumentMatchers.anyInt()) + } + + companion object { + fun obtain(target: Parcelable): Parcel { + val parcel = ParcelMocker(target).mockedParcel + target.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + return parcel + } + + fun obtain(targets: Array): Parcel { + require(targets.size != 0) { "The passed argument may not be empty" } + val parcel = ParcelMocker(targets[0]).mockedParcel + parcel.writeParcelableArray(targets, 0) + parcel.setDataPosition(0) + return parcel + } + } + } +}