Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding unit tests to maestro-utils module #2081

Merged
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
Loading