Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions kotlinx.fuzz.api/src/main/kotlin/kotlinx/fuzz/KFuzzConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class KFuzzConfigImpl private constructor() : KFuzzConfig {
)

override fun toPropertiesMap(): Map<String, String> = configProperties()
.associate { it.systemProperty.propertyName to it.stringValue }
.associate { it.systemProperty.name to it.stringValue }

private fun assertAllSet() {
configProperties().forEach { it.assertIsSet() }
Expand Down Expand Up @@ -165,7 +165,7 @@ class KFuzzConfigImpl private constructor() : KFuzzConfig {
wrapConfigErrors {
KFuzzConfigImpl().apply {
configProperties().forEach {
val propertyKey = it.systemProperty.propertyName
val propertyKey = it.systemProperty.name
it.setFromString(
properties[propertyKey] ?: error("map missing property $propertyKey"),
)
Expand Down Expand Up @@ -208,7 +208,7 @@ internal class KFuzzConfigProperty<T : Any> internal constructor(
private val toString: (T) -> String,
private val fromString: (String) -> T,
) : ReadWriteProperty<Any, T> {
private val name: String = systemProperty.propertyName.substringAfterLast('.')
private val name: String = systemProperty.name.substringAfterLast('.')
private var cachedValue: T? = null
val stringValue: String get() = toString(get())

Expand Down
12 changes: 6 additions & 6 deletions kotlinx.fuzz.api/src/main/kotlin/kotlinx/fuzz/KFuzzer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,20 @@ interface KFuzzer {
* insufficiently long. In this case it will be shorter.
*
* @param maxLength the maximum length of the array
* @param range denotes desired range for each value. Should be a subset of [Float.MIN_VALUE, Float.MAX_VALUE].
* [Float.MIN_VALUE, Float.MAX_VALUE] by default.
* @param range denotes desired range for each value. Should be a subset of [-Float.MAX_VALUE, Float.MAX_VALUE].
* [-Float.MAX_VALUE, Float.MAX_VALUE] by default.
* @return nullable float array that has each value in given range
*/
fun floatsOrNull(maxLength: Int, range: FloatRange = Float.MIN_VALUE..Float.MAX_VALUE): FloatArray?
fun floatsOrNull(maxLength: Int, range: FloatRange = -Float.MAX_VALUE..Float.MAX_VALUE): FloatArray?

/**
* Consumes a not null double from the fuzzer input.
*
* @param range denotes desired range for resulting value. Should be a subset of [Double.MIN_VALUE, Double.MAX_VALUE].
* [Double.MIN_VALUE, Double.MAX_VALUE] by default.
* @param range denotes desired range for resulting value. Should be a subset of [-Double.MAX_VALUE, Double.MAX_VALUE].
* [-Double.MAX_VALUE, Double.MAX_VALUE] by default.
* @return double that has value in the given range
*/
fun double(range: DoubleRange = Double.MIN_VALUE..Double.MAX_VALUE): Double
fun double(range: DoubleRange = -Double.MAX_VALUE..Double.MAX_VALUE): Double

/**
* Consumes a nullable double from the fuzzer input.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package kotlinx.fuzz

enum class SystemProperty(val propertyName: String) {
enum class SystemProperty(name: String) {
CUSTOM_HOOK_EXCLUDES("kotlinx.fuzz.customHookExcludes"),
DUMP_COVERAGE("kotlinx.fuzz.dumpCoverage"),
ENGINE("kotlinx.fuzz.engine"),
Expand All @@ -18,7 +18,7 @@ enum class SystemProperty(val propertyName: String) {
WORK_DIR("kotlinx.fuzz.workDir"),
;

fun get(): String? = System.getProperty(propertyName)
fun get(): String? = System.getProperty(name)

fun get(default: String): String = System.getProperty(propertyName, default)
fun get(default: String): String = System.getProperty(name, default)
}
84 changes: 53 additions & 31 deletions kotlinx.fuzz.engine/src/main/kotlin/kotlinx/fuzz/KFuzzerImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,56 @@
}
}

private fun fitIntoRange(
value: BigDecimal,
oldMin: BigDecimal,
oldMax: BigDecimal,
newMin: BigDecimal,
newMax: BigDecimal,
): BigDecimal {
val normalized = value.subtract(oldMin, MathContext.DECIMAL128)
.divide(oldMax.subtract(oldMin, MathContext.DECIMAL128), MathContext.DECIMAL128)

return newMin.add(
normalized.multiply(newMax.subtract(newMin, MathContext.DECIMAL128), MathContext.DECIMAL128),
MathContext.DECIMAL128,
)
/**
* Fits a float number into a range. Scales full range to a given one. Note that `fitIntoDoubleRange` has the same logic
*
* @param value a number
* @param range target range
* @return a number that fits into the given range
*/
private fun fitIntoFloatRange(
value: Float,
range: FloatRange,
context: MathContext = MathContext.DECIMAL128
): Float {
if (value.isInfinite() || value.isNaN()) {
return value
}

val normalized = value.toBigDecimal().add(Float.MAX_VALUE.toBigDecimal(), context)
.divide(Float.MAX_VALUE.toBigDecimal().multiply(BigDecimal(2), context), context)

return range.start.toBigDecimal().add(
normalized.multiply(
range.endInclusive.toBigDecimal().subtract(range.start.toBigDecimal(), context), context
), context
).toFloat()
}

/**
* Fits a double number into a range. Scales full range to a given one. Note that `fitIntoFloatRange` has the same logic
*
* @param value a number
* @param range target range
* @return a number that fits into the given range
*/
private fun fitIntoDoubleRange(
value: Double,
range: DoubleRange,
context: MathContext = MathContext.DECIMAL128
): Double {
if (value.isInfinite() || value.isNaN()) {
return value
}

val normalized = value.toBigDecimal().add(Double.MAX_VALUE.toBigDecimal(), context)
.divide(Double.MAX_VALUE.toBigDecimal().multiply(BigDecimal(2), context), context)

return range.start.toBigDecimal().add(
normalized.multiply(
range.endInclusive.toBigDecimal().subtract(range.start.toBigDecimal(), context), context
), context
).toDouble()
}

/**
Expand Down Expand Up @@ -258,14 +294,7 @@

override fun float(range: FloatRange): Float {
require(range.isNotEmpty()) { "range is empty" }

return fitIntoRange(
iterator.readFloat().toBigDecimal(),
Float.MIN_VALUE.toBigDecimal(),
Float.MAX_VALUE.toBigDecimal(),
range.start.toBigDecimal(),
range.endInclusive.toBigDecimal(),
).toFloat()
return fitIntoFloatRange(iterator.readFloat(), range)
}

override fun floatOrNull(range: FloatRange): Float? {
Expand Down Expand Up @@ -298,14 +327,7 @@

override fun double(range: DoubleRange): Double {
require(range.isNotEmpty()) { "range is empty" }

return fitIntoRange(
iterator.readDouble().toBigDecimal(),
Double.MIN_VALUE.toBigDecimal(),
Double.MAX_VALUE.toBigDecimal(),
range.start.toBigDecimal(),
range.endInclusive.toBigDecimal(),
).toDouble()
return fitIntoDoubleRange(iterator.readDouble(), range)
}

override fun doubleOrNull(range: DoubleRange): Double? {
Expand Down Expand Up @@ -518,7 +540,7 @@

fun readInt(): Int =
(readByte().toInt() shl 24) or ((readByte().toInt() and 0xFF) shl 16) or
((readByte().toInt() and 0xFF) shl 8) or (readByte().toInt() and 0xFF)
((readByte().toInt() and 0xFF) shl 8) or (readByte().toInt() and 0xFF)

fun readLong(): Long = (readInt().toLong() shl 32) or (readInt().toLong() and 0xFF_FF_FF_FFL)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ abstract class KFuzzPlugin : Plugin<Project> {
systemProperties(fuzzConfig.toPropertiesMap())
for (property in SystemProperty.values()) {
property.get()?.let {
systemProperties[property.propertyName] = property.get()
systemProperties[property.name] = property.get()
}
}
}
Expand All @@ -75,10 +75,10 @@ abstract class KFuzzPlugin : Plugin<Project> {
testClassesDirs = defaultTCD
outputs.upToDateWhen { false }
doFirst {
systemProperties(fuzzConfig.toPropertiesMap() + (SystemProperty.REGRESSION.propertyName to "true"))
systemProperties(fuzzConfig.toPropertiesMap() + (SystemProperty.REGRESSION.name to "true"))
for (property in SystemProperty.values()) {
property.get()?.let {
systemProperties[property.propertyName] = property.get()
systemProperties[property.name] = property.get()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import kotlinx.fuzz.SystemProperty
import kotlinx.fuzz.addAnnotationParams
import kotlinx.fuzz.log.LoggerFacade
import kotlinx.fuzz.log.error
import java.lang.management.ManagementFactory

internal val Method.fullName: String
get() = "${this.declaringClass.name}.${this.name}"
Expand All @@ -42,6 +43,8 @@ class JazzerEngine(private val config: KFuzzConfig) : KFuzzEngine {
config.exceptionsDir.createDirectories()
}

private fun isDebugMode(): Boolean = ManagementFactory.getRuntimeMXBean().inputArguments.any { it.contains("-agentlib:jdwp") }

private fun getDebugSetup(intellijDebuggerDispatchPort: Int, method: Method): List<String> {
val port = ServerSocket(0).use { it.localPort }
Socket("127.0.0.1", intellijDebuggerDispatchPort).use { socket ->
Expand All @@ -68,9 +71,11 @@ class JazzerEngine(private val config: KFuzzConfig) : KFuzzEngine {
val methodConfig = config.addAnnotationParams(method.getAnnotation(KFuzzTest::class.java))
val propertiesList = methodConfig.toPropertiesMap().map { (property, value) -> "-D$property=$value" }

val debugOptions = SystemProperty.INTELLIJ_DEBUGGER_DISPATCH_PORT.get()?.let { port ->
getDebugSetup(port.toInt(), method)
} ?: emptyList()
val debugOptions = if (isDebugMode()) {
getDebugSetup(SystemProperty.INTELLIJ_DEBUGGER_DISPATCH_PORT.get()!!.toInt(), method)
} else {
emptyList()
}

val exitCode = ProcessBuilder(
javaCommand,
Expand Down
Loading