Skip to content

Instantly share code, notes, and snippets.

@mikehearn
Created December 21, 2017 17:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikehearn/518e44670811a8af735708d46d1e5721 to your computer and use it in GitHub Desktop.
Save mikehearn/518e44670811a8af735708d46d1e5721 to your computer and use it in GitHub Desktop.
Simple dependency helpers
package net.corda.node.internal
import java.time.Clock
import java.time.Duration
import java.time.Instant
import java.time.ZoneId
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* A dependency delegate can be used with the Kotlin `by` keyword. It is intended for global variables that are lazily
* initialised on access to the result of some lambda, but which can be changed after the fact.
*/
class DependencyDelegate<T : Any>(private val newEachTime: Boolean = false, private val ctor: () -> T) : ReadWriteProperty<Nothing?, T> {
private var value: T? = null
override fun getValue(thisRef: Nothing?, property: KProperty<*>): T {
if (newEachTime) {
return ctor()
}
synchronized(this) {
if (value == null)
value = ctor()
return value!!
}
}
@Synchronized
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) {
this.value = value
}
}
internal var defaultClock: Clock by DependencyDelegate { Clock.systemUTC() }
class SomethingThatNeedsAClock(val clock: Clock = defaultClock) {
override fun toString() = clock.instant().toString()
}
/**
*
*/
class TestSensitiveDependency<T : Any>(private val regular: () -> T,
private val test: () -> T) : ReadWriteProperty<Nothing?, T> {
private val oldValue = ThreadLocal<T?>()
private val value = ThreadLocal<T?>()
companion object {
private val isJUnitPresent: Boolean by lazy {
try { Class.forName("org.junit.Test"); true } catch(e: ClassNotFoundException) { false }
}
}
private fun construct(): T = if (isJUnitPresent)
test()
else
regular()
override fun getValue(thisRef: Nothing?, property: KProperty<*>): T {
if (value.get() == null) {
value.set(construct())
}
return value.get()!!
}
override fun setValue(thisRef: Nothing?, property: KProperty<*>, value: T) {
oldValue.set(this.value.get())
this.value.set(value)
}
fun restore() {
value.set(oldValue.get())
oldValue.set(null)
}
}
internal var testableClockDependency = TestSensitiveDependency(
regular = { defaultClock },
test = { Clock.fixed(Instant.ofEpochSecond(1513877662), ZoneId.of("UTC")) }
)
var testableClock: Clock by testableClockDependency
fun main(args: Array<String>) {
println("Time is ${testableClock.instant()}")
testableClock = Clock.offset(defaultClock, Duration.ofDays(5))
println("Time is ${testableClock.instant()}")
testableClockDependency.restore()
println("Time is ${testableClock.instant()}")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment