diff --git a/.idea/dictionaries/mh.xml b/.idea/dictionaries/mh.xml index 92d80a7..d711466 100644 --- a/.idea/dictionaries/mh.xml +++ b/.idea/dictionaries/mh.xml @@ -5,6 +5,7 @@ ciphertext coronawarncompanion coronawarndetails + covid datapoint diagnosiskeys encryptor @@ -12,6 +13,7 @@ gmsreadout hkdf hmac + huebler protos rpik rpis @@ -21,4 +23,4 @@ vals - + \ No newline at end of file diff --git a/app/src/main/java/org/tosl/coronawarncompanion/matchentries/MatchesRecyclerViewAdapter.java b/app/src/main/java/org/tosl/coronawarncompanion/matchentries/MatchesRecyclerViewAdapter.java index 34a088d..bc0e8d6 100644 --- a/app/src/main/java/org/tosl/coronawarncompanion/matchentries/MatchesRecyclerViewAdapter.java +++ b/app/src/main/java/org/tosl/coronawarncompanion/matchentries/MatchesRecyclerViewAdapter.java @@ -66,12 +66,12 @@ public class MatchesRecyclerViewAdapter extends RecyclerView.Adapter { private static final String TAG = "CRRecyclerViewAdapter"; - private final int gridColor = Color.parseColor("#E0E0E0"); - private final int redColor = Color.parseColor("#FF0000"); - private final int orangeColor = Color.parseColor("#FFA500"); - private final int yellowColor = Color.parseColor("#FFFF00"); - private final int greenColor = Color.parseColor("#00FF00"); - private final int blackColor = Color.parseColor("#000000"); + private static final int gridColor = Color.parseColor("#E0E0E0"); + private static final int redColor = Color.parseColor("#FF0000"); + private static final int orangeColor = Color.parseColor("#FFA500"); + private static final int yellowColor = Color.parseColor("#FFFF00"); + private static final int greenColor = Color.parseColor("#00FF00"); + private static final int blackColor = Color.parseColor("#000000"); private final ArrayList> mValues; private CWCApplication mApp; @@ -128,7 +128,7 @@ public void onBindViewHolder(final ViewHolder holder, int position) { hasReportType = true; } - MatchEntryDetails matchEntryDetails = getMatchEntryDetails(list); + MatchEntryDetails matchEntryDetails = getMatchEntryDetails(list, mApp.getTimeZoneOffsetSeconds()); int minTimestampLocalTZDay0 = matchEntryDetails.minTimestampLocalTZDay0; int maxTimestampLocalTZDay0 = matchEntryDetails.maxTimestampLocalTZDay0; @@ -168,7 +168,7 @@ public void onBindViewHolder(final ViewHolder holder, int position) { holder.mChartView.getLineData().getDataSetByIndex(1).setVisible(this.showAllScans); } - public class MatchEntryDetails { + public static class MatchEntryDetails { public ArrayList dataPoints; public ArrayList dotColors; public ArrayList dataPointsMinAttenuation; @@ -182,7 +182,8 @@ public MatchEntryDetails() { } } - private MatchEntryDetails getMatchEntryDetails(ArrayList list) { + public static MatchEntryDetails getMatchEntryDetails(ArrayList list, + int timeZoneOffset) { // Threshold value for break detection: final int pauseThresholdSeconds = 10; @@ -210,7 +211,6 @@ private MatchEntryDetails getMatchEntryDetails(ArrayList lis //Log.d(TAG, "RSSI: "+rssi+" dBm"); int attenuation = txPower - rssi; //Log.d(TAG, "Attenuation: "+attenuation+" dB"); - int timeZoneOffset = mApp.getTimeZoneOffsetSeconds(); int timestampLocalTZ = scanRecord.getTimestamp() + timeZoneOffset; // reduce to "day0", to improve resolution within the float x value: int timestampLocalTZDay0 = timestampLocalTZ % (24*3600); @@ -318,7 +318,7 @@ private MatchEntryDetails getMatchEntryDetails(ArrayList lis return result; } - private int getDotColorForAttenuation(int attenuation) { + private static int getDotColorForAttenuation(int attenuation) { if (attenuation < 55) { return redColor; } else if (attenuation <= 63) { diff --git a/app/src/test/java/org/tosl/coronawarncompanion/ExampleUnitTest.java b/app/src/test/java/org/tosl/coronawarncompanion/ExampleUnitTest.java deleted file mode 100644 index f9a9d4a..0000000 --- a/app/src/test/java/org/tosl/coronawarncompanion/ExampleUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.tosl.coronawarncompanion; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Example local unit test, which will execute on the development machine (host). - * - * @see Testing documentation - */ -public class ExampleUnitTest { - @Test - public void addition_isCorrect() { - assertEquals(4, 2 + 2); - } -} diff --git a/app/src/test/java/org/tosl/coronawarncompanion/MatchesRecyclerViewAdapterUnitTest.java b/app/src/test/java/org/tosl/coronawarncompanion/MatchesRecyclerViewAdapterUnitTest.java new file mode 100644 index 0000000..c4b8813 --- /dev/null +++ b/app/src/test/java/org/tosl/coronawarncompanion/MatchesRecyclerViewAdapterUnitTest.java @@ -0,0 +1,107 @@ +package org.tosl.coronawarncompanion; + +import com.google.protobuf.ByteString; + +import org.junit.Test; +import org.tosl.coronawarncompanion.diagnosiskeys.DiagnosisKeysProtos; +import org.tosl.coronawarncompanion.gmsreadout.ContactRecordsProtos; +import org.tosl.coronawarncompanion.matchentries.MatchesRecyclerViewAdapter; +import org.tosl.coronawarncompanion.matcher.Matcher; + +import java.util.ArrayList; + +import static org.junit.Assert.*; +import static org.tosl.coronawarncompanion.tools.Utils.getENINFromSeconds; + +/** + * Local unit test, which will execute on the development machine (host). + * + * @see Testing documentation + */ +public class MatchesRecyclerViewAdapterUnitTest { + + @Test + public void getMatchEntryDetails_isCorrect() { + + // create content + + final int daysSinceEpoch = 18000; + final int numGroups = 10; + final int numEntriesPerGroup = 20; + + DiagnosisKeysProtos.TemporaryExposureKeyExport.Builder dkImportBuilder = + DiagnosisKeysProtos.TemporaryExposureKeyExport.newBuilder(); + byte[] keyBytes = new byte[] {(byte) 0, (byte) 1, (byte) 2, (byte) 3, + (byte) 4, (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9, + (byte) 10, (byte) 11, (byte) 12, (byte) 13, (byte) 14, (byte) 15}; + @SuppressWarnings("deprecation") DiagnosisKeysProtos.TemporaryExposureKey.Builder dkBuilder = + DiagnosisKeysProtos.TemporaryExposureKey.newBuilder() + .setKeyData(ByteString.copyFrom(keyBytes)) + .setTransmissionRiskLevel(8) + .setRollingStartIntervalNumber(getENINFromSeconds(daysSinceEpoch*24*3600)) + .setRollingPeriod(144) + .setReportType(DiagnosisKeysProtos.TemporaryExposureKey.ReportType.CONFIRMED_TEST); + dkImportBuilder.addKeys(dkBuilder.build()); + DiagnosisKeysProtos.TemporaryExposureKeyExport dkImport = dkImportBuilder.build(); + + byte[] aemBytes = new byte[] {(byte) 0, (byte) 1, (byte) 2, (byte) 3}; + byte[] aemXorBytes = new byte[] {(byte) 0, (byte) 1, (byte) 2, (byte) 3}; + + int TimestampLocalTZ = daysSinceEpoch * 24*3600; + + ArrayList list = new ArrayList<>(); + for (int groupPos = 0; groupPos < numGroups; groupPos++) { + for (int entryPos = 0; entryPos < numEntriesPerGroup; entryPos++) { + int startTimestampLocalTZ = TimestampLocalTZ; + TimestampLocalTZ += 3; + int endTimestampLocalTZ = TimestampLocalTZ; + TimestampLocalTZ += 3; + + DiagnosisKeysProtos.TemporaryExposureKey dk = dkImport.getKeys(0); + byte[] rpiBytes = {(byte) 0, (byte) 1, (byte) 2, (byte) 3, + (byte) 4, (byte) 5, (byte) 6, (byte) 7, (byte) 8, (byte) 9, + (byte) 10, (byte) 11, (byte) 12, (byte) 13, (byte) 14, (byte) 15}; + + ContactRecordsProtos.ContactRecords.Builder contactRecordsBuilder1 = + ContactRecordsProtos.ContactRecords.newBuilder() + .addRecord(ContactRecordsProtos.ScanRecord.newBuilder() + .setTimestamp(startTimestampLocalTZ) + .setRssi(-50) + .setAem(ByteString.copyFrom(aemBytes)) + ); + ContactRecordsProtos.ContactRecords contactRecords1 = contactRecordsBuilder1.build(); + Matcher.MatchEntry entry1 = new Matcher.MatchEntry(dk, rpiBytes, contactRecords1, + startTimestampLocalTZ, endTimestampLocalTZ, aemXorBytes); + list.add(entry1); + + ContactRecordsProtos.ContactRecords.Builder contactRecordsBuilder2 = + ContactRecordsProtos.ContactRecords.newBuilder() + .addRecord(ContactRecordsProtos.ScanRecord.newBuilder() + .setTimestamp(startTimestampLocalTZ+1) + .setRssi(-50) + .setAem(ByteString.copyFrom(aemBytes)) + ); + ContactRecordsProtos.ContactRecords contactRecords2 = contactRecordsBuilder2.build(); + Matcher.MatchEntry entry2 = new Matcher.MatchEntry(dk, rpiBytes, contactRecords2, + startTimestampLocalTZ, endTimestampLocalTZ, aemXorBytes); + list.add(entry2); + } + TimestampLocalTZ += 4*60; + } + + // assert that the list contains the correct number of items + assertEquals(numGroups*numEntriesPerGroup*2, list.size()); + + // run getMatchEntryDetails() + MatchesRecyclerViewAdapter.MatchEntryDetails matchEntryDetails = + MatchesRecyclerViewAdapter.getMatchEntryDetails(list,0); + + // assert that no entry was lost in the process + assertEquals(list.size(), + matchEntryDetails.dataPoints.size()+matchEntryDetails.dataPointsMinAttenuation.size()); + assertEquals(list.size(), + matchEntryDetails.dotColors.size()+matchEntryDetails.dotColorsMinAttenuation.size()); + // assert that there's a color for each dataPoint + assertEquals(matchEntryDetails.dataPoints.size(), matchEntryDetails.dotColors.size()); + } +}