Skip to content

Commit

Permalink
Support generating kotlin.time.Duration (#929)
Browse files Browse the repository at this point in the history
  • Loading branch information
this-is-spear authored and seongahjo committed Mar 28, 2024
1 parent 8a8c678 commit faee18c
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ import com.navercorp.fixturemonkey.kotlin.generator.PairDecomposedContainerValue
import com.navercorp.fixturemonkey.kotlin.generator.TripleContainerPropertyGenerator
import com.navercorp.fixturemonkey.kotlin.generator.TripleDecomposedContainerValueFactory
import com.navercorp.fixturemonkey.kotlin.instantiator.KotlinInstantiatorProcessor
import com.navercorp.fixturemonkey.kotlin.introspector.KotlinDurationIntrospector
import com.navercorp.fixturemonkey.kotlin.introspector.PairIntrospector
import com.navercorp.fixturemonkey.kotlin.introspector.PrimaryConstructorArbitraryIntrospector
import com.navercorp.fixturemonkey.kotlin.introspector.TripleIntrospector
import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.DURATION_TYPE_MATCHER
import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.PAIR_TYPE_MATCHER
import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.TRIPLE_TYPE_MATCHER
import com.navercorp.fixturemonkey.kotlin.property.KotlinPropertyGenerator
Expand Down Expand Up @@ -66,6 +68,10 @@ class KotlinPlugin : Plugin {
InterfaceKFunctionPropertyGenerator(),
),
)
.insertFirstArbitraryIntrospector(
DURATION_TYPE_MATCHER,
KotlinDurationIntrospector(),
)
.insertFirstArbitraryContainerPropertyGenerator(
PAIR_TYPE_MATCHER,
PairContainerPropertyGenerator(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Fixture Monkey
*
* Copyright (c) 2021-present NAVER Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.navercorp.fixturemonkey.kotlin.introspector

import com.navercorp.fixturemonkey.api.arbitrary.CombinableArbitrary
import com.navercorp.fixturemonkey.api.generator.ArbitraryGeneratorContext
import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospector
import com.navercorp.fixturemonkey.api.introspector.ArbitraryIntrospectorResult
import com.navercorp.fixturemonkey.api.matcher.Matcher
import com.navercorp.fixturemonkey.api.property.Property
import com.navercorp.fixturemonkey.kotlin.matcher.Matchers.DURATION_TYPE_MATCHER
import org.apiguardian.api.API
import kotlin.reflect.full.primaryConstructor
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.toDuration

@API(since = "1.0.15", status = API.Status.EXPERIMENTAL)
class KotlinDurationIntrospector : ArbitraryIntrospector, Matcher {
override fun match(property: Property) = DURATION_TYPE_MATCHER.match(property)

override fun introspect(context: ArbitraryGeneratorContext): ArbitraryIntrospectorResult {
val kClass = Duration::class
val primaryConstructor = kClass.primaryConstructor!!

require(primaryConstructor.parameters.size == 1) { "Duration class must have only one parameter" }

return ArbitraryIntrospectorResult(
CombinableArbitrary.objectBuilder()
.properties(context.combinableArbitrariesByArbitraryProperty)
.build {
val parameterName = primaryConstructor.parameters[0].name
val parameterValue = it.mapKeys { map -> map.key.objectProperty.property.name }[parameterName] as Long
parameterValue.toDuration(DurationUnit.values().random())
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@ class PrimaryConstructorArbitraryIntrospector : ArbitraryIntrospector {
parameter: KParameter,
arbitrariesByPropertyName: Map<String?, Any?>,
): Any? {
try {
return try {
val parameterKotlinType = parameter.type.jvmErasure
return if (parameterKotlinType.isValue) {
if (parameterKotlinType.isValue) {
parameterKotlinType.primaryConstructor!!.isAccessible = true
parameterKotlinType.primaryConstructor!!.call(arbitrariesByPropertyName[parameter.name])
} else {
arbitrariesByPropertyName[parameter.name]
}
} catch (ex: Exception) {
// omitted
return arbitrariesByPropertyName[parameter.name]
null
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package com.navercorp.fixturemonkey.kotlin.matcher
import com.navercorp.fixturemonkey.api.matcher.AssignableTypeMatcher
import com.navercorp.fixturemonkey.api.matcher.DoubleGenericTypeMatcher
import com.navercorp.fixturemonkey.api.matcher.TripleGenericTypeMatcher
import kotlin.time.Duration

object Matchers {
val PAIR_TYPE_MATCHER = AssignableTypeMatcher(Pair::class.java).intersect(DoubleGenericTypeMatcher())

val TRIPLE_TYPE_MATCHER = AssignableTypeMatcher(Triple::class.java).intersect(TripleGenericTypeMatcher())

val DURATION_TYPE_MATCHER = AssignableTypeMatcher(Duration::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ package com.navercorp.fixturemonkey.kotlin.test

import com.navercorp.fixturemonkey.FixtureMonkey
import com.navercorp.fixturemonkey.kotlin.KotlinPlugin
import com.navercorp.fixturemonkey.kotlin.giveMeBuilder
import com.navercorp.fixturemonkey.kotlin.giveMeOne
import com.navercorp.fixturemonkey.kotlin.set
import net.jqwik.api.Arbitraries
import net.jqwik.api.Property
import org.assertj.core.api.BDDAssertions.then
import org.assertj.core.api.BDDAssertions.thenNoException
import org.junit.jupiter.api.assertAll
import kotlin.time.Duration

class PrimaryConstructorArbitraryIntrospectorTest {
private val sut: FixtureMonkey = FixtureMonkey.builder()
Expand Down Expand Up @@ -63,6 +68,34 @@ class PrimaryConstructorArbitraryIntrospectorTest {
then(actual).isNotEqualTo("default_value")
}

@Property
fun sampleDuration() {
// when
val duration = sut.giveMeOne<Duration>()
then(duration).isNotNull()
}

@Property
fun sampleDurationInContainer() {
// when
val one = sut.giveMeBuilder<DurationValue>()
.set(DurationValue::duration, Arbitraries.longs().between(Long.MIN_VALUE, 0))
.sample()

then(one.duration).isNotEqualTo(Duration.INFINITE)
}

@Property
fun sampleGenericDuration() {
// when
val one = sut.giveMeOne<List<Duration>>()

assertAll(
{ one.forEach { then(it).isNotNull() } },
{ then(one.size).isGreaterThanOrEqualTo(0) }
)
}

@Property
fun sampleSecondaryConstructor() {
// when
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package com.navercorp.fixturemonkey.kotlin.test

import kotlin.time.Duration

class PrimaryConstructor(
val intValue: Int,
val stringValue: String,
Expand Down Expand Up @@ -59,3 +61,7 @@ class SecondaryConstructor(
interface InterfaceClass {
fun test()
}

class DurationValue(
val duration: Duration = Duration.INFINITE,
)

0 comments on commit faee18c

Please sign in to comment.