Moved serialization validation to it's own test (it's has nothing to do with RMI), refactored RmiTest

This commit is contained in:
nathan 2020-08-30 23:16:09 +02:00
parent 051f419300
commit ab2395845b
5 changed files with 199 additions and 185 deletions

View File

@ -13,34 +13,53 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package dorkboxTest.network.rmi package dorkboxTest.network
import dorkbox.network.Client import dorkbox.network.Client
import dorkbox.network.Configuration
import dorkbox.network.Server import dorkbox.network.Server
import dorkbox.network.connection.Connection import dorkbox.network.connection.Connection
import dorkbox.network.serialization.Serialization import dorkbox.network.serialization.Serialization
import dorkbox.util.exceptions.SecurityException
import dorkboxTest.network.BaseTest
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.Test import org.junit.Test
import java.io.IOException
class RmiInitValidationTest : BaseTest() { class SerializationValidationTest : BaseTest() {
@Test @Test
@Throws(SecurityException::class, IOException::class) fun checkObjects() {
fun rmiNetwork() { run {
rmi() val configuration = serverConfig()
} register(configuration.serialization)
@Test val server = Server<Connection>(configuration)
@Throws(SecurityException::class, IOException::class) addEndPoint(server)
fun rmiLocal() {
// rmi(object : Config() { server.onMessage<FinishedCommand> { connection, message ->
// fun apply(configuration: Configuration) { stopEndPoints()
// configuration.localChannelName = EndPoint.LOCAL_CHANNEL }
// }
// }) runBlocking {
server.bind(false)
}
}
run {
val configuration = clientConfig()
register(configuration.serialization)
val client = Client<Connection>(configuration)
addEndPoint(client)
client.onConnect { connection ->
connection.send(FinishedCommand())
}
runBlocking {
client.connect(LOOPBACK)
}
}
waitForThreads()
} }
private fun register(serialization: Serialization) { private fun register(serialization: Serialization) {
@ -246,51 +265,6 @@ class RmiInitValidationTest : BaseTest() {
serialization.register(FinishedCommand::class.java) serialization.register(FinishedCommand::class.java)
} }
/**
* In this test the server has two objects in an object space. The client
* uses the first remote object to get the second remote object.
*/
fun rmi(config: (Configuration) -> Unit = {}) {
run {
val configuration = serverConfig()
config(configuration)
register(configuration.serialization)
val server = Server<Connection>(configuration)
addEndPoint(server)
server.onMessage<FinishedCommand> { connection, message ->
stopEndPoints()
}
runBlocking {
server.bind(false)
}
}
run {
val configuration = clientConfig()
config(configuration)
register(configuration.serialization)
val client = Client<Connection>(configuration)
addEndPoint(client)
client.onConnect { connection ->
connection.send(FinishedCommand())
}
runBlocking {
client.connect(LOOPBACK)
}
}
// waitForThreads()
waitForThreads(99999999)
}
private class Command1 private class Command1
private class Command2 private class Command2
private class Command3 private class Command3

View File

@ -0,0 +1,149 @@
/*
* Copyright 2016 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2008, Nathan Sweet
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
* - Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package dorkboxTest.network.rmi
import dorkbox.network.connection.Connection
import dorkbox.network.rmi.RemoteObject
import dorkbox.network.serialization.Serialization
import dorkboxTest.network.rmi.classes.MessageWithTestCow
import dorkboxTest.network.rmi.classes.TestCow
import org.junit.Assert
object RmiCommonTest {
suspend fun runTests(connection: Connection, test: TestCow, remoteObjectID: Int) {
val remoteObject = test as RemoteObject
// Default behavior. RMI is transparent, method calls behave like normal
// (return values and exceptions are returned, call is synchronous)
connection.logger.error("hashCode: " + test.hashCode())
connection.logger.error("toString: $test")
test.withSuspend("test", 32)
val s1 = test.withSuspendAndReturn("test", 32)
Assert.assertEquals(s1, 32)
// see what the "remote" toString() method is
val s = remoteObject.toString()
remoteObject.enableToString(true)
Assert.assertFalse(s == remoteObject.toString())
test.moo()
test.moo("Cow")
Assert.assertEquals(remoteObjectID, test.id())
// Test that RMI correctly waits for the remotely invoked method to exit
remoteObject.responseTimeout = 5000
test.moo("You should see this two seconds before...", 2000)
connection.logger.error("...This")
remoteObject.responseTimeout = 3000
// Try exception handling
try {
test.throwException()
Assert.fail("sync should be throwing an exception!")
} catch (e: UnsupportedOperationException) {
connection.logger.error("Expected exception (exception log should also be on the object impl side).", e)
}
try {
test.throwSuspendException()
Assert.fail("sync should be throwing an exception!")
} catch (e: UnsupportedOperationException) {
connection.logger.error("\tExpected exception (exception log should also be on the object impl side).", e)
}
// Non-blocking call tests
// Non-blocking call tests
// Non-blocking call tests
connection.logger.error("I'm currently async: ${remoteObject.async}. Now testing ASYNC")
remoteObject.async = true
// calls that ignore the return value
test.moo("Meow")
// Non-blocking call that ignores the return value
Assert.assertEquals(0, test.id().toLong())
// exceptions are still dealt with properly
test.moo("Baa")
try {
test.throwException()
} catch (e: IllegalStateException) {
// exceptions are not caught when async = true!
Assert.fail("Async should not be throwing an exception!")
}
try {
test.throwSuspendException()
} catch (e: IllegalStateException) {
// exceptions are not caught when async = true!
Assert.fail("Async should not be throwing an exception!")
}
// Call will time out if non-blocking isn't working properly
test.moo("Mooooooooo", 4000)
// should wait for a small time
remoteObject.async = false
remoteObject.responseTimeout = 6000
connection.logger.error("You should see this 2 seconds before")
val slow = test.slow()
connection.logger.error("...This")
Assert.assertEquals(slow.toDouble(), 123.0, 0.0001)
// Test sending a reference to a remote object.
val m = MessageWithTestCow(test)
m.number = 678
m.text = "sometext"
connection.send(m)
connection.logger.error("Finished tests")
}
fun register(manager: Serialization) {
manager.register(Any::class.java) // Needed for Object#toString, hashCode, etc.
manager.register(TestCow::class.java)
manager.register(MessageWithTestCow::class.java)
manager.register(UnsupportedOperationException::class.java)
}
}

View File

@ -38,8 +38,6 @@ import dorkbox.network.Client
import dorkbox.network.Configuration import dorkbox.network.Configuration
import dorkbox.network.Server import dorkbox.network.Server
import dorkbox.network.connection.Connection import dorkbox.network.connection.Connection
import dorkbox.network.rmi.RemoteObject
import dorkbox.network.serialization.Serialization
import dorkboxTest.network.BaseTest import dorkboxTest.network.BaseTest
import dorkboxTest.network.rmi.classes.MessageWithTestCow import dorkboxTest.network.rmi.classes.MessageWithTestCow
import dorkboxTest.network.rmi.classes.TestCow import dorkboxTest.network.rmi.classes.TestCow
@ -48,114 +46,7 @@ import kotlinx.coroutines.runBlocking
import org.junit.Assert import org.junit.Assert
import org.junit.Test import org.junit.Test
class RmiTest : BaseTest() { class RmiSimpleTest : BaseTest() {
companion object {
suspend fun runTests(connection: Connection, test: TestCow, remoteObjectID: Int) {
val remoteObject = test as RemoteObject
// Default behavior. RMI is transparent, method calls behave like normal
// (return values and exceptions are returned, call is synchronous)
connection.logger.error("hashCode: " + test.hashCode())
connection.logger.error("toString: $test")
test.withSuspend("test", 32)
val s1 = test.withSuspendAndReturn("test", 32)
Assert.assertEquals(s1, 32)
// see what the "remote" toString() method is
val s = remoteObject.toString()
remoteObject.enableToString(true)
Assert.assertFalse(s == remoteObject.toString())
test.moo()
test.moo("Cow")
Assert.assertEquals(remoteObjectID, test.id())
// Test that RMI correctly waits for the remotely invoked method to exit
remoteObject.responseTimeout = 5000
test.moo("You should see this two seconds before...", 2000)
connection.logger.error("...This")
remoteObject.responseTimeout = 3000
// Try exception handling
try {
test.throwException()
Assert.fail("sync should be throwing an exception!")
} catch (e: UnsupportedOperationException) {
connection.logger.error("Expected exception (exception log should also be on the object impl side).", e)
}
try {
test.throwSuspendException()
Assert.fail("sync should be throwing an exception!")
} catch (e: UnsupportedOperationException) {
connection.logger.error("\tExpected exception (exception log should also be on the object impl side).", e)
}
// Non-blocking call tests
// Non-blocking call tests
// Non-blocking call tests
connection.logger.error("I'm currently async: ${remoteObject.async}. Now testing ASYNC")
remoteObject.async = true
// calls that ignore the return value
test.moo("Meow")
// Non-blocking call that ignores the return value
Assert.assertEquals(0, test.id().toLong())
// exceptions are still dealt with properly
test.moo("Baa")
try {
test.throwException()
} catch (e: IllegalStateException) {
// exceptions are not caught when async = true!
Assert.fail("Async should not be throwing an exception!")
}
try {
test.throwSuspendException()
} catch (e: IllegalStateException) {
// exceptions are not caught when async = true!
Assert.fail("Async should not be throwing an exception!")
}
// Call will time out if non-blocking isn't working properly
test.moo("Mooooooooo", 4000)
// should wait for a small time
remoteObject.async = false
remoteObject.responseTimeout = 6000
connection.logger.error("You should see this 2 seconds before")
val slow = test.slow()
connection.logger.error("...This")
Assert.assertEquals(slow.toDouble(), 123.0, 0.0001)
// Test sending a reference to a remote object.
val m = MessageWithTestCow(test)
m.number = 678
m.text = "sometext"
connection.send(m)
connection.logger.error("Finished tests")
}
fun register(manager: Serialization) {
manager.register(Any::class.java) // Needed for Object#toString, hashCode, etc.
manager.register(TestCow::class.java)
manager.register(MessageWithTestCow::class.java)
manager.register(UnsupportedOperationException::class.java)
}
}
@Test @Test
fun rmiNetworkGlobal() { fun rmiNetworkGlobal() {
@ -181,7 +72,7 @@ class RmiTest : BaseTest() {
run { run {
val configuration = serverConfig() val configuration = serverConfig()
config(configuration) config(configuration)
register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
// for Client -> Server RMI // for Client -> Server RMI
configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java) configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java)
@ -204,7 +95,7 @@ class RmiTest : BaseTest() {
System.err.println("Starting test for: Server -> Client") System.err.println("Starting test for: Server -> Client")
connection.createObject<TestCow>(123) { rmiId, remoteObject -> connection.createObject<TestCow>(123) { rmiId, remoteObject ->
System.err.println("Running test for: Server -> Client") System.err.println("Running test for: Server -> Client")
runTests(connection, remoteObject, 123) RmiCommonTest.runTests(connection, remoteObject, 123)
System.err.println("Done with test for: Server -> Client") System.err.println("Done with test for: Server -> Client")
} }
} }
@ -213,7 +104,7 @@ class RmiTest : BaseTest() {
run { run {
val configuration = clientConfig() val configuration = clientConfig()
config(configuration) config(configuration)
register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
// for Server -> Client RMI // for Server -> Client RMI
configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java) configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java)
@ -224,7 +115,7 @@ class RmiTest : BaseTest() {
client.onConnect { connection -> client.onConnect { connection ->
connection.createObject<TestCow>(23) { rmiId, remoteObject -> connection.createObject<TestCow>(23) { rmiId, remoteObject ->
System.err.println("Running test for: Client -> Server") System.err.println("Running test for: Client -> Server")
runTests(connection, remoteObject, 23) RmiCommonTest.runTests(connection, remoteObject, 23)
System.err.println("Done with test for: Client -> Server") System.err.println("Done with test for: Client -> Server")
} }
} }
@ -250,7 +141,7 @@ class RmiTest : BaseTest() {
run { run {
val configuration = serverConfig() val configuration = serverConfig()
config(configuration) config(configuration)
register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
// for Client -> Server RMI // for Client -> Server RMI
configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java) configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java)
@ -275,7 +166,7 @@ class RmiTest : BaseTest() {
// normally this is in the 'connected', but we do it here, so that it's more linear and easier to debug // normally this is in the 'connected', but we do it here, so that it's more linear and easier to debug
connection.createObject<TestCow>(4) { rmiId, remoteObject -> connection.createObject<TestCow>(4) { rmiId, remoteObject ->
System.err.println("Running test for: Server -> Client") System.err.println("Running test for: Server -> Client")
runTests(connection, remoteObject, 4) RmiCommonTest.runTests(connection, remoteObject, 4)
System.err.println("Done with test for: Server -> Client") System.err.println("Done with test for: Server -> Client")
} }
} }
@ -284,7 +175,7 @@ class RmiTest : BaseTest() {
run { run {
val configuration = clientConfig() val configuration = clientConfig()
config(configuration) config(configuration)
register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
// for Server -> Client RMI // for Server -> Client RMI
configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java) configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java)
@ -308,7 +199,7 @@ class RmiTest : BaseTest() {
// this creates a GLOBAL object on the server (instead of a connection specific object) // this creates a GLOBAL object on the server (instead of a connection specific object)
client.createObject<TestCow>(44) { rmiId, remoteObject -> client.createObject<TestCow>(44) { rmiId, remoteObject ->
System.err.println("Running test for: Client -> Server") System.err.println("Running test for: Client -> Server")
runTests(client.getConnection(), remoteObject, 44) RmiCommonTest.runTests(client.getConnection(), remoteObject, 44)
System.err.println("Done with test for: Client -> Server") System.err.println("Done with test for: Client -> Server")
} }
} }

View File

@ -25,7 +25,7 @@ import ch.qos.logback.core.ConsoleAppender
import dorkbox.network.Client import dorkbox.network.Client
import dorkbox.network.connection.Connection import dorkbox.network.connection.Connection
import dorkboxTest.network.BaseTest import dorkboxTest.network.BaseTest
import dorkboxTest.network.rmi.RmiTest import dorkboxTest.network.rmi.RmiCommonTest
import dorkboxTest.network.rmi.classes.TestBabyCow import dorkboxTest.network.rmi.classes.TestBabyCow
import dorkboxTest.network.rmi.classes.TestBabyCowImpl import dorkboxTest.network.rmi.classes.TestBabyCowImpl
import dorkboxTest.network.rmi.classes.TestCow import dorkboxTest.network.rmi.classes.TestCow
@ -68,7 +68,7 @@ object TestClient {
setup() setup()
val configuration = BaseTest.clientConfig() val configuration = BaseTest.clientConfig()
RmiTest.register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
configuration.serialization.registerRmi(TestBabyCow::class.java, TestBabyCowImpl::class.java) configuration.serialization.registerRmi(TestBabyCow::class.java, TestBabyCowImpl::class.java)
configuration.serialization.register(TestCow::class.java) configuration.serialization.register(TestCow::class.java)
configuration.enableRemoteSignatureValidation = false configuration.enableRemoteSignatureValidation = false

View File

@ -18,7 +18,7 @@ package dorkboxTest.network.rmi.multiJVM
import dorkbox.network.Server import dorkbox.network.Server
import dorkbox.network.connection.Connection import dorkbox.network.connection.Connection
import dorkboxTest.network.BaseTest import dorkboxTest.network.BaseTest
import dorkboxTest.network.rmi.RmiTest import dorkboxTest.network.rmi.RmiCommonTest
import dorkboxTest.network.rmi.classes.MessageWithTestCow import dorkboxTest.network.rmi.classes.MessageWithTestCow
import dorkboxTest.network.rmi.classes.TestBabyCow import dorkboxTest.network.rmi.classes.TestBabyCow
import dorkboxTest.network.rmi.classes.TestCow import dorkboxTest.network.rmi.classes.TestCow
@ -37,7 +37,7 @@ object TestServer {
val configuration = BaseTest.serverConfig() val configuration = BaseTest.serverConfig()
RmiTest.register(configuration.serialization) RmiCommonTest.register(configuration.serialization)
configuration.serialization.register(TestBabyCow::class.java) configuration.serialization.register(TestBabyCow::class.java)
configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java) configuration.serialization.registerRmi(TestCow::class.java, TestCowImpl::class.java)
configuration.enableRemoteSignatureValidation = false configuration.enableRemoteSignatureValidation = false