Skip to content

Commit

Permalink
Adding unit tests to maestro-utils module (#2081)
Browse files Browse the repository at this point in the history
* test: Adding unit tests to the MaestroTimerTest class

* test: Adding unit tests to the SocketUtils class

* test: Adding unit tests to the Strings class

* test: Adding unit tests to the Collections class

* test: Adding unit tests to the DepthTracker class

* test: Adding unit tests to the Insight class

* test: Adding unit tests to the Errors class

* test: Refactoring SocketUtils unit tests

* test: Resolving commands_optional_tournee test

* test: Refactoring test about localhost address

* test: Refactoring the tests about localIp method

* chore: Adding mockk dependency
  • Loading branch information
Matheeusb authored Oct 15, 2024
1 parent ab9e87c commit 40b01f7
Show file tree
Hide file tree
Showing 9 changed files with 379 additions and 0 deletions.
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ junit = "5.10.2"
kotlin = "1.8.22"
kotlinResult = "1.1.18"
ktor = "2.3.6"
mockk = "1.12.0"
mozillaRhino = "1.7.14"
picocli = "4.6.3"
selenium = "4.13.0"
Expand Down Expand Up @@ -100,6 +101,7 @@ ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-server-cors = { module = "io.ktor:ktor-server-cors", version.ref = "ktor" }
ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
ktor-server-status-pages = { module = "io.ktor:ktor-server-status-pages", version.ref = "ktor" }
mockk = { module = "io.mockk:mockk", version.ref = "mockk" }
mozilla-rhino = { module = "org.mozilla:rhino", version.ref = "mozillaRhino" }
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
picocli-codegen = { module = "info.picocli:picocli-codegen", version.ref = "picocli" }
Expand Down
1 change: 1 addition & 0 deletions maestro-utils/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ plugins {
dependencies {
api(libs.square.okio)

testImplementation(libs.mockk)
testImplementation(libs.junit.jupiter.api)
testRuntimeOnly(libs.junit.jupiter.engine)
testImplementation(libs.google.truth)
Expand Down
61 changes: 61 additions & 0 deletions maestro-utils/src/test/kotlin/CollectionsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import maestro.utils.isRegularFile
import maestro.utils.isSingleFile
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.nio.file.Files

class CollectionsTest {

@Test
fun `isSingleFile should return true for a single regular file`() {
val file = Files.createTempFile("testFile", ".txt").toFile()
val files = listOf(file)
assertTrue(files.isSingleFile)
file.delete()
}

@Test
fun `isSingleFile should return false for multiple files`() {
val file1 = Files.createTempFile("testFile1", ".txt").toFile()
val file2 = Files.createTempFile("testFile2", ".txt").toFile()
val files = listOf(file1, file2)
assertFalse(files.isSingleFile)
file1.delete()
file2.delete()
}

@Test
fun `isSingleFile should return false for a single directory`() {
val dir = Files.createTempDirectory("testDir").toFile()
val files = listOf(dir)
assertFalse(files.isSingleFile)
dir.delete()
}

@Test
fun `isRegularFile should return true for a single regular file`() {
val file = Files.createTempFile("testFile", ".txt")
val paths = listOf(file)
assertTrue(paths.isRegularFile)
Files.delete(file)
}

@Test
fun `isRegularFile should return false for multiple files`() {
val file1 = Files.createTempFile("testFile1", ".txt")
val file2 = Files.createTempFile("testFile2", ".txt")
val paths = listOf(file1, file2)
assertFalse(paths.isRegularFile)
Files.delete(file1)
Files.delete(file2)
}

@Test
fun `isRegularFile should return false for a single directory`() {
val dir = Files.createTempDirectory("testDir")
val paths = listOf(dir)
assertFalse(paths.isRegularFile)
Files.delete(dir)
}
}
27 changes: 27 additions & 0 deletions maestro-utils/src/test/kotlin/DepthTrackerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import maestro.utils.DepthTracker
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

class DepthTrackerTest {

@BeforeEach
fun setUp() {
DepthTracker.trackDepth(0)
}

@Test
fun `trackDepth should update currentDepth and maxDepth`() {
DepthTracker.trackDepth(10)
assertEquals(10, DepthTracker.getMaxDepth())
}

@Test
fun `getMaxDepth should return the maximum depth tracked`() {
DepthTracker.trackDepth(3)
DepthTracker.trackDepth(2)
DepthTracker.trackDepth(5)

assertEquals(5, DepthTracker.getMaxDepth())
}
}
43 changes: 43 additions & 0 deletions maestro-utils/src/test/kotlin/InsightTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import maestro.utils.Insight
import maestro.utils.Insights
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test

class InsightsTest {

@Test
fun `report should update insight and notify listeners`() {
val insight = Insight("Test message", Insight.Level.INFO)
var notifiedInsight: Insight? = null

Insights.onInsightsUpdated { notifiedInsight = it }
Insights.report(insight)

assertEquals(insight, notifiedInsight)
}

@Test
fun `onInsightsUpdated should add a listener`() {
val insight = Insight("Test message", Insight.Level.INFO)
var notified = false

Insights.onInsightsUpdated { notified = true }
Insights.report(insight)

assertTrue(notified)
}

@Test
fun `unregisterListener should remove a listener`() {
val insight = Insight("Test message", Insight.Level.INFO)
var notified = false
val listener: (Insight) -> Unit = { notified = true }

Insights.onInsightsUpdated(listener)
Insights.unregisterListener(listener)
Insights.report(insight)

assertTrue(!notified)
}
}
70 changes: 70 additions & 0 deletions maestro-utils/src/test/kotlin/MaestroTimerTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import maestro.utils.MaestroTimer
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

class MaestroTimerTest {

@BeforeEach
fun setUp() {
MaestroTimer.setTimerFunc { _, ms -> Thread.sleep(ms) }
}

@Test
fun `withTimeout should return result within timeout`() {
val result = MaestroTimer.withTimeout(1000) {
"Success"
}

assertEquals("Success", result)
}

@Test
fun `withTimeout should return null if body is null`() {
val result = MaestroTimer.withTimeout(1000) {
null
}

assertNull(result)
}

@Test
fun `retryUntilTrue should return true if block succeeds within timeout`() {
val result = MaestroTimer.retryUntilTrue(1000) {
true
}

assertTrue(result)
}

@Test
fun `retryUntilTrue should return false if block fails within timeout`() {
val result = MaestroTimer.retryUntilTrue(100) {
false
}

assertFalse(result)
}

@Test
fun `retryUntilTrue should handle exceptions and continue retrying`() {
var attempts = 0
val result = MaestroTimer.retryUntilTrue(1000, 100, { }) {
attempts++
if (attempts < 3) throw Exception("Test exception")
true
}

assertTrue(result)
assertEquals(3, attempts)
}

@Test
fun `setTimerFunc should change the sleep function`() {
var sleepCalled = false
MaestroTimer.setTimerFunc { _, _ -> sleepCalled = true }
MaestroTimer.sleep(MaestroTimer.Reason.BUFFER, 100)

assertTrue(sleepCalled)
}
}
55 changes: 55 additions & 0 deletions maestro-utils/src/test/kotlin/SocketUtilsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import io.mockk.every
import io.mockk.mockkStatic
import maestro.utils.SocketUtils
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import java.net.Inet4Address
import java.net.InetAddress
import java.net.NetworkInterface
import java.util.*

class SocketUtilsTest {

private fun <T> List<T>.toEnumeration(): Enumeration<T> = Collections.enumeration(this)

@Test
fun `nextFreePort should return a free port within the specified range`() {
val from = 5000
val to = 5100
val port = SocketUtils.nextFreePort(from, to)

assertTrue(port in from..to)
}

@Test
fun `nextFreePort should throw IllegalStateException when no ports are available in the range`() {
val from = 100000
val to = 100010

assertThrows(IllegalStateException::class.java) {
SocketUtils.nextFreePort(from, to)
}
}

@Test
fun `localIp should return local IP address`() {
val ip = SocketUtils.localIp()

assertNotNull(ip)
assertTrue(ip.startsWith("192") || ip.startsWith("10") || ip.startsWith("172") || ip.startsWith("127"))
assertTrue(InetAddress.getByName(ip) is Inet4Address)
}

@Test
fun `localIp should return localhost address if no network interfaces are available`() {
mockkStatic(NetworkInterface::class)
every { NetworkInterface.getNetworkInterfaces() } returns listOf<NetworkInterface>().toEnumeration()

val ip = SocketUtils.localIp()

assertEquals(InetAddress.getLocalHost().hostAddress, ip)
}
}
42 changes: 42 additions & 0 deletions maestro-utils/src/test/kotlin/StringsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import maestro.utils.chunkStringByWordCount
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test

class StringsTest {

@Test
fun `chunkStringByWordCount should return empty list for empty string`() {
val result = "".chunkStringByWordCount(2)
assertEquals(emptyList<String>(), result)
}

@Test
fun `chunkStringByWordCount should return single chunk for string with fewer words than chunk size`() {
val result = "hello world".chunkStringByWordCount(3)
assertEquals(listOf("hello world"), result)
}

@Test
fun `chunkStringByWordCount should return multiple chunks for string with more words than chunk size`() {
val result = "hello world this is a test".chunkStringByWordCount(2)
assertEquals(listOf("hello world", "this is", "a test"), result)
}

@Test
fun `chunkStringByWordCount should handle exact chunk size`() {
val result = "hello world this is a test".chunkStringByWordCount(5)
assertEquals(listOf("hello world this is a", "test"), result)
}

@Test
fun `chunkStringByWordCount should handle trailing spaces`() {
val result = " hello world ".chunkStringByWordCount(1)
assertEquals(listOf("hello", "world"), result)
}

@Test
fun `chunkStringByWordCount should handle multiple spaces between words`() {
val result = "hello world this is a test".chunkStringByWordCount(2)
assertEquals(listOf("hello world", "this is", "a test"), result)
}
}
Loading

0 comments on commit 40b01f7

Please sign in to comment.