Skip to content
Permalink
Browse files

Tweaking override

  • Loading branch information...
sksamuel committed Sep 4, 2019
1 parent 2243d42 commit 18577f8678ff835d70ca6484219f3319f4f2f024
@@ -3,7 +3,7 @@ root = true
[*]

indent_style = space
indent_size = 3
indent_size = 2
max_line_length = 120

trim_trailing_whitespace = true
@@ -2,59 +2,60 @@ package io.kotlintest.extensions.system

sealed class OverrideMode {

@PublishedApi
internal abstract fun override(originalValues: Map<String, String>, newValues: Map<String, String?>): MutableMap<String, String>

/**
* Sets specific values and overrides pre-existent ones, if any
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrOverride : OverrideMode() {
override fun override(originalValues: Map<String, String>, newValues: Map<String, String?>) =
originalValues.toMutableMap().apply { putReplacingNulls(newValues) }
}

/**
* Sets specific values, ignoring pre-existent ones, if any
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrIgnore : OverrideMode() {
override fun override(originalValues: Map<String, String>, newValues: Map<String, String?>) =
originalValues.toMutableMap().apply { putWithoutReplacements(newValues) }

private fun MutableMap<String, String>.putWithoutReplacements(map: Map<String, String?>) {
map.forEach { (key, value) ->
value?.let { this.putIfAbsent(key, it) }
}
}
}

/**
* Sets specific values and throws an exception if the chosen key already exists
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrError : OverrideMode() {
override fun override(originalValues: Map<String, String>, newValues: Map<String, String?>): MutableMap<String, String> {
val keysToForbidOverride = originalValues.keys

return if (newValues.keys.any { it in keysToForbidOverride }) {
throw IllegalOverrideException()
} else {
SetOrOverride.override(originalValues, newValues)
abstract fun override(originalValues: Map<String, String>,
newValues: Map<String, String?>): MutableMap<String, String>

/**
* Sets specific values and overrides pre-existent ones, if any
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrOverride : OverrideMode() {
override fun override(originalValues: Map<String, String>, newValues: Map<String, String?>) =
originalValues.toMutableMap().apply { putReplacingNulls(newValues) }
}

/**
* Sets specific values, ignoring pre-existent ones, if any
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrIgnore : OverrideMode() {
override fun override(originalValues: Map<String, String>, newValues: Map<String, String?>) =
originalValues.toMutableMap().apply { putWithoutReplacements(newValues) }

private fun MutableMap<String, String>.putWithoutReplacements(map: Map<String, String?>) {
map.forEach { (key, value) ->
value?.let { this.putIfAbsent(key, it) }
}
}
}

/**
* Sets specific values and throws an exception if the chosen key already exists
*
* Any values that are not present in the overrides will be left untouched.
*/
object SetOrError : OverrideMode() {
override fun override(originalValues: Map<String, String>,
newValues: Map<String, String?>): MutableMap<String, String> {
val keysToForbidOverride = originalValues.keys

return if (newValues.keys.any { it in keysToForbidOverride }) {
throw IllegalOverrideException()
} else {
SetOrOverride.override(originalValues, newValues)
}

}
}

class IllegalOverrideException : IllegalArgumentException("Overriding a variable when mode is set to SetOrError. Use another OverrideMode to allow this.")
}
class IllegalOverrideException : IllegalArgumentException("Overriding a variable when mode is set to SetOrError. Use another OverrideMode to allow this.")
}
}

@PublishedApi
internal fun MutableMap<String, String>.putReplacingNulls(map: Map<String, String?>) {
map.forEach { (key, value) ->
if (value == null) remove(key) else put(key, value)
}
map.forEach { (key, value) ->
if (value == null) remove(key) else put(key, value)
}
}
@@ -15,7 +15,7 @@ class OverrideModeTest : WordSpec() {

init {

"SetOrOverride" should {
"SetOrOverride" should {
val mode = SetOrOverride

"Set value if not already set" {
@@ -10,66 +10,66 @@ import io.kotlintest.specs.StringSpec
import java.security.Permission

class SecurityManagerExtensionFunctionTests : StringSpec() {

init {
"Should reset the security manager after execution" {
val originalSecurityManager = System.getSecurityManager()

withSecurityManager(MySecurityManager) { }

System.getSecurityManager() shouldBeSameInstanceAs originalSecurityManager
}

"Should reset the security manager even if there's an exception" {
val originalSecurityManager = System.getSecurityManager()

fun throwException(): Unit = throw RuntimeException() // Must be Unit. Nothing can't be used as reified

try {
withSecurityManager(MySecurityManager) { throwException() }
} catch(_: Exception) { }

System.getSecurityManager() shouldBeSameInstanceAs originalSecurityManager
}

"Should use custom security manager during execution" {
withSecurityManager(MySecurityManager) {
System.getSecurityManager() shouldBe MySecurityManager
}
}

"Should allow for suspend functions to be called" {

@Suppress("RedundantSuspendModifier")
suspend fun foo() { }

withSecurityManager(MySecurityManager) { foo() }
}
}
}

class SecurityManagerTestListenerTest : StringSpec() {

init {
"Should use custom security manager" {
System.getSecurityManager() shouldBe MySecurityManager
}
}

private var originalSecurityManager: SecurityManager? = null

override fun beforeTest(testCase: TestCase) {
originalSecurityManager = System.getSecurityManager()
}

override fun afterTest(testCase: TestCase, result: TestResult) {
// Should reset to system default
System.getSecurityManager() shouldBe originalSecurityManager
}

override fun listeners() = listOf(SecurityManagerTestListener(MySecurityManager))
}

private object MySecurityManager : SecurityManager() {
override fun checkPermission(perm: Permission?) { /* Throw nothing */ }
}
}

0 comments on commit 18577f8

Please sign in to comment.
You can’t perform that action at this time.