/**
*
*/
package org.rapidandroid.tests;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.rapidandroid.data.RapidSmsDBConstants;
import org.rapidandroid.data.controller.WorktableDataLayer;
import android.content.ContentValues;
import android.database.Cursor;
import android.test.AndroidTestCase;
import edu.jhuapl.sages.mobile.lib.rapidandroid.Demodulator;
/**
* @author POKUAM1
* @created Feb 13, 2012
*/
public class SagesMultiSmsTest extends AndroidTestCase {
// private Uri currUri;
private void rollCalDate(Calendar cal, int day, int hour, int min, int sec){
cal.roll(Calendar.DATE, day);
cal.roll(Calendar.HOUR, hour);
cal.roll(Calendar.MINUTE, min);
cal.roll(Calendar.SECOND, sec);
}
/* (non-Javadoc)
* @see android.test.AndroidTestCase#setUp()
*/
@Override
protected void setUp() throws Exception {
super.setUp();
@SuppressWarnings("unused") // for debug
int val = getContext().getContentResolver().delete(RapidSmsDBConstants.MultiSmsWorktable.CONTENT_URI, "tx_id >= ?", new String[] {"100"});
Calendar c = new GregorianCalendar();
final Calendar cRef = c;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
//c.roll(Calendar.MINUTE, 10);
//c.roll(Calendar.SECOND, 20);
// String dateStr = sdf.format(c.getTime());
//
//
//
// rollCalDate(c, 10, 10, 10, 10);
// String dateStr1 = sdf.format(c.getTime());
// c = cRef;
//
// rollCalDate(c, 20, 20, 20, 20);
// String dateStr2 = sdf.format(c.getTime());
// c = cRef;
//
// rollCalDate(c, 30, 30, 30, 30);
// String dateStr3 = sdf.format(c.getTime());
// c = cRef;
/** LIVE - complete set of 5 messages, received in order sequentially, within 4 minutes of "now" **/
//insertMultiSmsPart(31,1,5,100, "2012-02-09 15:17:28", "1of5_txid_100");
rollCalDate(c, 0, 0, 0, 0);
insertMultiSmsPart(/*31,*/1,5,100, sdf.format(c.getTime()), "1of5_txid_100");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(32,2,5,100, "2012-02-09 15:18:28", "2of5_txid_100");
rollCalDate(c, 0, 0, -1, 0);
insertMultiSmsPart(/*32,*/2,5,100, sdf.format(c.getTime()), "2of5_txid_100");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(33,3,5,100, "2012-02-09 15:19:28", "3of5_txid_100");
rollCalDate(c, 0, 0, -2, 0);
insertMultiSmsPart(/*33,*/3,5,100, sdf.format(c.getTime()), "3of5_txid_100");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(34,4,5,100, "2012-02-09 15:20:28", "4of5_txid_100");
rollCalDate(c, 0, 0, -3, 0);
insertMultiSmsPart(/*34,*/4,5,100, sdf.format(c.getTime()), "4of5_txid_100");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(35,5,5,100, "2012-02-09 15:21:28", "5of5_txid_100");
rollCalDate(c, 0, 0, -4, 0);
insertMultiSmsPart(/*35,*/5,5,100, sdf.format(c.getTime()), "5of5_txid_100");
c = (Calendar) cRef.clone();
/** LIVE - complete set of 3 messages, received out of order, within 2 days 5 minutes of "now" **/
//insertMultiSmsPart(36,1,3,111, "2012-02-09 15:21:28", "1of3_txid_111");
rollCalDate(c, 0, 0, -4, 0);
insertMultiSmsPart(/*36,*/1,3,111, sdf.format(c.getTime()), "1of3_txid_111");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(37,3,3,111, "2012-02-11 15:21:28", "3of3_txid_111");
rollCalDate(c, -2, 0, -4, 0);
insertMultiSmsPart(/*37,*/3,3,111, sdf.format(c.getTime()), "3of3_txid_111");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(38,2,3,111, "2012-02-11 15:22:28", "2of3_txid_111");
rollCalDate(c, -2, 0, -5, 0);
insertMultiSmsPart(/*38,*/2,3,111, sdf.format(c.getTime()), "2of3_txid_111");
c = (Calendar) cRef.clone();
/** STALE - incomplete set 2 of 3 messages, received out of order, within 3 days 14 minutes of "now" **/
//insertMultiSmsPart(39,1,3,333, "2012-02-13 15:30:28", "1of3_txid_333");
rollCalDate(c, -3, 0, -13, 0);
insertMultiSmsPart(/*39,*/1,3,333, sdf.format(c.getTime()), "1of3_txid_333");
c = (Calendar) cRef.clone();
//insertMultiSmsPart(40,3,3,333, "2012-02-13 15:31:28", "3of3_txid_333");
rollCalDate(c, -3, 0, -14, 0);
insertMultiSmsPart(/*40,*/3,3,333, sdf.format(c.getTime()), "3of3_txid_333");
c = (Calendar) cRef.clone();
/** LIVE - complete set of 3 messages, received out of order, within seconds of "now" **/
rollCalDate(c, 0, 0, 0, -1);
insertMultiSmsPart(/*36,*/1,3,4000, sdf.format(c.getTime()), "1of3_txid_4000");
c = (Calendar) cRef.clone();
rollCalDate(c, 0, 0, 0, -2);
insertMultiSmsPart(/*37,*/3,3,4000, sdf.format(c.getTime()), "3of3_txid_4000");
c = (Calendar) cRef.clone();
rollCalDate(c, 0, 0, 0, -3);
insertMultiSmsPart(/*38,*/2,3,4000, sdf.format(c.getTime()), "2of3_txid_4000");
c = (Calendar) cRef.clone();
/** LIVE - complete set of 3 messages, received out of order, within seconds of "now" **/
rollCalDate(c, 0, 0, 0, -1);
insertMultiSmsPart(/*36,*/3,3,4001, sdf.format(c.getTime()), "3of3_txid_4001");
c = (Calendar) cRef.clone();
rollCalDate(c, 0, 0, 0, -2);
insertMultiSmsPart(/*37,*/2,3,4001, sdf.format(c.getTime()), "2of3_txid_4001");
c = (Calendar) cRef.clone();
rollCalDate(c, 0, 0, 0, -3);
insertMultiSmsPart(/*38,*/1,3,4001, sdf.format(c.getTime()), "1of3_txid_4001");
c = (Calendar) cRef.clone();
}
/* (non-Javadoc)
* @see android.test.AndroidTestCase#tearDown()
*/
@Override
protected void tearDown() throws Exception {
super.tearDown();
@SuppressWarnings("unused") // for debug
int val = getContext().getContentResolver().delete(RapidSmsDBConstants.MultiSmsWorktable.CONTENT_URI, "tx_id >= ?", new String[] {"100"});
}
private void insertMultiSmsPart(/*int _id,*/ int segNum, int totSegs, long tx_id, String tx_ts, String payload) {
ContentValues initialValues = new ContentValues();
//initialValues.put(RapidSmsDBConstants.MultiSmsWorktable._ID, _id);
initialValues.put(RapidSmsDBConstants.MultiSmsWorktable.SEGMENT_NUMBER, segNum);
initialValues.put(RapidSmsDBConstants.MultiSmsWorktable.TOTAL_SEGMENTS, totSegs);
initialValues.put(RapidSmsDBConstants.MultiSmsWorktable.TX_ID, tx_id);
initialValues.put(RapidSmsDBConstants.MultiSmsWorktable.TX_TIMESTAMP, tx_ts);
initialValues.put(RapidSmsDBConstants.MultiSmsWorktable.PAYLOAD, payload);
getContext().getContentResolver().insert(RapidSmsDBConstants.MultiSmsWorktable.CONTENT_URI, initialValues);
}
public void testCategorizeCompleteVsIncomplete(){
try {
WorktableDataLayer.setTimerThreshold(300);
Map<String, List<Long>> statusMap = WorktableDataLayer.categorizeCompleteVsIncomplete(getContext());
assertNotNull(statusMap);
List<Long> ids = Arrays.asList(new Long[]{100L, 111L, 4000L, 4001L});
assertTrue("Did not contain expected tx_ids",statusMap.get(WorktableDataLayer.label_complete).containsAll(ids));
assertEquals("Incorrect categorization of completes", ids, statusMap.get(WorktableDataLayer.label_complete));
ids = Arrays.asList(new Long[]{333L});
assertTrue(statusMap.get(WorktableDataLayer.label_incomplete).containsAll(ids));
assertEquals("Incorrect categorization of incompletes", ids, statusMap.get(WorktableDataLayer.label_incomplete));
assertTrue(statusMap.get(WorktableDataLayer.label_bad).isEmpty());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail();
}
}
public void testGetStaleVsLiveTxIds(){
Cursor cursor = WorktableDataLayer.getStaleVsLiveTxIds(getContext(), null);
while (cursor.moveToNext()){
System.out.println(cursor.getString(0)); //ttl_timer
System.out.println(cursor.getString(1)); //now local
System.out.println(cursor.getString(2)); //DIFF
System.out.println(cursor.getString(3)); //_id
System.out.println(cursor.getString(4)); //seg num
System.out.println(cursor.getString(5)); //tot segs
System.out.println(cursor.getString(6)); //tx_id
System.out.println(cursor.getString(7)); //tx_timestamp
System.out.println(cursor.getString(8)); //payload
}
}
public void testCategorizedStaleVsLive(){
try {
WorktableDataLayer.setTimerThreshold(300);
Map<String, List<Long>> ttlMap = WorktableDataLayer.categorizeStaleVsLive(getContext(), null);
assertNotNull(ttlMap);
List<Long> ids = Arrays.asList(new Long[]{100L,111L,4000L,4001L});
assertEquals("Wrong number of live data",ids, ttlMap.get(WorktableDataLayer.label_ttlLive));
ids = Arrays.asList(new Long[]{333L});
assertEquals("Wrong number of stale data", ids,ttlMap.get(WorktableDataLayer.label_ttlStale));
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
/**
* Tests whether deletion nested in a transaction functions as expected
*/
public void testTransactionalDeleteStaleIncompletes(){
Map<String, List<Long>> ttlMap;
try {
// known stale txIds
ttlMap = WorktableDataLayer.categorizeStaleVsLive(getContext(), null);
List<Long> staleTxIds = ttlMap.get(WorktableDataLayer.label_ttlStale);
assertEquals("Wrong stale txIds categorized", Arrays.asList(new Long[]{333L}), staleTxIds);
/** the transactional delete is rolled back **/
// begin sql transaction
WorktableDataLayer.beginTransaction(getContext());
// delete records with stale txIds and verify gone
WorktableDataLayer.deleteTxIds(getContext(), staleTxIds);
Cursor cursor = WorktableDataLayer.getAvailableMessagesForTxId(getContext(), staleTxIds);
assertTrue(cursor.moveToFirst());
assertEquals(0, cursor.getInt(0));
//end transaction without setting successful -- triggers a rollback.
WorktableDataLayer.endTransaction();
// verify that the deleted records were rolled back
cursor = WorktableDataLayer.getAvailableMessagesForTxId(getContext(), staleTxIds);
assertTrue(cursor.moveToFirst());
assertEquals(2, cursor.getInt(0));
cursor.close();
/** the transactional delete is committed **/
// begin sql transaction
WorktableDataLayer.beginTransaction(getContext());
// delete records with stale txIds and verify gone
WorktableDataLayer.deleteTxIds(getContext(), staleTxIds);
cursor = WorktableDataLayer.getAvailableMessagesForTxId(getContext(), staleTxIds);
assertTrue(cursor.moveToFirst());
assertEquals(0, cursor.getInt(0));
//set transaction successful and end -- triggers a commit.
WorktableDataLayer.setTransactionSuccessful();
WorktableDataLayer.endTransaction();
// verify that the deleted records were rolled back
cursor = WorktableDataLayer.getAvailableMessagesForTxId(getContext(), staleTxIds);
assertTrue(cursor.moveToFirst());
assertEquals(0, cursor.getInt(0));
cursor.close();
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
public void testConcatCompleteMessags(){
Map<String, List<Long>> statusMap;
try {
statusMap = WorktableDataLayer.categorizeCompleteVsIncomplete(getContext());
List<Long> txIds = statusMap.get(WorktableDataLayer.label_complete);
WorktableDataLayer.getConcatenatedMessagesForTxIds(getContext(), txIds);
Map<Long, String> localBlobMap = WorktableDataLayer.getConcatenatedMessagesForTxIds(getContext(), txIds);
assertEquals(4, localBlobMap.size());
assertEquals("1of3_txid_1112of3_txid_1113of3_txid_111", localBlobMap.get(111L));
assertEquals("1of5_txid_1002of5_txid_1003of5_txid_1004of5_txid_1005of5_txid_100", localBlobMap.get(100L));
assertEquals("1of3_txid_40012of3_txid_40013of3_txid_4001", localBlobMap.get(4001L));
assertEquals("1of3_txid_40002of3_txid_40003of3_txid_4000", localBlobMap.get(4000L));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
fail();
}
}
/** mocked blobs and transaction ids**/
@SuppressWarnings("serial")
private static final Map<Long, String> blobMap = new HashMap<Long, String>(){{
put(1L,"#form1 val1a val2a val3a#form1 val1b val2b val3b#form1 val1c val2c val3c");
put(2L,"#formA a1 a2 a3#formB b1 b2 b3#formC c1 c2 c3");
put(3L,"#form4 val4a val4a val4a#form5 val5b val5b val5b#form6 val6c val6c val6c#formX x1 x2 x3#formY y1 y2 y3#formZ z1 z2 z3");
}};
/** mocked demoded blobs in String array to transaction ids **/
@SuppressWarnings("unused")
private static final Map<Long, String[]> demodedBlobs = Demodulator.deModulateBlobMap(blobMap);
String[] demodedBlobs1 = {"form1 val1a val2a val3a","form1 val1b val2b val3b","form1 val1c val2c val3c"};
String[] demodedBlobs2 = {"formA a1 a2 a3","formB b1 b2 b3","formC c1 c2 c3"};
String[] demodedBlobs3 = {"form4 val4a val4a val4a","form5 val5b val5b val5b","form6 val6c val6c val6c","formX x1 x2 x3","formY y1 y2 y3","formZ z1 z2 z3"};
public void testDemodulateBlob(){
Map<Long, String[]> demoded = Demodulator.deModulateBlobMap(blobMap);
assertEquals("Demodulation was wrong.",StringUtils.join(demodedBlobs1), StringUtils.join(demoded.get(1L)));
assertEquals("Demodulation was wrong.",StringUtils.join(demodedBlobs2), StringUtils.join(demoded.get(2L)));
assertEquals("Demodulation was wrong.",StringUtils.join(demodedBlobs3), StringUtils.join(demoded.get(3L)));
}
}