fix: allow setting empty strings with TestElement.set(...) API, and remove properties only in case the value is null

This commit is contained in:
Vladimir Sitnikov 2023-12-19 20:33:13 +03:00
parent 73b255962e
commit ef82a00cad
3 changed files with 137 additions and 14 deletions

View File

@ -285,13 +285,13 @@ public interface TestElement : Cloneable {
getPropertyOrNull(property)?.stringValue ?: property.defaultValueAsString ?: "" getPropertyOrNull(property)?.stringValue ?: property.defaultValueAsString ?: ""
/** /**
* Set property as string, or remove it if the given value is `null` or empty. * Set property as string, or remove it if the given value is `null`.
* @since 5.6 * @since 5.6
*/ */
@JMeterPropertySchemaUnchecked @JMeterPropertySchemaUnchecked
@API(status = API.Status.EXPERIMENTAL, since = "5.6") @API(status = API.Status.EXPERIMENTAL, since = "5.6")
public operator fun set(property: PropertyDescriptor<*, *>, value: String?) { public operator fun set(property: PropertyDescriptor<*, *>, value: String?) {
removeOrSet(value.isNullOrEmpty(), property.name) { removeOrSet(value == null, property.name) {
StringProperty(it, value) StringProperty(it, value)
} }
} }

View File

@ -84,7 +84,7 @@ public class PropertiesAccessor<out TestElementClass : TestElement, out Schema :
} }
// All properties can be set as strings // All properties can be set as strings
public operator fun set(property: PropertyDescriptor<Schema, *>, value: String) { public operator fun set(property: PropertyDescriptor<Schema, *>, value: String?) {
target[property] = value target[property] = value
} }
@ -116,13 +116,13 @@ public class PropertiesAccessor<out TestElementClass : TestElement, out Schema :
public inline operator fun get(propertySelector: Schema.() -> BooleanPropertyDescriptor<Schema>): Boolean = public inline operator fun get(propertySelector: Schema.() -> BooleanPropertyDescriptor<Schema>): Boolean =
target[propertySelector(schema)] target[propertySelector(schema)]
public operator fun set(property: BooleanPropertyDescriptor<Schema>, value: Boolean) { public operator fun set(property: BooleanPropertyDescriptor<Schema>, value: Boolean?) {
target[property] = value target[property] = value
} }
public inline operator fun set( public inline operator fun set(
propertySelector: Schema.() -> BooleanPropertyDescriptor<Schema>, propertySelector: Schema.() -> BooleanPropertyDescriptor<Schema>,
value: Boolean value: Boolean?
) { ) {
target[propertySelector(schema)] = value target[propertySelector(schema)] = value
} }

View File

@ -29,10 +29,14 @@ import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
class JMeterElementSchemaTest { class JMeterElementSchemaTest {
val warpDrive = WarpDriveElement()
abstract class WarpDriveElementSchema : TestElementSchema() { abstract class WarpDriveElementSchema : TestElementSchema() {
companion object INSTANCE : WarpDriveElementSchema() companion object INSTANCE : WarpDriveElementSchema()
val warpFactor by int("WarpDriveElement.warpFactor", default = 7) val warpFactor by int("WarpDriveElement.warpFactor", default = 7)
val turbo by boolean("WarpDriveElement.turbo")
val description by string("WarpDriveElement.description")
} }
open class WarpDriveElement : AbstractTestElement() { open class WarpDriveElement : AbstractTestElement() {
@ -44,7 +48,16 @@ class JMeterElementSchemaTest {
@Test @Test
fun `getPropertyOrNull returns null for unset props`() { fun `getPropertyOrNull returns null for unset props`() {
val warpDrive = WarpDriveElement() assertGetWarpDescription(
null,
warpDrive,
"${WarpDriveElementSchema.warpFactor} should be null for newly created element"
)
assertGetWarpTurbo(
null,
warpDrive,
"${WarpDriveElementSchema.warpFactor} should be null for newly created element"
)
assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.warpFactor)) { assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.warpFactor)) {
"${WarpDriveElementSchema.warpFactor} should be null for newly created element, getPropertyOrNull(PropertyDescriptor)" "${WarpDriveElementSchema.warpFactor} should be null for newly created element, getPropertyOrNull(PropertyDescriptor)"
} }
@ -54,22 +67,19 @@ class JMeterElementSchemaTest {
} }
@Test @Test
fun `get returns default value`() { fun `get int returns default value`() {
val warpDrive = WarpDriveElement()
assertGetWarpFactor(7, warpDrive, "element is empty, so default value expected") assertGetWarpFactor(7, warpDrive, "element is empty, so default value expected")
} }
@Test @Test
fun `set modifies value`() { fun `set int modifies value`() {
val warpDrive = WarpDriveElement()
warpDrive[warpDrive.schema.warpFactor] = 8 warpDrive[warpDrive.schema.warpFactor] = 8
assertGetWarpFactor(8, warpDrive, "value was modified with [warpFactor] = 8") assertGetWarpFactor(8, warpDrive, "value was modified with [warpFactor] = 8")
} }
@Test @Test
fun `props set modifies value`() { fun `props set int modifies value`() {
val warpDrive = WarpDriveElement()
warpDrive.props { warpDrive.props {
it[warpFactor] = 8 it[warpFactor] = 8
} }
@ -77,6 +87,74 @@ class JMeterElementSchemaTest {
assertGetWarpFactor(8, warpDrive, "value was modified with props { it[warpFactor] = 8 }") assertGetWarpFactor(8, warpDrive, "value was modified with props { it[warpFactor] = 8 }")
} }
@Test
fun `set string modifies value`() {
var value = "new description"
warpDrive[warpDrive.schema.description] = value
assertGetWarpDescription(value, warpDrive, "value was modified with [description] = \"$value\"")
value = ""
warpDrive[warpDrive.schema.description] = value
assertGetWarpDescription(value, warpDrive, "value was modified with [description] = \"$value\"")
warpDrive[warpDrive.schema.description] = null
assertGetWarpDescription(null, warpDrive, "value should be removed after [description] = null")
}
@Test
fun `props set string modifies value`() {
var value = "new description"
warpDrive.props {
it[description] = value
}
assertGetWarpDescription(value, warpDrive, "value was modified with props { it[description] = \"$value\" }")
value = ""
warpDrive.props {
it[description] = value
}
assertGetWarpDescription(value, warpDrive, "value was modified with props { it[description] = \"$value\" }")
warpDrive.props {
it[description] = null
}
assertGetWarpDescription(null, warpDrive, "value should be removed after props { it[description] = null }")
}
@Test
fun `set boolean modifies value`() {
var value = true
warpDrive[warpDrive.schema.turbo] = value
assertGetWarpTurbo(value, warpDrive, "value was modified with [turbo] = \"$value\"")
value = false
warpDrive[warpDrive.schema.turbo] = value
assertGetWarpTurbo(value, warpDrive, "value was modified with [turbo] = \"$value\"")
warpDrive[warpDrive.schema.turbo] = null as Boolean?
assertGetWarpTurbo(null, warpDrive, "value should be removed after [turbo] = null")
}
@Test
fun `props set boolean modifies value`() {
var value = true
warpDrive.props {
it[turbo] = value
}
assertGetWarpTurbo(value, warpDrive, "value was modified with props { it[turbo] = \"$value\" }")
value = false
warpDrive.props {
it[turbo] = value
}
assertGetWarpTurbo(value, warpDrive, "value was modified with props { it[turbo] = \"$value\" }")
warpDrive.props {
it[turbo] = null as Boolean?
}
assertGetWarpTurbo(null, warpDrive, "value should be removed after props { it[turbo] = null }")
}
@Test @Test
fun `property descriptor equals`() { fun `property descriptor equals`() {
assertEquals(TestElementSchema.name, ThreadGroupSchema.name) { assertEquals(TestElementSchema.name, ThreadGroupSchema.name) {
@ -90,7 +168,6 @@ class JMeterElementSchemaTest {
@Test @Test
fun `test string setter`() { fun `test string setter`() {
val warpDrive = WarpDriveElement()
warpDrive.props { warpDrive.props {
it[warpFactor] = "\${hello}" it[warpFactor] = "\${hello}"
} }
@ -103,7 +180,7 @@ class JMeterElementSchemaTest {
assertEquals(expected, warpDrive[warpDrive.schema.warpFactor]) { assertEquals(expected, warpDrive[warpDrive.schema.warpFactor]) {
"get(warpFactor): ${WarpDriveElementSchema.warpFactor}, $message" "get(warpFactor): ${WarpDriveElementSchema.warpFactor}, $message"
} }
assertEquals(expected, warpDrive.props[ { warpDrive.schema.warpFactor }]) { assertEquals(expected, warpDrive.props[ { warpFactor }]) {
"props.get[{warpFactor}]: ${WarpDriveElementSchema.warpFactor}, $message" "props.get[{warpFactor}]: ${WarpDriveElementSchema.warpFactor}, $message"
} }
assertEquals(expected.toString(), warpDrive.getString(warpDrive.schema.warpFactor)) { assertEquals(expected.toString(), warpDrive.getString(warpDrive.schema.warpFactor)) {
@ -111,6 +188,52 @@ class JMeterElementSchemaTest {
} }
} }
private fun assertGetWarpDescription(expected: String?, warpDrive: WarpDriveElement, message: String) {
assertEquals(expected ?: "", warpDrive[warpDrive.schema.description]) {
"get(description): ${WarpDriveElementSchema.description}, $message"
}
assertEquals(expected ?: "", warpDrive.props[ { description }]) {
"props.get[{description}]: ${WarpDriveElementSchema.description}, $message"
}
assertEquals(expected ?: "", warpDrive.getString(warpDrive.schema.description)) {
"getString(description): ${WarpDriveElementSchema.description}, $message"
}
assertEquals(expected ?: "", warpDrive.getPropertyAsString(warpDrive.schema.description.name)) {
"getPropertyAsString(description): ${WarpDriveElementSchema.description}, $message"
}
if (expected == null) {
assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.description)) {
"getPropertyOrNull(description) should return null for absent property, ${WarpDriveElementSchema.description}, $message"
}
assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.description.name)) {
"getPropertyOrNull(description.name) should return null for absent property, ${WarpDriveElementSchema.description}, $message"
}
}
}
private fun assertGetWarpTurbo(expected: Boolean?, warpDrive: WarpDriveElement, message: String) {
assertEquals(expected ?: false, warpDrive[warpDrive.schema.turbo]) {
"get(turbo): ${WarpDriveElementSchema.turbo}, $message"
}
assertEquals(expected ?: false, warpDrive.props[ { turbo }]) {
"props.get[{turbo}]: ${WarpDriveElementSchema.turbo}, $message"
}
assertEquals((expected ?: false).toString(), warpDrive.getString(warpDrive.schema.turbo)) {
"getString(turbo): ${WarpDriveElementSchema.turbo}, $message"
}
assertEquals(expected?.toString() ?: "", warpDrive.getPropertyAsString(warpDrive.schema.turbo.name)) {
"getPropertyAsString(turbo): ${WarpDriveElementSchema.turbo}, $message"
}
if (expected == null) {
assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.turbo)) {
"getPropertyOrNull(turbo) should return null for absent property, ${WarpDriveElementSchema.turbo}, $message"
}
assertNull(warpDrive.getPropertyOrNull(warpDrive.schema.turbo.name)) {
"getPropertyOrNull(turbo.name) should return null for absent property, ${WarpDriveElementSchema.turbo}, $message"
}
}
}
@Suppress("UNUSED_VARIABLE", "ReplaceGetOrSet") @Suppress("UNUSED_VARIABLE", "ReplaceGetOrSet")
fun `compilation succeeds`() { fun `compilation succeeds`() {
// Below code does not make much sense, and it tests different styles of using the properties // Below code does not make much sense, and it tests different styles of using the properties