Tracker { public Tracker track(TrackMe trackMe) { synchronized (mTrackingLock) { final boolean newSession = System.currentTimeMillis() - mSessionStartTime > mSessionTimeout; if (newSession) { mSessionStartTime = System.currentTimeMillis(); injectInitialParams(trackMe); } injectBaseParams(trackMe); for (Callback callback : mTrackingCallbacks) { trackMe = callback.onTrack(trackMe); if (trackMe == null) { Timber.tag(TAG).d("Tracking aborted by %s", callback); return this; } } mLastEvent = trackMe; if (!mOptOut) { mDispatcher.submit(trackMe); Timber.tag(TAG).d("Event added to the queue: %s", trackMe); } else { Timber.tag(TAG).d("Event omitted due to opt out: %s", trackMe); } return this; } } protected  Tracker(Matomo matomo, TrackerBuilder config); void addTrackingCallback(Callback callback); void removeTrackingCallback(Callback callback); void setOptOut(boolean optOut); boolean isOptOut(); String getName(); Matomo getMatomo(); String getAPIUrl(); TrackMe getDefaultTrackMe(); void startNewSession(); void setSessionTimeout(int milliseconds); long getSessionTimeout(); int getDispatchTimeout(); void setDispatchTimeout(int timeout); void dispatch(); void dispatchBlocking(); Tracker setDispatchInterval(long dispatchInterval); Tracker setDispatchGzipped(boolean dispatchGzipped); long getDispatchInterval(); void setOfflineCacheAge(long age); long getOfflineCacheAge(); void setOfflineCacheSize(long size); long getOfflineCacheSize(); DispatchMode getDispatchMode(); void setDispatchMode(DispatchMode mode); Tracker setUserId(String userId); String getUserId(); Tracker setVisitorId(String visitorId); String getVisitorId(); Tracker track(TrackMe trackMe); static String makeRandomVisitorId(); SharedPreferences getPreferences(); @Override boolean equals(Object o); @Override int hashCode(); @VisibleForTesting TrackMe getLastEventX(); void setDryRunTarget(List<Packet> dryRunTarget); List<Packet> getDryRunTarget();  }
@Test public void testLastScreenUrl() { Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); tracker.track(new TrackMe()); verify(mDispatcher).submit(mCaptor.capture()); assertEquals("http: tracker.track(new TrackMe().set(QueryParams.URL_PATH, "http: verify(mDispatcher, times(2)).submit(mCaptor.capture()); assertEquals("http: tracker.track(new TrackMe().set(QueryParams.URL_PATH, "http: verify(mDispatcher, times(3)).submit(mCaptor.capture()); assertEquals("http: tracker.track(new TrackMe()); verify(mDispatcher, times(4)).submit(mCaptor.capture()); assertEquals("http: tracker.track(new TrackMe().set(QueryParams.URL_PATH, "thang")); verify(mDispatcher, times(5)).submit(mCaptor.capture()); assertEquals("http: }
@Test public void testSetURL() { when(mTrackerBuilder.getApplicationBaseUrl()).thenReturn("http: Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); TrackMe trackMe = new TrackMe(); tracker.track(trackMe); assertEquals("http: trackMe.set(QueryParams.URL_PATH, "me"); tracker.track(trackMe); assertEquals("http: trackMe.set(QueryParams.URL_PATH, "https: tracker.track(trackMe); assertEquals("https: }
@Test public void testGetResolution() { Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); TrackMe trackMe = new TrackMe(); tracker.track(trackMe); verify(mDispatcher).submit(mCaptor.capture()); assertEquals("480x800", mCaptor.getValue().get(QueryParams.SCREEN_RESOLUTION)); }
@Test public void testUrlPathCorrection() { when(mTrackerBuilder.getApplicationBaseUrl()).thenReturn("https: Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); String[] paths = new String[]{null, "", "/",}; for (String path : paths) { TrackMe trackMe = new TrackMe(); trackMe.set(QueryParams.URL_PATH, path); tracker.track(trackMe); assertEquals("https: } }
@Test public void testVisitCountMultipleThreads() throws Exception { Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); int threadCount = 1000; final CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { new Thread(() -> { TestHelper.sleep(new Random().nextInt(20 - 0) + 0); TrackHelper.track().event("TestCategory", "TestAction").with(new Tracker(mMatomo, mTrackerBuilder)); countDownLatch.countDown(); }).start(); } countDownLatch.await(); assertEquals(threadCount, mTrackerPreferences.getLong(Tracker.PREF_KEY_TRACKER_VISITCOUNT, 0)); }
@Test public void testSessionStartRaceCondition() throws Exception { final List<TrackMe> trackMes = Collections.synchronizedList(new ArrayList<TrackMe>()); doAnswer(invocation -> { trackMes.add(invocation.getArgument(0)); return null; }).when(mDispatcher).submit(any(TrackMe.class)); when(mDispatcher.getConnectionTimeOut()).thenReturn(1000); for (int i = 0; i < 1000; i++) { trackMes.clear(); final Tracker tracker = new Tracker(mMatomo, mTrackerBuilder); final CountDownLatch countDownLatch = new CountDownLatch(10); for (int j = 0; j < 10; j++) { new Thread(() -> { try { TestHelper.sleep(new Random().nextInt(4 - 0) + 0); TrackMe trackMe = new TrackMe() .set(QueryParams.EVENT_ACTION, UUID.randomUUID().toString()) .set(QueryParams.EVENT_CATEGORY, UUID.randomUUID().toString()) .set(QueryParams.EVENT_NAME, UUID.randomUUID().toString()) .set(QueryParams.EVENT_VALUE, 1); tracker.track(trackMe); countDownLatch.countDown(); } catch (Exception e) { e.printStackTrace(); assertFalse(true); } }).start(); } countDownLatch.await(); for (TrackMe out : trackMes) { if (trackMes.indexOf(out) == 0) { assertTrue(i + "#" + out.toMap().size(), out.get(QueryParams.LANGUAGE) != null); assertTrue(out.get(QueryParams.FIRST_VISIT_TIMESTAMP) != null); assertTrue(out.get(SESSION_START) != null); } else { assertTrue(out.get(QueryParams.LANGUAGE) == null); assertTrue(out.get(QueryParams.FIRST_VISIT_TIMESTAMP) == null); assertTrue(out.get(SESSION_START) == null); } } } }