package com.samknows.measurement.storage;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import com.samknows.libcore.SKPorting;
import com.samknows.libcore.SKConstants;
import com.samknows.measurement.CachingStorage;
import com.samknows.measurement.SKApplication;
import com.samknows.measurement.schedule.ScheduleConfig;
import com.samknows.measurement.util.SKDateFormat;
import com.samknows.tests.HttpTest;
import com.samknows.tests.LatencyTest;
import com.samknows.tests.SKAbstractBaseTest;
//Model for the test_result table in the SQLite database
public class StorageTestResult extends JSONObject{
// These are DETAILED test ids.
// They are ONLY referenced INTERNALLY.
public enum DETAIL_TEST_ID {
DOWNLOAD_TEST_ID(0),
UPLOAD_TEST_ID(1),
LATENCY_TEST_ID(2),
PACKETLOSS_TEST_ID(3),
JITTER_TEST_ID(4);
private final int value;
DETAIL_TEST_ID(int value) {
this.value = value;
}
public int getValueAsInt() {
return value;
}
public static DETAIL_TEST_ID sGetTestIdForInt(int value) {
if (value == DETAIL_TEST_ID.DOWNLOAD_TEST_ID.value) {
return DETAIL_TEST_ID.DOWNLOAD_TEST_ID;
} else if (value == DETAIL_TEST_ID.UPLOAD_TEST_ID.value) {
return DETAIL_TEST_ID.UPLOAD_TEST_ID;
} else if (value == DETAIL_TEST_ID.LATENCY_TEST_ID.value) {
return DETAIL_TEST_ID.LATENCY_TEST_ID;
} else if (value == DETAIL_TEST_ID.PACKETLOSS_TEST_ID.value) {
return DETAIL_TEST_ID.PACKETLOSS_TEST_ID;
} else if (value == DETAIL_TEST_ID.JITTER_TEST_ID.value) {
return DETAIL_TEST_ID.JITTER_TEST_ID;
} else {
SKPorting.sAssert(false);
return DETAIL_TEST_ID.DOWNLOAD_TEST_ID;
}
}
}
//Test Result JSONObject implementation
public static final String JSON_TYPE_ID = "type";
public static final String JSON_TYPE_NAME = "type_name";
public static final String JSON_TESTNUMBER = "testnumber";
public static final String JSON_STATUS_COMPLETE = "status_complete";
public static final String JSON_DTIME = "dtime";
public static final String JSON_DATETIME = "datetime";
public static final String JSON_LOCATION = "location";
public static final String JSON_RESULT = "result";
public static final String JSON_SUCCESS = "success";
public static final String JSON_HRRESULT = "hrresult";
public static final String UPLOAD_TEST_STRING = "upload";
public static final String DOWNLOAD_TEST_STRING = "download";
public static final String LATENCY_TEST_STRING = "latency";
public static final String PACKETLOSS_TEST_STRING = "packetloss";
public static final String JITTER_TEST_STRING = "jitter";
private enum TESTSSTRINGID {
JHTTPGET, JHTTPGETMT, JHTTPPOST, JHTTPPOSTMT, JUDPLATENCY, JUDPJITTER
}
private DETAIL_TEST_ID _test_id;
private StorageTestResult(DETAIL_TEST_ID test_id){
_test_id = test_id;
put(JSON_TYPE_ID, _test_id+"");
put(JSON_TYPE_NAME, testIdToString(_test_id));
}
public String getTestIdAsString() {
return testIdToString(_test_id);
}
public static String testIdToString(DETAIL_TEST_ID test_id) {
switch (test_id) {
case UPLOAD_TEST_ID:
return UPLOAD_TEST_STRING;
case DOWNLOAD_TEST_ID:
return DOWNLOAD_TEST_STRING;
case LATENCY_TEST_ID:
return LATENCY_TEST_STRING;
case PACKETLOSS_TEST_ID:
return PACKETLOSS_TEST_STRING;
case JITTER_TEST_ID:
return JITTER_TEST_STRING;
}
return "";
}
public StorageTestResult(String type, long dtime, String location, long success, double result){
_test_id = testStringToId(type);
setTime(dtime);
setLocation(location);
putLong(JSON_SUCCESS, success);
// This writes the test result via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
setResult(result);
}
public static DETAIL_TEST_ID testStringToId(String testString) {
if (UPLOAD_TEST_STRING.equals(testString)) {
return DETAIL_TEST_ID.UPLOAD_TEST_ID;
} else if (DOWNLOAD_TEST_STRING.equals(testString)) {
return DETAIL_TEST_ID.DOWNLOAD_TEST_ID;
} else if (LATENCY_TEST_STRING.equals(testString)) {
return DETAIL_TEST_ID.LATENCY_TEST_ID;
} else if (PACKETLOSS_TEST_STRING.equals(testString)) {
return DETAIL_TEST_ID.PACKETLOSS_TEST_ID;
} else if (JITTER_TEST_STRING.equals(testString)) {
return DETAIL_TEST_ID.JITTER_TEST_ID;
}
SKPorting.sAssert(false);
return DETAIL_TEST_ID.DOWNLOAD_TEST_ID;
}
// public static String hrResult(String test_type, double value){
// return hrResult(testStringToId(test_type),value);
// }
public static String hrResult(DETAIL_TEST_ID test_type_id, double value){
String ret = value +"";
switch (test_type_id) {
case UPLOAD_TEST_ID:
case DOWNLOAD_TEST_ID:
ret = throughputToString(value);
break;
case LATENCY_TEST_ID:
case JITTER_TEST_ID:
ret = timeMicrosecondsToString(value);
break;
case PACKETLOSS_TEST_ID:
ret = String.format("%.2f %%", value);
break;
}
return ret;
}
// This writes the test result via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
private void setResult(double value) {
String hrresult = "";
switch (_test_id) {
case UPLOAD_TEST_ID:
Log.d("*******", "setResult for Upload test");
hrresult = throughputToString(value);
break;
case DOWNLOAD_TEST_ID:
Log.d("*******", "setResult for Download test");
hrresult = throughputToString(value);
break;
case LATENCY_TEST_ID:
hrresult = timeMicrosecondsToString(value);
break;
case JITTER_TEST_ID:
hrresult = timeMicrosecondsToString(value);
break;
case PACKETLOSS_TEST_ID:
hrresult = String.format("%.2f %%", value);
break;
}
putDouble(JSON_RESULT, value);
// The FOLLOWING FIELD is the value extracted from the Message instance...
put(JSON_HRRESULT, hrresult);
}
public static String throughputToString(double value) {
if (SKApplication.getAppInstance().getForceUploadDownloadSpeedToReportInMbps()) {
return String.format("%.2f Mbps", (double) (value / 1000000.0));
}
String ret = "";
if (value < 1000) {
ret = String.format("%.0f bps", value);
} else if (value < 1000000) {
ret = String.format("%.2f Kbps", (double) (value / 1000.0));
} else {
ret = String.format("%.2f Mbps", (double) (value / 1000000.0));
}
return ret;
}
// Use this method from the Summary screen; it is like timeMicrosecondsToString,
// but without the units; and ALWAYS in milliseconds.
public static String timeMicrosecondsToMillisecondsStringNoUnits(double valueMicroseconds) {
String ret = String.format("%.0f", valueMicroseconds/1000);
return ret;
}
public static String timeMicrosecondsToString(double valueMicroseconds) {
String ret = "";
if (valueMicroseconds < 1000) {
ret = String.format("%.0f microseconds", valueMicroseconds );
} else if (valueMicroseconds < 1000000) {
ret = String.format("%.0f ms", valueMicroseconds/1000);
} else {
ret = String.format("%.2f s", valueMicroseconds/1000000);
}
return ret;
}
private void put(String key, String value){
try{
super.put(key, value);
}catch(JSONException je){
SKPorting.sAssertE(StorageTestResult.class, "JSONException "+ key +" "+ value);
}
}
private void putLong(String key, long value){
try{
super.put(key, value);
}catch(JSONException je){
SKPorting.sAssertE(StorageTestResult.class, "JSONException "+ key +" "+ value);
}
}
private void setTime(long dtime_mills){
putLong(JSON_DTIME, dtime_mills);
put(JSON_DATETIME, SKDateFormat.sGetDateAsIso8601String(new java.util.Date(dtime_mills)));
}
private void putDouble(String key, double value){
try{
super.put(key, value);
}catch(JSONException je){
SKPorting.sAssertE(StorageTestResult.class, "JSONException "+ key +" "+ value);
}
}
//Empty constructor
public StorageTestResult(){}
public void setSuccess(int success){
put(JSON_SUCCESS, success+"");
}
// This writes the test resultsĀ§ via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
public static List<JSONObject> testOutput(SKAbstractBaseTest theTest, String testType) {
List<JSONObject> ret = new ArrayList<>();
// if (data[0].equals("NETACTIVITY")) {
// return ret;
// }
// if (data[0].equals("CPUACTIVITY")) {
// return ret;
// }
// if (data[0].equals("CLOSESTTARGET")) {
// return null;
// }
TESTSSTRINGID tsid;
//SKLogger.sAssert(data[0].equals(testType));
switch (testType) {
case SKConstants.TEST_TYPE_DOWNLOAD:
tsid = TESTSSTRINGID.JHTTPGETMT;
// Continue!
break;
case SKConstants.TEST_TYPE_UPLOAD:
tsid = TESTSSTRINGID.JHTTPPOSTMT;
// Continue!
break;
case SKConstants.TEST_TYPE_LATENCY:
tsid = TESTSSTRINGID.JUDPLATENCY;
// Continue!
break;
case SKConstants.TEST_TYPE_CLOSEST_TARGET:
return null;
case "NETACTIVITY":
SKPorting.sAssert(false);
return null;
// } else if (testType.equals("CPUACTIVITY")) {
// SKLogger.sAssert(false);
// return null;
default:
SKPorting.sAssert(false);
// Nothing to report!
return null;
}
switch (tsid) {
case JHTTPGET:
case JHTTPGETMT: {
// This writes the test result via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
StorageTestResult testResult = createStorageTestResultForUI_For_HttpTest(DETAIL_TEST_ID.DOWNLOAD_TEST_ID, (HttpTest) theTest);
ret.add(testResult);
}
break;
case JHTTPPOST:
case JHTTPPOSTMT: {
// This writes the test result via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
StorageTestResult testResult = createStorageTestResultForUI_For_HttpTest(DETAIL_TEST_ID.UPLOAD_TEST_ID, (HttpTest) theTest);
ret.add(testResult);
}
break;
case JUDPLATENCY: {
// This writes the test result via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
StorageTestResult latencyTestResult = createStorageTestResultForUI_For_LatencyTest_Latency((LatencyTest) theTest);
ret.add(latencyTestResult);
StorageTestResult lossTestResult = createStorageTestResultForUI_For_LatencyTest_Loss((LatencyTest) theTest);
ret.add(lossTestResult);
// And send as a JITTER test, as well!
StorageTestResult jitterTestResult = createStorageTestResultForUI_For_LatencyTest_Jitter((LatencyTest) theTest);
ret.add(jitterTestResult);
}
break;
case JUDPJITTER:
SKPorting.sAssert(false);
break;
}
return ret;
}
private static StorageTestResult createStorageTestResultForUI_For_HttpTest(DETAIL_TEST_ID test_id, HttpTest theTest) {
StorageTestResult ret = new StorageTestResult(test_id);
long dtimeNano = theTest.getTimestamp()*1000;
ret.setTime(dtimeNano);
String target = theTest.getTarget();
ret.setLocation(target);
// This writes the test results via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
Double bytesPerSecond = Math.max(0, theTest.getTransferBytesPerSecond());
Double bitsPerSecond = bytesPerSecond * 8.0;
ret.setResult(bitsPerSecond);
long success = theTest.isSuccessful() ? 1 : 0;
ret.putLong(JSON_SUCCESS, success);
ret.setTest(test_id);
ret.setComplete();
return ret;
}
// This writes the test results via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
private static StorageTestResult createStorageTestResultForUI_For_LatencyTest_Latency(LatencyTest theTest) {
StorageTestResult lat = new StorageTestResult(DETAIL_TEST_ID.LATENCY_TEST_ID);
lat.setTest(DETAIL_TEST_ID.LATENCY_TEST_ID);
long dtimeNano = theTest.getTimestamp()*1000;
lat.setTime(dtimeNano);
String target = theTest.getTarget();
lat.setLocation(target);
Double latencyResultMicroseconds = (double) theTest.getAverageMicroseconds();
lat.setResult(latencyResultMicroseconds);
long success = theTest.isSuccessful() ? 1 : 0;
lat.putLong(JSON_SUCCESS, success);
lat.setComplete();
return lat;
}
// This writes the test results via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
private static StorageTestResult createStorageTestResultForUI_For_LatencyTest_Loss(LatencyTest theTest) {
StorageTestResult pl = new StorageTestResult(DETAIL_TEST_ID.PACKETLOSS_TEST_ID);
pl.setTest(DETAIL_TEST_ID.PACKETLOSS_TEST_ID);
int lost = theTest.getLostPackets();
int sent = theTest.getSentPackets();
double packetLoss = 0.0;
if(sent != 0){
packetLoss = 100d * ((double) lost)/sent;
}
pl.setResult(packetLoss);
long dtimeNano = theTest.getTimestamp()*1000;
pl.setTime(dtimeNano);
String target = theTest.getTarget();
pl.setLocation(target);
long success = theTest.isSuccessful() ? 1 : 0;
pl.putLong(JSON_SUCCESS, success);
pl.setComplete();
return pl;
}
// This writes the test results via JSON_HRESULT, which is sent (a short while later) to the UI as Message instances...
// by ManualTestRunner:progressMessage
private static StorageTestResult createStorageTestResultForUI_For_LatencyTest_Jitter(LatencyTest theTest){
StorageTestResult ret = new StorageTestResult(DETAIL_TEST_ID.JITTER_TEST_ID);
ret.setTest(StorageTestResult.DETAIL_TEST_ID.JITTER_TEST_ID);
long dtimeNano = theTest.getTimestamp()*1000;
ret.setTime(dtimeNano);
String target = theTest.getTarget();
ret.setLocation(target);
Double jitterMilliseconds = (double) theTest.getResultJitterMilliseconds();
Double jitterMicroseconds = jitterMilliseconds * 1000.0;
ret.setResult(jitterMicroseconds);
long success = theTest.isSuccessful() ? 1 : 0;
ret.putLong(JSON_SUCCESS, success);
ret.setComplete();
return ret;
}
private void setTest(DETAIL_TEST_ID test_number){
put(JSON_TYPE_ID, "test");
put(JSON_TESTNUMBER, ""+test_number.getValueAsInt());
}
private void setComplete(){
put(JSON_STATUS_COMPLETE, "100");
}
private void setPassiveMetric(){
put(JSON_TYPE_ID, "passivemetric");
}
private void setLocation(String target){
put(JSON_LOCATION, targetToLocation(target));
}
private static String targetToLocation(String target){
String ret = target;
ScheduleConfig config = CachingStorage.getInstance().loadScheduleConfig();
if(config != null && config.hosts.containsKey(target)){
ret = config.hosts.get(target);
}
return ret;
}
}