Merge pull request #5801 from k9mail/refactor_NotificationData

Create NotificationDataStore and make NotificationData immutable
This commit is contained in:
cketti 2021-12-02 23:21:28 +01:00 committed by GitHub
commit b671c7dbe4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 450 additions and 714 deletions

View file

@ -1,25 +1,29 @@
package com.fsck.k9.notification
internal class AddNotificationResult private constructor(
val notificationData: NotificationData,
val notificationHolder: NotificationHolder,
@get:JvmName("shouldCancelNotification")
val shouldCancelNotification: Boolean
) {
val notificationId: Int
val cancelNotificationId: Int
get() {
check(shouldCancelNotification) { "shouldCancelNotification == false" }
return notificationHolder.notificationId
}
companion object {
@JvmStatic
fun newNotification(notificationHolder: NotificationHolder): AddNotificationResult {
return AddNotificationResult(notificationHolder, shouldCancelNotification = false)
fun newNotification(
notificationData: NotificationData,
notificationHolder: NotificationHolder
): AddNotificationResult {
return AddNotificationResult(notificationData, notificationHolder, shouldCancelNotification = false)
}
@JvmStatic
fun replaceNotification(notificationHolder: NotificationHolder): AddNotificationResult {
return AddNotificationResult(notificationHolder, shouldCancelNotification = true)
fun replaceNotification(
notificationData: NotificationData,
notificationHolder: NotificationHolder
): AddNotificationResult {
return AddNotificationResult(notificationData, notificationHolder, shouldCancelNotification = true)
}
}
}

View file

@ -37,8 +37,8 @@ internal class BaseNotificationDataCreator {
}
private fun getSenderNames(data: NotificationData): String {
return data.getContentForSummaryNotification().asSequence()
.map { it.sender }
return data.activeNotifications.asSequence()
.map { it.content.sender }
.distinct()
.take(MAX_NUMBER_OF_SENDERS_IN_LOCK_SCREEN_NOTIFICATION)
.joinToString()

View file

@ -15,84 +15,73 @@ internal class NewMailNotificationManager(
private val summaryNotificationDataCreator: SummaryNotificationDataCreator,
private val clock: Clock
) {
private val notifications = mutableMapOf<Int, NotificationData>()
private val lock = Any()
private val notificationDataStore = NotificationDataStore()
fun addNewMailNotification(account: Account, message: LocalMessage, silent: Boolean): NewMailNotificationData {
val content = contentCreator.createFromMessage(account, message)
synchronized(lock) {
val notificationData = getOrCreateNotificationData(account)
val result = notificationData.addNotificationContent(content, timestamp = now())
val result = notificationDataStore.addNotification(account, content, timestamp = now())
val singleNotificationData = createSingleNotificationData(
account = account,
notificationId = result.notificationHolder.notificationId,
content = result.notificationHolder.content,
timestamp = result.notificationHolder.timestamp,
addLockScreenNotification = notificationData.isSingleMessageNotification
)
val singleNotificationData = createSingleNotificationData(
account = account,
notificationId = result.notificationHolder.notificationId,
content = result.notificationHolder.content,
timestamp = result.notificationHolder.timestamp,
addLockScreenNotification = result.notificationData.isSingleMessageNotification
)
return NewMailNotificationData(
cancelNotificationIds = if (result.shouldCancelNotification) {
listOf(result.notificationId)
} else {
emptyList()
},
baseNotificationData = createBaseNotificationData(notificationData),
singleNotificationData = listOf(singleNotificationData),
summaryNotificationData = createSummaryNotificationData(notificationData, silent)
)
}
return NewMailNotificationData(
cancelNotificationIds = if (result.shouldCancelNotification) {
listOf(result.cancelNotificationId)
} else {
emptyList()
},
baseNotificationData = createBaseNotificationData(result.notificationData),
singleNotificationData = listOf(singleNotificationData),
summaryNotificationData = createSummaryNotificationData(result.notificationData, silent)
)
}
fun removeNewMailNotification(account: Account, messageReference: MessageReference): NewMailNotificationData? {
synchronized(lock) {
val notificationData = getNotificationData(account) ?: return null
val result = notificationDataStore.removeNotification(account, messageReference) ?: return null
val result = notificationData.removeNotificationForMessage(messageReference)
if (result.isUnknownNotification) return null
if (notificationData.newMessagesCount == 0) {
return NewMailNotificationData(
cancelNotificationIds = listOf(
NotificationIds.getNewMailSummaryNotificationId(account),
result.notificationId
),
baseNotificationData = createBaseNotificationData(notificationData),
singleNotificationData = emptyList(),
summaryNotificationData = null
)
val cancelNotificationIds = when {
result.shouldCancelNotification && result.notificationData.isEmpty() -> {
listOf(NotificationIds.getNewMailSummaryNotificationId(account), result.cancelNotificationId)
}
result.shouldCancelNotification -> {
listOf(result.cancelNotificationId)
}
else -> {
emptyList()
}
}
val singleNotificationData = if (result.shouldCreateNotification) {
val singleNotificationData = createSingleNotificationData(
val singleNotificationDataList = if (result.shouldCreateNotification) {
listOf(
createSingleNotificationData(
account = account,
notificationId = result.notificationHolder.notificationId,
content = result.notificationHolder.content,
timestamp = result.notificationHolder.timestamp,
addLockScreenNotification = notificationData.isSingleMessageNotification
addLockScreenNotification = result.notificationData.isSingleMessageNotification
)
listOf(singleNotificationData)
} else {
emptyList()
}
return NewMailNotificationData(
cancelNotificationIds = listOf(result.notificationId),
baseNotificationData = createBaseNotificationData(notificationData),
singleNotificationData = singleNotificationData,
summaryNotificationData = createSummaryNotificationData(notificationData, silent = true)
)
} else {
emptyList()
}
return NewMailNotificationData(
cancelNotificationIds = cancelNotificationIds,
baseNotificationData = createBaseNotificationData(result.notificationData),
singleNotificationData = singleNotificationDataList,
summaryNotificationData = createSummaryNotificationData(result.notificationData, silent = true)
)
}
fun clearNewMailNotifications(account: Account): List<Int> {
synchronized(lock) {
val notificationData = removeNotificationData(account) ?: return emptyList()
return notificationData.getActiveNotificationIds() +
NotificationIds.getNewMailSummaryNotificationId(account)
}
notificationDataStore.clearNotifications(account)
return NotificationIds.getAllMessageNotificationIds(account)
}
private fun createBaseNotificationData(notificationData: NotificationData): BaseNotificationData {
@ -115,31 +104,12 @@ internal class NewMailNotificationManager(
)
}
private fun createSummaryNotificationData(data: NotificationData, silent: Boolean): SummaryNotificationData {
return summaryNotificationDataCreator.createSummaryNotificationData(data, silent)
}
private fun getOrCreateNotificationData(account: Account): NotificationData {
val notificationData = getNotificationData(account)
if (notificationData != null) return notificationData
val accountNumber = account.accountNumber
val newNotificationHolder = NotificationData(account)
notifications[accountNumber] = newNotificationHolder
return newNotificationHolder
}
private fun getNotificationData(account: Account): NotificationData? {
val accountNumber = account.accountNumber
return notifications[accountNumber]
}
private fun removeNotificationData(account: Account): NotificationData? {
val accountNumber = account.accountNumber
val notificationData = notifications[accountNumber]
notifications.remove(accountNumber)
return notificationData
private fun createSummaryNotificationData(data: NotificationData, silent: Boolean): SummaryNotificationData? {
return if (data.isEmpty()) {
null
} else {
summaryNotificationDataCreator.createSummaryNotificationData(data, silent)
}
}
private fun now(): Long = clock.time

View file

@ -1,150 +1,26 @@
package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.controller.MessageReference
import java.util.LinkedList
/**
* A holder class for pending new mail notifications.
* Holds information about active and inactive new message notifications of an account.
*/
internal class NotificationData(val account: Account) {
private val activeNotifications = LinkedList<NotificationHolder>()
private val additionalNotifications = LinkedList<InactiveNotificationHolder>()
private val notificationIdsInUse = mutableMapOf<Int, Boolean>()
internal data class NotificationData(
val account: Account,
val activeNotifications: List<NotificationHolder>,
val inactiveNotifications: List<InactiveNotificationHolder>
) {
val newMessagesCount: Int
get() = activeNotifications.size + additionalNotifications.size
get() = activeNotifications.size + inactiveNotifications.size
val isSingleMessageNotification: Boolean
get() = activeNotifications.size == 1
val holderForLatestNotification: NotificationHolder
get() = activeNotifications.first
private val isMaxNumberOfActiveNotificationsReached: Boolean
get() = activeNotifications.size == MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS
fun addNotificationContent(content: NotificationContent, timestamp: Long): AddNotificationResult {
val notificationId: Int
val cancelNotificationIdBeforeReuse: Boolean
if (isMaxNumberOfActiveNotificationsReached) {
val notificationHolder = activeNotifications.removeLast()
addToAdditionalNotifications(notificationHolder)
notificationId = notificationHolder.notificationId
cancelNotificationIdBeforeReuse = true
} else {
notificationId = getNewNotificationId()
cancelNotificationIdBeforeReuse = false
}
val notificationHolder = NotificationHolder(notificationId, timestamp, content)
activeNotifications.addFirst(notificationHolder)
return if (cancelNotificationIdBeforeReuse) {
AddNotificationResult.replaceNotification(notificationHolder)
} else {
AddNotificationResult.newNotification(notificationHolder)
}
}
private fun addToAdditionalNotifications(notificationHolder: NotificationHolder) {
additionalNotifications.addFirst(
InactiveNotificationHolder(notificationHolder.timestamp, notificationHolder.content)
)
}
private fun getNewNotificationId(): Int {
for (index in 0 until MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) {
val notificationId = NotificationIds.getSingleMessageNotificationId(account, index)
if (!isNotificationInUse(notificationId)) {
markNotificationIdAsInUse(notificationId)
return notificationId
}
}
throw AssertionError("getNewNotificationId() called with no free notification ID")
}
private fun isNotificationInUse(notificationId: Int): Boolean {
return notificationIdsInUse[notificationId] ?: false
}
private fun markNotificationIdAsInUse(notificationId: Int) {
notificationIdsInUse[notificationId] = true
}
private fun markNotificationIdAsFree(notificationId: Int) {
notificationIdsInUse.remove(notificationId)
}
fun hasSummaryOverflowMessages(): Boolean {
return activeNotifications.size > MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION
}
fun getSummaryOverflowMessagesCount(): Int {
val activeOverflowCount = activeNotifications.size - MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION
return if (activeOverflowCount > 0) {
activeOverflowCount + additionalNotifications.size
} else {
additionalNotifications.size
}
}
fun getContentForSummaryNotification(): List<NotificationContent> {
return activeNotifications.asSequence()
.map { it.content }
.take(MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION)
.toList()
}
fun getActiveNotificationIds(): List<Int> {
return activeNotifications.map { it.notificationId }
}
fun removeNotificationForMessage(messageReference: MessageReference): RemoveNotificationResult {
val holder = getNotificationHolderForMessage(messageReference)
?: return RemoveNotificationResult.unknownNotification()
activeNotifications.remove(holder)
val notificationId = holder.notificationId
markNotificationIdAsFree(notificationId)
return if (additionalNotifications.isEmpty()) {
RemoveNotificationResult.cancelNotification(notificationId)
} else {
val replacementHolder = additionalNotifications.removeFirst()
val replacement = NotificationHolder(notificationId, replacementHolder.timestamp, replacementHolder.content)
activeNotifications.addLast(replacement)
RemoveNotificationResult.createNotification(replacement)
}
}
private fun getNotificationHolderForMessage(messageReference: MessageReference): NotificationHolder? {
return activeNotifications.firstOrNull { it.content.messageReference == messageReference }
}
fun getAllMessageReferences(): ArrayList<MessageReference> {
val newSize = activeNotifications.size + additionalNotifications.size
val messageReferences = ArrayList<MessageReference>(newSize)
for (holder in activeNotifications) {
messageReferences.add(holder.content.messageReference)
}
for (holder in additionalNotifications) {
messageReferences.add(holder.content.messageReference)
}
return messageReferences
}
fun isEmpty() = activeNotifications.isEmpty()
companion object {
// Note: As of Jellybean, phone notifications show a maximum of 5 lines, while tablet notifications show 7 lines.
const val MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION = 5
// Note: This class assumes that
// MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS >= MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION
const val MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS = 8
fun create(account: Account): NotificationData {
return NotificationData(account, activeNotifications = emptyList(), inactiveNotifications = emptyList())
}
}
}

View file

@ -0,0 +1,121 @@
package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.controller.MessageReference
internal const val MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS = 8
/**
* Stores information about new message notifications for all accounts.
*
* We only use a limited number of system notifications per account (see [MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS]);
* those are called active notifications. The rest are called inactive notifications. When an active notification is
* removed, the latest inactive notification is promoted to an active notification.
*/
internal class NotificationDataStore {
private val notificationDataMap = mutableMapOf<String, NotificationData>()
@Synchronized
fun addNotification(account: Account, content: NotificationContent, timestamp: Long): AddNotificationResult {
val notificationData = getNotificationData(account)
return if (notificationData.isMaxNumberOfActiveNotificationsReached) {
val lastNotificationHolder = notificationData.activeNotifications.last()
val inactiveNotificationHolder = lastNotificationHolder.toInactiveNotificationHolder()
val notificationId = lastNotificationHolder.notificationId
val notificationHolder = NotificationHolder(notificationId, timestamp, content)
val newNotificationData = notificationData.copy(
activeNotifications = listOf(notificationHolder) + notificationData.activeNotifications.dropLast(1),
inactiveNotifications = listOf(inactiveNotificationHolder) + notificationData.inactiveNotifications
)
notificationDataMap[account.uuid] = newNotificationData
AddNotificationResult.replaceNotification(newNotificationData, notificationHolder)
} else {
val notificationId = notificationData.getNewNotificationId()
val notificationHolder = NotificationHolder(notificationId, timestamp, content)
val newNotificationData = notificationData.copy(
activeNotifications = listOf(notificationHolder) + notificationData.activeNotifications
)
notificationDataMap[account.uuid] = newNotificationData
AddNotificationResult.newNotification(newNotificationData, notificationHolder)
}
}
@Synchronized
fun removeNotification(account: Account, messageReference: MessageReference): RemoveNotificationResult? {
val notificationData = getNotificationData(account)
if (notificationData.isEmpty()) return null
val notificationHolder = notificationData.activeNotifications.firstOrNull {
it.content.messageReference == messageReference
}
return if (notificationHolder == null) {
val inactiveNotificationHolder = notificationData.inactiveNotifications.firstOrNull {
it.content.messageReference == messageReference
} ?: return null
val newNotificationData = notificationData.copy(
inactiveNotifications = notificationData.inactiveNotifications - inactiveNotificationHolder
)
notificationDataMap[account.uuid] = newNotificationData
RemoveNotificationResult.recreateSummaryNotification(newNotificationData)
} else if (notificationData.inactiveNotifications.isNotEmpty()) {
val newNotificationHolder = notificationData.inactiveNotifications.first()
.toNotificationHolder(notificationHolder.notificationId)
val newNotificationData = notificationData.copy(
activeNotifications = notificationData.activeNotifications - notificationHolder + newNotificationHolder,
inactiveNotifications = notificationData.inactiveNotifications.drop(1)
)
notificationDataMap[account.uuid] = newNotificationData
RemoveNotificationResult.replaceNotification(newNotificationData, newNotificationHolder)
} else {
val newNotificationData = notificationData.copy(
activeNotifications = notificationData.activeNotifications - notificationHolder
)
notificationDataMap[account.uuid] = newNotificationData
RemoveNotificationResult.cancelNotification(newNotificationData, notificationHolder.notificationId)
}
}
@Synchronized
fun clearNotifications(account: Account) {
notificationDataMap.remove(account.uuid)
}
private fun getNotificationData(account: Account): NotificationData {
return notificationDataMap[account.uuid] ?: NotificationData.create(account).also { notificationData ->
notificationDataMap[account.uuid] = notificationData
}
}
private val NotificationData.isMaxNumberOfActiveNotificationsReached: Boolean
get() = activeNotifications.size == MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS
private fun NotificationData.getNewNotificationId(): Int {
val notificationIdsInUse = activeNotifications.map { it.notificationId }.toSet()
for (index in 0 until MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) {
val notificationId = NotificationIds.getSingleMessageNotificationId(account, index)
if (notificationId !in notificationIdsInUse) {
return notificationId
}
}
throw AssertionError("getNewNotificationId() called with no free notification ID")
}
private fun NotificationHolder.toInactiveNotificationHolder() = InactiveNotificationHolder(timestamp, content)
private fun InactiveNotificationHolder.toNotificationHolder(notificationId: Int): NotificationHolder {
return NotificationHolder(notificationId, timestamp, content)
}
}

View file

@ -5,7 +5,6 @@ import com.fsck.k9.Account
object NotificationGroupKeys {
private const val NOTIFICATION_GROUP_KEY_PREFIX = "newMailNotifications-"
@JvmStatic
fun getGroupKey(account: Account): String {
return NOTIFICATION_GROUP_KEY_PREFIX + account.accountNumber
}

View file

@ -1,12 +1,12 @@
package com.fsck.k9.notification
internal class NotificationHolder(
internal data class NotificationHolder(
val notificationId: Int,
val timestamp: Long,
val content: NotificationContent
)
internal class InactiveNotificationHolder(
internal data class InactiveNotificationHolder(
val timestamp: Long,
val content: NotificationContent
)

View file

@ -15,40 +15,41 @@ internal object NotificationIds {
private const val OFFSET_NEW_MAIL_SUMMARY = 6
private const val OFFSET_NEW_MAIL_SINGLE = 7
private const val NUMBER_OF_MISC_ACCOUNT_NOTIFICATIONS = 7
private const val NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS = NotificationData.MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS
private const val NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS = MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS
private const val NUMBER_OF_NOTIFICATIONS_PER_ACCOUNT =
NUMBER_OF_MISC_ACCOUNT_NOTIFICATIONS + NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS
@JvmStatic
fun getNewMailSummaryNotificationId(account: Account): Int {
return getBaseNotificationId(account) + OFFSET_NEW_MAIL_SUMMARY
}
@JvmStatic
fun getSingleMessageNotificationId(account: Account, index: Int): Int {
require(index in 0 until NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) { "Invalid index: $index" }
return getBaseNotificationId(account) + OFFSET_NEW_MAIL_SINGLE + index
}
@JvmStatic
fun getAllMessageNotificationIds(account: Account): List<Int> {
val singleMessageNotificationIdRange = (0 until NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) +
(getBaseNotificationId(account) + OFFSET_NEW_MAIL_SINGLE)
return singleMessageNotificationIdRange.toList() + getNewMailSummaryNotificationId(account)
}
fun getFetchingMailNotificationId(account: Account): Int {
return getBaseNotificationId(account) + OFFSET_FETCHING_MAIL
}
@JvmStatic
fun getSendFailedNotificationId(account: Account): Int {
return getBaseNotificationId(account) + OFFSET_SEND_FAILED_NOTIFICATION
}
@JvmStatic
fun getCertificateErrorNotificationId(account: Account, incoming: Boolean): Int {
val offset = if (incoming) OFFSET_CERTIFICATE_ERROR_INCOMING else OFFSET_CERTIFICATE_ERROR_OUTGOING
return getBaseNotificationId(account) + offset
}
@JvmStatic
fun getAuthenticationErrorNotificationId(account: Account, incoming: Boolean): Int {
val offset = if (incoming) OFFSET_AUTHENTICATION_ERROR_INCOMING else OFFSET_AUTHENTICATION_ERROR_OUTGOING

View file

@ -1,45 +1,48 @@
package com.fsck.k9.notification
internal class RemoveNotificationResult private constructor(
val notificationData: NotificationData,
private val holder: NotificationHolder?,
notificationId: Int,
val isUnknownNotification: Boolean
private val notificationId: Int?
) {
val notificationId: Int = notificationId
get() {
check(!isUnknownNotification) { "isUnknownNotification == true" }
return field
}
@get:JvmName("shouldCreateNotification")
val shouldCreateNotification: Boolean
get() = holder != null
val notificationHolder: NotificationHolder
get() = holder ?: error("shouldCreateNotification == false")
val shouldCancelNotification: Boolean
get() = notificationId != null
val cancelNotificationId: Int
get() = notificationId ?: error("shouldCancelNotification == false")
companion object {
@JvmStatic
fun createNotification(notificationHolder: NotificationHolder): RemoveNotificationResult {
return RemoveNotificationResult(
holder = notificationHolder,
notificationId = notificationHolder.notificationId,
isUnknownNotification = false
)
}
@JvmStatic
fun cancelNotification(notificationId: Int): RemoveNotificationResult {
fun cancelNotification(notificationData: NotificationData, notificationId: Int): RemoveNotificationResult {
return RemoveNotificationResult(
notificationData = notificationData,
holder = null,
notificationId = notificationId,
isUnknownNotification = false
notificationId = notificationId
)
}
@JvmStatic
fun unknownNotification(): RemoveNotificationResult {
return RemoveNotificationResult(holder = null, notificationId = 0, isUnknownNotification = true)
fun replaceNotification(
notificationData: NotificationData,
notificationHolder: NotificationHolder
): RemoveNotificationResult {
return RemoveNotificationResult(
notificationData = notificationData,
holder = notificationHolder,
notificationId = notificationHolder.notificationId
)
}
fun recreateSummaryNotification(notificationData: NotificationData): RemoveNotificationResult {
return RemoveNotificationResult(
notificationData = notificationData,
holder = null,
notificationId = null
)
}
}
}

View file

@ -33,7 +33,7 @@ internal class SingleMessageNotificationDataCreator {
notificationId = NotificationIds.getNewMailSummaryNotificationId(data.account),
isSilent = silent,
timestamp = timestamp,
content = data.holderForLatestNotification.content,
content = data.activeNotifications.first().content,
actions = createSingleNotificationActions(),
wearActions = createSingleNotificationWearActions(data.account),
addLockScreenNotification = false,

View file

@ -2,12 +2,15 @@ package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.K9
import com.fsck.k9.controller.MessageReference
private const val MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION = 5
internal class SummaryNotificationDataCreator(
private val singleMessageNotificationDataCreator: SingleMessageNotificationDataCreator
) {
fun createSummaryNotificationData(data: NotificationData, silent: Boolean): SummaryNotificationData {
val timestamp = data.holderForLatestNotification.timestamp
val timestamp = data.latestTimestamp
val shouldBeSilent = silent || K9.isQuietTime
return if (data.isSingleMessageNotification) {
createSummarySingleNotificationData(data, timestamp, shouldBeSilent)
@ -33,18 +36,14 @@ internal class SummaryNotificationDataCreator(
notificationId = NotificationIds.getNewMailSummaryNotificationId(data.account),
isSilent = silent,
timestamp = timestamp,
content = getSummaryContent(data),
additionalMessagesCount = data.getSummaryOverflowMessagesCount(),
messageReferences = data.getAllMessageReferences(),
content = data.summaryContent,
additionalMessagesCount = data.additionalMessagesCount,
messageReferences = data.messageReferences,
actions = createSummaryNotificationActions(),
wearActions = createSummaryWearNotificationActions(data.account)
)
}
private fun getSummaryContent(data: NotificationData): List<CharSequence> {
return data.getContentForSummaryNotification().map { it.summary }
}
@OptIn(ExperimentalStdlibApi::class)
private fun createSummaryNotificationActions(): List<SummaryNotificationAction> {
return buildList {
@ -79,4 +78,31 @@ internal class SummaryNotificationDataCreator(
private fun isDeleteActionAvailableForWear(): Boolean {
return isDeleteActionEnabled() && !K9.isConfirmDeleteFromNotification
}
private val NotificationData.latestTimestamp: Long
get() = activeNotifications.first().timestamp
private val NotificationData.summaryContent: List<CharSequence>
get() {
return activeNotifications.asSequence()
.map { it.content.summary }
.take(MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION)
.toList()
}
private val NotificationData.additionalMessagesCount: Int
get() = (newMessagesCount - MAX_NUMBER_OF_MESSAGES_FOR_SUMMARY_NOTIFICATION).coerceAtLeast(0)
@OptIn(ExperimentalStdlibApi::class)
private val NotificationData.messageReferences: List<MessageReference>
get() {
return buildList(capacity = newMessagesCount) {
for (activeNotification in activeNotifications) {
add(activeNotification.content.messageReference)
}
for (inactiveNotification in inactiveNotifications) {
add(inactiveNotification.content.messageReference)
}
}
}
}

View file

@ -1,56 +0,0 @@
package com.fsck.k9.notification
import com.fsck.k9.controller.MessageReference
import com.google.common.truth.Truth.assertThat
import org.junit.Test
private const val NOTIFICATION_ID = 23
class AddNotificationResultTest {
private val notificationHolder = NotificationHolder(
notificationId = NOTIFICATION_ID,
timestamp = 0L,
content = NotificationContent(
messageReference = MessageReference("irrelevant", 1, "irrelevant"),
sender = "irrelevant",
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant"
)
)
@Test
fun newNotification_shouldCancelNotification_shouldReturnFalse() {
val result = AddNotificationResult.newNotification(notificationHolder)
assertThat(result.shouldCancelNotification).isFalse()
}
@Test(expected = IllegalStateException::class)
fun newNotification_getNotificationId_shouldReturnNotificationId() {
val result = AddNotificationResult.newNotification(notificationHolder)
result.notificationId
}
@Test
fun replaceNotification_shouldCancelNotification_shouldReturnTrue() {
val result = AddNotificationResult.replaceNotification(notificationHolder)
assertThat(result.shouldCancelNotification).isTrue()
}
@Test
fun replaceNotification_getNotificationId_shouldReturnNotificationId() {
val result = AddNotificationResult.replaceNotification(notificationHolder)
assertThat(result.notificationId).isEqualTo(NOTIFICATION_ID)
}
@Test
fun getNotificationHolder_shouldReturnNotificationHolder() {
val result = AddNotificationResult.replaceNotification(notificationHolder)
assertThat(result.notificationHolder).isEqualTo(notificationHolder)
}
}

View file

@ -123,7 +123,7 @@ class BaseNotificationDataCreatorTest {
assertThat(result.lockScreenNotificationData).isInstanceOf(LockScreenNotificationData.SenderNames::class.java)
val senderNamesData = result.lockScreenNotificationData as LockScreenNotificationData.SenderNames
assertThat(senderNamesData.senderNames).isEqualTo("Sender Three, Sender Two, Sender One")
assertThat(senderNamesData.senderNames).isEqualTo("Sender One, Sender Two, Sender Three")
}
@Test
@ -172,20 +172,20 @@ class BaseNotificationDataCreatorTest {
}
private fun createNotificationData(senders: List<String> = emptyList()): NotificationData {
val notificationData = NotificationData(account)
for (sender in senders) {
notificationData.addNotificationContent(
NotificationContent(
val activeNotifications = senders.mapIndexed { index, sender ->
NotificationHolder(
notificationId = index,
timestamp = 0L,
content = NotificationContent(
messageReference = mock(),
sender = sender,
preview = "irrelevant",
summary = "irrelevant",
subject = "irrelevant"
),
timestamp = 0L
)
)
}
return notificationData
return NotificationData(account, activeNotifications, inactiveNotifications = emptyList())
}
private fun createAccount(): Account {

View file

@ -227,7 +227,7 @@ class NewMailNotificationManagerTest {
assertNotNull(result) { data ->
assertThat(data.cancelNotificationIds).hasSize(1)
assertThat(data.baseNotificationData.newMessagesCount)
.isEqualTo(NotificationData.MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS)
.isEqualTo(MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS)
val singleNotificationData = data.singleNotificationData.first()
assertThat(singleNotificationData.notificationId).isEqualTo(data.cancelNotificationIds.first())
@ -253,7 +253,7 @@ class NewMailNotificationManagerTest {
}
private fun addMaximumNumberOfNotifications() {
repeat(NotificationData.MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) { index ->
repeat(MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS) { index ->
val message = addMessageToNotificationContentCreator(
sender = "sender",
subject = "subject",

View file

@ -0,0 +1,154 @@
package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.RobolectricTest
import com.fsck.k9.controller.MessageReference
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertNotNull
import org.junit.Test
private const val ACCOUNT_UUID = "1-2-3"
private const val ACCOUNT_NUMBER = 23
private const val FOLDER_ID = 42L
private const val TIMESTAMP = 0L
class NotificationDataStoreTest : RobolectricTest() {
private val account = createAccount()
private val notificationDataStore = NotificationDataStore()
@Test
fun testAddNotificationContent() {
val content = createNotificationContent("1")
val result = notificationDataStore.addNotification(account, content, TIMESTAMP)
assertThat(result.shouldCancelNotification).isFalse()
val holder = result.notificationHolder
assertThat(holder).isNotNull()
assertThat(holder.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
assertThat(holder.content).isEqualTo(content)
}
@Test
fun testAddNotificationContentWithReplacingNotification() {
notificationDataStore.addNotification(account, createNotificationContent("1"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("2"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("3"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("4"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("5"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("6"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("7"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("8"), TIMESTAMP)
val result = notificationDataStore.addNotification(account, createNotificationContent("9"), TIMESTAMP)
assertThat(result.shouldCancelNotification).isTrue()
assertThat(result.cancelNotificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
}
@Test
fun testRemoveNotificationForMessage() {
val content = createNotificationContent("1")
notificationDataStore.addNotification(account, content, TIMESTAMP)
val result = notificationDataStore.removeNotification(account, content.messageReference)
assertNotNull(result) { removeResult ->
assertThat(removeResult.cancelNotificationId)
.isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
assertThat(removeResult.shouldCreateNotification).isFalse()
}
}
@Test
fun testRemoveNotificationForMessageWithRecreatingNotification() {
notificationDataStore.addNotification(account, createNotificationContent("1"), TIMESTAMP)
val content = createNotificationContent("2")
notificationDataStore.addNotification(account, content, TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("3"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("4"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("5"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("6"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("7"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("8"), TIMESTAMP)
notificationDataStore.addNotification(account, createNotificationContent("9"), TIMESTAMP)
val latestContent = createNotificationContent("10")
notificationDataStore.addNotification(account, latestContent, TIMESTAMP)
val result = notificationDataStore.removeNotification(account, latestContent.messageReference)
assertNotNull(result) { removeResult ->
assertThat(removeResult.cancelNotificationId)
.isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 1))
assertThat(removeResult.shouldCreateNotification).isTrue()
assertNotNull(removeResult.notificationHolder) { holder ->
assertThat(holder.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 1))
assertThat(holder.content).isEqualTo(content)
}
}
}
@Test
fun testRemoveDoesNotLeakNotificationIds() {
for (i in 1..MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS + 1) {
val content = createNotificationContent(i.toString())
notificationDataStore.addNotification(account, content, TIMESTAMP)
notificationDataStore.removeNotification(account, content.messageReference)
}
}
@Test
fun testNewMessagesCount() {
val contentOne = createNotificationContent("1")
val resultOne = notificationDataStore.addNotification(account, contentOne, TIMESTAMP)
assertThat(resultOne.notificationData.newMessagesCount).isEqualTo(1)
val contentTwo = createNotificationContent("2")
val resultTwo = notificationDataStore.addNotification(account, contentTwo, TIMESTAMP)
assertThat(resultTwo.notificationData.newMessagesCount).isEqualTo(2)
}
@Test
fun testIsSingleMessageNotification() {
val resultOne = notificationDataStore.addNotification(account, createNotificationContent("1"), TIMESTAMP)
assertThat(resultOne.notificationData.isSingleMessageNotification).isTrue()
val resultTwo = notificationDataStore.addNotification(account, createNotificationContent("2"), TIMESTAMP)
assertThat(resultTwo.notificationData.isSingleMessageNotification).isFalse()
}
@Test
fun testGetHolderForLatestNotification() {
val content = createNotificationContent("1")
val addResult = notificationDataStore.addNotification(account, content, TIMESTAMP)
assertThat(addResult.notificationData.activeNotifications.first()).isEqualTo(addResult.notificationHolder)
}
private fun createAccount(): Account {
return Account("00000000-0000-4000-0000-000000000000").apply {
accountNumber = ACCOUNT_NUMBER
}
}
private fun createMessageReference(uid: String): MessageReference {
return MessageReference(ACCOUNT_UUID, FOLDER_ID, uid)
}
private fun createNotificationContent(uid: String): NotificationContent {
val messageReference = createMessageReference(uid)
return createNotificationContent(messageReference)
}
private fun createNotificationContent(messageReference: MessageReference): NotificationContent {
return NotificationContent(
messageReference = messageReference,
sender = "irrelevant",
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant"
)
}
}

View file

@ -1,262 +0,0 @@
package com.fsck.k9.notification
import com.fsck.k9.Account
import com.fsck.k9.RobolectricTest
import com.fsck.k9.controller.MessageReference
import com.google.common.truth.Truth.assertThat
import kotlin.test.assertNotNull
import org.junit.Test
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
private const val ACCOUNT_UUID = "1-2-3"
private const val ACCOUNT_NUMBER = 23
private const val FOLDER_ID = 42L
private const val TIMESTAMP = 0L
class NotificationDataTest : RobolectricTest() {
private val account = createFakeAccount()
private val notificationData = NotificationData(account)
@Test
fun testAddNotificationContent() {
val content = createNotificationContent("1")
val result = notificationData.addNotificationContent(content, TIMESTAMP)
assertThat(result.shouldCancelNotification).isFalse()
val holder = result.notificationHolder
assertThat(holder).isNotNull()
assertThat(holder.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
assertThat(holder.content).isEqualTo(content)
}
@Test
fun testAddNotificationContentWithReplacingNotification() {
notificationData.addNotificationContent(createNotificationContent("1"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("2"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("3"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("4"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("5"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("6"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("7"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("8"), TIMESTAMP)
val result = notificationData.addNotificationContent(createNotificationContent("9"), TIMESTAMP)
assertThat(result.shouldCancelNotification).isTrue()
assertThat(result.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
}
@Test
fun testRemoveNotificationForMessage() {
val content = createNotificationContent("1")
notificationData.addNotificationContent(content, TIMESTAMP)
val result = notificationData.removeNotificationForMessage(content.messageReference)
assertThat(result.isUnknownNotification).isFalse()
assertThat(result.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
assertThat(result.shouldCreateNotification).isFalse()
}
@Test
fun testRemoveNotificationForMessageWithRecreatingNotification() {
notificationData.addNotificationContent(createNotificationContent("1"), TIMESTAMP)
val content = createNotificationContent("2")
notificationData.addNotificationContent(content, TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("3"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("4"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("5"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("6"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("7"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("8"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("9"), TIMESTAMP)
val latestContent = createNotificationContent("10")
notificationData.addNotificationContent(latestContent, TIMESTAMP)
val result = notificationData.removeNotificationForMessage(latestContent.messageReference)
assertThat(result.isUnknownNotification).isFalse()
assertThat(result.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 1))
assertThat(result.shouldCreateNotification).isTrue()
assertNotNull(result.notificationHolder) { holder ->
assertThat(holder.notificationId).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 1))
assertThat(holder.content).isEqualTo(content)
}
}
@Test
fun testRemoveDoesNotLeakNotificationIds() {
for (i in 1..NotificationData.MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS + 1) {
val content = createNotificationContent(i.toString())
notificationData.addNotificationContent(content, TIMESTAMP)
notificationData.removeNotificationForMessage(content.messageReference)
}
}
@Test
fun testNewMessagesCount() {
assertThat(notificationData.newMessagesCount).isEqualTo(0)
val contentOne = createNotificationContent("1")
notificationData.addNotificationContent(contentOne, TIMESTAMP)
assertThat(notificationData.newMessagesCount).isEqualTo(1)
val contentTwo = createNotificationContent("2")
notificationData.addNotificationContent(contentTwo, TIMESTAMP)
assertThat(notificationData.newMessagesCount).isEqualTo(2)
}
@Test
fun testIsSingleMessageNotification() {
assertThat(notificationData.isSingleMessageNotification).isFalse()
notificationData.addNotificationContent(createNotificationContent("1"), TIMESTAMP)
assertThat(notificationData.isSingleMessageNotification).isTrue()
notificationData.addNotificationContent(createNotificationContent("2"), TIMESTAMP)
assertThat(notificationData.isSingleMessageNotification).isFalse()
}
@Test
fun testGetHolderForLatestNotification() {
val content = createNotificationContent("1")
val addResult = notificationData.addNotificationContent(content, TIMESTAMP)
val holder = notificationData.holderForLatestNotification
assertThat(holder).isEqualTo(addResult.notificationHolder)
}
@Test
fun testGetContentForSummaryNotification() {
notificationData.addNotificationContent(createNotificationContent("1"), TIMESTAMP)
val content4 = createNotificationContent("2")
notificationData.addNotificationContent(content4, TIMESTAMP)
val content3 = createNotificationContent("3")
notificationData.addNotificationContent(content3, TIMESTAMP)
val content2 = createNotificationContent("4")
notificationData.addNotificationContent(content2, TIMESTAMP)
val content1 = createNotificationContent("5")
notificationData.addNotificationContent(content1, TIMESTAMP)
val content0 = createNotificationContent("6")
notificationData.addNotificationContent(content0, TIMESTAMP)
val contents = notificationData.getContentForSummaryNotification()
assertThat(contents.size.toLong()).isEqualTo(5)
assertThat(contents[0]).isEqualTo(content0)
assertThat(contents[1]).isEqualTo(content1)
assertThat(contents[2]).isEqualTo(content2)
assertThat(contents[3]).isEqualTo(content3)
assertThat(contents[4]).isEqualTo(content4)
}
@Test
fun testGetActiveNotificationIds() {
notificationData.addNotificationContent(createNotificationContent("1"), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent("2"), TIMESTAMP)
val notificationIds = notificationData.getActiveNotificationIds()
assertThat(notificationIds.size).isEqualTo(2)
assertThat(notificationIds[0]).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 1))
assertThat(notificationIds[1]).isEqualTo(NotificationIds.getSingleMessageNotificationId(account, 0))
}
@Test
fun testGetAccount() {
assertThat(notificationData.account).isEqualTo(account)
}
@Test
fun testGetAllMessageReferences() {
val messageReference0 = createMessageReference("1")
val messageReference1 = createMessageReference("2")
val messageReference2 = createMessageReference("3")
val messageReference3 = createMessageReference("4")
val messageReference4 = createMessageReference("5")
val messageReference5 = createMessageReference("6")
val messageReference6 = createMessageReference("7")
val messageReference7 = createMessageReference("8")
val messageReference8 = createMessageReference("9")
notificationData.addNotificationContent(createNotificationContent(messageReference8), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference7), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference6), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference5), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference4), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference3), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference2), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference1), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference0), TIMESTAMP)
val messageReferences = notificationData.getAllMessageReferences()
assertThat(messageReferences).isEqualTo(
listOf(
messageReference0,
messageReference1,
messageReference2,
messageReference3,
messageReference4,
messageReference5,
messageReference6,
messageReference7,
messageReference8
)
)
}
@Test
fun testOverflowNotifications() {
val messageReference0 = createMessageReference("1")
val messageReference1 = createMessageReference("2")
val messageReference2 = createMessageReference("3")
val messageReference3 = createMessageReference("4")
val messageReference4 = createMessageReference("5")
val messageReference5 = createMessageReference("6")
val messageReference6 = createMessageReference("7")
val messageReference7 = createMessageReference("8")
val messageReference8 = createMessageReference("9")
notificationData.addNotificationContent(createNotificationContent(messageReference8), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference7), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference6), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference5), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference4), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference3), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference2), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference1), TIMESTAMP)
notificationData.addNotificationContent(createNotificationContent(messageReference0), TIMESTAMP)
assertThat(notificationData.hasSummaryOverflowMessages()).isTrue()
assertThat(notificationData.getSummaryOverflowMessagesCount()).isEqualTo(4)
}
private fun createFakeAccount(): Account {
return mock {
on { accountNumber } doReturn ACCOUNT_NUMBER
}
}
private fun createMessageReference(uid: String): MessageReference {
return MessageReference(ACCOUNT_UUID, FOLDER_ID, uid)
}
private fun createNotificationContent(uid: String): NotificationContent {
val messageReference = createMessageReference(uid)
return createNotificationContent(messageReference)
}
private fun createNotificationContent(messageReference: MessageReference): NotificationContent {
return NotificationContent(
messageReference = messageReference,
sender = "irrelevant",
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant"
)
}
}

View file

@ -94,7 +94,7 @@ class NotificationIdsTest {
NotificationIds.getAuthenticationErrorNotificationId(account, false),
NotificationIds.getFetchingMailNotificationId(account),
NotificationIds.getNewMailSummaryNotificationId(account),
) + (0 until NotificationData.MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS).map { index ->
) + (0 until MAX_NUMBER_OF_NEW_MESSAGE_NOTIFICATIONS).map { index ->
NotificationIds.getSingleMessageNotificationId(account, index)
}
}

View file

@ -1,108 +0,0 @@
package com.fsck.k9.notification
import com.fsck.k9.controller.MessageReference
import com.fsck.k9.notification.RemoveNotificationResult.Companion.cancelNotification
import com.fsck.k9.notification.RemoveNotificationResult.Companion.createNotification
import com.fsck.k9.notification.RemoveNotificationResult.Companion.unknownNotification
import com.google.common.truth.Truth.assertThat
import org.junit.Test
private const val NOTIFICATION_ID = 23
class RemoveNotificationResultTest {
private val notificationHolder = NotificationHolder(
notificationId = NOTIFICATION_ID,
timestamp = 0L,
content = NotificationContent(
messageReference = MessageReference("irrelevant", 1, "irrelevant"),
sender = "irrelevant",
subject = "irrelevant",
preview = "irrelevant",
summary = "irrelevant"
)
)
@Test
fun createNotification_shouldCancelNotification_shouldReturnTrue() {
val result = createNotification(notificationHolder)
assertThat(result.shouldCreateNotification).isTrue()
}
@Test
fun createNotification_getNotificationId_shouldReturnNotificationId() {
val result = createNotification(notificationHolder)
assertThat(result.notificationId).isEqualTo(NOTIFICATION_ID)
}
@Test
fun createNotification_isUnknownNotification_shouldReturnFalse() {
val result = createNotification(notificationHolder)
assertThat(result.isUnknownNotification).isFalse()
}
@Test
fun createNotification_getNotificationHolder_shouldReturnNotificationHolder() {
val result = createNotification(notificationHolder)
assertThat(result.notificationHolder).isEqualTo(notificationHolder)
}
@Test
fun cancelNotification_shouldCancelNotification_shouldReturnFalse() {
val result = cancelNotification(NOTIFICATION_ID)
assertThat(result.shouldCreateNotification).isFalse()
}
@Test
fun cancelNotification_getNotificationId_shouldReturnNotificationId() {
val result = cancelNotification(NOTIFICATION_ID)
assertThat(result.notificationId).isEqualTo(NOTIFICATION_ID)
}
@Test
fun cancelNotification_isUnknownNotification_shouldReturnFalse() {
val result = cancelNotification(NOTIFICATION_ID)
assertThat(result.isUnknownNotification).isFalse()
}
@Test(expected = IllegalStateException::class)
fun cancelNotification_getNotificationHolder_shouldThrowException() {
val result = cancelNotification(NOTIFICATION_ID)
result.notificationHolder
}
@Test
fun unknownNotification_shouldCancelNotification_shouldReturnFalse() {
val result = unknownNotification()
assertThat(result.shouldCreateNotification).isFalse()
}
@Test(expected = IllegalStateException::class)
fun unknownNotification_getNotificationId_shouldThrowException() {
val result = unknownNotification()
result.notificationId
}
@Test
fun unknownNotification_isUnknownNotification_shouldReturnTrue() {
val result = unknownNotification()
assertThat(result.isUnknownNotification).isTrue()
}
@Test(expected = IllegalStateException::class)
fun unknownNotification_getNotificationHolder_shouldThrowException() {
val result = unknownNotification()
result.notificationHolder
}
}

View file

@ -267,8 +267,16 @@ class SingleMessageNotificationDataCreatorTest {
)
private fun createNotificationData(content: NotificationContent): NotificationData {
return NotificationData(account).apply {
addNotificationContent(content, timestamp = 0L)
}
return NotificationData(
account,
activeNotifications = listOf(
NotificationHolder(
notificationId = 1,
timestamp = 0,
content = content
)
),
inactiveNotifications = emptyList()
)
}
}

View file

@ -259,11 +259,11 @@ class SummaryNotificationDataCreatorTest {
private fun createNotificationData(
contentList: List<NotificationContent> = listOf(createNotificationContent())
): NotificationData {
return NotificationData(account).apply {
for (content in contentList) {
addNotificationContent(content, TIMESTAMP)
}
val activeNotifications = contentList.mapIndexed { index, content ->
NotificationHolder(notificationId = index, TIMESTAMP, content)
}
return NotificationData(account, activeNotifications, inactiveNotifications = emptyList())
}
@OptIn(ExperimentalStdlibApi::class)