blob: 5b0945996b437cf9255dcc440f4a10ea0fdaabaf [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.device.geolocation;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doAnswer;
import android.content.Context;
import android.location.LocationManager;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.FusedLocationProviderApi;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.ParameterizedRobolectricTestRunner;
import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.internal.Shadow;
import org.robolectric.shadows.ShadowLocationManager;
import org.robolectric.shadows.ShadowLog; // remove me ?
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Feature;
import java.util.Arrays;
import java.util.Collection;
/**
* Test suite for Java Geolocation.
*/
@RunWith(ParameterizedRobolectricTestRunner.class)
@Config(sdk = 21, manifest = Config.NONE)
public class LocationProviderTest {
public static enum LocationProviderType { MOCK, ANDROID, GMS_CORE }
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{LocationProviderType.MOCK},
{LocationProviderType.ANDROID}, {LocationProviderType.GMS_CORE}});
}
@Mock
private Context mContext;
// Member variables for LocationProviderType.GMS_CORE case.
@Mock
private GoogleApiClient mGoogleApiClient;
private boolean mGoogleApiClientIsConnected;
// Member variables for LocationProviderType.ANDROID case.
private LocationManager mLocationManager;
private ShadowLocationManager mShadowLocationManager;
private LocationProviderAdapter mLocationProviderAdapter;
private final LocationProviderType mApi;
public LocationProviderTest(LocationProviderType api) {
mApi = api;
}
@Before
public void setUp() {
ShadowLog.stream = System.out;
MockitoAnnotations.initMocks(this);
mContext = Mockito.mock(Context.class);
}
/**
* Verify a normal start/stop call pair with the given LocationProvider.
*/
@Test
@Feature({"Location"})
public void testStartStop() {
assertTrue("Should be on UI thread", ThreadUtils.runningOnUiThread());
setLocationProvider();
createLocationProviderAdapter();
startLocationProviderAdapter(false);
stopLocationProviderAdapter();
}
/**
* Verify a start/upgrade/stop call sequencewith the given LocationProvider.
*/
@Test
@Feature({"Location"})
public void testStartUpgradeStop() {
assertTrue("Should be on UI thread", ThreadUtils.runningOnUiThread());
setLocationProvider();
createLocationProviderAdapter();
startLocationProviderAdapter(false);
startLocationProviderAdapter(true);
stopLocationProviderAdapter();
}
private void createLocationProviderAdapter() {
mLocationProviderAdapter = LocationProviderAdapter.create(mContext);
assertNotNull("LocationProvider", mLocationProviderAdapter);
}
private void setLocationProvider() {
if (mApi == LocationProviderType.MOCK) {
setLocationProviderMock();
} else if (mApi == LocationProviderType.ANDROID) {
setLocationProviderAndroid();
} else if (mApi == LocationProviderType.GMS_CORE) {
setLocationProviderGmsCore();
} else {
assert false;
}
}
private void setLocationProviderMock() {
LocationProviderFactory.setLocationProviderImpl(new MockLocationProvider());
}
private void setLocationProviderAndroid() {
LocationProviderAndroid locationProviderAndroid = new LocationProviderAndroid(mContext);
// Robolectric has a ShadowLocationManager class that mocks the behaviour of the real
// class very closely. Use it here.
mLocationManager = Shadow.newInstanceOf(LocationManager.class);
mShadowLocationManager = Shadows.shadowOf(mLocationManager);
locationProviderAndroid.setLocationManagerForTesting(mLocationManager);
LocationProviderFactory.setLocationProviderImpl(locationProviderAndroid);
}
private void setLocationProviderGmsCore() {
// Robolectric has a ShadowGoogleApiClientBuilder class that mocks the behaviour of the real
// class very closely, but it's not available in our build
mGoogleApiClient = Mockito.mock(GoogleApiClient.class);
mGoogleApiClientIsConnected = false;
doAnswer(new Answer<Boolean>() {
public Boolean answer(InvocationOnMock invocation) {
return mGoogleApiClientIsConnected;
}
})
.when(mGoogleApiClient)
.isConnected();
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
mGoogleApiClientIsConnected = true;
return null;
}
})
.when(mGoogleApiClient)
.connect();
doAnswer(new Answer<Void>() {
public Void answer(InvocationOnMock invocation) {
mGoogleApiClientIsConnected = false;
return null;
}
})
.when(mGoogleApiClient)
.disconnect();
FusedLocationProviderApi fusedLocationProviderApi =
Mockito.mock(FusedLocationProviderApi.class);
LocationProviderGmsCore locationProviderGmsCore =
new LocationProviderGmsCore(mGoogleApiClient, fusedLocationProviderApi);
LocationProviderFactory.setLocationProviderImpl(locationProviderGmsCore);
}
private void startLocationProviderAdapter(boolean highResolution) {
mLocationProviderAdapter.start(highResolution);
assertTrue("Should be running", mLocationProviderAdapter.isRunning());
}
private void stopLocationProviderAdapter() {
mLocationProviderAdapter.stop();
assertFalse("Should have stopped", mLocationProviderAdapter.isRunning());
}
}