Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
1,294 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
80 changes: 80 additions & 0 deletions
80
kotlintest-extensions/src/jvmMain/kotlin/io/kotlintest/extensions/locale/LocaleExtensions.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package io.kotlintest.extensions.locale | ||
|
||
import io.kotlintest.TestCase | ||
import io.kotlintest.TestResult | ||
import io.kotlintest.extensions.TestListener | ||
import java.util.* | ||
|
||
/** | ||
* Replaces the default Locale | ||
* | ||
* This function replaces the current default locale with [locale], then executes [block] and finally | ||
* returns the original default locale to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default locale, and if you | ||
* change the locale while it was already changed, the result may be inconsistent. | ||
*/ | ||
inline fun <reified T> withDefaultLocale(locale: Locale, block: () -> T): T { | ||
val previous = Locale.getDefault() | ||
Locale.setDefault(locale) | ||
|
||
try { | ||
return block() | ||
} finally { | ||
Locale.setDefault(previous) | ||
} | ||
} | ||
|
||
abstract class LocaleListener(private val locale: Locale) : TestListener { | ||
|
||
private val originalLocale = Locale.getDefault() | ||
|
||
protected fun changeLocale() { | ||
Locale.setDefault(locale) | ||
} | ||
|
||
protected fun resetLocale() { | ||
Locale.setDefault(originalLocale) | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Replaces the default Locale | ||
* | ||
* This listener replaces the current default locale with [locale], then executes the test and finally | ||
* returns the original default locale to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default locale, and if you | ||
* change the locale while it was already changed, the result may be inconsistent. | ||
*/ | ||
class LocaleTestListener(locale: Locale): LocaleListener(locale) { | ||
|
||
override fun beforeTest(testCase: TestCase) { | ||
changeLocale() | ||
} | ||
|
||
override fun afterTest(testCase: TestCase, result: TestResult) { | ||
resetLocale() | ||
} | ||
} | ||
|
||
/** | ||
* Replaces the default Locale | ||
* | ||
* This listener replaces the current default locale with [locale], then executes the project and finally | ||
* returns the original default locale to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default locale, and if you | ||
* change the locale while it was already changed, the result may be inconsistent. | ||
*/ | ||
class LocaleProjectListener(newLocale: Locale): LocaleListener(newLocale) { | ||
|
||
override fun beforeProject() { | ||
changeLocale() | ||
} | ||
|
||
override fun afterProject() { | ||
resetLocale() | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
...ntest-extensions/src/jvmMain/kotlin/io/kotlintest/extensions/locale/TimezoneExtensions.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package io.kotlintest.extensions.locale | ||
|
||
import io.kotlintest.TestCase | ||
import io.kotlintest.TestResult | ||
import io.kotlintest.extensions.TestListener | ||
import java.util.* | ||
|
||
/** | ||
* Replaces the default TimeZone | ||
* | ||
* This function replaces the current default timeZone with [timeZone], then executes [block] and finally | ||
* returns the original default timeZone to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default timeZone, and if you | ||
* change the timeZone while it was already changed, the result may be inconsistent. | ||
*/ | ||
inline fun <reified T> withDefaultTimeZone(timeZone: TimeZone, block: () -> T): T { | ||
val previous = TimeZone.getDefault() | ||
|
||
TimeZone.setDefault(timeZone) | ||
|
||
try { | ||
return block() | ||
} finally { | ||
TimeZone.setDefault(previous) | ||
} | ||
} | ||
|
||
abstract class TimeZoneListener(private val timeZone: TimeZone) : TestListener { | ||
|
||
private val originalTimeZone = TimeZone.getDefault() | ||
|
||
protected fun changeTimeZone() { | ||
TimeZone.setDefault(timeZone) | ||
} | ||
|
||
protected fun resetTimeZone() { | ||
TimeZone.setDefault(originalTimeZone) | ||
} | ||
} | ||
|
||
/** | ||
* Replaces the default TimeZone | ||
* | ||
* This function replaces the current default timezone with [timeZone], then executes the test and finally | ||
* returns the original default timezone to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default timezone, and if you | ||
* change the timezone while it was already changed, the result may be inconsistent. | ||
*/ | ||
class TimeZoneTestListener(timeZone: TimeZone) : TimeZoneListener(timeZone) { | ||
|
||
override fun beforeTest(testCase: TestCase) { | ||
changeTimeZone() | ||
} | ||
|
||
override fun afterTest(testCase: TestCase, result: TestResult) { | ||
resetTimeZone() | ||
} | ||
} | ||
|
||
/** | ||
* Replaces the default TimeZone | ||
* | ||
* This function replaces the current default timezone with [timeZone], then executes the project and finally | ||
* returns the original default timezone to it's place. | ||
* | ||
* **Attention:** This code is subject to race conditions. The System can only have one default timezone, and if you | ||
* change the timezone while it was already changed, the result may be inconsistent. | ||
*/ | ||
class TimeZoneProjectListener(timeZone: TimeZone) : TimeZoneListener(timeZone) { | ||
|
||
override fun beforeProject() { | ||
changeTimeZone() | ||
} | ||
|
||
override fun afterProject() { | ||
resetTimeZone() | ||
} | ||
} |
60 changes: 60 additions & 0 deletions
60
kotlintest-extensions/src/jvmMain/kotlin/io/kotlintest/extensions/system/MapOverrides.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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) | ||
} | ||
|
||
} | ||
|
||
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) | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...st-extensions/src/jvmMain/kotlin/io/kotlintest/extensions/system/NoSystemOutExtensions.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package io.kotlintest.extensions.system | ||
|
||
import io.kotlintest.Spec | ||
import io.kotlintest.extensions.TestListener | ||
import java.io.ByteArrayOutputStream | ||
import java.io.PrintStream | ||
|
||
class SystemOutWriteException(val str: String?) : RuntimeException() | ||
class SystemErrWriteException(val str: String?) : RuntimeException() | ||
|
||
object NoSystemOutListener : TestListener { | ||
private fun setup() { | ||
val out = ByteArrayOutputStream() | ||
System.setOut(object : PrintStream(out) { | ||
private fun error(a: Any?): Nothing = throw SystemOutWriteException(a?.toString()) | ||
override fun print(b: Boolean) = error(b) | ||
override fun print(c: Char) = error(c) | ||
override fun print(i: Int) = error(i) | ||
override fun print(l: Long) = error(l) | ||
override fun print(s: String) = error(s) | ||
override fun print(o: Any) = error(o) | ||
override fun print(c: CharArray) = error(c) | ||
override fun print(d: Double) = error(d) | ||
override fun print(f: Float) = error(f) | ||
}) | ||
} | ||
|
||
override fun beforeProject() = setup() | ||
override fun beforeSpec(spec: Spec) = setup() | ||
} | ||
|
||
object NoSystemErrListener : TestListener { | ||
private fun setup() { | ||
val out = ByteArrayOutputStream() | ||
System.setErr(object : PrintStream(out) { | ||
private fun error(a: Any?): Nothing = throw SystemErrWriteException(a?.toString()) | ||
override fun print(b: Boolean) = error(b) | ||
override fun print(c: Char) = error(c) | ||
override fun print(i: Int) = error(i) | ||
override fun print(l: Long) = error(l) | ||
override fun print(s: String) = error(s) | ||
override fun print(o: Any) = error(o) | ||
override fun print(c: CharArray) = error(c) | ||
override fun print(d: Double) = error(d) | ||
override fun print(f: Float) = error(f) | ||
}) | ||
} | ||
|
||
override fun beforeProject() = setup() | ||
override fun beforeSpec(spec: Spec) = setup() | ||
} |
Oops, something went wrong.