Skip to content

Commit b45b10c

Browse files
Merge branch 'master' into dependabot/maven/logback.version-1.5.15
2 parents b928b75 + 0778b48 commit b45b10c

File tree

26 files changed

+470
-44
lines changed

26 files changed

+470
-44
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
### Relevant Articles
2-
- [Convert a Data Class to ByteBuffer in Kotlin](https://www.baeldung.com/kotlin/convert-data-class-to-bytebuffer)
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
### Relevant Articles
2+
- Difference between "*" and "Any" in Kotlin generics - Link to be updated
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
<artifactId>core-kotlin-12</artifactId>
8+
<name>core-kotlin-12</name>
9+
<packaging>jar</packaging>
10+
11+
<parent>
12+
<groupId>com.baeldung</groupId>
13+
<artifactId>core-kotlin-modules</artifactId>
14+
<version>1.0.0-SNAPSHOT</version>
15+
</parent>
16+
17+
<build>
18+
<sourceDirectory>src/main/kotlin</sourceDirectory>
19+
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
20+
<plugins>
21+
<plugin>
22+
<groupId>org.jetbrains.kotlin</groupId>
23+
<artifactId>kotlin-maven-plugin</artifactId>
24+
<version>${kotlin.version}</version>
25+
<executions>
26+
<execution>
27+
<id>compile</id>
28+
<phase>compile</phase>
29+
<goals>
30+
<goal>compile</goal>
31+
</goals>
32+
</execution>
33+
</executions>
34+
</plugin>
35+
</plugins>
36+
</build>
37+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.baeldung.casting
2+
3+
sealed class Candy(val name: String) {
4+
override fun toString() = name
5+
}
6+
7+
object ChocolateBar: Candy("Chocolate Bar")
8+
object Lollipop : Candy("Lollipop")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.baeldung.casting
2+
3+
sealed class SpookyTrinket(val name: String) {
4+
override fun toString() = name
5+
}
6+
object FakeSpider : SpookyTrinket("Fake Spider")
7+
object VampireFang : SpookyTrinket("Vampire Fang")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.baeldung.casting
2+
3+
import kotlin.collections.MutableList
4+
import kotlin.collections.mutableListOf
5+
import kotlin.collections.firstOrNull
6+
7+
class TreatDispenser<T>(private val treats: MutableList<T> = mutableListOf()) {
8+
9+
// Dispense the first treat
10+
fun dispenseTreat(): T? {
11+
return if (treats.isNotEmpty()) treats.removeFirst() else null
12+
}
13+
14+
// Peek at the next treat without removing it
15+
fun peekNextTreat(): T? {
16+
return treats.firstOrNull()
17+
}
18+
19+
// Add a treat to the dispenser
20+
fun addTreat(treat: T) {
21+
treats.add(treat)
22+
}
23+
}
24+
25+
// Function using * (Star Projection)
26+
fun peekAtNextTreat(dispenser: TreatDispenser<*>) {
27+
val nextTreat = dispenser.peekNextTreat()
28+
println("The next treat is: $nextTreat")
29+
}
30+
31+
// Function using Any (restricted to non-nullable types)
32+
fun peekAtNextTreatAny(dispenser: TreatDispenser<Any>) {
33+
val nextTreat = dispenser.peekNextTreat()
34+
println("The next treat is: $nextTreat")
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.baeldung.casting
2+
3+
import org.junit.Test
4+
import org.junit.jupiter.api.Assertions.*
5+
6+
class TreatDispenserUnitTest {
7+
8+
@Test
9+
fun `dispenseTreat should return the first treat`() {
10+
11+
val dispenser = TreatDispenser<Candy>()
12+
dispenser.addTreat(ChocolateBar)
13+
dispenser.addTreat(Lollipop)
14+
15+
assertEquals(ChocolateBar, dispenser.dispenseTreat())
16+
assertEquals(Lollipop, dispenser.dispenseTreat())
17+
assertNull(dispenser.dispenseTreat())
18+
}
19+
20+
@Test
21+
fun `peekNextTreat should show the next treat without removing it`() {
22+
val dispenser = TreatDispenser<Candy>()
23+
dispenser.addTreat(Lollipop)
24+
25+
assertEquals(Lollipop, dispenser.peekNextTreat())
26+
assertEquals(Lollipop, dispenser.peekNextTreat())
27+
}
28+
29+
@Test
30+
fun `peekAtNextTreat using star projection works for all types`() {
31+
val candyDispenser = TreatDispenser<Candy>()
32+
candyDispenser.addTreat(ChocolateBar)
33+
34+
val trinketDispenser = TreatDispenser<SpookyTrinket>()
35+
trinketDispenser.addTreat(VampireFang)
36+
trinketDispenser.addTreat(FakeSpider)
37+
38+
// Test with Candy dispenser
39+
assertDoesNotThrow {
40+
peekAtNextTreat(candyDispenser)
41+
}
42+
43+
// Test with Trinket dispenser
44+
assertDoesNotThrow {
45+
peekAtNextTreat(trinketDispenser)
46+
}
47+
}
48+
49+
@Test
50+
fun `peekAtNextTreatAny fails for non-Any dispensers`() {
51+
val candyDispenser = TreatDispenser<Candy>()
52+
candyDispenser.addTreat(ChocolateBar)
53+
54+
// This would fail type checking, hence commented:
55+
// peekAtNextTreatAny(candyDispenser) // Error: Type mismatch
56+
57+
val anyDispenser = TreatDispenser<Any>()
58+
anyDispenser.addTreat("Surprise Treat")
59+
60+
assertDoesNotThrow {
61+
peekAtNextTreatAny(anyDispenser)
62+
}
63+
}
64+
65+
}

core-kotlin-modules/core-kotlin-6/src/test/kotlin/com/baeldung/elapsed/ElapsedTimeUnitTest.kt

-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import kotlin.time.ExperimentalTime
1010
import kotlin.time.TimedValue
1111
import kotlin.time.measureTime
1212
import kotlin.time.measureTimedValue
13-
import kotlin.time.milliseconds
1413
import kotlin.time.toDuration
1514

1615
class ElapsedTimeUnitTest {

core-kotlin-modules/core-kotlin-advanced-4/pom.xml

+17
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@
2626
<version>${kotlinx-coroutines.version}</version>
2727
<scope>test</scope>
2828
</dependency>
29+
30+
<dependency>
31+
<groupId>io.projectreactor</groupId>
32+
<artifactId>reactor-core</artifactId>
33+
<version>${reactor-core.version}</version>
34+
<scope>test</scope>
35+
</dependency>
36+
37+
<dependency>
38+
<groupId>io.projectreactor</groupId>
39+
<artifactId>reactor-test</artifactId>
40+
<scope>test</scope>
41+
<version>${reactor-core.version}</version>
42+
</dependency>
43+
2944
<dependency>
3045
<groupId>org.jetbrains.kotlin</groupId>
3146
<artifactId>kotlin-scripting-jsr223</artifactId>
@@ -55,6 +70,8 @@
5570

5671
<properties>
5772
<kotlin-scripting.version>1.8.0</kotlin-scripting.version>
73+
<kotlin.version>2.0.21</kotlin.version>
74+
<reactor-core.version>3.6.10</reactor-core.version>
5875
</properties>
5976

6077
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.baeldung.mono
2+
3+
import org.junit.jupiter.api.Assertions
4+
import org.junit.jupiter.api.Test
5+
import reactor.core.publisher.Mono
6+
import reactor.test.StepVerifier
7+
import java.util.concurrent.atomic.AtomicInteger
8+
9+
class MonoUnitTest {
10+
11+
@Test
12+
fun `mapping function is skipped for empty Mono`() {
13+
val callCount = AtomicInteger(0)
14+
val emptyMono = Mono.empty<String>()
15+
val resultMono = emptyMono.map {
16+
callCount.incrementAndGet()
17+
it.uppercase()
18+
}
19+
20+
StepVerifier.create(resultMono).verifyComplete() // No value emitted, Mono completes directly
21+
Assertions.assertEquals(0, callCount.get())
22+
}
23+
24+
@Test
25+
fun `should provide default value for empty Mono`() {
26+
val emptyMono = Mono.empty<String>()
27+
val resultMono = emptyMono.defaultIfEmpty("Default Value")
28+
StepVerifier.create(resultMono)
29+
.expectNext("Default Value")
30+
.verifyComplete()
31+
}
32+
33+
@Test
34+
fun `should not override value for non-empty Mono`() {
35+
val nonEmptyMono = Mono.just("Actual Value")
36+
val resultMono = nonEmptyMono.defaultIfEmpty("Default Value")
37+
StepVerifier.create(resultMono)
38+
.expectNext("Actual Value")
39+
.verifyComplete()
40+
}
41+
42+
@Test fun `should detect empty Mono using hasElement`() {
43+
val emptyMono = Mono.empty<String>()
44+
StepVerifier.create(emptyMono.hasElement())
45+
.expectNext(false)
46+
.verifyComplete()
47+
}
48+
49+
@Test fun `should detect non-empty Mono using hasElement`() {
50+
val nonEmptyMono = Mono.just("Hello, World!")
51+
StepVerifier.create(nonEmptyMono.hasElement())
52+
.expectNext(true)
53+
.verifyComplete()
54+
}
55+
56+
@Test
57+
fun `should provide fallback value for empty Mono`() {
58+
val emptyMono = Mono.empty<String>()
59+
val fallbackMono = emptyMono.switchIfEmpty(Mono.just("Fallback Value"))
60+
StepVerifier.create(fallbackMono)
61+
.expectNext("Fallback Value")
62+
.verifyComplete()
63+
}
64+
65+
@Test
66+
fun `should not invoke fallback for non-empty Mono`() {
67+
val nonEmptyMono = Mono.just("Hello, World!")
68+
val resultMono = nonEmptyMono.switchIfEmpty(Mono.just("Fallback Value"))
69+
StepVerifier.create(resultMono)
70+
.expectNext("Hello, World!")
71+
.verifyComplete()
72+
}
73+
}

core-kotlin-modules/core-kotlin-advanced-4/src/test/kotlin/com/baeldung/runKotlinScripts/RunKotlinScriptsIntegrationTest.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package com.baeldung.runKotlinScripts
22

33
import org.junit.jupiter.api.Assertions.assertEquals
4+
import org.junit.jupiter.api.Disabled
45
import org.junit.jupiter.api.Test
56
import java.io.File
67

7-
// requires `kotlinc` to be installed on the machine.
8+
@Disabled("Requires `kotlinc` to be installed on the machine. JAVA-42077")
89
class RunKotlinScriptsIntegrationTest {
910
@Test
1011
fun `run Kotlin script with ProcessBuilder`() {

core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/fileupload/FileUploadUnitTest.kt

+2-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import com.github.tomakehurst.wiremock.client.WireMock.matching
88
import com.github.tomakehurst.wiremock.client.WireMock.post
99
import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
1010
import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo
11+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration
1112
import com.github.tomakehurst.wiremock.junit.WireMockRule
1213
import io.ktor.client.HttpClient
1314
import io.ktor.client.engine.cio.CIO
@@ -18,16 +19,12 @@ import io.ktor.client.statement.readText
1819
import io.ktor.http.Headers
1920
import io.ktor.http.HttpHeaders
2021
import kotlinx.coroutines.runBlocking
21-
import okhttp3.Call
22-
import okhttp3.Callback
2322
import okhttp3.MediaType.Companion.toMediaTypeOrNull
2423
import okhttp3.MultipartBody
2524
import okhttp3.OkHttpClient
2625
import okhttp3.Request
2726
import okhttp3.RequestBody.Companion.asRequestBody
28-
import okhttp3.Response
2927
import okhttp3.ResponseBody
30-
import okhttp3.internal.wait
3128
import org.junit.jupiter.api.AfterEach
3229
import org.junit.jupiter.api.BeforeEach
3330
import org.junit.Rule
@@ -38,7 +35,6 @@ import retrofit2.http.Multipart
3835
import retrofit2.http.POST
3936
import retrofit2.http.Part
4037
import java.io.File
41-
import java.io.IOException
4238

4339
fun uploadFileFuel(filePath: String, uploadUrl: String) {
4440
val file = File(filePath)
@@ -112,7 +108,7 @@ fun uploadFileRetrofit(filePath: String, uploadUrl: String) {
112108
class FileUploadUnitTest {
113109
@Rule
114110
@JvmField
115-
val wireMockRule = WireMockRule(8080)
111+
val wireMockRule = WireMockRule(WireMockConfiguration.wireMockConfig().dynamicPort())
116112

117113
@BeforeEach
118114
fun startWireMock() {

core-kotlin-modules/core-kotlin-lang-3/src/test/kotlin/com/baeldung/typeCheckAndCasts/TypeCheckAndCastsUnitTest.kt

+30
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ fun doubleTheValue(obj: Any): Any =
2121
else -> "Unsupported Type Found"
2222
}
2323

24+
inline fun <reified T> Any.isType() = this is T
25+
inline fun <reified T> Any.isTypedList() = this is List<*> && all { it is T }
26+
2427
class TypeCheckAndSmartCastsUnitTest {
2528
@Test
2629
fun `given type check functions when pass an object should get expected result`() {
@@ -34,6 +37,33 @@ class TypeCheckAndSmartCastsUnitTest {
3437
assertThat(isNotString(aLong)).isTrue
3538
}
3639

40+
@Test
41+
fun `given an object when check type without generic type parameter should get expected exception`() {
42+
val aStringList: Any = listOf("string1", "string2", "string3")
43+
// assertThat(aStringList is List<String>).isTrue() // doesn't compile!!
44+
assertThat(aStringList is List<*>).isTrue
45+
}
46+
47+
@Test
48+
fun `given generic type check functions when check type with isType() should get expected incorrect result`() {
49+
val aStringList: Any = listOf("string1", "string2", "string3")
50+
assertThat(aStringList.isType<List<String>>()).isTrue
51+
52+
val anIntList: Any = listOf(1, 2, 3)
53+
assertThat(anIntList.isType<List<String>>()).isTrue //expect: false
54+
}
55+
56+
@Test
57+
fun `given generic type check functions when check type with type parameters should get expected result`() {
58+
val aStringList: Any = listOf("string1", "string2", "string3")
59+
assertThat(aStringList.isTypedList<String>()).isTrue
60+
61+
62+
val anIntList: Any = listOf(1, 2, 3)
63+
assertThat(anIntList.isTypedList<String>()).isFalse
64+
assertThat(anIntList.isTypedList<Int>()).isTrue
65+
}
66+
3767
@Test
3868
fun `given unsafe cast function when pass an object should get expected result`() {
3969
val aString: Any = "I am a String"

core-kotlin-modules/core-kotlin-strings-4/src/test/kotlin/com/baeldung/booleanValueOfKotlinEquivalent/BooleanValueOfKotlinEquivalentUnitTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ fun convertStringToBooleanUsingRegex(input: String): Boolean {
7575
}
7676

7777
fun String.toBooleanValue(): Boolean =
78-
when (this.toLowerCase()) {
78+
when (this.lowercase()) {
7979
"true" -> true
8080
else -> false
8181
}

0 commit comments

Comments
 (0)