Skip to content

Commit

Permalink
Merge pull request #265 from MyPureCloud/release/2.6.1
Browse files Browse the repository at this point in the history
Release/2.6.1
  • Loading branch information
AfanasievAnton authored Mar 7, 2024
2 parents 62ae001 + e800bce commit 74cbbfc
Show file tree
Hide file tree
Showing 12 changed files with 137 additions and 26 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ plugins {
}

// CocoaPods requires the podspec to have a `version`.
val buildVersion = "2.6.0-rc2"
val buildVersion = "2.6.1"
val snapshot = System.getenv("SNAPSHOT_BUILD") ?: ""
version = "${buildVersion}${snapshot}"
group = "cloud.genesys"
Expand Down
4 changes: 2 additions & 2 deletions iosApp/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- transport (2.5.4)
- transport (2.6.1)

DEPENDENCIES:
- transport (from `../transport`)
Expand All @@ -9,7 +9,7 @@ EXTERNAL SOURCES:
:path: "../transport"

SPEC CHECKSUMS:
transport: 7662bf9e182ffdce4b7d2c1028c7dd25c58080c0
transport: c61966fff0c01844ba9640dd6ec99970739990cd

PODFILE CHECKSUM: 10743e43aeaf72bb49673a0e57360c028906ace5

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ class CustomAttributesStoreTest {
private val mockLogger: Log = mockk(relaxed = true)
private val logSlot = mutableListOf<() -> String>()
private val mockEventHandler = mockk<EventHandler>(relaxed = true)
private val subject: CustomAttributesStoreImpl =
private var subject: CustomAttributesStoreImpl =
CustomAttributesStoreImpl(mockLogger, mockEventHandler).also { it.maxCustomDataBytes = TestValues.MaxCustomDataBytes }

@Test
fun `when add a new customAttribute`() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap

val result = subject.add(givenCustomAttributes)

Expand All @@ -34,7 +34,12 @@ class CustomAttributesStoreTest {
assertThat(subject.get()).isEqualTo(expectedCustomAttributes)
assertThat(subject.getCustomAttributesToSend()).isEqualTo(expectedCustomAttributes)
assertThat(result).isTrue()
assertThat(logSlot[0].invoke()).isEqualTo(LogMessages.addCustomAttribute(expectedCustomAttributes, State.PENDING.name))
assertThat(logSlot[0].invoke()).isEqualTo(
LogMessages.addCustomAttribute(
expectedCustomAttributes,
State.PENDING.name
)
)
}

@Test
Expand All @@ -60,8 +65,8 @@ class CustomAttributesStoreTest {

@Test
fun `when add the same customAttribute twice`() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap

val result1 = subject.add(givenCustomAttributes)
val result2 = subject.add(givenCustomAttributes)
Expand All @@ -78,7 +83,7 @@ class CustomAttributesStoreTest {

@Test
fun `when add customAttributes with similar key but different value`() {
val initialCustomAttributes = mapOf("A" to "B")
val initialCustomAttributes = TestValues.defaultMap
val updatedCustomAttributes = mapOf("A" to "C")
val expectedCustomAttributes = mapOf("A" to "C")

Expand All @@ -92,8 +97,8 @@ class CustomAttributesStoreTest {

@Test
fun `when getCustomAttributesToSend and current state is Pending `() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap
subject.add(givenCustomAttributes)

val result = subject.getCustomAttributesToSend()
Expand All @@ -105,8 +110,8 @@ class CustomAttributesStoreTest {

@Test
fun `when getCustomAttributesToSend and current state is Sending`() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap
subject.add(givenCustomAttributes)
subject.onSending()

Expand All @@ -119,8 +124,8 @@ class CustomAttributesStoreTest {

@Test
fun `when getCustomAttributesToSend and current state is Sent`() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap
subject.add(givenCustomAttributes)
subject.onSending()
subject.onSent()
Expand All @@ -134,7 +139,7 @@ class CustomAttributesStoreTest {

@Test
fun `when getCustomAttributesToSend and current state is Error`() {
val givenCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
subject.add(givenCustomAttributes)
subject.onError()

Expand Down Expand Up @@ -170,6 +175,7 @@ class CustomAttributesStoreTest {
subject.onSessionClosed()

assertThat(subject.state).isPending()
assertThat(subject.maxCustomDataBytes).isEqualTo(MAX_CUSTOM_DATA_BYTES_UNSET)
verify { mockLogger.i(capture(logSlot)) }
assertThat(logSlot[0].invoke()).isEqualTo(LogMessages.ON_SESSION_CLOSED)
}
Expand All @@ -185,8 +191,8 @@ class CustomAttributesStoreTest {

@Test
fun `when add customAttributes and then onSessionClosed`() {
val givenCustomAttributes = mapOf("A" to "B")
val expectedCustomAttributes = mapOf("A" to "B")
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap

subject.add(givenCustomAttributes)
subject.onSessionClosed()
Expand Down Expand Up @@ -253,7 +259,7 @@ class CustomAttributesStoreTest {
)
subject.maxCustomDataBytes = 0

val result = subject.add(mapOf("A" to "B"))
val result = subject.add(TestValues.defaultMap)

assertThat(subject.get()).isEmpty()
assertThat(subject.getCustomAttributesToSend()).isEmpty()
Expand All @@ -265,4 +271,54 @@ class CustomAttributesStoreTest {
}
assertThat(logSlot[0].invoke()).isEqualTo(LogMessages.CUSTOM_ATTRIBUTES_SIZE_EXCEEDED)
}

@Test
fun `when maxCustomDataBytes was not set yet`() {
// Given
val expectedMaxCustomDataBytes = MAX_CUSTOM_DATA_BYTES_UNSET
subject = CustomAttributesStoreImpl(mockLogger, mockEventHandler)

// When
val result = subject.maxCustomDataBytes

// Then
assertThat(result).isEqualTo(expectedMaxCustomDataBytes)
}

@Test
fun `when maxCustomDataBytes is updated with valid size and ca are already added`() {
// Given
subject = CustomAttributesStoreImpl(mockLogger, mockEventHandler)
val givenMaxCustomDataBytes = TestValues.MaxCustomDataBytes
val givenCustomAttributes = TestValues.defaultMap
val expectedCustomAttributes = TestValues.defaultMap
val result = subject.add(givenCustomAttributes)
assertThat(subject.maxCustomDataBytes).isEqualTo(MAX_CUSTOM_DATA_BYTES_UNSET)
// When
subject.maxCustomDataBytes = givenMaxCustomDataBytes
// Then
verify(exactly = 0) {
mockEventHandler.onEvent(any())
}
assertThat(subject.get()).isEqualTo(expectedCustomAttributes)
assertThat(result).isTrue()
}

@Test
fun `when custom attributes are already added but are bigger than updated maxCustomDataBytes`() {
// Given
subject = CustomAttributesStoreImpl(mockLogger, mockEventHandler)
val givenMaxCustomDataBytes = TestValues.DefaultNumber
val givenCustomAttributes = TestValues.defaultMap
val result = subject.add(givenCustomAttributes)
assertThat(subject.maxCustomDataBytes).isEqualTo(MAX_CUSTOM_DATA_BYTES_UNSET)
// When
subject.maxCustomDataBytes = givenMaxCustomDataBytes
// Then
verify {
mockEventHandler.onEvent(any())
}
assertThat(subject.get()).isEmpty()
assertThat(result).isTrue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,14 @@ class JwtHandlerTest {
assertThat(exp).isEqualTo(0)
}
}

@Test
fun `when clear() after jwt was set`() {
val expectedJwtResponse = JwtResponse()
subject.jwtResponse = JwtResponse(AuthTest.JwtToken, Platform().epochMillis())

subject.clear()

assertThat(subject.jwtResponse).isEqualTo(expectedJwtResponse)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ open class BaseMessagingClientTest {
}
mockPlatformSocket.sendMessage(configureRequest)
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
mockStateChangedListener(fromConnectedToConfigured)
}
Expand All @@ -216,6 +217,7 @@ open class BaseMessagingClientTest {
mockLogger.i(capture(logSlot))
mockPlatformSocket.sendMessage(Request.configureRequest())
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
mockStateChangedListener(fromConnectedToReadOnly)
}
Expand Down Expand Up @@ -254,12 +256,14 @@ open class BaseMessagingClientTest {
mockStateChangedListener(stateChange)
mockAttachmentHandler.clearAll()
mockReconnectionHandler.clear()
mockJwtHandler.clear()
}

protected fun verifyCleanUp() {
mockMessageStore.invalidateConversationCache()
mockAttachmentHandler.clearAll()
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.onSessionClosed()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ class MCConversationDisconnectTests : BaseMessagingClientTest() {
mockPlatformSocket.sendMessage(Request.closeAllConnections)
mockStateChangedListener(fromReadOnlyToError(errorState = expectedErrorState))
mockReconnectionHandler.clear()
mockJwtHandler.clear()
}
}

Expand All @@ -247,6 +248,7 @@ class MCConversationDisconnectTests : BaseMessagingClientTest() {
mockLogger.i(capture(logSlot))
mockPlatformSocket.sendMessage(Request.closeAllConnections)
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
mockLogger.i(capture(logSlot))
verifyCleanUp()
Expand All @@ -273,6 +275,7 @@ class MCConversationDisconnectTests : BaseMessagingClientTest() {
mockLogger.i(capture(logSlot))
mockPlatformSocket.sendMessage(Request.closeAllConnections)
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
}
verify(exactly = 0) {
Expand All @@ -292,6 +295,7 @@ class MCConversationDisconnectTests : BaseMessagingClientTest() {
verifySequence {
connectSequence()
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
mockStateChangedListener(fromConfiguredToReadOnly())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class MCHealthCheckTests : BaseMessagingClientTest() {
mockLogger.i(capture(logSlot))
mockPlatformSocket.sendMessage(Request.configureRequest())
mockReconnectionHandler.clear()
mockJwtHandler.clear()
mockCustomAttributesStore.maxCustomDataBytes = TestValues.MaxCustomDataBytes
mockStateChangedListener(fromConnectedToConfigured)
mockLogger.i(capture(logSlot))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,22 @@ import com.genesys.cloud.messenger.transport.util.logs.LogMessages
import io.ktor.utils.io.charsets.Charsets
import io.ktor.utils.io.core.toByteArray

internal const val MAX_CUSTOM_DATA_BYTES_UNSET = -1

internal class CustomAttributesStoreImpl(
private val log: Log,
private val eventHandler: EventHandler,
) : CustomAttributesStore {
private var customAttributes: MutableMap<String, String> = mutableMapOf()
var maxCustomDataBytes: Int = 0
var maxCustomDataBytes: Int = MAX_CUSTOM_DATA_BYTES_UNSET
internal set(value) {
field = value
if (maxCustomDataBytes.isSet()) {
if (maybeReportFailure(customAttributes)) {
customAttributes.clear()
}
}
}

internal var state: State = State.PENDING
private set
Expand All @@ -30,10 +40,22 @@ internal class CustomAttributesStoreImpl(
}

private fun isCustomAttributesValid(customAttributes: Map<String, String>): Boolean {
if (maxCustomDataBytes.isUnset()) {
return true
}
if (customAttributes.isEmpty() || this.customAttributes == customAttributes) {
log.w { LogMessages.CUSTOM_ATTRIBUTES_EMPTY_OR_SAME }
return false
} else if (isSizeExceeded(customAttributes)) {
}
if (maybeReportFailure(customAttributes)) {
return false
}
return true
}

private fun maybeReportFailure(customAttributes: Map<String, String>): Boolean {
val isSizeExceeded = isSizeExceeded(customAttributes)
if (isSizeExceeded) {
eventHandler.onEvent(
Event.Error(
ErrorCode.CustomAttributeSizeTooLarge,
Expand All @@ -42,13 +64,13 @@ internal class CustomAttributesStoreImpl(
)
)
log.e { LogMessages.CUSTOM_ATTRIBUTES_SIZE_EXCEEDED }
return false
}
return true
return isSizeExceeded
}

private fun isSizeExceeded(attributes: Map<String, String>): Boolean {
val totalSize = attributes.entries.sumOf { (key, value) ->
val attributesToValidate = customAttributes + attributes
val totalSize = attributesToValidate.entries.sumOf { (key, value) ->
key.toByteArray(Charsets.UTF_8).size + value.toByteArray(Charsets.UTF_8).size
}
return totalSize > maxCustomDataBytes
Expand Down Expand Up @@ -86,6 +108,7 @@ internal class CustomAttributesStoreImpl(
internal fun onSessionClosed() {
log.i { LogMessages.ON_SESSION_CLOSED }
state = State.PENDING
maxCustomDataBytes = MAX_CUSTOM_DATA_BYTES_UNSET
}

internal enum class State {
Expand All @@ -95,3 +118,6 @@ internal class CustomAttributesStoreImpl(
ERROR,
}
}

private fun Int.isUnset(): Boolean = this == MAX_CUSTOM_DATA_BYTES_UNSET
private fun Int.isSet(): Boolean = this != MAX_CUSTOM_DATA_BYTES_UNSET
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ internal class JwtHandler(private val webSocket: PlatformSocket, private val tok
internal var jwtResponse: JwtResponse = JwtResponse()
set(value) {
field = value
if (field.jwt.isEmpty()) return
socketDispatcher.launch {
jwtChannel.send(field.jwt)
}
Expand All @@ -35,6 +36,10 @@ internal class JwtHandler(private val webSocket: PlatformSocket, private val tok
}
}

internal fun clear() {
jwtResponse = JwtResponse()
}

private fun fetchJwt() {
val request = JwtRequest(token)
val encodedJson = WebMessagingJson.json.encodeToString(request)
Expand Down
Loading

0 comments on commit 74cbbfc

Please sign in to comment.