/** * All unique identifiers used in Rum don't have dashes... */ private static String rumUniqueId() { return UUIDUtils.randomUUID().toString().replace("-", ""); }
@Test public void utilsCoverage() { new UUIDUtils(); }
/** * Get a version 4 variant 2 random UUID. * * @return random UUID. */ public static UUID randomUUID() { try { return sImplementation.randomUUID(); } catch (SecurityException e) { /* Some devices can crash while allocating a SecureRandom, used by UUID, fall back... */ initFailOver(e); long highest = (sRandom.nextLong() & -61441L) | 16384L; long lowest = (sRandom.nextLong() & 4611686018427387903L) | -9223372036854775808L; return new UUID(highest, lowest); } }
/** * Get the installID from the Shared preferences. In case this fails, will generate a new installId. * * @return the installID */ @NonNull public static UUID getInstallId() { String installIdString = SharedPreferencesManager.getString(KEY_INSTALL_ID, ""); UUID installId; try { installId = UUID.fromString(installIdString); } catch (Exception e) { AppCenterLog.warn(AppCenter.LOG_TAG, "Unable to get installID from Shared Preferences"); installId = UUIDUtils.randomUUID(); SharedPreferencesManager.putString(KEY_INSTALL_ID, installId.toString()); } return installId; } }
/** * Update setup using native tester app. * * @param activity activity from which to start tester app. * @param packageInfo package info. */ static void updateSetupUsingTesterApp(Activity activity, PackageInfo packageInfo) { /* Compute hash. */ String releaseHash = computeReleaseHash(packageInfo); /* Generate request identifier. */ String requestId = UUIDUtils.randomUUID().toString(); /* Build URL. */ String url = "ms-actesterapp://update-setup"; url += "?" + PARAMETER_RELEASE_HASH + "=" + releaseHash; url += "&" + PARAMETER_REDIRECT_ID + "=" + activity.getPackageName(); url += "&" + PARAMETER_REDIRECT_SCHEME + "=" + "appcenter"; url += "&" + PARAMETER_REQUEST_ID + "=" + requestId; url += "&" + PARAMETER_PLATFORM + "=" + PARAMETER_PLATFORM_VALUE; AppCenterLog.debug(LOG_TAG, "No token, need to open tester app to url=" + url); /* Store request id. */ SharedPreferencesManager.putString(PREFERENCE_KEY_REQUEST_ID, requestId); /* Open the native tester app */ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivity(intent); }
@Override @SuppressWarnings("unchecked") public String answer(InvocationOnMock invocation) { Object[] args = invocation.getArguments(); if (args[3] instanceof ArrayList) { ArrayList logs = (ArrayList) args[3]; int length = size >= 0 ? size : (int) args[2]; for (int i = 0; i < length; i++) { logs.add(mock(Log.class)); } } return UUIDUtils.randomUUID().toString(); } };
@Test public void dontConvertCommonSchemaLogs() { /* Setup mocks. */ Channel channel = mock(Channel.class); LogSerializer logSerializer = mock(LogSerializer.class); /* Init listener. */ OneCollectorChannelListener listener = new OneCollectorChannelListener(mock(Context.class), channel, logSerializer, UUIDUtils.randomUUID()); listener.onPreparedLog(mock(CommonSchemaLog.class), TEST_GROUP, DEFAULTS); /* Verify no conversion. */ verify(logSerializer, never()).toCommonSchemaLog(any(Log.class)); /* Verify no enqueuing. */ verify(channel, never()).enqueue(any(Log.class), anyString(), anyInt()); }
@Test public void invalidGroup() throws Persistence.PersistenceException { Persistence persistence = mock(Persistence.class); Channel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, mock(Ingestion.class), mAppCenterHandler); /* Enqueue a log before group is registered = failure. */ Log log = mock(Log.class); channel.enqueue(log, TEST_GROUP, Flags.DEFAULTS); verify(log, never()).setDevice(any(Device.class)); verify(log, never()).setTimestamp(any(Date.class)); verify(persistence, never()).putLog(eq(log), eq(TEST_GROUP), anyInt()); /* Trying remove group that not registered. */ channel.removeGroup(TEST_GROUP); verify(mAppCenterHandler, never()).removeCallbacks(any(Runnable.class)); }
@Test @SuppressWarnings("unchecked") public void setLogUrl() { Ingestion ingestion = mock(Ingestion.class); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mock(Persistence.class), ingestion, mAppCenterHandler); String logUrl = "http://mockUrl"; channel.setLogUrl(logUrl); verify(ingestion).setLogUrl(logUrl); }
@Test public void errorLogDiscarded() { Channel.GroupListener mockListener = mock(Channel.GroupListener.class); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mock(Persistence.class), mock(Ingestion.class), mAppCenterHandler); channel.addGroup(TEST_GROUP, 1, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, mockListener); channel.setEnabled(false); channel.enqueue(mock(Log.class), TEST_GROUP, Flags.DEFAULTS); verify(mockListener).onFailure(any(Log.class), any(CancellationException.class)); }
@Test public void somehowDatabaseEmptiedAfterTimer() throws IOException { /* Cover the if (batchId != null) test though it could happen only if the database content disappear after the timer... */ AtomicReference<Runnable> runnable = catchPostRunnable(); Ingestion ingestion = mock(Ingestion.class); doThrow(new IOException()).when(ingestion).close(); Persistence persistence = mock(Persistence.class); when(persistence.countLogs(anyString())).thenReturn(2); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, ingestion, mAppCenterHandler); channel.addGroup(TEST_GROUP, 50, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, null); verify(ingestion, never()).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); assertEquals(2, channel.getGroupState(TEST_GROUP).mPendingLogCount); assertNotNull(runnable.get()); runnable.get().run(); verify(ingestion, never()).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); verify(mAppCenterHandler).postDelayed(any(Runnable.class), eq(BATCH_TIME_INTERVAL)); verify(mAppCenterHandler, never()).removeCallbacks(any(Runnable.class)); }
@Test public void validateCommonSchemaLogs() { /* Setup mocks. */ Channel channel = mock(Channel.class); LogSerializer logSerializer = mock(LogSerializer.class); when(logSerializer.toCommonSchemaLog(any(Log.class))).thenThrow(new IllegalArgumentException()); Log log = mock(Log.class); when(log.getTransmissionTargetTokens()).thenReturn(Collections.singleton("token")); /* Init listener. */ OneCollectorChannelListener listener = new OneCollectorChannelListener(mock(Context.class), channel, logSerializer, UUIDUtils.randomUUID()); listener.onPreparedLog(log, TEST_GROUP, DEFAULTS); /* Verify conversion attempted. */ verify(logSerializer).toCommonSchemaLog(any(Log.class)); /* Verify no enqueuing as the log was invalid. */ verify(channel, never()).enqueue(any(Log.class), anyString(), anyInt()); }
@Test public void clearCorrespondingGroup() { Channel channel = mock(Channel.class); OneCollectorChannelListener listener = new OneCollectorChannelListener(mock(Context.class), channel, mock(LogSerializer.class), UUIDUtils.randomUUID()); /* Clear a group. */ listener.onClear(TEST_GROUP); /* Verify group added. */ verify(channel).clear(TEST_GROUP + ONE_COLLECTOR_GROUP_NAME_SUFFIX); /* Clear the one collector group: nothing more happens. */ listener.onClear(TEST_GROUP + ONE_COLLECTOR_GROUP_NAME_SUFFIX); verifyNoMoreInteractions(channel); }
@Test public void clear() { Persistence mockPersistence = mock(Persistence.class); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), mockPersistence, mock(AppCenterIngestion.class), mAppCenterHandler); channel.addGroup(TEST_GROUP, 50, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, null); /* Clear an existing channel. */ channel.clear(TEST_GROUP); verify(mockPersistence).deleteLogs(TEST_GROUP); reset(mockPersistence); /* Clear a non-existing channel. */ channel.clear(TEST_GROUP + "2"); verify(mockPersistence, never()).deleteLogs(anyString()); }
@Test public void removeCorrespondingGroup() { Channel channel = mock(Channel.class); OneCollectorChannelListener listener = new OneCollectorChannelListener(mock(Context.class), channel, mock(LogSerializer.class), UUIDUtils.randomUUID()); /* Mock group removed. */ listener.onGroupRemoved(TEST_GROUP); /* Verify one collector group added. */ verify(channel).removeGroup(TEST_GROUP + ONE_COLLECTOR_GROUP_NAME_SUFFIX); /* Mock one collector group added callback, should not loop indefinitely. */ listener.onGroupRemoved(TEST_GROUP + ONE_COLLECTOR_GROUP_NAME_SUFFIX); verifyNoMoreInteractions(channel); }
@Test public void useBrowserUpdateSetupIfAppIsTesterApp() throws Exception { /* Setup mock. */ UUID requestId = UUID.randomUUID(); when(UUIDUtils.randomUUID()).thenReturn(requestId); when(SharedPreferencesManager.getString(PREFERENCE_KEY_REQUEST_ID)).thenReturn(requestId.toString()); when(mPackageManager.getPackageInfo(DistributeUtils.TESTER_APP_PACKAGE_NAME, 0)).thenReturn(mock(PackageInfo.class)); when(mContext.getPackageName()).thenReturn(DistributeUtils.TESTER_APP_PACKAGE_NAME); /* Mock install id from AppCenter. */ UUID installId = UUID.randomUUID(); when(mAppCenterFuture.get()).thenReturn(installId); when(AppCenter.getInstallId()).thenReturn(mAppCenterFuture); /* Start and resume: open browser. */ start(); Distribute.getInstance().onActivityResumed(mActivity); verifyStatic(); BrowserUtils.openBrowser(anyString(), any(Activity.class)); }
@Test public void initialLogs() throws IOException { AtomicReference<Runnable> runnable = catchPostRunnable(); Ingestion ingestion = mock(Ingestion.class); doThrow(new IOException()).when(ingestion).close(); Persistence persistence = mock(Persistence.class); when(persistence.countLogs(anyString())).thenReturn(3); when(persistence.getLogs(anyString(), anyListOf(String.class), anyInt(), anyListOf(Log.class))).thenAnswer(getGetLogsAnswer(3)); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, ingestion, mAppCenterHandler); channel.addGroup(TEST_GROUP, 50, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, null); verify(ingestion, never()).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); assertEquals(3, channel.getGroupState(TEST_GROUP).mPendingLogCount); assertNotNull(runnable.get()); runnable.get().run(); verify(ingestion).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); verify(mAppCenterHandler).postDelayed(any(Runnable.class), eq(BATCH_TIME_INTERVAL)); verify(mAppCenterHandler, never()).removeCallbacks(any(Runnable.class)); }
@Test public void initialLogsMoreThan1Batch() throws IOException { AtomicReference<Runnable> runnable = catchPostRunnable(); Ingestion ingestion = mock(Ingestion.class); doThrow(new IOException()).when(ingestion).close(); Persistence persistence = mock(Persistence.class); when(persistence.countLogs(anyString())).thenReturn(103); when(persistence.getLogs(anyString(), anyListOf(String.class), anyInt(), anyListOf(Log.class))).thenAnswer(getGetLogsAnswer(50)).thenAnswer(getGetLogsAnswer(50)).thenAnswer(getGetLogsAnswer(3)); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, ingestion, mAppCenterHandler); channel.addGroup(TEST_GROUP, 50, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, null); verify(ingestion, times(2)).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); assertEquals(3, channel.getGroupState(TEST_GROUP).mPendingLogCount); assertNotNull(runnable.get()); runnable.get().run(); verify(ingestion, times(3)).sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class)); verify(mAppCenterHandler).postDelayed(any(Runnable.class), eq(BATCH_TIME_INTERVAL)); verify(mAppCenterHandler, never()).removeCallbacks(any(Runnable.class)); }
@Test public void disableBeforeCheckingPendingLogs() { Ingestion ingestion = mock(Ingestion.class); Persistence persistence = mock(Persistence.class); final DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, ingestion, mAppCenterHandler); when(persistence.getLogs(anyString(), anyListOf(String.class), anyInt(), anyListOf(Log.class))).thenAnswer(getGetLogsAnswer(1)); when(ingestion.sendAsync(anyString(), any(UUID.class), any(LogContainer.class), any(ServiceCallback.class))).thenAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) { /* Simulate a service disabled in the middle of network transaction. */ ServiceCallback callback = (ServiceCallback) invocation.getArguments()[3]; channel.removeGroup(TEST_GROUP); callback.onCallSucceeded(""); return null; } }); channel.addGroup(TEST_GROUP, 1, BATCH_TIME_INTERVAL, MAX_PARALLEL_BATCHES, null, null); channel.enqueue(mock(Log.class), TEST_GROUP, Flags.DEFAULTS); verify(mAppCenterHandler, never()).postDelayed(any(Runnable.class), eq(BATCH_TIME_INTERVAL)); }
@Test public void checkSetStorageSizeForwarding() { /* The real Android test for checking size is in DatabaseManagerAndroidTest. */ Persistence persistence = mock(Persistence.class); when(persistence.setMaxStorageSize(anyLong())).thenReturn(true).thenReturn(false); DefaultChannel channel = new DefaultChannel(mock(Context.class), UUIDUtils.randomUUID().toString(), persistence, mock(Ingestion.class), mAppCenterHandler); /* Just checks calls are forwarded to the low level database layer. */ assertTrue(channel.setMaxStorageSize(20480)); assertFalse(channel.setMaxStorageSize(2)); } }