diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/flags/BufferActivity.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/BufferActivity.kt similarity index 53% rename from libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/flags/BufferActivity.kt rename to libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/BufferActivity.kt index 7b106be66c411f9b9aa418b7dd79bc78aa262860..6f6b274840f66838d87ba375241f7884329a2623 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/flags/BufferActivity.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/models/BufferActivity.kt @@ -7,41 +7,39 @@ * obtain one at https://mozilla.org/MPL/2.0/. */ -package de.justjanne.libquassel.protocol.models.flags - -import de.justjanne.bitflags.Flag -import de.justjanne.bitflags.Flags -import de.justjanne.bitflags.toEnumSet +package de.justjanne.libquassel.protocol.models /** * Model representing all seen activity on a buffer */ enum class BufferActivity( - override val value: UInt, -) : Flag<UInt> { + /** + * Underlying representation + */ + val value: Int, +) { /** * Other, unspecified activity has occurred on this buffer (join, part, quit, etc) */ - OtherActivity(0x01u), + OtherActivity(1), /** * A new unread mesage is available on this buffer */ - NewMessage(0x02u), + NewMessage(2), /** * A highlight for the current user is available on this buffer */ - Highlight(0x04u); + Highlight(4); - companion object : Flags<UInt, BufferActivity> { - private val values = enumValues<BufferActivity>() + companion object { + private val map = enumValues<BufferActivity>() .associateBy(BufferActivity::value) - override val all: BufferActivities = values.values.toEnumSet() + + /** + * Obtain a zone specification by its underlying representation + */ + fun of(type: Int) = map[type] } } - -/** - * Model representing a bitfield of [BufferActivity] flags - */ -typealias BufferActivities = Set<BufferActivity> diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt index ad98e36a9458e1b30ebe50cefde68b6a0dd20de7..60b878ec966aa060f16d8837b18a9c9fe409a06c 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfig.kt @@ -11,8 +11,8 @@ package de.justjanne.libquassel.protocol.syncables import de.justjanne.bitflags.of import de.justjanne.bitflags.toBits +import de.justjanne.libquassel.protocol.models.BufferActivity import de.justjanne.libquassel.protocol.models.BufferInfo -import de.justjanne.libquassel.protocol.models.flags.BufferActivity import de.justjanne.libquassel.protocol.models.flags.BufferType import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.NetworkId @@ -43,7 +43,7 @@ open class BufferViewConfig( ?.mapNotNull { it.into<BufferId>() } ?.toSet() .orEmpty(), - temporarilyRemovedBuffers = properties["TemporarilyRemovedBuffers"].into<QVariantList>() + hiddenBuffers = properties["TemporarilyRemovedBuffers"].into<QVariantList>() ?.mapNotNull { it.into<BufferId>() } ?.toSet() .orEmpty(), @@ -59,7 +59,6 @@ open class BufferViewConfig( ?.let(BufferType.Companion::of) ?: allowedBufferTypes, minimumActivity = properties["minimumActivity"].into<Int>() - ?.let(Int::toUInt) ?.let(BufferActivity.Companion::of) ?: minimumActivity, showSearch = properties["showSearch"].into(showSearch), @@ -81,7 +80,7 @@ open class BufferViewConfig( QtType.QVariantList ), "TemporarilyRemovedBuffers" to qVariant( - temporarilyRemovedBuffers().map { + hiddenBuffers().map { qVariant(it, QuasselType.BufferId) }, QtType.QVariantList @@ -94,7 +93,7 @@ open class BufferViewConfig( "hideInactiveNetworks" to qVariant(hideInactiveNetworks(), QtType.Bool), "disableDecoration" to qVariant(disableDecoration(), QtType.Bool), "allowedBufferTypes" to qVariant(allowedBufferTypes().toBits().toInt(), QtType.Int), - "minimumActivity" to qVariant(minimumActivity().toBits().toInt(), QtType.Int), + "minimumActivity" to qVariant(minimumActivity()?.value?.toInt() ?: 0, QtType.Int), "showSearch" to qVariant(showSearch(), QtType.Bool) ) @@ -112,42 +111,46 @@ open class BufferViewConfig( fun buffers() = state().buffers fun removedBuffers() = state().removedBuffers - fun temporarilyRemovedBuffers() = state().temporarilyRemovedBuffers + fun hiddenBuffers() = state().hiddenBuffers override fun addBuffer(buffer: BufferId, pos: Int) { + if (buffers().contains(buffer)) { + return + } + state.update { copy( buffers = buffers.insert(buffer, pos), removedBuffers = removedBuffers - buffer, - temporarilyRemovedBuffers = temporarilyRemovedBuffers - buffer + hiddenBuffers = hiddenBuffers - buffer ) } super.addBuffer(buffer, pos) } - override fun removeBuffer(buffer: BufferId) { + override fun hideBuffer(buffer: BufferId) { state.update { copy( buffers = buffers - buffer, removedBuffers = removedBuffers - buffer, - temporarilyRemovedBuffers = temporarilyRemovedBuffers + buffer + hiddenBuffers = hiddenBuffers + buffer ) } - super.removeBuffer(buffer) + super.hideBuffer(buffer) } - override fun removeBufferPermanently(buffer: BufferId) { + override fun removeBuffer(buffer: BufferId) { state.update { copy( buffers = buffers - buffer, removedBuffers = removedBuffers + buffer, - temporarilyRemovedBuffers = temporarilyRemovedBuffers - buffer + hiddenBuffers = hiddenBuffers - buffer ) } - super.removeBufferPermanently(buffer) + super.removeBuffer(buffer) } override fun moveBuffer(buffer: BufferId, pos: Int) { @@ -159,7 +162,7 @@ open class BufferViewConfig( copy( buffers = buffers.move(buffer, pos), removedBuffers = removedBuffers - buffer, - temporarilyRemovedBuffers = temporarilyRemovedBuffers - buffer + hiddenBuffers = hiddenBuffers - buffer ) } @@ -210,7 +213,7 @@ open class BufferViewConfig( override fun setMinimumActivity(value: Int) { state.update { - copy(minimumActivity = BufferActivity.of(value.toUInt())) + copy(minimumActivity = BufferActivity.of(value)) } super.setMinimumActivity(value) } @@ -259,14 +262,14 @@ open class BufferViewConfig( fun handleBuffer(info: BufferInfo, unhide: Boolean = false) { if (addNewBuffersAutomatically() && !buffers().contains(info.bufferId) && - !temporarilyRemovedBuffers().contains(info.bufferId) && + !hiddenBuffers().contains(info.bufferId) && !removedBuffers().contains(info.bufferId) && !info.type.contains(BufferType.Status) ) { insertBufferSorted(info) } else if (unhide && !buffers().contains(info.bufferId) && - temporarilyRemovedBuffers().contains(info.bufferId) + hiddenBuffers().contains(info.bufferId) ) { insertBufferSorted(info) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt index 16ade00a5cc60592780de291c21fa17c0d481f7a..bfd6d0c39e7628e5923baae6859cad78ca23827f 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManager.kt @@ -18,6 +18,7 @@ import de.justjanne.libquassel.protocol.models.rules.StrictnessType import de.justjanne.libquassel.protocol.models.types.QtType import de.justjanne.libquassel.protocol.syncables.state.IgnoreListManagerState import de.justjanne.libquassel.protocol.syncables.stubs.IgnoreListManagerStub +import de.justjanne.libquassel.protocol.util.collections.removeAt import de.justjanne.libquassel.protocol.util.update import de.justjanne.libquassel.protocol.variant.QVariantList import de.justjanne.libquassel.protocol.variant.QVariantMap @@ -132,7 +133,7 @@ class IgnoreListManager( fun count() = state().count() fun removeAt(index: Int) { state.update { - copy(rules = rules.drop(index)) + copy(rules = rules.removeAt(index)) } } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt index 7867743de65e320e44cfd9878118e0c1a3cc2db8..d47d37f6b7d13f42202df2cd9a4488e7aded3370 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannel.kt @@ -234,6 +234,7 @@ open class IrcChannel( override fun removeChannelMode(mode: Char, value: String?) { val network = session?.network(network()) + println(network?.channelModeType(mode)) state.update { copy( channelModes = channelModes.run { @@ -243,13 +244,15 @@ open class IrcChannel( "Mode $mode of ChannelModeType A must have a value" } - copy(a = a + Pair(mode, a[mode].orEmpty() - value)) + val result = Pair(mode, a[mode].orEmpty() - value) + if (result.second.isNotEmpty()) copy(a = a + result) + else copy(a = a - mode) } ChannelModeType.B_CHANMODE -> { copy(b = b - mode) } ChannelModeType.C_CHANMODE -> { - copy(b = c - mode) + copy(c = c - mode) } ChannelModeType.D_CHANMODE -> copy(d = d - mode) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewConfigState.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewConfigState.kt index 5f8823368cade6d19f7522906b432cf5c55af46f..141716a85e5eb0b8e748c1753d393adb0822febd 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewConfigState.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/state/BufferViewConfigState.kt @@ -9,9 +9,7 @@ package de.justjanne.libquassel.protocol.syncables.state -import de.justjanne.bitflags.none -import de.justjanne.libquassel.protocol.models.flags.BufferActivities -import de.justjanne.libquassel.protocol.models.flags.BufferActivity +import de.justjanne.libquassel.protocol.models.BufferActivity import de.justjanne.libquassel.protocol.models.flags.BufferType import de.justjanne.libquassel.protocol.models.flags.BufferTypes import de.justjanne.libquassel.protocol.models.ids.BufferId @@ -27,9 +25,9 @@ data class BufferViewConfigState( val hideInactiveNetworks: Boolean = false, val disableDecoration: Boolean = false, val allowedBufferTypes: BufferTypes = BufferType.all, - val minimumActivity: BufferActivities = BufferActivity.none(), + val minimumActivity: BufferActivity? = null, val showSearch: Boolean = false, val buffers: List<BufferId> = emptyList(), val removedBuffers: Set<BufferId> = emptySet(), - val temporarilyRemovedBuffers: Set<BufferId> = emptySet(), + val hiddenBuffers: Set<BufferId> = emptySet(), ) diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt index 31544498a54968b33bcdb94373e7faeb3fd8720d..9fe8c77603ab51114ba43a6e61050416d79e1e0c 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/syncables/stubs/BufferViewConfigStub.kt @@ -62,8 +62,8 @@ interface BufferViewConfigStub : SyncableStub { ) } - @SyncedCall(target = ProtocolSide.CLIENT) - fun removeBuffer(buffer: BufferId) { + @SyncedCall(target = ProtocolSide.CLIENT, name = "removeBuffer") + fun hideBuffer(buffer: BufferId) { sync( target = ProtocolSide.CLIENT, "removeBuffer", @@ -72,7 +72,7 @@ interface BufferViewConfigStub : SyncableStub { } @SyncedCall(target = ProtocolSide.CORE) - fun requestRemoveBuffer(buffer: BufferId) { + fun requestHideBuffer(buffer: BufferId) { sync( target = ProtocolSide.CORE, "requestRemoveBuffer", @@ -80,8 +80,8 @@ interface BufferViewConfigStub : SyncableStub { ) } - @SyncedCall(target = ProtocolSide.CLIENT) - fun removeBufferPermanently(buffer: BufferId) { + @SyncedCall(target = ProtocolSide.CLIENT, name = "removeBufferPermanently") + fun removeBuffer(buffer: BufferId) { sync( target = ProtocolSide.CLIENT, "removeBufferPermanently", @@ -90,7 +90,7 @@ interface BufferViewConfigStub : SyncableStub { } @SyncedCall(target = ProtocolSide.CORE) - fun requestRemoveBufferPermanently(buffer: BufferId) { + fun requestRemoveBuffer(buffer: BufferId) { sync( target = ProtocolSide.CORE, "requestRemoveBufferPermanently", diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/move.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/move.kt index db54c8999ca90a0cfb4cbdfdaed699d19a16e5df..2df834d0dedc5982186a2e72145cbb5e9fe6afac 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/move.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/move.kt @@ -13,9 +13,6 @@ fun <T> List<T>.move(value: T, pos: Int = size): List<T> { val newPos = pos.coerceIn(0, size) val oldPos = indexOf(value) - return when { - newPos > oldPos -> remove(value).insert(value, newPos - 1) - newPos < oldPos -> remove(value).insert(value, newPos) - else -> this - } + return if (newPos == oldPos) this + else remove(value).insert(value, newPos) } diff --git a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/remove.kt b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/remove.kt index 405dfa2c193c6d3041eba4d86777fbb45ed05e32..2aa1d58b3ff21c1348da36d23d00b3db15ff1519 100644 --- a/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/remove.kt +++ b/libquassel-protocol/src/main/kotlin/de/justjanne/libquassel/protocol/util/collections/remove.kt @@ -10,3 +10,12 @@ package de.justjanne.libquassel.protocol.util.collections fun <T> List<T>.remove(value: T): List<T> = this.filter { it != value } +fun <T> List<T>.removeAt(index: Int): List<T> { + if (index < 0 || index >= size) return this + + val before = subList(0, index) + val after = subList(index + 1, size) + if (before.isEmpty()) return after + if (after.isEmpty()) return before + return before + after +} diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfigTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfigTest.kt index 00e208b03fca35ac5c73d1f8e789a7441516c353..d4c68d4c1379f61ebcb10ac3568220fdca2b7761 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfigTest.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewConfigTest.kt @@ -9,9 +9,17 @@ package de.justjanne.libquassel.protocol.syncables +import de.justjanne.bitflags.of +import de.justjanne.bitflags.toBits +import de.justjanne.libquassel.protocol.models.BufferActivity +import de.justjanne.libquassel.protocol.models.flags.BufferType +import de.justjanne.libquassel.protocol.models.ids.BufferId +import de.justjanne.libquassel.protocol.models.ids.NetworkId import de.justjanne.libquassel.protocol.syncables.state.BufferViewConfigState import de.justjanne.libquassel.protocol.testutil.nextBufferViewConfig import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotEquals +import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import kotlin.random.Random @@ -41,4 +49,435 @@ class BufferViewConfigTest { assertEquals(expected, actual) } + + @Nested + inner class AddBuffer { + @Test + fun new() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = BufferId(105) + value.addBuffer(buffer, 3) + assertEquals(3, value.buffers().indexOf(buffer)) + assertEquals(bufferSize + 1, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun existing() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.buffers().first() + value.addBuffer(buffer, 3) + assertEquals(0, value.buffers().indexOf(buffer)) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun hidden() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.hiddenBuffers().first() + value.addBuffer(buffer, 3) + assertEquals(3, value.buffers().indexOf(buffer)) + assertEquals(bufferSize + 1, value.buffers().size) + assertEquals(hiddenSize - 1, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun removed() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.removedBuffers().first() + value.addBuffer(buffer, 3) + assertEquals(3, value.buffers().indexOf(buffer)) + assertEquals(bufferSize + 1, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize - 1, value.removedBuffers().size) + } + } + + @Nested + inner class HideBuffer { + @Test + fun new() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = BufferId(105) + value.hideBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize + 1, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun existing() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.buffers().first() + value.hideBuffer(buffer) + assertEquals(bufferSize - 1, value.buffers().size) + assertEquals(hiddenSize + 1, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun hidden() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.hiddenBuffers().first() + value.hideBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun removed() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.removedBuffers().first() + value.hideBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize + 1, value.hiddenBuffers().size) + assertEquals(removedSize - 1, value.removedBuffers().size) + } + } + + @Nested + inner class RemoveBuffer { + @Test + fun new() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = BufferId(105) + value.removeBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize + 1, value.removedBuffers().size) + } + + @Test + fun existing() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.buffers().first() + value.removeBuffer(buffer) + assertEquals(bufferSize - 1, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize + 1, value.removedBuffers().size) + } + + @Test + fun hidden() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.hiddenBuffers().first() + value.removeBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize - 1, value.hiddenBuffers().size) + assertEquals(removedSize + 1, value.removedBuffers().size) + } + + @Test + fun removed() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.removedBuffers().first() + value.removeBuffer(buffer) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + } + + @Nested + inner class MoveBuffer { + @Test + fun new() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = BufferId(105) + value.moveBuffer(buffer, 3) + assertEquals(-1, value.buffers().indexOf(buffer)) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun existing() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.buffers().first() + println(value.buffers()) + value.moveBuffer(buffer, 3) + println(value.buffers()) + assertEquals(3, value.buffers().indexOf(buffer)) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun hidden() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.hiddenBuffers().first() + value.moveBuffer(buffer, 3) + assertEquals(-1, value.buffers().indexOf(buffer)) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + + @Test + fun removed() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val bufferSize = value.buffers().size + val hiddenSize = value.hiddenBuffers().size + val removedSize = value.removedBuffers().size + val buffer = value.removedBuffers().first() + value.moveBuffer(buffer, 3) + assertEquals(-1, value.buffers().indexOf(buffer)) + assertEquals(bufferSize, value.buffers().size) + assertEquals(hiddenSize, value.hiddenBuffers().size) + assertEquals(removedSize, value.removedBuffers().size) + } + } + + @Nested + inner class Setters { + @Test + fun testBufferViewName() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val data = "All Chats" + assertNotEquals(data, value.bufferViewName()) + value.setBufferViewName(data) + assertEquals(data, value.bufferViewName()) + } + + @Test + fun testAddNewBuffersAutomatically() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setAddNewBuffersAutomatically(false) + assertEquals(false, value.addNewBuffersAutomatically()) + value.setAddNewBuffersAutomatically(true) + assertEquals(true, value.addNewBuffersAutomatically()) + } + + @Test + fun testAllowedBufferTypes() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val data = BufferType.of( + BufferType.Channel, + BufferType.Status, + BufferType.Query + ) + assertNotEquals(data, value.allowedBufferTypes()) + value.setAllowedBufferTypes(data.toBits().toInt()) + assertEquals(data, value.allowedBufferTypes()) + } + + @Test + fun testDisableDecoration() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setDisableDecoration(false) + assertEquals(false, value.disableDecoration()) + value.setDisableDecoration(true) + assertEquals(true, value.disableDecoration()) + } + + @Test + fun testHideInactiveBuffers() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setHideInactiveBuffers(false) + assertEquals(false, value.hideInactiveBuffers()) + value.setHideInactiveBuffers(true) + assertEquals(true, value.hideInactiveBuffers()) + } + + @Test + fun testHideInactiveNetworks() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setHideInactiveNetworks(false) + assertEquals(false, value.hideInactiveNetworks()) + value.setHideInactiveNetworks(true) + assertEquals(true, value.hideInactiveNetworks()) + } + + @Test + fun testMinimumActivity() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val data = BufferActivity.Highlight + assertNotEquals(data, value.minimumActivity()) + value.setMinimumActivity(data.value) + assertEquals(data, value.minimumActivity()) + } + + @Test + fun testNetworkId() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + val data = NetworkId(random.nextInt()) + assertNotEquals(data, value.networkId()) + value.setNetworkId(data) + assertEquals(data, value.networkId()) + } + + @Test + fun testShowSearch() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setShowSearch(false) + assertEquals(false, value.showSearch()) + value.setShowSearch(true) + assertEquals(true, value.showSearch()) + } + + @Test + fun testSortAlphabetically() { + val random = Random(1337) + val value = BufferViewConfig( + state = random.nextBufferViewConfig(bufferViewId = 1) + ) + + value.setSortAlphabetically(false) + assertEquals(false, value.sortAlphabetically()) + value.setSortAlphabetically(true) + assertEquals(true, value.sortAlphabetically()) + } + } } diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManagerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManagerTest.kt index 7f611aa5c878983839c13ac3e653b3e9a647afc9..281fcaeade5b6f50929f5dc033f49abb20e11e87 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManagerTest.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/BufferViewManagerTest.kt @@ -18,12 +18,11 @@ import kotlin.random.Random class BufferViewManagerTest { @Test fun testEmpty() { - val state = BufferViewManagerState() - val actual = BufferViewManager(state = state).apply { + val actual = BufferViewManager().apply { update(emptyMap()) }.state() - assertEquals(state, actual) + assertEquals(BufferViewManagerState(), actual) } @Test diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManagerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManagerTest.kt index acd04e80029e11016fea9a09066d1c373b64d1d0..7073f57adce4e9707f6abccfdd4b6c0f85351972 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManagerTest.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/HighlightRuleManagerTest.kt @@ -31,12 +31,11 @@ import kotlin.random.Random class HighlightRuleManagerTest { @Test fun testEmpty() { - val state = HighlightRuleManagerState() - val actual = HighlightRuleManager(state = state).apply { + val actual = HighlightRuleManager().apply { update(emptyMap()) }.state() - assertEquals(state, actual) + assertEquals(HighlightRuleManagerState(), actual) } @Test @@ -160,8 +159,7 @@ class HighlightRuleManagerTest { } @Test - fun testNulLData() { - val random = Random(1337) + fun testNullData() { val actual = HighlightRuleManager( state = HighlightRuleManagerState() ).apply { @@ -219,7 +217,8 @@ class HighlightRuleManagerTest { ) ), QtType.QVariantMap - ) + ), + "highlightNick" to qVariant(-2, QtType.Int) ) ) }.state() diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManagerTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManagerTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..9f38d5d9de4441761cca2c958e28f48e0c207bfb --- /dev/null +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IgnoreListManagerTest.kt @@ -0,0 +1,426 @@ +/* + * libquassel + * Copyright (c) 2021 Janne Mareike Koschinski + * + * This Source Code Form is subject to the terms of the Mozilla Public License, + * v. 2.0. If a copy of the MPL was not distributed with this file, You can + * obtain one at https://mozilla.org/MPL/2.0/. + */ + +package de.justjanne.libquassel.protocol.syncables + +import de.justjanne.libquassel.protocol.models.QStringList +import de.justjanne.libquassel.protocol.models.rules.IgnoreRule +import de.justjanne.libquassel.protocol.models.rules.IgnoreType +import de.justjanne.libquassel.protocol.models.rules.ScopeType +import de.justjanne.libquassel.protocol.models.rules.StrictnessType +import de.justjanne.libquassel.protocol.models.types.QtType +import de.justjanne.libquassel.protocol.syncables.state.IgnoreListManagerState +import de.justjanne.libquassel.protocol.testutil.nextIgnoreRule +import de.justjanne.libquassel.protocol.variant.QVariantList +import de.justjanne.libquassel.protocol.variant.QVariantMap +import de.justjanne.libquassel.protocol.variant.qVariant +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertFalse +import org.junit.jupiter.api.Assertions.assertNotEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import kotlin.random.Random + +class IgnoreListManagerTest { + @Test + fun testEmpty() { + val actual = IgnoreListManager().apply { + update(emptyMap()) + }.state() + + assertEquals(IgnoreListManagerState(), actual) + } + + @Test + fun testInvalidData() { + val state = IgnoreListManagerState() + val actual = IgnoreListManager(state = state).apply { + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "ignoreRule" to qVariant<QStringList>(listOf(""), QtType.QStringList), + ), + QtType.QVariantMap + ) + ) + ) + } + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "isRegEx" to qVariant<QVariantList>( + listOf( + qVariant(false, QtType.Bool) + ), + QtType.QVariantList + ), + ), + QtType.QVariantMap + ) + ) + ) + } + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "strictness" to qVariant<QVariantList>( + listOf( + qVariant(StrictnessType.SoftStrictness.value, QtType.Int) + ), + QtType.QVariantList + ), + ), + QtType.QVariantMap + ) + ) + ) + } + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "isActive" to qVariant<QVariantList>( + listOf( + qVariant(false, QtType.Bool) + ), + QtType.QVariantList + ), + ), + QtType.QVariantMap + ) + ) + ) + } + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "scope" to qVariant<QVariantList>( + listOf( + qVariant(ScopeType.GlobalScope.value, QtType.Int) + ), + QtType.QVariantList + ), + ), + QtType.QVariantMap + ) + ) + ) + } + assertThrows<IllegalArgumentException> { + update( + mapOf( + "IgnoreList" to qVariant<QVariantMap>( + mapOf( + "ignoreType" to qVariant<QVariantList>(emptyList(), QtType.QVariantList), + "scopeRule" to qVariant<QStringList>(listOf(""), QtType.QStringList), + ), + QtType.QVariantMap + ) + ) + ) + } + }.state() + + assertEquals(state, actual) + } + + @Test + fun testNulLData() { + val actual = IgnoreListManager( + state = IgnoreListManagerState() + ).apply { + update( + mapOf( + "IgnoreList" to qVariant( + mapOf( + "ignoreType" to qVariant( + listOf( + qVariant(-2, QtType.Int) + ), + QtType.QVariantList + ), + "ignoreRule" to qVariant( + listOf(null), + QtType.QStringList + ), + "isRegEx" to qVariant( + listOf( + qVariant(false, QtType.Bool) + ), + QtType.QVariantList + ), + "strictness" to qVariant( + listOf( + qVariant(-2, QtType.Int) + ), + QtType.QVariantList + ), + "isActive" to qVariant( + listOf( + qVariant(false, QtType.Bool) + ), + QtType.QVariantList + ), + "scope" to qVariant( + listOf( + qVariant(-2, QtType.Int) + ), + QtType.QVariantList + ), + "scopeRule" to qVariant( + listOf( + null + ), + QtType.QStringList + ) + ), + QtType.QVariantMap + ) + ) + ) + }.state() + + assertEquals( + IgnoreRule( + type = IgnoreType.SenderIgnore, + ignoreRule = "", + isRegEx = false, + strictness = StrictnessType.UnmatchedStrictness, + isEnabled = false, + scope = ScopeType.GlobalScope, + scopeRule = "" + ), + actual.rules.first() + ) + } + + @Test + fun testSerialization() { + val random = Random(1337) + val expected = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + + val actual = IgnoreListManager( + state = IgnoreListManagerState() + ).apply { + update(IgnoreListManager(state = expected).toVariantMap()) + }.state() + + assertEquals(expected, actual) + } + + @Nested + inner class Setters { + @Test + fun testRemoveIgnoreRule() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = value.state().rules.random(random) + assertTrue(value.contains(rule.ignoreRule)) + assertNotEquals(-1, value.indexOf(rule.ignoreRule)) + value.removeIgnoreListItem(rule.ignoreRule) + assertFalse(value.contains(rule.ignoreRule)) + assertEquals(-1, value.indexOf(rule.ignoreRule)) + } + + @Test + fun testRemoveAll() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + assertFalse(value.isEmpty()) + for (rule in value.state().rules) { + println(rule) + val index = value.state().indexOf(rule.ignoreRule) + println(index) + println(value.state().rules[index]) + value.removeIgnoreListItem(rule.ignoreRule) + } + assertTrue(value.isEmpty()) + assertEquals(0, value.count()) + } + + @Test + fun testToggleHighlightRule() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = value.state().rules.random(random) + assertTrue(value.contains(rule.ignoreRule)) + assertNotEquals(-1, value.indexOf(rule.ignoreRule)) + assertTrue(value.state().rules[value.indexOf(rule.ignoreRule)].isEnabled) + value.toggleIgnoreRule(rule.ignoreRule) + assertTrue(value.contains(rule.ignoreRule)) + assertNotEquals(-1, value.indexOf(rule.ignoreRule)) + assertFalse(value.state().rules[value.indexOf(rule.ignoreRule)].isEnabled) + value.toggleIgnoreRule(rule.ignoreRule) + assertTrue(value.contains(rule.ignoreRule)) + assertNotEquals(-1, value.indexOf(rule.ignoreRule)) + assertTrue(value.state().rules[value.indexOf(rule.ignoreRule)].isEnabled) + } + + @Test + fun testAddExisting() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = value.state().rules.random(random) + val sizeBefore = value.count() + value.addIgnoreListItem( + type = rule.type.value, + ignoreRule = rule.ignoreRule, + isRegEx = rule.isRegEx, + strictness = rule.strictness.value, + scope = rule.scope.value, + scopeRule = rule.scopeRule, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore, value.count()) + } + + @Test + fun testAddNew() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = random.nextIgnoreRule() + val sizeBefore = value.count() + value.addIgnoreListItem( + type = rule.type.value, + ignoreRule = rule.ignoreRule, + isRegEx = rule.isRegEx, + strictness = rule.strictness.value, + scope = rule.scope.value, + scopeRule = rule.scopeRule, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore + 1, value.count()) + } + + @Test + fun testAddEdgeCase() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = random.nextIgnoreRule() + val sizeBefore = value.count() + value.addIgnoreListItem( + type = rule.type.value, + ignoreRule = null, + isRegEx = rule.isRegEx, + strictness = rule.strictness.value, + scope = rule.scope.value, + scopeRule = null, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore + 1, value.count()) + } + + @Test + fun testAddEdgeCaseUnchanged() { + val random = Random(1337) + val value = IgnoreListManager( + state = IgnoreListManagerState( + rules = List(random.nextInt(20)) { + random.nextIgnoreRule() + } + ) + ) + + val rule = random.nextIgnoreRule() + val sizeBefore = value.count() + value.addIgnoreListItem( + type = -2, + ignoreRule = null, + isRegEx = rule.isRegEx, + strictness = rule.strictness.value, + scope = rule.scope.value, + scopeRule = null, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore, value.count()) + value.addIgnoreListItem( + type = rule.type.value, + ignoreRule = null, + isRegEx = rule.isRegEx, + strictness = -2, + scope = rule.scope.value, + scopeRule = null, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore, value.count()) + value.addIgnoreListItem( + type = rule.type.value, + ignoreRule = null, + isRegEx = rule.isRegEx, + strictness = rule.strictness.value, + scope = -2, + scopeRule = null, + isActive = rule.isEnabled + ) + assertEquals(sizeBefore, value.count()) + } + } +} diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannelTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannelTest.kt index fb4d1e7f7b12982fa43620a2f8e3b11c183ab5d7..7616b8cb60bbe6aad4a41a741033ede53078703e 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannelTest.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/syncables/IrcChannelTest.kt @@ -10,10 +10,14 @@ package de.justjanne.libquassel.protocol.syncables import de.justjanne.libquassel.protocol.models.ids.NetworkId +import de.justjanne.libquassel.protocol.models.network.ChannelModes import de.justjanne.libquassel.protocol.syncables.state.IrcChannelState +import de.justjanne.libquassel.protocol.testutil.MockSession import de.justjanne.libquassel.protocol.testutil.nextIrcChannel +import de.justjanne.libquassel.protocol.testutil.nextNetwork import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotEquals +import org.junit.jupiter.api.Assertions.assertThrows import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test import kotlin.random.Random @@ -82,4 +86,573 @@ class IrcChannelTest { assertEquals(true, channel.isEncrypted()) } } + + @Nested + inner class AddChannelMode { + @Test + fun noSession() { + val random = Random(1337) + val channel = IrcChannel(state = random.nextIrcChannel(NetworkId(random.nextInt()))) + + val channelModes = channel.state().channelModes + channel.addChannelMode('a', value = "*!*@*") + assertEquals(channelModes, channel.state().channelModes) + } + + @Test + fun chanmodeUnknown() { + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel(session, it.value.state()) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('e', value = "*!*@*") + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + } + + @Test + fun chanmodeA() { + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel(session, it.value.state()) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('a', value = "*!*@*") + assertEquals( + mapOf( + 'a' to setOf("*!*@*") + ), + channel.state().channelModes.a + ) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('a', value = "user!ident@host") + assertEquals( + mapOf( + 'a' to setOf("*!*@*", "user!ident@host") + ), + channel.state().channelModes.a + ) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + + assertThrows(IllegalArgumentException::class.java) { + channel.addChannelMode('a', value = null) + } + } + + @Test + fun chanmodeB() { + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel(session, it.value.state()) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('b', value = "*!*@*") + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals( + mapOf( + 'b' to "*!*@*" + ), + channel.state().channelModes.b + ) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + + assertThrows(IllegalArgumentException::class.java) { + channel.addChannelMode('b', value = null) + } + } + + @Test + fun chanmodeC() { + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel(session, it.value.state()) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('c', value = "*!*@*") + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals( + mapOf( + 'c' to "*!*@*" + ), + channel.state().channelModes.c + ) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + + assertThrows(IllegalArgumentException::class.java) { + channel.addChannelMode('c', value = null) + } + } + + @Test + fun chanmodeD() { + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel(session, it.value.state()) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.supports()) + println(network.channelModes()) + println(network.session) + println(channel.session) + + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + channel.addChannelMode('d', value = "*!*@*") + assertEquals(emptyMap<Char, Set<String>>(), channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(setOf('d'), channel.state().channelModes.d) + } + } + + @Nested + inner class RemoveChannelMode { + @Test + fun noSession() { + + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2"), + 'A' to setOf("A1", "A2") + ), + b = mapOf( + 'b' to "b1", + 'B' to "B1" + ), + c = mapOf( + 'c' to "c1", + 'C' to "C1" + ), + d = setOf('d', 'D') + ) + + val random = Random(1337) + val channel = IrcChannel( + state = random.nextIrcChannel(NetworkId(random.nextInt())) + .copy(channelModes = expected) + ) + + channel.removeChannelMode('a', value = "a1") + assertEquals(expected, channel.state().channelModes) + } + + @Test + fun chanmodeUnknown() { + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2"), + 'A' to setOf("A1", "A2") + ), + b = mapOf( + 'b' to "b1", + 'B' to "B1" + ), + c = mapOf( + 'c' to "c1", + 'C' to "C1" + ), + d = setOf('d', 'D') + ) + + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "a,b,c,d" + ), + ircChannels = ircChannels.mapValues { + IrcChannel( + session, + it.value.state() + .copy(channelModes = expected) + ) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.channelModes()) + + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('e', value = "*!*@*") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + } + + @Test + fun chanmodeA() { + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2") + ), + b = mapOf( + 'b' to "b1" + ), + c = mapOf( + 'c' to "c1" + ), + d = setOf('d') + ) + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "aA,bB,cC,dD" + ), + ircChannels = ircChannels.mapValues { + IrcChannel( + session, + it.value.state() + .copy(channelModes = expected) + ) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.channelModes()) + + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('A', value = "a1") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('a', value = "a1") + assertEquals( + mapOf( + 'a' to setOf("a2"), + ), + channel.state().channelModes.a + ) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('a', value = "a1") + assertEquals( + mapOf( + 'a' to setOf("a2"), + ), + channel.state().channelModes.a + ) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + + assertThrows(IllegalArgumentException::class.java) { + channel.removeChannelMode('a', value = null) + } + } + + @Test + fun chanmodeB() { + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2") + ), + b = mapOf( + 'b' to "b1" + ), + c = mapOf( + 'c' to "c1" + ), + d = setOf('d') + ) + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "aA,bB,cC,dD" + ), + ircChannels = ircChannels.mapValues { + IrcChannel( + session, + it.value.state() + .copy(channelModes = expected) + ) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.channelModes()) + + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('B', value = "b1") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('b', value = "b1") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('b', value = "b2") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + } + + @Test + fun chanmodeC() { + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2") + ), + b = mapOf( + 'b' to "b1" + ), + c = mapOf( + 'c' to "c1" + ), + d = setOf('d') + ) + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "aA,bB,cC,dD" + ), + ircChannels = ircChannels.mapValues { + IrcChannel( + session, + it.value.state() + .copy(channelModes = expected) + ) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.channelModes()) + + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('C', value = "c1") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('c', value = "c1") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('c', value = "c2") + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(emptyMap<Char, String>(), channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + } + + @Test + fun chanmodeD() { + val expected = ChannelModes( + a = mapOf( + 'a' to setOf("a1", "a2") + ), + b = mapOf( + 'b' to "b1" + ), + c = mapOf( + 'c' to "c1" + ), + d = setOf('d') + ) + val random = Random(1337) + val session = ChannelMockSession() + val network = Network( + session, + state = random.nextNetwork(NetworkId(random.nextInt())).run { + copy( + supports = mapOf( + "CHANMODES" to "aA,bB,cC,dD" + ), + ircChannels = ircChannels.mapValues { + IrcChannel( + session, + it.value.state() + .copy(channelModes = expected) + ) + }, + ircUsers = ircUsers.mapValues { + IrcUser(session, it.value.state()) + } + ) + } + ) + session.networks.add(network) + val channel = network.state().ircChannels.values.first() + println(network.channelModes()) + + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('D') + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(expected.d, channel.state().channelModes.d) + channel.removeChannelMode('d') + assertEquals(expected.a, channel.state().channelModes.a) + assertEquals(expected.b, channel.state().channelModes.b) + assertEquals(expected.c, channel.state().channelModes.c) + assertEquals(emptySet<Char>(), channel.state().channelModes.d) + } + } + + class ChannelMockSession : MockSession() { + val networks = mutableListOf<Network>() + override fun network(id: NetworkId) = networks.find { it.networkId() == id } + } } diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt index 4575d537f3ed7f6e657039a15a10d0895a9620dc..fb29e95207f0ce659a64ebb48108927efbd4e654 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/testutil/Random.kt @@ -10,7 +10,7 @@ package de.justjanne.libquassel.protocol.testutil import de.justjanne.bitflags.of -import de.justjanne.libquassel.protocol.models.flags.BufferActivity +import de.justjanne.libquassel.protocol.models.BufferActivity import de.justjanne.libquassel.protocol.models.flags.BufferType import de.justjanne.libquassel.protocol.models.ids.BufferId import de.justjanne.libquassel.protocol.models.ids.IdentityId @@ -168,16 +168,16 @@ fun Random.nextBufferViewConfig( nextEnum() } ), - minimumActivity = BufferActivity.of(nextEnum<BufferActivity>()), + minimumActivity = nextEnum<BufferActivity>(), showSearch = nextBoolean(), - buffers = List(nextInt(20)) { - BufferId(nextInt()) - }, - removedBuffers = List(nextInt(20)) { - BufferId(nextInt()) + buffers = List(nextInt(5, 20)) { + BufferId(nextInt(0, 33)) + }.toSet().toList().shuffled(), + removedBuffers = List(nextInt(5, 20)) { + BufferId(nextInt(34, 66)) }.toSet(), - temporarilyRemovedBuffers = List(nextInt(20)) { - BufferId(nextInt()) + hiddenBuffers = List(nextInt(5, 20)) { + BufferId(nextInt(67, 100)) }.toSet() ) diff --git a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/util/collections/MoveTest.kt b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/util/collections/MoveTest.kt index ea75256ca4ebb2581101cec282481fddc64083aa..84e203a80fc5c025edf49c217fbf4d6a2b31caf4 100644 --- a/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/util/collections/MoveTest.kt +++ b/libquassel-protocol/src/test/kotlin/de/justjanne/libquassel/protocol/util/collections/MoveTest.kt @@ -51,4 +51,13 @@ class MoveTest { ) } } + + @Test + fun movesCorrectly() { + val data = listOf(1, 2, 3, 4, 5, 7).shuffled() + assertEquals( + listOf('a', 'c', 'd', 'e', 'b', 'f'), + listOf('a', 'b', 'c', 'd', 'e', 'f').move('b', 4) + ) + } }