Skip to content

Commit

Permalink
�Modify the way a value class is used to output arbitrary value (#967)
Browse files Browse the repository at this point in the history
  • Loading branch information
this-is-spear authored May 2, 2024
1 parent e67fbc5 commit 1c34d3a
Show file tree
Hide file tree
Showing 9 changed files with 77 additions and 31 deletions.
6 changes: 6 additions & 0 deletions docs/content/v1.0.x-kor/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ docs:
weight: 100
---

sectionStart
### v.1.0.17
Modify the way a value class is used to output arbitrary value

sectionEnd

sectionStart
### v.1.0.16
Add resolve the candidate concrete type of container type.
Expand Down
6 changes: 6 additions & 0 deletions docs/content/v1.0.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ docs:
weight: 100
---

sectionStart
### v.1.0.17
Modify the way a value class is used to output arbitrary value

sectionEnd

sectionStart
### v.1.0.16
Add resolve the candidate concrete type of container type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ import org.apiguardian.api.API
import kotlin.reflect.full.primaryConstructor
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.DurationUnit.NANOSECONDS
import kotlin.time.toDuration

private const val STORAGE_UNIT = "storageUnit"
private const val IN_WHOLE_NANOSECONDS = "inWholeNanoseconds"
private const val IN_WHOLE_MILLISECONDS = "inWholeMilliseconds"

@API(since = "1.0.15", status = API.Status.EXPERIMENTAL)
class KotlinDurationIntrospector : ArbitraryIntrospector, Matcher {
override fun match(property: Property) = DURATION_TYPE_MATCHER.match(property)
Expand All @@ -45,9 +50,15 @@ class KotlinDurationIntrospector : ArbitraryIntrospector, Matcher {
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())
val arbitrariesByPropertyName = it.mapKeys { map -> map.key.objectProperty.property.name }
val durationUnit = arbitrariesByPropertyName[STORAGE_UNIT] as DurationUnit

val value = when (durationUnit) {
NANOSECONDS -> arbitrariesByPropertyName[IN_WHOLE_NANOSECONDS] as Long
else -> arbitrariesByPropertyName[IN_WHOLE_MILLISECONDS] as Long
}

value.toDuration(durationUnit)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import kotlin.reflect.KFunction
import kotlin.reflect.KParameter
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.jvmErasure

@API(since = "0.4.0", status = MAINTAINED)
class PrimaryConstructorArbitraryIntrospector : ArbitraryIntrospector {
Expand All @@ -63,37 +62,20 @@ class PrimaryConstructorArbitraryIntrospector : ArbitraryIntrospector {
.build {
val arbitrariesByPropertyName: Map<String?, Any?> =
it.mapKeys { map -> map.key.objectProperty.property.name }

val generatedByParameters = mutableMapOf<KParameter, Any?>()

for (parameter in constructor.parameters) {
val resolvedArbitrary = resolveArbitrary(parameter, arbitrariesByPropertyName)
val resolvedArbitrary = arbitrariesByPropertyName[parameter.name]
generatedByParameters[parameter] = resolvedArbitrary
}

constructor.callBy(generatedByParameters)
},
)
}

override fun getRequiredPropertyGenerator(property: Property): PropertyGenerator = KOTLIN_PROPERTY_GENERATOR

private fun resolveArbitrary(
parameter: KParameter,
arbitrariesByPropertyName: Map<String?, Any?>,
): Any? {
return try {
val parameterKotlinType = parameter.type.jvmErasure
if (parameterKotlinType.isValue) {
parameterKotlinType.primaryConstructor!!.isAccessible = true
parameterKotlinType.primaryConstructor!!.call(arbitrariesByPropertyName[parameter.name])
} else {
arbitrariesByPropertyName[parameter.name]
}
} catch (ex: Exception) {
// omitted
null
}
}

companion object {
val INSTANCE = PrimaryConstructorArbitraryIntrospector()
private val LOGGER = LoggerFactory.getLogger(PrimaryConstructorArbitraryIntrospector::class.java)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import com.navercorp.fixturemonkey.api.property.Property
import org.apiguardian.api.API
import org.slf4j.LoggerFactory
import java.lang.reflect.AnnotatedType
import java.lang.reflect.Modifier
import java.lang.reflect.Type
import kotlin.reflect.KProperty
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.javaField
import kotlin.reflect.jvm.javaMethod

Expand All @@ -44,7 +44,8 @@ data class KPropertyProperty(
override fun getValue(instance: Any): Any? {
val javaMethod = this.kProperty.getter.javaMethod

if (javaMethod != null && Modifier.isPublic(javaMethod.modifiers)) {
if (javaMethod != null) {
this.kProperty.isAccessible = true
return this.kProperty.getter.call(instance)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import java.lang.reflect.AnnotatedType
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type
import java.lang.reflect.TypeVariable
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KParameter
import kotlin.reflect.KProperty
Expand All @@ -35,7 +36,13 @@ import kotlin.reflect.jvm.javaType

@API(since = "0.4.0", status = API.Status.INTERNAL)
fun getAnnotatedType(ownerType: AnnotatedType, kProperty: KProperty<*>): AnnotatedType {
val type = kProperty.returnType.javaType
val kClassifier = kProperty.returnType.classifier
val type = if (kClassifier is KClass<*> && kClassifier.isValue) {
kClassifier.java
} else {
kProperty.returnType.javaType
}

val annotations = mutableSetOf<Annotation>()
annotations.addAll(kProperty.findAnnotations())
annotations.addAll(kProperty.javaField?.annotations?.toList() ?: listOf())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@ 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 java.util.Random
import kotlin.time.Duration
import kotlin.time.DurationUnit
import kotlin.time.toDuration

class PrimaryConstructorArbitraryIntrospectorTest {
private val sut: FixtureMonkey = FixtureMonkey.builder()
Expand Down Expand Up @@ -76,13 +78,26 @@ class PrimaryConstructorArbitraryIntrospectorTest {
}

@Property
fun sampleDurationInContainer() {
fun sampleDurationValue() {
// when
val durationValue = sut.giveMeBuilder<DurationValue>()
.sample()

then(durationValue.duration).isNotNull()
}

@Property
fun setDurationValue() {
// given
val duration = Random().nextLong().toDuration(DurationUnit.values().random())

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

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

@Property
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,8 @@ interface InterfaceClass {
class DurationValue(
val duration: Duration = Duration.INFINITE,
)

@JvmInline
value class JvmInlineValue(
val intValue: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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 org.assertj.core.api.BDDAssertions.then
import org.junit.jupiter.api.Test

Expand All @@ -44,6 +45,18 @@ class ValueClassTest {
then(actual.foo).isNotNull
}

@Test
fun setValueClassProperty() {
class ValueClassObject(val foo: Foo)
val settingFoo = Foo("hello")

val actual: ValueClassObject = SUT.giveMeBuilder<ValueClassObject>()
.set(ValueClassObject::foo, settingFoo)
.sample()

then(actual.foo).isEqualTo(settingFoo)
}

@Test
fun valueClassPropertyFixed() {
class ValueClassObject(val foo: Foo)
Expand Down

0 comments on commit 1c34d3a

Please sign in to comment.