From 9d93d172b22f9695a68e61a842e4ba2c33c2cef1 Mon Sep 17 00:00:00 2001 From: Kaz Date: Tue, 21 May 2024 13:12:34 +0200 Subject: [PATCH 01/10] changed attendees in RollCallViewModel from Set to TreeSet to sort it constantly. --- .../popstellar/ui/lao/event/rollcall/RollCallViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt index 68afe7d9a4..d61a88476a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt @@ -36,6 +36,7 @@ import java.time.Instant import java.util.stream.Collectors import javax.inject.Inject import timber.log.Timber +import java.util.TreeSet @HiltViewModel class RollCallViewModel @@ -52,7 +53,7 @@ constructor( ) : AndroidViewModel(application), QRCodeScanningViewModel { private lateinit var laoId: String - private val attendees: MutableSet = HashSet() +private val attendees: TreeSet = TreeSet(Comparator.comparing { it.toString() }) override val nbScanned = MutableLiveData() lateinit var attendedRollCalls: Observable> private set From 9a28a61a70d64f0d89cae4b0c2067403631a611d Mon Sep 17 00:00:00 2001 From: Kaz Date: Mon, 3 Jun 2024 18:16:23 +0200 Subject: [PATCH 02/10] added stringListIsSorted and modified greaterOrEqualThan --- .../method/message/data/election/QuestionResult.kt | 4 +++- .../dedis/popstellar/utility/MessageValidator.kt | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/election/QuestionResult.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/election/QuestionResult.kt index bd0ca42bf0..d05a7275ae 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/election/QuestionResult.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/election/QuestionResult.kt @@ -11,7 +11,9 @@ class QuestionResult(ballotOption: String?, count: Int) { val count: Int init { - verify().stringNotEmpty(ballotOption, "ballot option").greaterOrEqualThan(count, 0, "count") + verify() + .stringNotEmpty(ballotOption, "ballot option") + .greaterOrEqualThan(count.toLong(), 0, "count") ballot = ballotOption!! this.count = count diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt index b5d39bda37..10c891e770 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt @@ -211,7 +211,7 @@ object MessageValidator { * @param value the value to compare to * @throws IllegalArgumentException if the value is not greater or equal than the given value */ - fun greaterOrEqualThan(input: Int, value: Int, field: String): MessageValidatorBuilder { + fun greaterOrEqualThan(input: Long, value: Long, field: String): MessageValidatorBuilder { require(input >= value) { "$field must be greater or equal than $value" } return this } @@ -305,6 +305,14 @@ object MessageValidator { return this } + /** Helper method to check that a string list is sorted */ + fun stringListIsSorted(list: List, field: String): MessageValidatorBuilder { + for (i in 0 until list.size - 1) { + require(list[i + 1] >= list[i]) { "$field must be sorted" } + } + return this + } + private fun validBallotOptions(ballotOptions: List?): MessageValidatorBuilder { requireNotNull(ballotOptions) { "Ballot options cannot be null" } listNotEmpty(ballotOptions) From 94f1e76155b09c752308065e091aa2fbfc8f8200 Mon Sep 17 00:00:00 2001 From: Kaz Date: Mon, 3 Jun 2024 18:16:56 +0200 Subject: [PATCH 03/10] added validation to CloseRollCall --- .../message/data/rollcall/CloseRollCall.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt index 41308a917f..e800c391cb 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt @@ -4,8 +4,9 @@ import com.github.dedis.popstellar.model.Immutable import com.github.dedis.popstellar.model.network.method.message.data.Action import com.github.dedis.popstellar.model.network.method.message.data.Data import com.github.dedis.popstellar.model.network.method.message.data.Objects -import com.github.dedis.popstellar.model.objects.RollCall +import com.github.dedis.popstellar.model.objects.RollCall.Companion.generateCloseRollCallId import com.github.dedis.popstellar.model.objects.security.PublicKey +import com.github.dedis.popstellar.utility.MessageValidator.verify import com.google.gson.annotations.SerializedName /** Data sent to close a Roll-Call */ @@ -25,12 +26,23 @@ class CloseRollCall( @field:SerializedName("closed_at") val closedAt: Long, attendees: List ) : Data { - @SerializedName("update_id") - val updateId: String = RollCall.generateCloseRollCallId(laoId, closes, closedAt) + @SerializedName("update_id") val updateId: String - val attendees: List = ArrayList(attendees) + var attendees: List = ArrayList() get() = ArrayList(field) + init { + verify() + .stringListIsSorted(attendees.map { toString() }, "attendees") + .validPastTimes(closedAt) + .isNotEmptyBase64(laoId, "laoId") + .isNotEmptyBase64(closes, "closes") + .greaterOrEqualThan(closedAt, 0, "closedAt") + + this.updateId = generateCloseRollCallId(laoId, closes, closedAt) + this.attendees = ArrayList(attendees) + } + override val `object`: String get() = Objects.ROLL_CALL.`object` From c8e7e3817f0e0206b03005fc1035108094ed9672 Mon Sep 17 00:00:00 2001 From: Kaz Date: Mon, 3 Jun 2024 18:18:12 +0200 Subject: [PATCH 04/10] organizer is responsible for sorting attendee list before sending + verifying list is sorted when displaying (organizer or attendee) + keeping order of attendees list as received --- .../model/objects/event/RollCallBuilder.kt | 4 ++-- .../event/rollcall/RollCallArrayAdapter.kt | 4 ++++ .../ui/lao/event/rollcall/RollCallFragment.kt | 16 ++++++++++++++- .../lao/event/rollcall/RollCallViewModel.kt | 4 ++-- .../utility/handler/data/RollCallHandler.kt | 20 ++++++++++++++++--- .../app/src/main/res/values/strings.xml | 2 ++ 6 files changed, 42 insertions(+), 8 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt index 4028f33ab8..2a31b37037 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt @@ -66,12 +66,12 @@ class RollCallBuilder { } fun setAttendees(attendees: Set): RollCallBuilder { - this.attendees = HashSet(attendees) + this.attendees = LinkedHashSet(attendees) return this } fun setEmptyAttendees(): RollCallBuilder { - attendees = HashSet() + attendees = LinkedHashSet() return this } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt index b69162085c..c0287d6016 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt @@ -16,6 +16,10 @@ class RollCallArrayAdapter( private val myToken: PoPToken?, ) : ArrayAdapter(context, layout, attendeesList) { + init { + RollCallFragment.isAttendeeListSorted(attendeesList, context) + } + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val view = super.getView(position, convertView, parent) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index 9abe2c818a..71360da584 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -1,6 +1,7 @@ package com.github.dedis.popstellar.ui.lao.event.rollcall import android.annotation.SuppressLint +import android.content.Context import android.content.pm.ActivityInfo import android.graphics.Color import android.os.Bundle @@ -9,6 +10,8 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.VisibleForTesting import androidx.appcompat.content.res.AppCompatResources +import androidx.core.content.ContentProviderCompat.requireContext +import androidx.lifecycle.MutableLiveData import com.github.dedis.popstellar.R import com.github.dedis.popstellar.databinding.RollCallFragmentBinding import com.github.dedis.popstellar.model.objects.RollCall @@ -253,6 +256,7 @@ class RollCallFragment : AbstractEventFragment { .getAttendees() .stream() .map(PublicKey::encoded) + .sorted(compareBy(String::toString)) .collect(Collectors.toList()) binding.rollCallAttendeesText.text = @@ -342,17 +346,27 @@ class RollCallFragment : AbstractEventFragment { companion object { val TAG: String = RollCallFragment::class.java.simpleName + private val deAnonymizationWarned = MutableLiveData(false) @JvmStatic fun newInstance(persistentId: String?): RollCallFragment { + deAnonymizationWarned.value = false val fragment = RollCallFragment() val bundle = Bundle(1) bundle.putString(ROLL_CALL_ID, persistentId) fragment.arguments = bundle - return fragment } + fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { + if (attendeesList != attendeesList.sorted() && deAnonymizationWarned.value == false) { + deAnonymizationWarned.value = true + logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) + return false + } + return true + } + /** * The following is only for testing purposes. Production should never pass arguments to a * fragment instantiation but should rather use arguments diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt index d61a88476a..0fe5be283d 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt @@ -33,10 +33,10 @@ import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single import java.time.Instant +import java.util.TreeSet import java.util.stream.Collectors import javax.inject.Inject import timber.log.Timber -import java.util.TreeSet @HiltViewModel class RollCallViewModel @@ -53,7 +53,7 @@ constructor( ) : AndroidViewModel(application), QRCodeScanningViewModel { private lateinit var laoId: String -private val attendees: TreeSet = TreeSet(Comparator.comparing { it.toString() }) + private val attendees: TreeSet = TreeSet(compareBy { it.toString() }) override val nbScanned = MutableLiveData() lateinit var attendedRollCalls: Observable> private set diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt index 5d24e57512..1a6e027093 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt @@ -125,8 +125,23 @@ constructor( val updateId = closeRollCall.updateId val closes = closeRollCall.closes val existingRollCall = rollCallRepo.getRollCallWithId(laoView.id, closes) - val currentAttendees = existingRollCall.attendees - currentAttendees.addAll(closeRollCall.attendees) + + val currentAttendees: Set + if (closeRollCall.attendees.containsAll(existingRollCall.attendees)) { + // closeRollCall.attendees is sorted, so we prefer to use it if we can + currentAttendees = closeRollCall.attendees.toMutableSet() + } else { + // if both lists have different attendees, we merge them even though we lose the order + // We are not ordering it because it is important to keep the order that we received to know if we face de-anonymization + currentAttendees = existingRollCall.attendees + currentAttendees.addAll(closeRollCall.attendees) + } + + // log existingRollCall.attendees and closeRollCall.attendees + Timber.tag(TAG).d("existingRollCall.attendees: %s", existingRollCall.attendees) + Timber.tag(TAG).d("closeRollCall.attendees: %s", closeRollCall.attendees) + // log currentAttendees + Timber.tag(TAG).d("currentAttendees: %s", currentAttendees) val builder = RollCallBuilder() builder @@ -142,7 +157,6 @@ constructor( .setEnd(closeRollCall.closedAt) val laoId = laoView.id val rollCall = builder.build() - witnessingRepo.addWitnessMessage(laoId, closeRollCallWitnessMessage(messageId, rollCall)) if (witnessingRepo.areWitnessesEmpty(laoId)) { addRollCallRoutine(rollCallRepo, digitalCashRepo, laoId, rollCall) diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index aa7253eec5..930914a9b8 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -176,6 +176,8 @@ Scanned tokens : %1$d Description Location +Attendees list is not sorted, risk of de-anonymization + Meeting From bf479ad64b2743d710b9cb5d2f911df838d73512 Mon Sep 17 00:00:00 2001 From: Kaz Date: Mon, 3 Jun 2024 19:01:23 +0200 Subject: [PATCH 05/10] added tests for CloseRollCall data validation --- .../message/data/rollcall/CloseRollCall.kt | 4 +- .../ui/lao/event/rollcall/RollCallFragment.kt | 1 - .../popstellar/utility/MessageValidator.kt | 6 +- .../utility/handler/data/RollCallHandler.kt | 7 +- .../data/rollcall/CloseRollCallTest.kt | 80 ++++++++++++++++++- 5 files changed, 87 insertions(+), 11 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt index e800c391cb..701b676789 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCall.kt @@ -33,11 +33,11 @@ class CloseRollCall( init { verify() - .stringListIsSorted(attendees.map { toString() }, "attendees") + .stringListIsSorted(attendees, "attendees") .validPastTimes(closedAt) + .greaterOrEqualThan(closedAt, 0, "closedAt") .isNotEmptyBase64(laoId, "laoId") .isNotEmptyBase64(closes, "closes") - .greaterOrEqualThan(closedAt, 0, "closedAt") this.updateId = generateCloseRollCallId(laoId, closes, closedAt) this.attendees = ArrayList(attendees) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index 71360da584..ae046bd407 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -10,7 +10,6 @@ import android.view.View import android.view.ViewGroup import androidx.annotation.VisibleForTesting import androidx.appcompat.content.res.AppCompatResources -import androidx.core.content.ContentProviderCompat.requireContext import androidx.lifecycle.MutableLiveData import com.github.dedis.popstellar.R import com.github.dedis.popstellar.databinding.RollCallFragmentBinding diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt index 10c891e770..28d995d2d9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt @@ -306,10 +306,8 @@ object MessageValidator { } /** Helper method to check that a string list is sorted */ - fun stringListIsSorted(list: List, field: String): MessageValidatorBuilder { - for (i in 0 until list.size - 1) { - require(list[i + 1] >= list[i]) { "$field must be sorted" } - } + fun stringListIsSorted(list: List<*>, field: String): MessageValidatorBuilder { + require(list == list.sortedBy{it.toString()}) { "$field must be sorted" } return this } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt index 1a6e027093..520438a9d4 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt @@ -128,11 +128,12 @@ constructor( val currentAttendees: Set if (closeRollCall.attendees.containsAll(existingRollCall.attendees)) { - // closeRollCall.attendees is sorted, so we prefer to use it if we can + // closeRollCall.attendees is sorted, so we prefer to use it if we can currentAttendees = closeRollCall.attendees.toMutableSet() } else { - // if both lists have different attendees, we merge them even though we lose the order - // We are not ordering it because it is important to keep the order that we received to know if we face de-anonymization + // if both lists have different attendees, we merge them even though we lose the order + // We are not ordering it because it is important to keep the order that we received to know + // if we face de-anonymization currentAttendees = existingRollCall.attendees currentAttendees.addAll(closeRollCall.attendees) } diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt index 376ea63c77..e6ccc5e9c6 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt @@ -6,13 +6,18 @@ import com.github.dedis.popstellar.model.network.method.message.data.Action import com.github.dedis.popstellar.model.network.method.message.data.Objects import com.github.dedis.popstellar.model.objects.event.EventState import com.github.dedis.popstellar.model.objects.event.EventType +import com.github.dedis.popstellar.model.objects.security.Base64URLData +import com.github.dedis.popstellar.testutils.Base64DataUtils +import com.github.dedis.popstellar.utility.MessageValidator import com.github.dedis.popstellar.utility.security.HashSHA256.hash -import java.time.Instant +import junit.framework.TestCase.assertNotNull import org.hamcrest.CoreMatchers import org.hamcrest.MatcherAssert import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith +import java.time.Instant +import java.util.Collections @RunWith(AndroidJUnit4::class) class CloseRollCallTest { @@ -80,6 +85,57 @@ class CloseRollCallTest { ) } + @Test + fun constructorSucceedsWithValidData() { + val closeRollCall = CloseRollCall(validBase64LaoId, validBase64Closes, pastTime, validAttendees) + assertNotNull(closeRollCall) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenAttendeesNotSorted() { + val unsortedAttendees = ArrayList(attendees).toMutableList() + if (unsortedAttendees[0].toString() > unsortedAttendees[1].toString()) { + Collections.swap(unsortedAttendees, 0, 1) + } + + CloseRollCall(validBase64LaoId, validBase64Closes, pastTime, unsortedAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenClosedAtInFuture() { + CloseRollCall(validBase64LaoId, validBase64Closes, futureTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenTooLongPastTime() { + CloseRollCall(validBase64LaoId, validBase64Closes, tooLongPastTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenLaoIdNotBase64() { + CloseRollCall(invalidBase64, validBase64Closes, pastTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenLaoIdEmpty() { + CloseRollCall(emptyBase64, validBase64Closes, pastTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenClosesNotBase64() { + CloseRollCall(validBase64LaoId, invalidBase64, pastTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenClosesEmpty() { + CloseRollCall(validBase64LaoId, emptyBase64, pastTime, validAttendees) + } + + @Test(expected = IllegalArgumentException::class) + fun constructorFailsWhenClosedAtNegative() { + CloseRollCall(validBase64LaoId, validBase64Closes, negativeClosedAt, validAttendees) + } + companion object { private val LAO_ID = hash("LAO_ID") private const val NAME = "NAME" @@ -88,5 +144,27 @@ class CloseRollCallTest { private val CREATE_ROLL_CALL = CreateRollCall(NAME, TIME, TIME, TIME, LOCATION, null, LAO_ID) private val OPEN_ROLL_CALL = OpenRollCall(LAO_ID, CREATE_ROLL_CALL.id, TIME, EventState.CREATED) private val CLOSE_ROLL_CALL = CloseRollCall(LAO_ID, OPEN_ROLL_CALL.updateId, TIME, ArrayList()) + + private val attendees = listOf( + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey() + ) + + private val validAttendees = attendees.sortedBy { it.toString() } + + private val pastTime = Instant.now().epochSecond - 1000 + private val futureTime = Instant.now().epochSecond + 10000 + private val tooLongPastTime = Instant.now().epochSecond - MessageValidator.MessageValidatorBuilder.VALID_PAST_DELAY + private val negativeClosedAt = (-1).toLong() + + private val invalidBase64 = "invalidBase64String" + private val emptyBase64 = Base64URLData("".toByteArray()).encoded + private val validBase64LaoId = Base64URLData("validLaoId".toByteArray()).encoded + private val validBase64Closes = Base64URLData("validCloses".toByteArray()).encoded + } } From 9f62fb86fb96a3ad13d095542901238e2cb321aa Mon Sep 17 00:00:00 2001 From: Kaz Date: Tue, 4 Jun 2024 20:25:08 +0200 Subject: [PATCH 06/10] changed use of HashSet to LinkedHashSet in roll call + added tests for de-anonymization toast + other things --- .../model/objects/event/RollCallBuilder.kt | 4 +- .../ui/lao/event/rollcall/RollCallFragment.kt | 10 +- .../lao/event/rollcall/RollCallViewModel.kt | 2 + .../popstellar/utility/MessageValidator.kt | 2 +- .../app/src/main/res/values/strings.xml | 2 +- .../rollcall/RollCallFragmentPageObject.java | 1 - .../dedis/popstellar/testutils/UITestUtils.kt | 24 ++++ .../CastVoteOpenBallotFragmentTest.kt | 2 +- .../CastVoteSecretBallotFragmentTest.kt | 2 +- .../event/election/ElectionFragmentTest.kt | 2 +- .../event/eventlist/EventListAdapterTest.kt | 4 +- .../rollcall/RollCallArrayAdapterTest.kt | 4 +- .../event/rollcall/RollCallFragmentTest.kt | 113 ++++++++++++++++-- .../ui/lao/popcha/PoPCHAHomeFragmentTest.kt | 2 +- .../lao/socialmedia/ChirpListAdapterTest.kt | 2 +- .../lao/socialmedia/ChirpListFragmentTest.kt | 2 +- .../SocialMediaHomeFragmentTest.kt | 2 +- .../ui/lao/token/TokenFragmentTest.kt | 2 +- .../ui/lao/token/TokenListFragmentTest.kt | 2 +- .../data/rollcall/CloseRollCallTest.kt | 6 +- .../repository/WitnessingRepositoryTest.kt | 2 +- .../database/RollCallDatabaseTest.kt | 2 +- .../database/WitnessDatabaseTest.kt | 2 +- .../utility/handler/RollCallHandlerTest.kt | 2 +- .../utility/security/KeyManagerTest.kt | 6 +- 25 files changed, 162 insertions(+), 42 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt index 2a31b37037..018a2cbab9 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt @@ -30,7 +30,7 @@ class RollCallBuilder { start = rollCall.startTimestamp end = rollCall.end state = rollCall.state - attendees = HashSet(rollCall.attendees) + attendees = LinkedHashSet(rollCall.attendees) location = rollCall.location description = rollCall.description } @@ -102,7 +102,7 @@ class RollCallBuilder { start, end, state!!, - attendees!!, + LinkedHashSet(attendees), location!!, description!!) } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index ae046bd407..7a9192d220 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -30,6 +30,7 @@ import com.github.dedis.popstellar.utility.ActivityUtils.getQRCodeColor import com.github.dedis.popstellar.utility.ActivityUtils.handleExpandArrow import com.github.dedis.popstellar.utility.Constants.ID_NULL import com.github.dedis.popstellar.utility.Constants.ROLL_CALL_ID +import com.github.dedis.popstellar.utility.error.ErrorUtils import com.github.dedis.popstellar.utility.error.ErrorUtils.logAndShow import com.github.dedis.popstellar.utility.error.UnknownLaoException import com.github.dedis.popstellar.utility.error.UnknownRollCallException @@ -263,10 +264,10 @@ class RollCallFragment : AbstractEventFragment { resources.getString(R.string.roll_call_scanned), rollCallViewModel.getAttendees().size) } else if (rollCall.isClosed) { - attendeesList = - rollCall.attendees.stream().map(PublicKey::encoded).collect(Collectors.toList()) + val orderedAttendees: MutableSet = LinkedHashSet(rollCall.attendees) + attendeesList = orderedAttendees.stream().map(PublicKey::encoded).collect(Collectors.toList()) - // Show the list of attendees if the roll call has ended + // Show the list of attendees if the roll call has ended binding.rollCallAttendeesText.text = String.format(resources.getString(R.string.roll_call_attendees), rollCall.attendees.size) } @@ -358,7 +359,8 @@ class RollCallFragment : AbstractEventFragment { } fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { - if (attendeesList != attendeesList.sorted() && deAnonymizationWarned.value == false) { + + if (attendeesList.isNotEmpty() && attendeesList != attendeesList.sorted() && deAnonymizationWarned.value == false) { deAnonymizationWarned.value = true logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) return false diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt index 0fe5be283d..993ea0110a 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt @@ -37,6 +37,7 @@ import java.util.TreeSet import java.util.stream.Collectors import javax.inject.Inject import timber.log.Timber +import java.util.ArrayList @HiltViewModel class RollCallViewModel @@ -262,6 +263,7 @@ constructor( nbScanned.postValue(attendees.size) } + @Inject fun getAttendees(): Set { return attendees } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt index 28d995d2d9..537599f83e 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/MessageValidator.kt @@ -307,7 +307,7 @@ object MessageValidator { /** Helper method to check that a string list is sorted */ fun stringListIsSorted(list: List<*>, field: String): MessageValidatorBuilder { - require(list == list.sortedBy{it.toString()}) { "$field must be sorted" } + require(list == list.sortedBy { it.toString() }) { "$field must be sorted" } return this } diff --git a/fe2-android/app/src/main/res/values/strings.xml b/fe2-android/app/src/main/res/values/strings.xml index 930914a9b8..b32b592019 100644 --- a/fe2-android/app/src/main/res/values/strings.xml +++ b/fe2-android/app/src/main/res/values/strings.xml @@ -176,7 +176,7 @@ Scanned tokens : %1$d Description Location -Attendees list is not sorted, risk of de-anonymization +Attendees list is not sorted, risk of de-anonymization" diff --git a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/lao/event/rollcall/RollCallFragmentPageObject.java b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/lao/event/rollcall/RollCallFragmentPageObject.java index 84d372151b..56f271b7ae 100644 --- a/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/lao/event/rollcall/RollCallFragmentPageObject.java +++ b/fe2-android/app/src/test/framework/common/java/com/github/dedis/popstellar/testutils/pages/lao/event/rollcall/RollCallFragmentPageObject.java @@ -17,7 +17,6 @@ private RollCallFragmentPageObject() { public static ViewInteraction rollCallTitle() { return onView(withId(R.id.roll_call_fragment_title)); } - public static ViewInteraction rollCallStatusText() { return onView(withId(R.id.roll_call_status)); } diff --git a/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt b/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt index c3c5febb67..9966a69463 100644 --- a/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt +++ b/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt @@ -43,6 +43,30 @@ object UITestUtils { Assert.assertEquals(expected, ShadowToast.getTextOfLatestToast()) } + /** + * Assert that the latest toast was shown with the expected text + * + * @param resId expected + * @param args arguments to the resource + */ + @JvmStatic + fun assertToastDisplayedHasNotText(@StringRes resId: Int, vararg args: Any?) { + MatcherAssert.assertThat( + "No toast was displayed", + ShadowToast.getLatestToast(), + Matchers.notNullValue() + ) + + val expected = ApplicationProvider.getApplicationContext().getString(resId, *args) + Assert.assertNotEquals(expected, ShadowToast.getTextOfLatestToast()) + } + + + @JvmStatic + fun assertNoToastIsDisplayed() { + Assert.assertNull(ShadowToast.getLatestToast()) + } + @JvmStatic fun assertToastIsDisplayedContainsText(@StringRes resId: Int, vararg args: Any?) { MatcherAssert.assertThat( diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteOpenBallotFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteOpenBallotFragmentTest.kt index 6177ee4f61..86360bda81 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteOpenBallotFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteOpenBallotFragmentTest.kt @@ -202,7 +202,7 @@ class CastVoteOpenBallotFragmentTest { private const val PLURALITY = "Plurality" private val laoSubject = BehaviorSubject.createDefault(LaoView(LAO)) private val ROLL_CALL = - RollCall("id", "id", "rc", 0L, 1L, 2L, EventState.CLOSED, HashSet(), "nowhere", "none") + RollCall("id", "id", "rc", 0L, 1L, 2L, EventState.CLOSED, LinkedHashSet(), "nowhere", "none") private val ELECTION_ID = generateElectionSetupId(LAO_ID, CREATION, TITLE) private val ELECTION_QUESTION_1 = ElectionQuestion( diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteSecretBallotFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteSecretBallotFragmentTest.kt index a80a0943cd..530c7cf7dc 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteSecretBallotFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/CastVoteSecretBallotFragmentTest.kt @@ -136,7 +136,7 @@ class CastVoteSecretBallotFragmentTest { private const val PLURALITY = "Plurality" private val laoSubject = BehaviorSubject.createDefault(LaoView(LAO)) private val ROLL_CALL = - RollCall("id", "id", "rc", 0L, 1L, 2L, EventState.CLOSED, HashSet(), "nowhere", "none") + RollCall("id", "id", "rc", 0L, 1L, 2L, EventState.CLOSED, LinkedHashSet(), "nowhere", "none") private val ELECTION_ID = generateElectionSetupId(LAO_ID, CREATION, TITLE) private val ELECTION_QUESTION_1 = ElectionQuestion( diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/ElectionFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/ElectionFragmentTest.kt index a846b86a91..dabf57c127 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/ElectionFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/election/ElectionFragmentTest.kt @@ -66,7 +66,7 @@ class ElectionFragmentTest { START, END, EventState.CLOSED, - HashSet(), + LinkedHashSet(), LOCATION, ROLL_CALL_DESC ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/eventlist/EventListAdapterTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/eventlist/EventListAdapterTest.kt index f3092831aa..017216528f 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/eventlist/EventListAdapterTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/eventlist/EventListAdapterTest.kt @@ -44,12 +44,12 @@ class EventListAdapterTest { 1L, 2L, EventState.CREATED, - HashSet(), + LinkedHashSet(), "not lausanne", "no" ) private val ROLL_CALL2 = - RollCall("12345", "12345", "Name", 2L, 3L, 4L, EventState.CREATED, HashSet(), "nowhere", "foo") + RollCall("12345", "12345", "Name", 2L, 3L, 4L, EventState.CREATED, LinkedHashSet(), "nowhere", "foo") private lateinit var events: Subject> diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt index 15b69dda93..3fa36943a6 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt @@ -51,14 +51,14 @@ class RollCallArrayAdapterTest { } @Test - fun verify_our_token_is_highlighted() { + fun verifyOurTokenIsHighlighted() { val view = adapter.getView(0, mockView, mock(ViewGroup::class.java)) as TextView val color = ContextCompat.getColor(context, R.color.colorAccent) Assert.assertEquals(color, view.currentTextColor) } @Test - fun verify_other_token_is_not_highlighted() { + fun verifyOtherTokenIsNotHighlighted() { val view = adapter.getView(1, mockView, mock(ViewGroup::class.java)) as TextView val color = ContextCompat.getColor(context, R.color.textOnBackground) Assert.assertEquals(color, view.currentTextColor) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt index e1ecdd73af..bb9c6537c1 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt @@ -6,6 +6,7 @@ import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.matcher.ViewMatchers import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry +import com.github.dedis.popstellar.R import com.github.dedis.popstellar.model.objects.Lao import com.github.dedis.popstellar.model.objects.RollCall import com.github.dedis.popstellar.model.objects.RollCall.Companion.closeRollCall @@ -19,6 +20,7 @@ import com.github.dedis.popstellar.testutils.Base64DataUtils import com.github.dedis.popstellar.testutils.BundleBuilder import com.github.dedis.popstellar.testutils.MessageSenderHelper import com.github.dedis.popstellar.testutils.MockitoKotlinHelpers +import com.github.dedis.popstellar.testutils.UITestUtils import com.github.dedis.popstellar.testutils.fragment.ActivityFragmentScenarioRule import com.github.dedis.popstellar.testutils.pages.lao.LaoActivityPageObject import com.github.dedis.popstellar.testutils.pages.lao.event.rollcall.RollCallFragmentPageObject @@ -29,15 +31,11 @@ import com.github.dedis.popstellar.utility.Constants import com.github.dedis.popstellar.utility.error.UnknownLaoException import com.github.dedis.popstellar.utility.error.keys.KeyException import com.github.dedis.popstellar.utility.security.KeyManager +import com.google.android.gms.common.util.CollectionUtils.listOf import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest import io.reactivex.subjects.BehaviorSubject -import java.text.DateFormat -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale -import javax.inject.Inject import org.junit.Assert import org.junit.Rule import org.junit.Test @@ -48,6 +46,12 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoTestRule +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.Collections +import java.util.Date +import java.util.Locale +import javax.inject.Inject @HiltAndroidTest @RunWith(AndroidJUnit4::class) @@ -61,9 +65,9 @@ class RollCallFragmentTest { ROLL_CALL_START, ROLL_CALL_END, EventState.CREATED, - HashSet(), + LinkedHashSet(), LOCATION, - ROLL_CALL_EMPTY_DESC + ROLL_CALL_EMPTY_DESC, ) private val ROLL_CALL_2 = RollCall( @@ -74,9 +78,37 @@ class RollCallFragmentTest { ROLL_CALL_START + 3, ROLL_CALL_END + 3, EventState.CREATED, - HashSet(), + LinkedHashSet(), + LOCATION, + ROLL_CALL_DESC, + ) + + private val ROLL_CALL_SORTED_ATTENDEES = + RollCall( + LAO.id + "3", + LAO.id + "3", + ROLL_CALL_TITLE + "3", + CREATION, + ROLL_CALL_START, + ROLL_CALL_END, + EventState.OPENED, + validAttendees, LOCATION, - ROLL_CALL_DESC + ROLL_CALL_EMPTY_DESC, + ) + + private val ROLL_CALL_UNSORTED_ATTENDEES = + RollCall( + LAO.id + "4", + LAO.id + "4", + ROLL_CALL_TITLE + "4", + CREATION, + ROLL_CALL_START, + ROLL_CALL_END, + EventState.OPENED, + LinkedHashSet(unSortedAttendees), + LOCATION, + ROLL_CALL_EMPTY_DESC, ) @Inject lateinit var rollCallRepo: RollCallRepository @@ -108,6 +140,8 @@ class RollCallFragmentTest { Mockito.`when`(laoRepo.getLaoView(MockitoKotlinHelpers.any())).thenAnswer { LaoView(LAO) } rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL) rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_2) + rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_SORTED_ATTENDEES) + rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_UNSORTED_ATTENDEES) Mockito.`when`(keyManager.mainPublicKey).thenReturn(SENDER) Mockito.`when`(networkManager.messageSender).thenReturn(messageSenderHelper.mockedSender) @@ -488,6 +522,42 @@ class RollCallFragmentTest { ) } + @Test + fun sortedAttendeeListShowsNoToast() { + rollCallRepo.updateRollCall(LAO_ID, closeRollCall(ROLL_CALL_SORTED_ATTENDEES)) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + openRollCallWithDescription(ROLL_CALL_SORTED_ATTENDEES) + + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + RollCallFragmentPageObject.rollCallListAttendees() + .check( + ViewAssertions.matches( + ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE) + ) + ) + + UITestUtils.assertToastDisplayedHasNotText(R.string.roll_call_attendees_list_not_sorted) + } + + @Test + fun unSortedAttendeeListShowsToast() { + rollCallRepo.updateRollCall(LAO_ID, closeRollCall(ROLL_CALL_UNSORTED_ATTENDEES)) + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + openRollCallWithDescription(ROLL_CALL_UNSORTED_ATTENDEES) + + InstrumentationRegistry.getInstrumentation().waitForIdleSync() + + RollCallFragmentPageObject.rollCallListAttendees() + .check( + ViewAssertions.matches( + ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE) + ) + ) + + UITestUtils.assertToastIsDisplayedWithText(R.string.roll_call_attendees_list_not_sorted) + } + /** Utility function to create a LAO when the user is not the organizer */ @Throws(UnknownLaoException::class) private fun fakeClientLao() { @@ -495,14 +565,20 @@ class RollCallFragmentTest { Mockito.`when`(laoRepo.getLaoView(MockitoKotlinHelpers.any())).thenAnswer { LaoView(LAO_2) } rollCallRepo.updateRollCall(LAO_ID2, ROLL_CALL) rollCallRepo.updateRollCall(LAO_ID2, ROLL_CALL_2) + rollCallRepo.updateRollCall(LAO_ID2, ROLL_CALL_SORTED_ATTENDEES) + rollCallRepo.updateRollCall(LAO_ID2, ROLL_CALL_UNSORTED_ATTENDEES) Mockito.`when`(keyManager.mainPublicKey).thenReturn(SENDER_2) } /** Utility function to open the fragment of an alternative roll call */ private fun openRollCallWithDescription() { + openRollCallWithDescription(ROLL_CALL_2) + } + + private fun openRollCallWithDescription(rollCall: RollCall) { activityScenarioRule.scenario.onActivity { activity: LaoActivity -> setCurrentFragment(activity.supportFragmentManager, RollCallFragmentPageObject.fragmentId()) { - newInstance(ROLL_CALL_2.persistentId) + newInstance(rollCall.persistentId) } } } @@ -527,5 +603,22 @@ class RollCallFragmentTest { private val laoSubject2 = BehaviorSubject.createDefault(LaoView(LAO_2)) private val DATE_FORMAT: DateFormat = SimpleDateFormat("dd/MM/yyyy HH:mm z", Locale.ENGLISH) private val POP_TOKEN = Base64DataUtils.generatePoPToken() + + private val attendees = listOf( + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey(), + Base64DataUtils.generatePublicKey() + ) + + private val validAttendees = LinkedHashSet(attendees.sortedBy { it.toString() }) + + private val unSortedAttendees = ArrayList(validAttendees).toMutableList().apply { } + + init { + Collections.swap(unSortedAttendees, 0, 1) + } } } diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/popcha/PoPCHAHomeFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/popcha/PoPCHAHomeFragmentTest.kt index 88189baf9f..681309e56a 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/popcha/PoPCHAHomeFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/popcha/PoPCHAHomeFragmentTest.kt @@ -95,7 +95,7 @@ class PoPCHAHomeFragmentTest { 1632204910, 1632204900, EventState.CLOSED, - attendees, + LinkedHashSet(attendees), "bc", "" ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListAdapterTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListAdapterTest.kt index 5661fd8f46..23bbdbc216 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListAdapterTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListAdapterTest.kt @@ -62,7 +62,7 @@ class ChirpListAdapterTest { TIMESTAMP_1, TIMESTAMP_2, EventState.CLOSED, - HashSet(), + LinkedHashSet(), "", "", ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragmentTest.kt index fc6b394570..8ae049821c 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/ChirpListFragmentTest.kt @@ -64,7 +64,7 @@ class ChirpListFragmentTest { TIMESTAMP_1, TIMESTAMP_2, EventState.CLOSED, - HashSet(), + LinkedHashSet(), "", "", ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/SocialMediaHomeFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/SocialMediaHomeFragmentTest.kt index d4c6da10a4..3d4f78cfd0 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/SocialMediaHomeFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/socialmedia/SocialMediaHomeFragmentTest.kt @@ -59,7 +59,7 @@ class SocialMediaHomeFragmentTest { CREATION_TIME, CREATION_TIME, EventState.CLOSED, - HashSet(), + LinkedHashSet(), "", "", ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenFragmentTest.kt index 6aeaf372eb..f721fa8766 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenFragmentTest.kt @@ -51,7 +51,7 @@ class TokenFragmentTest { ROLL_CALL_START, ROLL_CALL_END, EventState.CLOSED, - HashSet(), + LinkedHashSet(), LOCATION, ROLL_CALL_DESC ) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenListFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenListFragmentTest.kt index b06cfb8d13..08a949d60e 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenListFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/token/TokenListFragmentTest.kt @@ -54,7 +54,7 @@ class TokenListFragmentTest { ROLL_CALL_START, ROLL_CALL_END, EventState.CREATED, - HashSet(), + LinkedHashSet(), LOCATION, ROLL_CALL_DESC ) diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt index e6ccc5e9c6..d6360945c0 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/model/network/method/message/data/rollcall/CloseRollCallTest.kt @@ -10,6 +10,7 @@ import com.github.dedis.popstellar.model.objects.security.Base64URLData import com.github.dedis.popstellar.testutils.Base64DataUtils import com.github.dedis.popstellar.utility.MessageValidator import com.github.dedis.popstellar.utility.security.HashSHA256.hash +import com.google.android.gms.common.util.CollectionUtils.listOf import junit.framework.TestCase.assertNotNull import org.hamcrest.CoreMatchers import org.hamcrest.MatcherAssert @@ -17,6 +18,7 @@ import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith import java.time.Instant +import java.util.ArrayList import java.util.Collections @RunWith(AndroidJUnit4::class) @@ -94,9 +96,7 @@ class CloseRollCallTest { @Test(expected = IllegalArgumentException::class) fun constructorFailsWhenAttendeesNotSorted() { val unsortedAttendees = ArrayList(attendees).toMutableList() - if (unsortedAttendees[0].toString() > unsortedAttendees[1].toString()) { - Collections.swap(unsortedAttendees, 0, 1) - } + Collections.swap(unsortedAttendees, 0, 1) CloseRollCall(validBase64LaoId, validBase64Closes, pastTime, unsortedAttendees) } diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/WitnessingRepositoryTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/WitnessingRepositoryTest.kt index b2475b164b..73dc487768 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/WitnessingRepositoryTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/WitnessingRepositoryTest.kt @@ -194,7 +194,7 @@ class WitnessingRepositoryTest { CREATION + 10, CREATION + 20, EventState.CREATED, - HashSet(), + LinkedHashSet(), "loc", "" ) diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/RollCallDatabaseTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/RollCallDatabaseTest.kt index af39117bb0..5784cbcd07 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/RollCallDatabaseTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/RollCallDatabaseTest.kt @@ -65,7 +65,7 @@ class RollCallDatabaseTest { CREATION + 10, CREATION + 20, EventState.CREATED, - HashSet(), + LinkedHashSet(), "loc", "" ) diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/WitnessDatabaseTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/WitnessDatabaseTest.kt index 597490f2d2..a633c07289 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/WitnessDatabaseTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/repository/database/WitnessDatabaseTest.kt @@ -212,7 +212,7 @@ class WitnessDatabaseTest { CREATION + 10, CREATION + 20, EventState.CREATED, - HashSet(), + LinkedHashSet(), "loc", "" ) diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/handler/RollCallHandlerTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/handler/RollCallHandlerTest.kt index baab9bdaf7..2f7284a074 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/handler/RollCallHandlerTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/handler/RollCallHandlerTest.kt @@ -185,7 +185,7 @@ class RollCallHandlerTest { now + 1, now + 2, EventState.CREATED, - HashSet(), + LinkedHashSet(), "somewhere", "desc" ) diff --git a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/security/KeyManagerTest.kt b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/security/KeyManagerTest.kt index 7ff8a0264a..949ce5edd8 100644 --- a/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/security/KeyManagerTest.kt +++ b/fe2-android/app/src/test/unit/java/com/github/dedis/popstellar/utility/security/KeyManagerTest.kt @@ -106,7 +106,7 @@ class KeyManagerTest { creation1 + 1, creation1 + 75, EventState.CLOSED, - HashSet(), + LinkedHashSet(), "location", "desc" ) @@ -119,7 +119,7 @@ class KeyManagerTest { creation2 + 1, creation2 + 75, EventState.CLOSED, - HashSet(), + LinkedHashSet(), "EPFL", "do not come" ) @@ -160,7 +160,7 @@ class KeyManagerTest { (5421364 + 1).toLong(), (5421364 + 145).toLong(), EventState.CLOSED, - HashSet(), + LinkedHashSet(), "ETHZ", "do come" ) From 2d068f88b3ee54ec48f53466e4d046d61bb71a99 Mon Sep 17 00:00:00 2001 From: Kaz Date: Tue, 4 Jun 2024 20:28:49 +0200 Subject: [PATCH 07/10] fixed a test + fmt --- .../popstellar/model/objects/event/RollCallBuilder.kt | 2 +- .../ui/lao/event/rollcall/RollCallFragment.kt | 11 ++++++----- .../ui/lao/event/rollcall/RollCallViewModel.kt | 4 ++-- .../ui/lao/event/rollcall/RollCallFragmentTest.kt | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt index 018a2cbab9..598bc919eb 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/model/objects/event/RollCallBuilder.kt @@ -102,7 +102,7 @@ class RollCallBuilder { start, end, state!!, - LinkedHashSet(attendees), + LinkedHashSet(attendees), location!!, description!!) } diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index 7a9192d220..6bb9e95329 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -30,7 +30,6 @@ import com.github.dedis.popstellar.utility.ActivityUtils.getQRCodeColor import com.github.dedis.popstellar.utility.ActivityUtils.handleExpandArrow import com.github.dedis.popstellar.utility.Constants.ID_NULL import com.github.dedis.popstellar.utility.Constants.ROLL_CALL_ID -import com.github.dedis.popstellar.utility.error.ErrorUtils import com.github.dedis.popstellar.utility.error.ErrorUtils.logAndShow import com.github.dedis.popstellar.utility.error.UnknownLaoException import com.github.dedis.popstellar.utility.error.UnknownRollCallException @@ -264,10 +263,10 @@ class RollCallFragment : AbstractEventFragment { resources.getString(R.string.roll_call_scanned), rollCallViewModel.getAttendees().size) } else if (rollCall.isClosed) { - val orderedAttendees: MutableSet = LinkedHashSet(rollCall.attendees) - attendeesList = orderedAttendees.stream().map(PublicKey::encoded).collect(Collectors.toList()) + val orderedAttendees: MutableSet = LinkedHashSet(rollCall.attendees) + attendeesList = orderedAttendees.stream().map(PublicKey::encoded).collect(Collectors.toList()) - // Show the list of attendees if the roll call has ended + // Show the list of attendees if the roll call has ended binding.rollCallAttendeesText.text = String.format(resources.getString(R.string.roll_call_attendees), rollCall.attendees.size) } @@ -360,7 +359,9 @@ class RollCallFragment : AbstractEventFragment { fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { - if (attendeesList.isNotEmpty() && attendeesList != attendeesList.sorted() && deAnonymizationWarned.value == false) { + if (attendeesList.isNotEmpty() && + attendeesList != attendeesList.sorted() && + deAnonymizationWarned.value == false) { deAnonymizationWarned.value = true logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) return false diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt index 993ea0110a..4a18a8de13 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallViewModel.kt @@ -33,11 +33,11 @@ import io.reactivex.Completable import io.reactivex.Observable import io.reactivex.Single import java.time.Instant +import java.util.ArrayList import java.util.TreeSet import java.util.stream.Collectors import javax.inject.Inject import timber.log.Timber -import java.util.ArrayList @HiltViewModel class RollCallViewModel @@ -263,7 +263,7 @@ constructor( nbScanned.postValue(attendees.size) } - @Inject + @Inject fun getAttendees(): Set { return attendees } diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt index bb9c6537c1..06fd5b5e36 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt @@ -140,8 +140,6 @@ class RollCallFragmentTest { Mockito.`when`(laoRepo.getLaoView(MockitoKotlinHelpers.any())).thenAnswer { LaoView(LAO) } rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL) rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_2) - rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_SORTED_ATTENDEES) - rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_UNSORTED_ATTENDEES) Mockito.`when`(keyManager.mainPublicKey).thenReturn(SENDER) Mockito.`when`(networkManager.messageSender).thenReturn(messageSenderHelper.mockedSender) @@ -524,6 +522,7 @@ class RollCallFragmentTest { @Test fun sortedAttendeeListShowsNoToast() { + rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_SORTED_ATTENDEES) rollCallRepo.updateRollCall(LAO_ID, closeRollCall(ROLL_CALL_SORTED_ATTENDEES)) InstrumentationRegistry.getInstrumentation().waitForIdleSync() openRollCallWithDescription(ROLL_CALL_SORTED_ATTENDEES) @@ -542,6 +541,7 @@ class RollCallFragmentTest { @Test fun unSortedAttendeeListShowsToast() { + rollCallRepo.updateRollCall(LAO_ID, ROLL_CALL_UNSORTED_ATTENDEES) rollCallRepo.updateRollCall(LAO_ID, closeRollCall(ROLL_CALL_UNSORTED_ATTENDEES)) InstrumentationRegistry.getInstrumentation().waitForIdleSync() openRollCallWithDescription(ROLL_CALL_UNSORTED_ATTENDEES) From c239d41e3d5a7d412d26f84395b529ccd86f78a3 Mon Sep 17 00:00:00 2001 From: Kaz Date: Wed, 5 Jun 2024 18:13:34 +0200 Subject: [PATCH 08/10] addressed comments --- .../event/rollcall/RollCallArrayAdapter.kt | 7 +++-- .../ui/lao/event/rollcall/RollCallFragment.kt | 30 +++++++++---------- .../utility/handler/data/RollCallHandler.kt | 6 ---- .../popstellar/ui/lao/InviteFragmentTest.kt | 6 +--- .../rollcall/RollCallArrayAdapterTest.kt | 2 +- .../event/rollcall/RollCallFragmentTest.kt | 1 + 6 files changed, 22 insertions(+), 30 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt index c0287d6016..a20b0f6b57 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt @@ -14,11 +14,12 @@ class RollCallArrayAdapter( private val layout: Int, private val attendeesList: List, private val myToken: PoPToken?, + private val fragment: RollCallFragment ) : ArrayAdapter(context, layout, attendeesList) { - init { - RollCallFragment.isAttendeeListSorted(attendeesList, context) - } + init { + fragment.isAttendeeListSorted(attendeesList, context) + } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { val view = super.getView(position, convertView, parent) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index 6bb9e95329..f011a9ca86 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -53,7 +53,9 @@ class RollCallFragment : AbstractEventFragment { private val managementTextMap = buildManagementTextMap() private val managementIconMap = buildManagementIconMap() - constructor() + private val deAnonymizationWarned = MutableLiveData(false) + + constructor() override fun onCreateView( inflater: LayoutInflater, @@ -278,6 +280,7 @@ class RollCallFragment : AbstractEventFragment { android.R.layout.simple_list_item_1, attendeesList, popToken, + this ) } } @@ -338,6 +341,17 @@ class RollCallFragment : AbstractEventFragment { return map } + fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { + if (attendeesList.isNotEmpty() && + attendeesList != attendeesList.sorted() && + deAnonymizationWarned.value == false) { + deAnonymizationWarned.value = true + logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) + return false + } + return true + } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) constructor(rollCall: RollCall) { this.rollCall = rollCall @@ -345,11 +359,9 @@ class RollCallFragment : AbstractEventFragment { companion object { val TAG: String = RollCallFragment::class.java.simpleName - private val deAnonymizationWarned = MutableLiveData(false) @JvmStatic fun newInstance(persistentId: String?): RollCallFragment { - deAnonymizationWarned.value = false val fragment = RollCallFragment() val bundle = Bundle(1) bundle.putString(ROLL_CALL_ID, persistentId) @@ -357,18 +369,6 @@ class RollCallFragment : AbstractEventFragment { return fragment } - fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { - - if (attendeesList.isNotEmpty() && - attendeesList != attendeesList.sorted() && - deAnonymizationWarned.value == false) { - deAnonymizationWarned.value = true - logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) - return false - } - return true - } - /** * The following is only for testing purposes. Production should never pass arguments to a * fragment instantiation but should rather use arguments diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt index 520438a9d4..ff7680df58 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt @@ -138,12 +138,6 @@ constructor( currentAttendees.addAll(closeRollCall.attendees) } - // log existingRollCall.attendees and closeRollCall.attendees - Timber.tag(TAG).d("existingRollCall.attendees: %s", existingRollCall.attendees) - Timber.tag(TAG).d("closeRollCall.attendees: %s", closeRollCall.attendees) - // log currentAttendees - Timber.tag(TAG).d("currentAttendees: %s", currentAttendees) - val builder = RollCallBuilder() builder .setId(updateId) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt index dbeb74ee95..350ce58274 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt @@ -2,10 +2,7 @@ package com.github.dedis.popstellar.ui.lao import android.content.ClipboardManager import android.content.Context -import android.widget.Button import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.test.espresso.Espresso -import androidx.test.espresso.EspressoException import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions.scrollTo import androidx.test.espresso.assertion.ViewAssertions @@ -20,13 +17,11 @@ import com.github.dedis.popstellar.testutils.BundleBuilder import com.github.dedis.popstellar.testutils.fragment.ActivityFragmentScenarioRule import com.github.dedis.popstellar.testutils.pages.lao.InviteFragmentPageObject import com.github.dedis.popstellar.testutils.pages.lao.LaoActivityPageObject -import com.github.dedis.popstellar.ui.lao.event.election.CastVoteOpenBallotFragmentTest import com.github.dedis.popstellar.utility.security.KeyManager import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest import junit.framework.TestCase -import javax.inject.Inject import org.junit.Rule import org.junit.Test import org.junit.rules.ExternalResource @@ -35,6 +30,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoTestRule +import javax.inject.Inject @SmallTest @HiltAndroidTest diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt index 3fa36943a6..9846703e28 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt @@ -44,7 +44,7 @@ class RollCallArrayAdapterTest { val myToken = PoPToken(MY_PRIVATE_KEY, MY_PUBLIC_KEY) val otherToken = PoPToken(OTHER_PRIVATE_KEY, OTHER_PUBLIC_KEY) attendeesList = listOf(myToken.publicKey.encoded, otherToken.publicKey.encoded) - adapter = RollCallArrayAdapter(context, R.id.valid_token_layout_text, attendeesList, myToken) + adapter = RollCallArrayAdapter(context, R.id.valid_token_layout_text, attendeesList, myToken, mock(RollCallFragment::class.java)) mockView = TextView(context) val colorAccent = ContextCompat.getColor(context, R.color.textOnBackground) (mockView as TextView).setTextColor(colorAccent) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt index 06fd5b5e36..d009e6f8de 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt @@ -537,6 +537,7 @@ class RollCallFragmentTest { ) UITestUtils.assertToastDisplayedHasNotText(R.string.roll_call_attendees_list_not_sorted) + UITestUtils.assertNoToastIsDisplayed() } @Test From e76865201af939e0c0ab09c4a0aea32ce162f078 Mon Sep 17 00:00:00 2001 From: Kaz Date: Wed, 5 Jun 2024 18:13:34 +0200 Subject: [PATCH 09/10] addressed comments --- .../event/rollcall/RollCallArrayAdapter.kt | 3 +- .../ui/lao/event/rollcall/RollCallFragment.kt | 33 ++++++++----------- .../utility/handler/data/RollCallHandler.kt | 6 ---- .../popstellar/ui/lao/InviteFragmentTest.kt | 6 +--- .../rollcall/RollCallArrayAdapterTest.kt | 2 +- .../event/rollcall/RollCallFragmentTest.kt | 1 + 6 files changed, 19 insertions(+), 32 deletions(-) diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt index c0287d6016..74f098b098 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapter.kt @@ -14,10 +14,11 @@ class RollCallArrayAdapter( private val layout: Int, private val attendeesList: List, private val myToken: PoPToken?, + private val fragment: RollCallFragment ) : ArrayAdapter(context, layout, attendeesList) { init { - RollCallFragment.isAttendeeListSorted(attendeesList, context) + fragment.isAttendeeListSorted(attendeesList, context) } override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt index 6bb9e95329..e23865a64f 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragment.kt @@ -53,6 +53,8 @@ class RollCallFragment : AbstractEventFragment { private val managementTextMap = buildManagementTextMap() private val managementIconMap = buildManagementIconMap() + private val deAnonymizationWarned = MutableLiveData(false) + constructor() override fun onCreateView( @@ -274,11 +276,7 @@ class RollCallFragment : AbstractEventFragment { if (attendeesList != null) { binding.listViewAttendees.adapter = RollCallArrayAdapter( - requireContext(), - android.R.layout.simple_list_item_1, - attendeesList, - popToken, - ) + requireContext(), android.R.layout.simple_list_item_1, attendeesList, popToken, this) } } @@ -338,6 +336,17 @@ class RollCallFragment : AbstractEventFragment { return map } + fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { + if (attendeesList.isNotEmpty() && + attendeesList != attendeesList.sorted() && + deAnonymizationWarned.value == false) { + deAnonymizationWarned.value = true + logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) + return false + } + return true + } + @VisibleForTesting(otherwise = VisibleForTesting.NONE) constructor(rollCall: RollCall) { this.rollCall = rollCall @@ -345,11 +354,9 @@ class RollCallFragment : AbstractEventFragment { companion object { val TAG: String = RollCallFragment::class.java.simpleName - private val deAnonymizationWarned = MutableLiveData(false) @JvmStatic fun newInstance(persistentId: String?): RollCallFragment { - deAnonymizationWarned.value = false val fragment = RollCallFragment() val bundle = Bundle(1) bundle.putString(ROLL_CALL_ID, persistentId) @@ -357,18 +364,6 @@ class RollCallFragment : AbstractEventFragment { return fragment } - fun isAttendeeListSorted(attendeesList: List, context: Context): Boolean { - - if (attendeesList.isNotEmpty() && - attendeesList != attendeesList.sorted() && - deAnonymizationWarned.value == false) { - deAnonymizationWarned.value = true - logAndShow(context, TAG, R.string.roll_call_attendees_list_not_sorted) - return false - } - return true - } - /** * The following is only for testing purposes. Production should never pass arguments to a * fragment instantiation but should rather use arguments diff --git a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt index 520438a9d4..ff7680df58 100644 --- a/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt +++ b/fe2-android/app/src/main/java/com/github/dedis/popstellar/utility/handler/data/RollCallHandler.kt @@ -138,12 +138,6 @@ constructor( currentAttendees.addAll(closeRollCall.attendees) } - // log existingRollCall.attendees and closeRollCall.attendees - Timber.tag(TAG).d("existingRollCall.attendees: %s", existingRollCall.attendees) - Timber.tag(TAG).d("closeRollCall.attendees: %s", closeRollCall.attendees) - // log currentAttendees - Timber.tag(TAG).d("currentAttendees: %s", currentAttendees) - val builder = RollCallBuilder() builder .setId(updateId) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt index dbeb74ee95..350ce58274 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/InviteFragmentTest.kt @@ -2,10 +2,7 @@ package com.github.dedis.popstellar.ui.lao import android.content.ClipboardManager import android.content.Context -import android.widget.Button import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.test.espresso.Espresso -import androidx.test.espresso.EspressoException import androidx.test.espresso.action.ViewActions import androidx.test.espresso.action.ViewActions.scrollTo import androidx.test.espresso.assertion.ViewAssertions @@ -20,13 +17,11 @@ import com.github.dedis.popstellar.testutils.BundleBuilder import com.github.dedis.popstellar.testutils.fragment.ActivityFragmentScenarioRule import com.github.dedis.popstellar.testutils.pages.lao.InviteFragmentPageObject import com.github.dedis.popstellar.testutils.pages.lao.LaoActivityPageObject -import com.github.dedis.popstellar.ui.lao.event.election.CastVoteOpenBallotFragmentTest import com.github.dedis.popstellar.utility.security.KeyManager import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.HiltAndroidRule import dagger.hilt.android.testing.HiltAndroidTest import junit.framework.TestCase -import javax.inject.Inject import org.junit.Rule import org.junit.Test import org.junit.rules.ExternalResource @@ -35,6 +30,7 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoTestRule +import javax.inject.Inject @SmallTest @HiltAndroidTest diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt index 3fa36943a6..9846703e28 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallArrayAdapterTest.kt @@ -44,7 +44,7 @@ class RollCallArrayAdapterTest { val myToken = PoPToken(MY_PRIVATE_KEY, MY_PUBLIC_KEY) val otherToken = PoPToken(OTHER_PRIVATE_KEY, OTHER_PUBLIC_KEY) attendeesList = listOf(myToken.publicKey.encoded, otherToken.publicKey.encoded) - adapter = RollCallArrayAdapter(context, R.id.valid_token_layout_text, attendeesList, myToken) + adapter = RollCallArrayAdapter(context, R.id.valid_token_layout_text, attendeesList, myToken, mock(RollCallFragment::class.java)) mockView = TextView(context) val colorAccent = ContextCompat.getColor(context, R.color.textOnBackground) (mockView as TextView).setTextColor(colorAccent) diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt index 06fd5b5e36..d009e6f8de 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt @@ -537,6 +537,7 @@ class RollCallFragmentTest { ) UITestUtils.assertToastDisplayedHasNotText(R.string.roll_call_attendees_list_not_sorted) + UITestUtils.assertNoToastIsDisplayed() } @Test From d3eb88c327490b33c839ed07d8d07d09e5b8b8ce Mon Sep 17 00:00:00 2001 From: Kaz Date: Wed, 5 Jun 2024 19:42:13 +0200 Subject: [PATCH 10/10] fixed last test --- .../com/github/dedis/popstellar/testutils/UITestUtils.kt | 6 ------ .../ui/lao/event/rollcall/RollCallFragmentTest.kt | 1 - 2 files changed, 7 deletions(-) diff --git a/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt b/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt index 9966a69463..dd4bbb0932 100644 --- a/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt +++ b/fe2-android/app/src/test/framework/robolectric/java/com/github/dedis/popstellar/testutils/UITestUtils.kt @@ -61,12 +61,6 @@ object UITestUtils { Assert.assertNotEquals(expected, ShadowToast.getTextOfLatestToast()) } - - @JvmStatic - fun assertNoToastIsDisplayed() { - Assert.assertNull(ShadowToast.getLatestToast()) - } - @JvmStatic fun assertToastIsDisplayedContainsText(@StringRes resId: Int, vararg args: Any?) { MatcherAssert.assertThat( diff --git a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt index d009e6f8de..06fd5b5e36 100644 --- a/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt +++ b/fe2-android/app/src/test/ui/robolectric/com/github/dedis/popstellar/ui/lao/event/rollcall/RollCallFragmentTest.kt @@ -537,7 +537,6 @@ class RollCallFragmentTest { ) UITestUtils.assertToastDisplayedHasNotText(R.string.roll_call_attendees_list_not_sorted) - UITestUtils.assertNoToastIsDisplayed() } @Test