ENT-6588 Restrict database operations platform flag (#7053) (#7073) (#7074)

* ENT-6588 Restrict database operations platform flag

Put the restricting of database operations in `RestrictedConnection` and
`RestrictedEntityManager` behind a platform version flag.

`RESTRICTED_DATABASE_OPERATIONS = 7` was added to signify this.

If the version is less than 7, then the database operations will not be
restricted. A warning is logged to indicate that they are using
potentially dangerous methods.

If the version is 7 or greater, then the database operations are
restricted and throw an error if called.

Co-authored-by: Dan Newton <dan.newton@r3.com>

Co-authored-by: Dan Newton <dan.newton@r3.com>
This commit is contained in:
Adel El-Beik 2022-02-17 16:59:34 +00:00 committed by GitHub
parent 48707e595a
commit 470bce8a6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 559 additions and 124 deletions

View File

@ -16,4 +16,5 @@ object PlatformVersionSwitches {
const val LIMIT_KEYS_IN_SIGNATURE_CONSTRAINTS = 5 const val LIMIT_KEYS_IN_SIGNATURE_CONSTRAINTS = 5
const val BATCH_DOWNLOAD_COUNTERPARTY_BACKCHAIN = 6 const val BATCH_DOWNLOAD_COUNTERPARTY_BACKCHAIN = 6
const val ENABLE_P2P_COMPRESSION = 7 const val ENABLE_P2P_COMPRESSION = 7
const val RESTRICTED_DATABASE_OPERATIONS = 7
} }

View File

@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.PLATFORM_VERSION
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.nodeapi.internal.persistence.RestrictedConnection import net.corda.nodeapi.internal.persistence.RestrictedConnection
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.MockNetworkParameters
import net.corda.testing.node.StartedMockNode import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.internal.enclosedCordapp
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.junit.After import org.junit.After
import org.junit.Before
import org.junit.Test import org.junit.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -38,40 +39,63 @@ class RestrictedConnectionFlowTest {
} }
@InitiatingFlow @InitiatingFlow
class TestCloseMethodIsBlocked : FlowLogic<Unit>() { class TestClearWarningsMethodIsBlocked : FlowLogic<Unit>() {
@Suspendable @Suspendable
override fun call() { override fun call() {
val connection = serviceHub.jdbcSession() val connection = serviceHub.jdbcSession()
connection.close() connection.clearWarnings()
} }
} }
@Before
fun init() {
mockNetwork = MockNetwork(MockNetworkParameters())
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
}
@After @After
fun done() { fun done() {
mockNetwork.stopNodes() mockNetwork.stopNodes()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
fun testIfItIsRestrictedConnection() { fun `restricted connection is returned from ServiceHub#jdbcSession`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() } assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() }
mockNetwork.runNetwork() mockNetwork.runNetwork()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
fun testMethodsAreBlocked() { fun `restricted methods are blocked when the target platform is the current corda version`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() } .isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() }
.withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") .withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called")
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } .isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() }
.withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") .withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called")
mockNetwork.runNetwork()
}
@Test(timeout=300_000)
fun `restricted methods are blocked when the target platform is 7`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() }
.withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called")
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() }
.withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called")
mockNetwork.runNetwork()
}
@Test(timeout=300_000)
fun `restricted methods are not blocked when the target platform is 6`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow()
aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow()
mockNetwork.runNetwork() mockNetwork.runNetwork()
} }

View File

@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.flows.InitiatingFlow import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.CordaX500Name import net.corda.core.identity.CordaX500Name
import net.corda.core.internal.PLATFORM_VERSION
import net.corda.core.utilities.getOrThrow import net.corda.core.utilities.getOrThrow
import net.corda.nodeapi.internal.persistence.RestrictedEntityManager import net.corda.nodeapi.internal.persistence.RestrictedEntityManager
import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetwork
import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.MockNetworkParameters
import net.corda.testing.node.StartedMockNode import net.corda.testing.node.StartedMockNode
import net.corda.testing.node.internal.enclosedCordapp
import org.assertj.core.api.Assertions import org.assertj.core.api.Assertions
import org.junit.After import org.junit.After
import org.junit.Before
import org.junit.Test import org.junit.Test
import kotlin.test.assertTrue import kotlin.test.assertTrue
@ -25,7 +26,7 @@ class RestrictedEntityManagerFlowTest {
@Suspendable @Suspendable
override fun call() : Boolean { override fun call() : Boolean {
var result = false var result = false
serviceHub.withEntityManager() { serviceHub.withEntityManager {
result = this is RestrictedEntityManager result = this is RestrictedEntityManager
} }
return result return result
@ -33,11 +34,11 @@ class RestrictedEntityManagerFlowTest {
} }
@InitiatingFlow @InitiatingFlow
class TestCloseMethodIsBlocked : FlowLogic<Unit>() { class TestGetMetamodelMethodIsBlocked : FlowLogic<Unit>() {
@Suspendable @Suspendable
override fun call() { override fun call() {
serviceHub.withEntityManager() { serviceHub.withEntityManager {
this.close() this.metamodel
} }
} }
} }
@ -46,38 +47,61 @@ class RestrictedEntityManagerFlowTest {
class TestJoinTransactionMethodIsBlocked : FlowLogic<Unit>() { class TestJoinTransactionMethodIsBlocked : FlowLogic<Unit>() {
@Suspendable @Suspendable
override fun call() { override fun call() {
serviceHub.withEntityManager() { serviceHub.withEntityManager {
this.joinTransaction() this.joinTransaction()
} }
} }
} }
@Before
fun init() {
mockNetwork = MockNetwork(MockNetworkParameters())
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
}
@After @After
fun done() { fun done() {
mockNetwork.stopNodes() mockNetwork.stopNodes()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
fun testIfItIsRestrictedConnection() { fun `restricted connection is returned from ServiceHub#withEntityManager`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() } assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() }
mockNetwork.runNetwork() mockNetwork.runNetwork()
} }
@Test(timeout=300_000) @Test(timeout=300_000)
fun testMethodsAreBlocked() { fun `restricted methods are blocked when the target platform is the current corda version`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } .isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() }
.withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") .withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called")
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() } .isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() }
.withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") .withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called")
mockNetwork.runNetwork()
}
@Test(timeout=300_000)
fun `restricted methods are blocked when the target platform is 7`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() }
.withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called")
Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java)
.isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() }
.withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called")
mockNetwork.runNetwork()
}
@Test(timeout=300_000)
fun `restricted methods are not blocked when the target platform is 6`() {
mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6))))
aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB"))
aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow()
aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow()
mockNetwork.runNetwork() mockNetwork.runNetwork()
} }

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.persistence package net.corda.nodeapi.internal.persistence
import net.corda.core.node.ServiceHub
import java.sql.Connection import java.sql.Connection
import java.sql.Savepoint import java.sql.Savepoint
import java.util.concurrent.Executor import java.util.concurrent.Executor
@ -8,73 +9,73 @@ import java.util.concurrent.Executor
* A delegate of [Connection] which disallows some operations. * A delegate of [Connection] which disallows some operations.
*/ */
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
class RestrictedConnection(private val delegate : Connection) : Connection by delegate { class RestrictedConnection(private val delegate: Connection, private val serviceHub: ServiceHub) : Connection by delegate {
override fun abort(executor: Executor?) { override fun abort(executor: Executor?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("abort", serviceHub) { delegate.abort(executor) }
} }
override fun clearWarnings() { override fun clearWarnings() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("clearWarnings", serviceHub) { delegate.clearWarnings() }
} }
override fun close() { override fun close() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("close", serviceHub) { delegate.close() }
} }
override fun commit() { override fun commit() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("commit", serviceHub) { delegate.commit() }
} }
override fun setSavepoint(): Savepoint? { override fun setSavepoint(): Savepoint? {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint() }
} }
override fun setSavepoint(name : String?): Savepoint? { override fun setSavepoint(name: String?): Savepoint? {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint(name) }
} }
override fun releaseSavepoint(savepoint: Savepoint?) { override fun releaseSavepoint(savepoint: Savepoint?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("releaseSavepoint", serviceHub) { delegate.releaseSavepoint(savepoint) }
} }
override fun rollback() { override fun rollback() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback() }
} }
override fun rollback(savepoint: Savepoint?) { override fun rollback(savepoint: Savepoint?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback(savepoint) }
} }
override fun setCatalog(catalog : String?) { override fun setCatalog(catalog: String?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setCatalog", serviceHub) { delegate.catalog = catalog }
} }
override fun setTransactionIsolation(level: Int) { override fun setTransactionIsolation(level: Int) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setTransactionIsolation", serviceHub) { delegate.transactionIsolation = level }
} }
override fun setTypeMap(map: MutableMap<String, Class<*>>?) { override fun setTypeMap(map: MutableMap<String, Class<*>>?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setTypeMap", serviceHub) { delegate.typeMap = map }
} }
override fun setHoldability(holdability: Int) { override fun setHoldability(holdability: Int) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setHoldability", serviceHub) { delegate.holdability = holdability }
} }
override fun setSchema(schema: String?) { override fun setSchema(schema: String?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setSchema", serviceHub) { delegate.schema = schema }
} }
override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) { override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setNetworkTimeout", serviceHub) { delegate.setNetworkTimeout(executor, milliseconds) }
} }
override fun setAutoCommit(autoCommit: Boolean) { override fun setAutoCommit(autoCommit: Boolean) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setAutoCommit", serviceHub) { delegate.autoCommit = autoCommit }
} }
override fun setReadOnly(readOnly: Boolean) { override fun setReadOnly(readOnly: Boolean) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") restrictDatabaseOperationFromJdbcSession("setReadOnly", serviceHub) { delegate.isReadOnly = readOnly }
} }
} }

View File

@ -0,0 +1,31 @@
package net.corda.nodeapi.internal.persistence
import net.corda.core.internal.PlatformVersionSwitches.RESTRICTED_DATABASE_OPERATIONS
import net.corda.core.internal.warnOnce
import net.corda.core.node.ServiceHub
import org.slf4j.LoggerFactory
private val log = LoggerFactory.getLogger("RestrictedDatabaseOperations")
internal inline fun <T> restrictDatabaseOperationFromJdbcSession(method: String, serviceHub: ServiceHub, operation: () -> T): T {
return restrictDatabaseOperation("ServiceHub.jdbcSession.$method", serviceHub, operation)
}
internal inline fun <T> restrictDatabaseOperationFromEntityManager(method: String, serviceHub: ServiceHub, operation: () -> T): T {
return restrictDatabaseOperation("ServiceHub.withEntityManager.$method", serviceHub, operation)
}
internal inline fun <T> restrictDatabaseOperation(method: String, serviceHub: ServiceHub, operation: () -> T): T {
return if (serviceHub.getAppContext().cordapp.targetPlatformVersion >= RESTRICTED_DATABASE_OPERATIONS) {
throw UnsupportedOperationException("$method is restricted and cannot be called")
} else {
log.warnOnce(
"$method should not be called, as manipulating database transactions and connections breaks the Corda flow state machine in " +
"ways that only become evident in failure scenarios. Purely for API backwards compatibility reasons, the prior " +
"behaviour is continued for target platform versions less than $RESTRICTED_DATABASE_OPERATIONS. You should evolve " +
"the CorDapp away from using these problematic APIs as soon as possible. For target platform version of " +
"$RESTRICTED_DATABASE_OPERATIONS or above, an exception will be thrown instead."
)
operation()
}
}

View File

@ -1,5 +1,6 @@
package net.corda.nodeapi.internal.persistence package net.corda.nodeapi.internal.persistence
import net.corda.core.node.ServiceHub
import javax.persistence.EntityManager import javax.persistence.EntityManager
import javax.persistence.EntityTransaction import javax.persistence.EntityTransaction
import javax.persistence.LockModeType import javax.persistence.LockModeType
@ -8,56 +9,59 @@ import javax.persistence.metamodel.Metamodel
/** /**
* A delegate of [EntityManager] which disallows some operations. * A delegate of [EntityManager] which disallows some operations.
*/ */
class RestrictedEntityManager(private val delegate: EntityManager) : EntityManager by delegate { class RestrictedEntityManager(private val delegate: EntityManager, private val serviceHub: ServiceHub) : EntityManager by delegate {
override fun getTransaction(): EntityTransaction { override fun getTransaction(): EntityTransaction {
return RestrictedEntityTransaction(delegate.transaction) return RestrictedEntityTransaction(delegate.transaction, serviceHub)
} }
override fun close() { override fun close() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("close", serviceHub) { delegate.close() }
} }
override fun <T : Any?> unwrap(cls: Class<T>?): T { override fun <T : Any?> unwrap(cls: Class<T>?): T {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") return restrictDatabaseOperationFromEntityManager("unwrap", serviceHub) { delegate.unwrap(cls) }
} }
override fun getDelegate(): Any { override fun getDelegate(): Any {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") return restrictDatabaseOperationFromEntityManager("getDelegate", serviceHub) { delegate.delegate }
} }
override fun getMetamodel(): Metamodel? { override fun getMetamodel(): Metamodel? {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") return restrictDatabaseOperationFromEntityManager("getMetamodel", serviceHub) { delegate.metamodel }
} }
override fun joinTransaction() { override fun joinTransaction() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("joinTransaction", serviceHub) { delegate.joinTransaction() }
} }
override fun lock(entity: Any?, lockMode: LockModeType?) { override fun lock(entity: Any?, lockMode: LockModeType?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode) }
} }
override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap<String, Any>?) { override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap<String, Any>?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode, properties) }
} }
override fun setProperty(propertyName: String?, value: Any?) { override fun setProperty(propertyName: String?, value: Any?) {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.setProperty(propertyName, value) }
} }
} }
class RestrictedEntityTransaction(private val delegate: EntityTransaction) : EntityTransaction by delegate { class RestrictedEntityTransaction(
private val delegate: EntityTransaction,
private val serviceHub: ServiceHub
) : EntityTransaction by delegate {
override fun rollback() { override fun rollback() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("EntityTransaction.rollback", serviceHub) { delegate.rollback() }
} }
override fun commit() { override fun commit() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("EntityTransaction.commit", serviceHub) { delegate.commit() }
} }
override fun begin() { override fun begin() {
throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") restrictDatabaseOperationFromEntityManager("EntityTransaction.begin", serviceHub) { delegate.begin() }
} }
} }

View File

@ -1,104 +1,337 @@
package net.corda.nodeapi.internal.persistence package net.corda.nodeapi.internal.persistence
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.cordapp.Cordapp
import net.corda.core.cordapp.CordappContext
import net.corda.core.internal.PLATFORM_VERSION
import net.corda.core.node.ServiceHub
import org.junit.Test import org.junit.Test
import java.sql.Connection import java.sql.Connection
import java.sql.Savepoint import java.sql.Savepoint
class RestrictedConnectionTest { class RestrictedConnectionTest {
private val connection : Connection = mock() private val connection: Connection = mock()
private val savePoint : Savepoint = mock() private val savePoint: Savepoint = mock()
private val restrictedConnection : RestrictedConnection = RestrictedConnection(connection) private val cordapp = mock<Cordapp>()
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
private val serviceHub = mock<ServiceHub>().apply {
whenever(getAppContext()).thenReturn(cordappContext)
}
private val restrictedConnection: RestrictedConnection = RestrictedConnection(connection, serviceHub)
companion object { companion object {
private const val TEST_STRING : String = "test" private const val TEST_STRING: String = "test"
private const val TEST_INT : Int = 1 private const val TEST_INT: Int = 1
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testAbort() { fun `abort with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.abort { println("I'm just an executor for this test...") } restrictedConnection.abort { println("I'm just an executor for this test...") }
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testClearWarnings() { fun `clearWarnings with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.clearWarnings() restrictedConnection.clearWarnings()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testClose() { fun `close with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.close() restrictedConnection.close()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testCommit() { fun `commit with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.commit() restrictedConnection.commit()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetSavepoint() { fun `setSavepoint with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.setSavepoint() restrictedConnection.setSavepoint()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetSavepointWithName() { fun `setSavepoint with name with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.setSavepoint(TEST_STRING) restrictedConnection.setSavepoint(TEST_STRING)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testReleaseSavepoint() { fun `releaseSavepoint with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.releaseSavepoint(savePoint) restrictedConnection.releaseSavepoint(savePoint)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testRollback() { fun `rollback with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.rollback() restrictedConnection.rollback()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testRollbackWithSavepoint() { fun `rollbackWithSavepoint with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.rollback(savePoint) restrictedConnection.rollback(savePoint)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetCatalog() { fun `setCatalog with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.catalog = TEST_STRING restrictedConnection.catalog = TEST_STRING
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetTransactionIsolation() { fun `setTransactionIsolation with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.transactionIsolation = TEST_INT restrictedConnection.transactionIsolation = TEST_INT
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetTypeMap() { fun `setTypeMap with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
val map: MutableMap<String, Class<*>> = mutableMapOf() val map: MutableMap<String, Class<*>> = mutableMapOf()
restrictedConnection.typeMap = map restrictedConnection.typeMap = map
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetHoldability() { fun `setHoldability with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.holdability = TEST_INT restrictedConnection.holdability = TEST_INT
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetSchema() { fun `setSchema with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.schema = TEST_STRING restrictedConnection.schema = TEST_STRING
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetNetworkTimeout() { fun `setNetworkTimeout with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetAutoCommit() { fun `setAutoCommit with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.autoCommit = true restrictedConnection.autoCommit = true
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetReadOnly() { fun `setReadOnly with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedConnection.isReadOnly = true
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `abort with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.abort { println("I'm just an executor for this test...") }
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `clearWarnings with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.clearWarnings()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `close with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.close()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `commit with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.commit()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setSavepoint with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.setSavepoint()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setSavepoint with name with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.setSavepoint(TEST_STRING)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `releaseSavepoint with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.releaseSavepoint(savePoint)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `rollback with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.rollback()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `rollbackWithSavepoint with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.rollback(savePoint)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setCatalog with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.catalog = TEST_STRING
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setTransactionIsolation with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.transactionIsolation = TEST_INT
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setTypeMap with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
val map: MutableMap<String, Class<*>> = mutableMapOf()
restrictedConnection.typeMap = map
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setHoldability with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.holdability = TEST_INT
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setSchema with target platform version of current 7 unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.schema = TEST_STRING
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setNetworkTimeout with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setAutoCommit with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.autoCommit = true
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setReadOnly with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedConnection.isReadOnly = true
}
@Test(timeout = 300_000)
fun `abort with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.abort { println("I'm just an executor for this test...") }
}
@Test(timeout = 300_000)
fun `clearWarnings with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.clearWarnings()
}
@Test(timeout = 300_000)
fun `close with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.close()
}
@Test(timeout = 300_000)
fun `commit with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.commit()
}
@Test(timeout = 300_000)
fun `setSavepoint with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.setSavepoint()
}
@Test(timeout = 300_000)
fun `setSavepoint with name with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.setSavepoint(TEST_STRING)
}
@Test(timeout = 300_000)
fun `releaseSavepoint with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.releaseSavepoint(savePoint)
}
@Test(timeout = 300_000)
fun `rollback with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.rollback()
}
@Test(timeout = 300_000)
fun `rollbackWithSavepoint with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.rollback(savePoint)
}
@Test(timeout = 300_000)
fun `setCatalog with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.catalog = TEST_STRING
}
@Test(timeout = 300_000)
fun `setTransactionIsolation with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.transactionIsolation = TEST_INT
}
@Test(timeout = 300_000)
fun `setTypeMap with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
val map: MutableMap<String, Class<*>> = mutableMapOf()
restrictedConnection.typeMap = map
}
@Test(timeout = 300_000)
fun `setHoldability with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.holdability = TEST_INT
}
@Test(timeout = 300_000)
fun `setSchema with target platform version of current 6 unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.schema = TEST_STRING
}
@Test(timeout = 300_000)
fun `setNetworkTimeout with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT)
}
@Test(timeout = 300_000)
fun `setAutoCommit with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.autoCommit = true
}
@Test(timeout = 300_000)
fun `setReadOnly with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedConnection.isReadOnly = true restrictedConnection.isReadOnly = true
} }
} }

View File

@ -3,6 +3,10 @@ package net.corda.nodeapi.internal.persistence
import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import com.nhaarman.mockito_kotlin.whenever import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.cordapp.Cordapp
import net.corda.core.cordapp.CordappContext
import net.corda.core.internal.PLATFORM_VERSION
import net.corda.core.node.ServiceHub
import org.junit.Test import org.junit.Test
import javax.persistence.EntityManager import javax.persistence.EntityManager
import javax.persistence.EntityTransaction import javax.persistence.EntityTransaction
@ -12,47 +16,160 @@ import kotlin.test.assertTrue
class RestrictedEntityManagerTest { class RestrictedEntityManagerTest {
private val entitymanager = mock<EntityManager>() private val entitymanager = mock<EntityManager>()
private val transaction = mock<EntityTransaction>() private val transaction = mock<EntityTransaction>()
private val restrictedEntityManager = RestrictedEntityManager(entitymanager) private val cordapp = mock<Cordapp>()
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
private val serviceHub = mock<ServiceHub>().apply {
whenever(getAppContext()).thenReturn(cordappContext)
}
private val restrictedEntityManager = RestrictedEntityManager(entitymanager, serviceHub)
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testClose() { fun `close with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.close() restrictedEntityManager.close()
} }
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun testClear() { fun `clear with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.clear() restrictedEntityManager.clear()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testGetMetaModel() { fun `getMetaModel with target platform version of current corda version throws unsupported exception`() {
restrictedEntityManager.getMetamodel() whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.metamodel
} }
@Test(timeout = 300_000) @Test(timeout = 300_000)
fun testGetTransaction() { fun `getTransaction with target platform version of current corda version executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
whenever(entitymanager.transaction).doReturn(transaction) whenever(entitymanager.transaction).doReturn(transaction)
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testJoinTransaction() { fun `joinTransaction with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.joinTransaction() restrictedEntityManager.joinTransaction()
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testLockWithTwoParameters() { fun `lock with two parameters with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testLockWithThreeParameters() { fun `lock with three parameters with target platform version of current corda version throws unsupported exception`() {
val map: MutableMap<String,Any> = mutableMapOf() whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC,map) val map: MutableMap<String, Any> = mutableMapOf()
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
} }
@Test(expected = UnsupportedOperationException::class, timeout=300_000) @Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun testSetProperty() { fun `setProperty with target platform version of current corda version throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION)
restrictedEntityManager.setProperty("number", 12)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `close with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.close()
}
@Test(timeout = 300_000)
fun `clear with target platform version of 7 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.clear()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `getMetaModel with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.metamodel
}
@Test(timeout = 300_000)
fun `getTransaction with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
whenever(entitymanager.transaction).doReturn(transaction)
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `joinTransaction with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.joinTransaction()
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `lock with two parameters with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `lock with three parameters with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
val map: MutableMap<String, Any> = mutableMapOf()
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
}
@Test(expected = UnsupportedOperationException::class, timeout = 300_000)
fun `setProperty with target platform version of 7 throws unsupported exception`() {
whenever(cordapp.targetPlatformVersion).thenReturn(7)
restrictedEntityManager.setProperty("number", 12)
}
@Test(timeout = 300_000)
fun `close with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.close()
}
@Test(timeout = 300_000)
fun `clear with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.clear()
}
@Test(timeout = 300_000)
fun `getMetaModel with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.metamodel
}
@Test(timeout = 300_000)
fun `getTransaction with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
whenever(entitymanager.transaction).doReturn(transaction)
assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction)
}
@Test(timeout = 300_000)
fun `joinTransaction with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.joinTransaction()
}
@Test(timeout = 300_000)
fun `lock with two parameters with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC)
}
@Test(timeout = 300_000)
fun `lock with three parameters with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
val map: MutableMap<String, Any> = mutableMapOf()
restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map)
}
@Test(timeout = 300_000)
fun `setProperty with target platform version of 6 executes successfully`() {
whenever(cordapp.targetPlatformVersion).thenReturn(6)
restrictedEntityManager.setProperty("number", 12) restrictedEntityManager.setProperty("number", 12)
} }
} }

View File

@ -1273,7 +1273,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
/** /**
* Exposes the database connection as a [RestrictedConnection] to the users. * Exposes the database connection as a [RestrictedConnection] to the users.
*/ */
override fun jdbcSession(): Connection = RestrictedConnection(database.createSession()) override fun jdbcSession(): Connection = RestrictedConnection(database.createSession(), services)
@Suppress("TooGenericExceptionCaught") @Suppress("TooGenericExceptionCaught")
override fun <T : Any?> withEntityManager(block: EntityManager.() -> T): T { override fun <T : Any?> withEntityManager(block: EntityManager.() -> T): T {
@ -1283,7 +1283,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
withSavePoint { savepoint -> withSavePoint { savepoint ->
// Restrict what entity manager they can use inside the block // Restrict what entity manager they can use inside the block
try { try {
block(RestrictedEntityManager(manager)).also { block(RestrictedEntityManager(manager, services)).also {
if (!manager.transaction.rollbackOnly) { if (!manager.transaction.rollbackOnly) {
manager.flush() manager.flush()
} else { } else {