package org.physical_web.physicalweb; import org.physical_web.collection.PhysicalWebCollection; import org.physical_web.collection.PwPair; import org.physical_web.collection.PwsClient; import org.physical_web.collection.PwsResult; import org.physical_web.collection.UrlDevice; import android.content.Context; import android.content.res.Resources; import org.json.JSONException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.mockito.Matchers; import org.mockito.Mockito; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; /** * Unit tests for Utils. */ public class UtilsTest { private static final String GOOGLE_PWS_URL = "https://physicalweb.googleapis.com"; private static final int GOOGLE_PWS_VERSION = 2; private static final String PROD_PWS_URL = "https://url-caster.appspot.com"; private static final int PROD_PWS_VERSION = 1; public static final String BLE_DEVICE_TYPE = "ble"; private static final String SCAN_TIME_KEY = "scantime"; private static final String PUBLIC_KEY = "public"; private static final String RSSI_KEY = "rssi"; private static final String TYPE_KEY = "type"; private static final String TXPOWER_KEY = "tx"; private static final String PWS_TRIP_TIME_KEY = "pwstriptime"; private static final String GOOGLE_API_KEY_RESOURCE_KEY = "google_api_key"; private static final String GOOGLE_API_KEY_RESOURCE_TYPE = "string"; private static final String SAMPLE_API_KEY = "key"; private static final String SAMPLE_PACKAGE_NAME = "test"; List<String> siteUrls = Arrays.asList((new String[]{"www.google.com", "www.google.com/maps"})); @Before public void setUp() throws Exception { for (String url : siteUrls) { if (Utils.isFavorite(url)) { Utils.toggleFavorite(url); } } } /* * Tests containsFavorite with empty list. * * Prerequisites: * - Set of favorites is empty * Procedure: * 1. Verify list does not contain favorite */ @Test public void testContainsFavoriteEmptyList() throws Exception { List<PwPair> pairs = new ArrayList<>(); Assert.assertFalse(Utils.containsFavorite(pairs)); } /* * Tests containsFavorite with a one element list. Also exercises isFavorite and toggleFavorite. * * Prerequisites: * - Set of favorites is empty * Procedure: * 1. Add 1 PwPair to list * 2. Verify list does not contain favorite * 3. Add site used for PwPair to favorites * 4. Verify list contains favorite */ @Test public void testContainsFavoriteOneItem() throws Exception { String siteUrl = siteUrls.get(0); List<PwPair> pairs = new ArrayList<>(); pairs.add(new PwPair(null, new PwsResult("", siteUrl))); Assert.assertFalse(Utils.containsFavorite(pairs)); Utils.toggleFavorite(siteUrl); Assert.assertTrue(Utils.containsFavorite(pairs)); } /* * Tests containsFavorite with a two element list. Also exercises isFavorite and toggleFavorite. * * Prerequisites: * - Set of favorites is empty * Procedure: * 1. Add 1 PwPair to list * 2. Verify list does not contain favorite * 3. Add site used for PwPair to favorites * 4. Verify list contains favorite */ @Test public void testContainsFavoriteTwoItems() throws Exception { String siteUrl = siteUrls.get(0); List<PwPair> pairs = new ArrayList<>(); pairs.add(new PwPair(null, new PwsResult("", siteUrl))); pairs.add(new PwPair(null, new PwsResult("", siteUrls.get(1)))); Assert.assertFalse(Utils.containsFavorite(pairs)); Utils.toggleFavorite(siteUrl); Assert.assertTrue(Utils.containsFavorite(pairs)); } /* * Tests formatEndpointForSharedPreferences. * * Procedure: * 1. Verify string with null values and 0 * 2. Verify string with empty values and the minimum integer value * 3. Verify string with non empty values and the maximum integer value */ @Test public void testFormatEndpointForSharedPreferences() throws Exception { String url = null; int version = 0; String key = null; Assert.assertArrayEquals("Null values", new String[]{"", Integer.toString(version)}, Utils.formatEndpointForSharedPrefernces(url, version, key).split("\0")); url = ""; version = Integer.MIN_VALUE; key = ""; Assert.assertArrayEquals("Empty Strings and min", new String[]{url, Integer.toString(version)}, Utils.formatEndpointForSharedPrefernces(url, version, key).split("\0")); url = "url"; version = Integer.MAX_VALUE; key = SAMPLE_API_KEY; Assert.assertArrayEquals("Non empty strings and max", new String[]{url, Integer.toString(version), key}, Utils.formatEndpointForSharedPrefernces(url, version, key).split("\0")); } /* * Tests getDefaultPwsEndpointPreferenceString. Also exercises isGoogleApiKeyAvailable and * formatEndpointForSharedPreferences. * * Procedure: * 1. Configure there to not be an api key * 2. Verify default is the prod pws * 3. Configure there to be an api key * 4. Verify default is the Google pws */ @Test public void testGetDefaultPwsEndpointPreferenceString() throws Exception { int resId = 1; String apiKey = SAMPLE_API_KEY; String packageName = SAMPLE_PACKAGE_NAME; Resources mockResources = Mockito.mock(Resources.class); Mockito.when(mockResources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(0); Context mockContext = Mockito.mock(Context.class); Mockito.when(mockContext.getResources()).thenReturn(mockResources); Mockito.when(mockContext.getPackageName()).thenReturn(packageName); Assert.assertEquals(PROD_PWS_URL + "\0" + PROD_PWS_VERSION + "\0", Utils.getDefaultPwsEndpointPreferenceString(mockContext)); Mockito.when(mockResources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(resId); Mockito.when(mockContext.getString(resId)).thenReturn(apiKey); Assert.assertEquals(GOOGLE_PWS_URL + "\0" + GOOGLE_PWS_VERSION + "\0" + apiKey, Utils.getDefaultPwsEndpointPreferenceString(mockContext)); } /* * Tests getDefaultPwsEndpointPreferenceString. Also exercises isGoogleApiKeyAvailable and * formatEndpointForSharedPreferences. * * Procedure: * 1. Configure there to be an api key * 2. Verify setEnpoint is called with Google pws */ @Test public void testSetPwsEndPointToGoogle() throws Exception { int resId = 1; String apiKey = SAMPLE_API_KEY; String packageName = SAMPLE_PACKAGE_NAME; Resources mockResources = Mockito.mock(Resources.class); Mockito.when(mockResources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(resId); Context mockContext = Mockito.mock(Context.class); Mockito.when(mockContext.getResources()).thenReturn(mockResources); Mockito.when(mockContext.getString(resId)).thenReturn(apiKey); Mockito.when(mockContext.getPackageName()).thenReturn(packageName); PwsClient client = Mockito.mock(PwsClient.class); Utils.setPwsEndPointToGoogle(mockContext, client); Mockito.verify(client, Mockito.times(1)).setEndpoint(GOOGLE_PWS_URL, GOOGLE_PWS_VERSION, apiKey); } /* * Tests isGoogleApiKeyAvailable. * * Procedure: * 1. Configure there to not be an api key * 2. Verify that there is no api key * 3. Configure there to be an api key * 4. Verify that there is an api key */ @Test public void testIsGoogleApiKeyAvailable() throws Exception { String packageName = "test"; Resources resources = Mockito.mock(Resources.class); Mockito.when(resources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(0); Context context = Mockito.mock(Context.class); Mockito.when(context.getResources()).thenReturn(resources); Mockito.when(context.getPackageName()).thenReturn(packageName); Assert.assertFalse(Utils.isGoogleApiKeyAvailable(context)); Mockito.when(resources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(1); Assert.assertTrue(Utils.isGoogleApiKeyAvailable(context)); } /* * Tests getGoogleApiKey. Also exercises isGoogleApiKeyAvailable. * * Procedure: * 1. Configure there to be an api key * 2. Verify api key is equal to apiKey * 3. Configure there to not be an api key * 4. Verify api key is empty */ @Test public void testGetGoogleApiKey() throws Exception { int resId = 1; String apiKey = SAMPLE_API_KEY; String packageName = SAMPLE_PACKAGE_NAME; Resources resources = Mockito.mock(Resources.class); Mockito.when(resources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(resId); Context context = Mockito.mock(Context.class); Mockito.when(context.getResources()).thenReturn(resources); Mockito.when(context.getString(resId)).thenReturn(apiKey); Mockito.when(context.getPackageName()).thenReturn(packageName); Assert.assertEquals(apiKey, Utils.getGoogleApiKey(context)); resId = 0; Mockito.when(resources.getIdentifier(GOOGLE_API_KEY_RESOURCE_KEY, GOOGLE_API_KEY_RESOURCE_TYPE, packageName)).thenReturn(resId); Mockito.when(context.getString(resId)).thenReturn(apiKey); Assert.assertEquals("", Utils.getGoogleApiKey(context)); } /* * Tests getTopRankedPwPairByGroupId with an empty collection. Also exercises getGroupId. * * Procedure: * 1. Configure there to be an empty list of PwPairs to be sorted * 2. Verify top ranked PwPair is null */ @Test public void testGetTopRankedPwPairByGroupIdEmptyCollection() throws Exception { String groupId = ""; PhysicalWebCollection mockCollection = Mockito.mock(PhysicalWebCollection.class); List<PwPair> pairs = Arrays.asList(new PwPair[]{}); Mockito.when(mockCollection.getGroupedPwPairsSortedByRank( (Comparator<PwPair>) Matchers.anyObject())).thenReturn(pairs); Assert.assertNull(Utils.getTopRankedPwPairByGroupId(mockCollection, groupId)); } /* * Tests getTopRankedPwPairByGroupId with one item in the collection. Also exercises getGroupId. * * Procedure: * 1. Configure there to be an list of 1 PwPair to be sorted * 2. Verify top ranked PwPair for groupId that is in list is the expected pair * 3. Verify top ranked PwPair for groupId that is not in list is null */ @Test public void testGetTopRankedPwPairByGroupIdOneItemCollection() throws Exception { String groupId = "group"; PwsResult mockResult = Mockito.mock(PwsResult.class); Mockito.when(mockResult.getGroupId()).thenReturn(groupId); PwPair mockPair = Mockito.mock(PwPair.class); Mockito.when(mockPair.getPwsResult()).thenReturn(mockResult); PhysicalWebCollection mockCollection = Mockito.mock(PhysicalWebCollection.class); List<PwPair> pairs = Arrays.asList(new PwPair[]{mockPair}); Mockito.when(mockCollection.getGroupedPwPairsSortedByRank( (Comparator<PwPair>) Matchers.anyObject())).thenReturn(pairs); Assert.assertEquals(mockPair, Utils.getTopRankedPwPairByGroupId(mockCollection, groupId)); // Check with groupId that is not in the list of pairs. Assert.assertNull(Utils.getTopRankedPwPairByGroupId(mockCollection, "not in list")); } /* * Tests getTopRankedPwPairByGroupId with two items in the collection. Also exercises getGroupId. * * Procedure: * 1. Configure there to be an list of 2 PwPairs with the same ids to be sorted * 2. Verify top ranked PwPair for groupId that is in list is the expected pair * 3. Verify top ranked PwPair for groupId that is not in list is null */ @Test public void testGetTopRankedPwPairByGroupIdTwoItemCollection() throws Exception { String groupId = "group"; PwsResult mockResult1 = Mockito.mock(PwsResult.class); Mockito.when(mockResult1.getGroupId()).thenReturn(groupId); PwsResult mockResult2 = Mockito.mock(PwsResult.class); Mockito.when(mockResult2.getGroupId()).thenReturn(groupId); PwPair mockPair1 = Mockito.mock(PwPair.class); Mockito.when(mockPair1.getPwsResult()).thenReturn(mockResult1); PwPair mockPair2 = Mockito.mock(PwPair.class); Mockito.when(mockPair2.getPwsResult()).thenReturn(mockResult2); PhysicalWebCollection mockCollection = Mockito.mock(PhysicalWebCollection.class); List<PwPair> pairs = Arrays.asList(new PwPair[]{mockPair1, mockPair2}); Mockito.when(mockCollection.getGroupedPwPairsSortedByRank( (Comparator<PwPair>) Matchers.anyObject())).thenReturn(pairs); Assert.assertEquals(mockPair1, Utils.getTopRankedPwPairByGroupId(mockCollection, groupId)); // Check with groupId that is not in the list of pairs. Assert.assertNull(Utils.getTopRankedPwPairByGroupId(mockCollection, "not in list")); } /* * Tests getBitmapIcon. * * Procedure: * 1. Configure there to be a null icon * 2. Verify null is returned */ @Test public void testGetBitmapIcon() throws Exception { String iconUrl = "icon"; PwsResult mockResult = Mockito.mock(PwsResult.class); Mockito.when(mockResult.getIconUrl()).thenReturn(iconUrl); PhysicalWebCollection mockCollection = Mockito.mock(PhysicalWebCollection.class); Mockito.when(mockCollection.getIcon(iconUrl)).thenReturn(null); Assert.assertNull(Utils.getBitmapIcon(mockCollection, mockResult)); } /* * Tests getScanTimeMillis. * * Procedure: * 1. Configure mock device to return scanTime * 2. Verify scanTime is returned */ @Test public void testGetScanTimeMillis() throws Exception { long scanTime = 0L; UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraLong(SCAN_TIME_KEY)).thenReturn(scanTime); Assert.assertEquals(scanTime, Utils.getScanTimeMillis(mockDevice)); } /* * Tests getScanTimeMillis. * * Procedure: * 1. Configure mock device to throw JSONException * 2. Verify RuntimeException is thrown */ @Test(expected = RuntimeException.class) public void testGetScanTimeMillisWithException() throws Exception { UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraLong(SCAN_TIME_KEY)).thenThrow(new JSONException("")); Utils.getScanTimeMillis(mockDevice); } /* * Tests isPublic. * * Procedure: * 1. Configure mock device to return true * 2. Verify true is returned * 3. Configure mock device to return false * 4. Verify false is returned */ @Test public void testIsPublic() throws Exception { UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.optExtraBoolean(PUBLIC_KEY, true)).thenReturn(true); Assert.assertTrue(Utils.isPublic(mockDevice)); Mockito.when(mockDevice.optExtraBoolean(PUBLIC_KEY, true)).thenReturn(false); Assert.assertFalse(Utils.isPublic(mockDevice)); } /* * Tests isBleUrlDevice. * * Procedure: * 1. Configure mock device return RSSI * 2. Verify true is returned * 3. Configure mock device to throw JSONException * 4. Verify false is returned */ @Test public void testIsBleUrlDevice() throws Exception { UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.optExtraString(TYPE_KEY, "")).thenReturn(BLE_DEVICE_TYPE); Assert.assertTrue(Utils.isBleUrlDevice(mockDevice)); Mockito.when(mockDevice.optExtraString(TYPE_KEY, "")).thenReturn("not ble"); Assert.assertFalse(Utils.isBleUrlDevice(mockDevice)); } /* * Tests getRssi. * * Procedure: * 1. Configure mock device to return RSSI * 2. Verify RSSI is returned */ @Test public void testGetRssi() throws Exception { int rssi = Integer.MAX_VALUE; UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraInt(RSSI_KEY)).thenReturn(rssi); Assert.assertEquals(rssi, Utils.getRssi(mockDevice)); } /* * Tests getRssi. * * Procedure: * 1. Configure mock device to throw JSONException * 2. Verify RuntimeException is thrown */ @Test(expected = RuntimeException.class) public void testGetRssiWithException() throws Exception { UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraInt(RSSI_KEY)).thenThrow(new JSONException("")); Utils.getRssi(mockDevice); } /* * Tests getTxPower. * * Procedure: * 1. Configure mock device to return Tx Power * 2. Verify Tx Power is returned */ @Test public void testGetTxPower() throws Exception { int txPower = Integer.MIN_VALUE; UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraInt(TXPOWER_KEY)).thenReturn(txPower); Assert.assertEquals(txPower, Utils.getTxPower(mockDevice)); } /* * Tests getTxPower. * * Procedure: * 1. Configure mock device to throw JSONException * 2. Verify RuntimeException is thrown */ @Test(expected = RuntimeException.class) public void testGetTxPowerWithException() throws Exception { UrlDevice mockDevice = Mockito.mock(UrlDevice.class); Mockito.when(mockDevice.getExtraInt(TXPOWER_KEY)).thenThrow(new JSONException("")); Utils.getTxPower(mockDevice); } /* * Tests getPwsTripTimeMillis. * * Procedure: * 1. Configure mock result to return trip time * 2. Verify trip time is returned */ @Test public void testGetPwsTripTimeMillis() throws Exception { long tripTime = Long.MAX_VALUE; PwsResult mockResult = Mockito.mock(PwsResult.class); Mockito.when(mockResult.getExtraLong(PWS_TRIP_TIME_KEY)).thenReturn(tripTime); Assert.assertEquals(tripTime, Utils.getPwsTripTimeMillis(mockResult)); } /* * Tests getPwsTripTimeMillis. * * Procedure: * 1. Configure mock result to throw JSONException * 2. Verify RuntimeException is thrown */ @Test(expected = RuntimeException.class) public void testGetPwsTripTimeMillisWithException() throws Exception { PwsResult mockResult = Mockito.mock(PwsResult.class); Mockito.when(mockResult.getExtraLong(PWS_TRIP_TIME_KEY)).thenThrow(new JSONException("")); Utils.getPwsTripTimeMillis(mockResult); } /* * Tests getGroupId. * * Procedure: * 1. Configure mock result to return groupId * 2. Verify groupId is returned */ @Test public void testGetGroupId() throws Exception { String groupId = "group"; PwsResult mockResult = Mockito.mock(PwsResult.class); Mockito.when(mockResult.getGroupId()).thenReturn(groupId); Assert.assertEquals(groupId, Utils.getGroupId(mockResult)); } /* * Tests getGroupId. * * Procedure: * 1. Configure mock result to return: {groupId:null, title:non Empty, siteUrl:https://url} * 2. Verify url + title is returned * 3. Configure mock result to return: {groupId:empty string, title:non Empty, * siteUrl:url containing '\'} * 4. Verify url is returned */ @Test public void testGetGroupIdNotDefined() throws Exception { String url = siteUrls.get(0); String title = "Google"; PwsResult mockResult = Mockito.mock(PwsResult.class); // Test null groupId and use site url that URI can parse Mockito.when(mockResult.getGroupId()).thenReturn(null); Mockito.when(mockResult.getSiteUrl()).thenReturn("https://" + url); Mockito.when(mockResult.getTitle()).thenReturn(title); Assert.assertEquals(url + title, Utils.getGroupId(mockResult)); // Test empty groupId and use site url that causes URISyntaxException url = "\\invalid"; Mockito.when(mockResult.getSiteUrl()).thenReturn(url); Mockito.when(mockResult.getGroupId()).thenReturn(""); Assert.assertEquals(url, Utils.getGroupId(mockResult)); } }