ReportHandler { public synchronized HandleStatus handleReport(Intent intent) { HandleStatus status = HandleStatus.HANDLED; boolean isOnline = mNetworkManager.isOnline() && canUseNetwork(); try { if (null == intent.getExtras()) return status; int event = intent.getIntExtra(ReportIntent.EXTRA_SDK_EVENT, SdkEvent.ERROR); Bundle bundle = intent.getExtras(); JSONObject dataObject = new JSONObject(); try { String[] fields = {ReportIntent.TABLE, ReportIntent.TOKEN, ReportIntent.DATA}; for (String key : fields) { Object value = bundle.get(key); dataObject.put(key, value); } } catch (Exception e) { Logger.log(TAG, "Failed extracting the data from Intent", Logger.SDK_ERROR); } List<Table> tablesToFlush = new ArrayList<>(); switch (event) { case SdkEvent.FLUSH_QUEUE: if (isOnline) { tablesToFlush = mStorage.getTables(); break; } return HandleStatus.RETRY; case SdkEvent.POST_SYNC: if (isOnline) { String message = createMessage(dataObject, false); String url = mConfig.getIBEndPoint(dataObject.getString(ReportIntent.TOKEN)); if (SendStatus.RETRY != send(message, url)) break; } case SdkEvent.ENQUEUE: Table table = new Table(dataObject.getString(ReportIntent.TABLE), dataObject.getString(ReportIntent.TOKEN)); int nRows = mStorage.addEvent(table, dataObject.getString(ReportIntent.DATA)); if (isOnline && mConfig.getBulkSize() <= nRows) { tablesToFlush.add(table); } else { return HandleStatus.RETRY; } } for (Table table: tablesToFlush) flush(table); } catch (Exception e) { status = HandleStatus.RETRY; Logger.log(TAG, e.getMessage(), Logger.SDK_DEBUG); } return status; } ReportHandler(Context context); synchronized HandleStatus handleReport(Intent intent); void flush(Table table);  }
@Test public void trackOnly() throws Exception { mConfig.setBulkSize(Integer.MAX_VALUE); Intent intent = newReport(SdkEvent.ENQUEUE, reportMap); mHandler.handleReport(intent); verify(mStorage, times(1)).addEvent(mTable, DATA); verify(mClient, never()).post(anyString(), anyString()); }
@Test public void trackCauseFlush() { mConfig.setBulkSize(2); when(mStorage.addEvent(mTable, DATA)).thenReturn(2); Intent intent = newReport(SdkEvent.ENQUEUE, reportMap); mHandler.handleReport(intent); verify(mStorage, times(1)).addEvent(mTable, DATA); verify(mStorage, times(1)).getEvents(mTable, mConfig.getBulkSize()); }
@Test public void maxRequestLimit() throws Exception { when(mConfig.getBulkSize()).thenReturn(2); when(mConfig.getMaximumRequestLimit()).thenReturn((long) (1024 * 1024 + 1)); final String chunk = new String(new char[1024 * 1024]).replace('\0', 'b'); when(mStorage.getTables()).thenReturn(new ArrayList<Table>() {{ add(mTable); }}); when(mStorage.getEvents(eq(mTable), anyInt())).thenReturn(new Batch("2", new ArrayList<String>() {{ add(chunk); add(chunk); }}), new Batch("1", new ArrayList<String>() {{ add(chunk); }}), new Batch("2", new ArrayList<String>() {{ add(chunk); }})); when(mStorage.deleteEvents(eq(mTable), anyString())).thenReturn(1); when(mStorage.count(mTable)).thenReturn(1, 0); when(mClient.post(anyString(), anyString())).thenReturn(ok, ok); Intent intent = newReport(SdkEvent.FLUSH_QUEUE, new HashMap<String, String>()); mHandler.handleReport(intent); verify(mStorage, times(2)).getEvents(mTable, 2); verify(mStorage, times(1)).getEvents(mTable, 1); verify(mStorage, times(1)).deleteTable(mTable); }
@Test public void dataFormat() throws Exception { when(mClient.post(any(String.class), any(String.class))).thenReturn(ok); Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); JSONObject report = new JSONObject(reportMap); String token = reportMap.get(ReportIntent.TOKEN); report.put(ReportIntent.AUTH, Utils.auth(report.getString(ReportIntent.DATA), report.getString(ReportIntent.TOKEN))).remove(ReportIntent.TOKEN); verify(mClient, times(1)).post(eq(report.toString()), anyString()); }
@Test public void postSuccess() throws Exception { String url = "http: when(mClient.post(anyString(), anyString())).thenReturn(ok); Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); when(mConfig.getIBEndPoint(anyString())).thenReturn(url); assertTrue(mHandler.handleReport(intent) == ReportHandler.HandleStatus.HANDLED); verify(mNetManager, times(1)).isOnline(); verify(mClient, times(1)).post(anyString(), eq(url)); verify(mStorage, never()).addEvent(mTable, DATA); }
@Test public void postAuthFailed() throws Exception { String url = "http: when(mConfig.getNumOfRetries()).thenReturn(10); when(mConfig.getIBEndPoint(TOKEN)).thenReturn(url); when(mClient.post(anyString(), anyString())).thenReturn(new Response() {{ code = 401; body = "Unauthorized"; }}); Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); verify(mNetManager, times(1)).isOnline(); verify(mClient, times(1)).post(anyString(), eq(url)); verify(mStorage, never()).addEvent(mTable, DATA); }
@Test public void postWithoutNetwork() throws Exception { when(mNetManager.isOnline()).thenReturn(false); Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); when(mConfig.getNumOfRetries()).thenReturn(10); assertEquals(mHandler.handleReport(intent), HandleStatus.RETRY); verify(mNetManager, times(1)).isOnline(); verify(mClient, never()).post(anyString(), anyString()); verify(mStorage, times(1)).addEvent(mTable, DATA); }
@Test public void postOnRoaming() throws Exception { Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); when(mConfig.isAllowedOverRoaming()).thenReturn(false, false, true); when(mNetManager.isDataRoamingEnabled()).thenReturn(false, true, true); when(mClient.post(anyString(), anyString())).thenReturn(ok); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); assertEquals(mHandler.handleReport(intent), HandleStatus.RETRY); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); verify(mClient, times(2)).post(anyString(), anyString()); }
@Test public void isNetworkTypeAllowed() throws Exception { Intent intent = newReport(SdkEvent.POST_SYNC, reportMap); int WIFI = IronBeast.NETWORK_WIFI, MOBILE = IronBeast.NETWORK_MOBILE; List<TestScenario> scenarios = new ArrayList<>(); scenarios.add(new TestScenario(~0, MOBILE, HandleStatus.HANDLED)); scenarios.add(new TestScenario(WIFI | MOBILE, MOBILE, HandleStatus.HANDLED)); scenarios.add(new TestScenario(WIFI | MOBILE, WIFI, HandleStatus.HANDLED)); scenarios.add(new TestScenario(WIFI, WIFI, HandleStatus.HANDLED)); scenarios.add(new TestScenario(MOBILE, MOBILE, HandleStatus.HANDLED)); scenarios.add(new TestScenario(WIFI, MOBILE, HandleStatus.RETRY)); scenarios.add(new TestScenario(MOBILE, WIFI, HandleStatus.RETRY)); when(mClient.post(anyString(), anyString())).thenReturn(ok); for (TestScenario test: scenarios) { when(mConfig.getAllowedNetworkTypes()).thenReturn(test.configStatus); when(mNetManager.getNetworkIBType()).thenReturn(test.networkStatus); assertEquals(mHandler.handleReport(intent), test.expected); } }
@Test public void flushNothing() { Intent intent = newReport(SdkEvent.FLUSH_QUEUE, new HashMap<String, String>()); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); verify(mStorage, times(1)).getTables(); }
@Test public void flushSuccess() throws Exception { when(mConfig.getBulkSize()).thenReturn(2); when(mConfig.getMaximumRequestLimit()).thenReturn((long) (1024)); final Table mTable1 = new Table("a8m", "a8m_token") { @Override public boolean equals(Object obj) { Table table = (Table) obj; return this.name.equals(table.name) && this.token.equals(table.token); } }; List<Table> tables = new ArrayList<Table>() {{ add(mTable); add(mTable1); }}; when(mStorage.getTables()).thenReturn(tables); when(mStorage.getEvents(mTable, mConfig.getBulkSize())) .thenReturn(new Batch("2", new ArrayList<String>() {{ add("foo"); add("bar"); }}), new Batch("3", new ArrayList<String>() {{ add("foo"); }})); when(mStorage.getEvents(mTable1, mConfig.getBulkSize())) .thenReturn(new Batch("4", new ArrayList<String>() {{ add("foo"); }})); when(mStorage.deleteEvents(mTable, "2")).thenReturn(2); when(mStorage.deleteEvents(mTable1, "4")).thenReturn(1); when(mStorage.count(mTable)).thenReturn(1); Intent intent = newReport(SdkEvent.FLUSH_QUEUE, new HashMap<String, String>()); when(mClient.post(anyString(), anyString())).thenReturn(ok, ok, ok); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); verify(mStorage, times(2)).getEvents(mTable, mConfig.getBulkSize()); verify(mStorage, times(1)).deleteEvents(mTable, "2"); verify(mStorage, times(1)).deleteEvents(mTable, "3"); verify(mStorage, times(1)).count(mTable); verify(mStorage, times(1)).deleteTable(mTable); verify(mStorage, times(1)).getEvents(mTable1, mConfig.getBulkSize()); verify(mStorage, times(1)).deleteEvents(mTable1, "4"); verify(mStorage, times(1)).deleteTable(mTable1); }
@Test public void flushNoItems() throws Exception { Intent intent = newReport(SdkEvent.FLUSH_QUEUE, new HashMap<String, String>()); assertEquals(mHandler.handleReport(intent), HandleStatus.HANDLED); verify(mStorage, times(1)).getTables(); verify(mStorage, never()).getEvents(any(Table.class), anyInt()); }
@Test public void flushFailed() throws Exception { Intent intent = newReport(SdkEvent.FLUSH_QUEUE, new HashMap<String, String>()); when(mStorage.getEvents(mTable, mConfig.getBulkSize())) .thenReturn(new Batch("2", new ArrayList<String>() {{ add("foo"); add("bar"); }})); when(mStorage.getTables()).thenReturn(new ArrayList<Table>() {{ add(mTable); }}); when(mClient.post(anyString(), anyString())).thenReturn(fail); assertEquals(mHandler.handleReport(intent), HandleStatus.RETRY); verify(mStorage, times(1)).getEvents(mTable, mConfig.getBulkSize()); verify(mStorage, never()).deleteEvents(mTable, "2"); verify(mStorage, never()).deleteTable(mTable); }