From 71589b4c4ad8c2cd01ee5fc653f02f7dfc8094cc Mon Sep 17 00:00:00 2001 From: Mariano Barrios Date: Sun, 29 Oct 2023 15:48:02 +0100 Subject: [PATCH] Migrate some test utilities to Java --- .../helpers/BlockerByteChannel.java | 60 +++++++ .../helpers/BlockerByteChannel.scala | 25 --- .../tlschannel/helpers/NullSslContext.java | 50 ++++++ .../tlschannel/helpers/NullSslContext.scala | 20 --- .../tlschannel/helpers/NullSslEngine.java | 151 ++++++++++++++++++ .../tlschannel/helpers/NullSslEngine.scala | 74 --------- .../helpers/RandomChunkingByteChannel.java | 58 +++++++ .../helpers/RandomChunkingByteChannel.scala | 37 ----- 8 files changed, 319 insertions(+), 156 deletions(-) create mode 100644 src/test/scala/tlschannel/helpers/BlockerByteChannel.java delete mode 100644 src/test/scala/tlschannel/helpers/BlockerByteChannel.scala create mode 100644 src/test/scala/tlschannel/helpers/NullSslContext.java delete mode 100644 src/test/scala/tlschannel/helpers/NullSslContext.scala create mode 100644 src/test/scala/tlschannel/helpers/NullSslEngine.java delete mode 100644 src/test/scala/tlschannel/helpers/NullSslEngine.scala create mode 100644 src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.java delete mode 100644 src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.scala diff --git a/src/test/scala/tlschannel/helpers/BlockerByteChannel.java b/src/test/scala/tlschannel/helpers/BlockerByteChannel.java new file mode 100644 index 00000000..524a4846 --- /dev/null +++ b/src/test/scala/tlschannel/helpers/BlockerByteChannel.java @@ -0,0 +1,60 @@ +package tlschannel.helpers; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousByteChannel; +import java.nio.channels.ByteChannel; +import java.util.concurrent.ExecutionException; + +import tlschannel.WouldBlockException; + +/** + * Transforms a non-blocking {@link ByteChannel} into a blocking one. + */ +class BlockerByteChannel implements ByteChannel { + + private final AsynchronousByteChannel impl; + + public BlockerByteChannel(AsynchronousByteChannel impl) { + this.impl = impl; + } + + @Override + public int write(ByteBuffer src)throws IOException { + try { + return impl.write(src).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + @Override + public int read(ByteBuffer dst) throws IOException { + try { + return impl.read(dst).get(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + @Override + public boolean isOpen() { + return impl.isOpen(); + } + + @Override + public void close() throws IOException { + try { + impl.close(); + } catch (WouldBlockException e) { + // OK + } + } + +} diff --git a/src/test/scala/tlschannel/helpers/BlockerByteChannel.scala b/src/test/scala/tlschannel/helpers/BlockerByteChannel.scala deleted file mode 100644 index 5ae7f2f6..00000000 --- a/src/test/scala/tlschannel/helpers/BlockerByteChannel.scala +++ /dev/null @@ -1,25 +0,0 @@ -package tlschannel.helpers - -import java.nio.ByteBuffer -import java.nio.channels.AsynchronousByteChannel -import java.nio.channels.ByteChannel - -import tlschannel.WouldBlockException - -class BlockerByteChannel(impl: AsynchronousByteChannel) extends ByteChannel { - - override def write(src: ByteBuffer) = impl.write(src).get() - - override def read(dst: ByteBuffer) = impl.read(dst).get() - - override def isOpen = impl.isOpen - - override def close() = { - try { - impl.close() - } catch { - case _: WouldBlockException => // OK - } - } - -} diff --git a/src/test/scala/tlschannel/helpers/NullSslContext.java b/src/test/scala/tlschannel/helpers/NullSslContext.java new file mode 100644 index 00000000..5c344812 --- /dev/null +++ b/src/test/scala/tlschannel/helpers/NullSslContext.java @@ -0,0 +1,50 @@ +package tlschannel.helpers; + +import javax.net.ssl.*; +import java.security.SecureRandom; + + +public class NullSslContext extends SSLContext { + public NullSslContext() { + super(new NullSslContextSpi(), null, null); + } + +} + +class NullSslContextSpi extends SSLContextSpi { + + @Override + public SSLEngine engineCreateSSLEngine() { + return new NullSslEngine(); + } + + @Override + public SSLEngine engineCreateSSLEngine(String s, int i) { + throw new UnsupportedOperationException(); + } + + @Override + public SSLSessionContext engineGetClientSessionContext() { + throw new UnsupportedOperationException(); + } + + @Override + public SSLSessionContext engineGetServerSessionContext() { + throw new UnsupportedOperationException(); + } + @Override + public SSLServerSocketFactory engineGetServerSocketFactory() { + throw new UnsupportedOperationException(); + } + + @Override + public SSLSocketFactory engineGetSocketFactory() { + throw new UnsupportedOperationException(); + } + + @Override + public void engineInit(KeyManager[] km, TrustManager[] tm, SecureRandom sc) { + throw new UnsupportedOperationException(); + } + +} \ No newline at end of file diff --git a/src/test/scala/tlschannel/helpers/NullSslContext.scala b/src/test/scala/tlschannel/helpers/NullSslContext.scala deleted file mode 100644 index 7ce33b02..00000000 --- a/src/test/scala/tlschannel/helpers/NullSslContext.scala +++ /dev/null @@ -1,20 +0,0 @@ -package tlschannel.helpers - -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLContextSpi -import javax.net.ssl.KeyManager -import javax.net.ssl.TrustManager -import java.security.SecureRandom - -class NullSslContextSpi extends SSLContextSpi { - override def engineCreateSSLEngine() = new NullSslEngine - def engineCreateSSLEngine(x$1: String, x$2: Int) = throw new UnsupportedOperationException - def engineGetClientSessionContext() = throw new UnsupportedOperationException - def engineGetServerSessionContext() = throw new UnsupportedOperationException - def engineGetServerSocketFactory() = throw new UnsupportedOperationException - def engineGetSocketFactory() = throw new UnsupportedOperationException - def engineInit(x$1: Array[KeyManager], x$2: Array[TrustManager], x$3: SecureRandom): Unit = - throw new UnsupportedOperationException -} - -class NullSslContext extends SSLContext(new NullSslContextSpi, null, null) diff --git a/src/test/scala/tlschannel/helpers/NullSslEngine.java b/src/test/scala/tlschannel/helpers/NullSslEngine.java new file mode 100644 index 00000000..1687d91e --- /dev/null +++ b/src/test/scala/tlschannel/helpers/NullSslEngine.java @@ -0,0 +1,151 @@ +package tlschannel.helpers; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import java.nio.ByteBuffer; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLSession; + +import tlschannel.impl.ByteBufferSet; +import tlschannel.impl.ByteBufferUtil; + +/** + * "Null" {@link SSLEngine} that does nothing to the bytesProduced. + */ +class NullSslEngine extends SSLEngine { + + /** Internal buffers are still used to prevent any underlying optimization of the wrap/unwrap. + */ + private final int bufferSize = 16000; + + @Override + public void beginHandshake() {} + + @Override + public void closeInbound() {} + + @Override + public void closeOutbound() {} + + @Override + public Runnable getDelegatedTask() { + return null; + } + + @Override + public boolean getEnableSessionCreation() { + return true; + } + + @Override + public String[] getEnabledCipherSuites() { + return new String[]{}; + } + + @Override + public String[] getEnabledProtocols() { + return new String[]{}; + } + + @Override + public HandshakeStatus getHandshakeStatus() { + return HandshakeStatus.NOT_HANDSHAKING; + } + + @Override + public boolean getNeedClientAuth() { + return false; + } + + @Override + public SSLSession getSession() { + return new NullSslSession(bufferSize); + } + + @Override + public String[] getSupportedCipherSuites() { + return new String[]{}; + } + + @Override + public String[] getSupportedProtocols(){ + return new String[]{}; + } + + @Override + public boolean getUseClientMode() { + return true; + } + + @Override + public boolean getWantClientAuth() { + return false; + } + + @Override + public boolean isInboundDone() { + return false; + } + + @Override + public boolean isOutboundDone() { + return false; + } + + @Override + public void setEnableSessionCreation(boolean b) {} + + @Override + public void setEnabledCipherSuites(String[] a) {} + + @Override + public void setEnabledProtocols(String[] a) {} + + @Override + public void setNeedClientAuth(boolean b) {} + + @Override + public void setUseClientMode(boolean b) {} + + @Override + public void setWantClientAuth(boolean b) {} + + private final ByteBuffer unwrapBuffer = ByteBuffer.allocate(bufferSize); + private final ByteBuffer wrapBuffer = ByteBuffer.allocate(bufferSize); + + @Override + public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length) { + var dstSet = new ByteBufferSet(dsts, offset, length); + if (!src.hasRemaining()) { + return new SSLEngineResult(Status.BUFFER_UNDERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0); + } + int unwrapSize = Math.min(unwrapBuffer.capacity(), src.remaining()); + if (dstSet.remaining() < unwrapSize) { + return new SSLEngineResult(Status.BUFFER_OVERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0); + } + unwrapBuffer.clear(); + ByteBufferUtil.copy(src, unwrapBuffer, unwrapSize); + unwrapBuffer.flip(); + dstSet.putRemaining(unwrapBuffer); + return new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, unwrapSize, unwrapSize); + } + + @Override + public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst) { + var srcSet = new ByteBufferSet(srcs, offset, length); + if (!srcSet.hasRemaining()) { + return new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, 0, 0); + } + int wrapSize = (int) Math.min(wrapBuffer.capacity(), srcSet.remaining()); + if (dst.remaining() < wrapSize) { + return new SSLEngineResult(Status.BUFFER_OVERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0); + } + wrapBuffer.clear(); + srcSet.get(wrapBuffer, wrapSize); + wrapBuffer.flip(); + dst.put(wrapBuffer); + return new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, wrapSize, wrapSize); + } + +} diff --git a/src/test/scala/tlschannel/helpers/NullSslEngine.scala b/src/test/scala/tlschannel/helpers/NullSslEngine.scala deleted file mode 100644 index 885f321d..00000000 --- a/src/test/scala/tlschannel/helpers/NullSslEngine.scala +++ /dev/null @@ -1,74 +0,0 @@ -package tlschannel.helpers - -import javax.net.ssl.SSLEngine -import javax.net.ssl.SSLEngineResult.HandshakeStatus -import java.nio.ByteBuffer -import javax.net.ssl.SSLEngineResult -import javax.net.ssl.SSLEngineResult.Status - -import tlschannel.impl.{ByteBufferSet, ByteBufferUtil} - -/* - * "Null" {@link SSLEngine} that does nothing to the bytesProduced. - */ -class NullSslEngine extends SSLEngine { - - /** Internal buffers are still used to prevent any underlying optimization of the wrap/unwrap. - */ - val bufferSize = 16000 - - def beginHandshake() = {} - def closeInbound() = {} - def closeOutbound() = {} - def getDelegatedTask() = null - def getEnableSessionCreation() = true - def getEnabledCipherSuites() = Array() - def getEnabledProtocols() = Array() - def getHandshakeStatus() = HandshakeStatus.NOT_HANDSHAKING - def getNeedClientAuth() = false - def getSession() = new NullSslSession(bufferSize) - def getSupportedCipherSuites() = Array() - def getSupportedProtocols() = Array() - def getUseClientMode() = true - def getWantClientAuth() = false - def isInboundDone() = false - def isOutboundDone() = false - def setEnableSessionCreation(b: Boolean) = {} - def setEnabledCipherSuites(a: Array[String]) = {} - def setEnabledProtocols(a: Array[String]) = {} - def setNeedClientAuth(b: Boolean) = {} - def setUseClientMode(b: Boolean) = {} - def setWantClientAuth(b: Boolean) = {} - - val unwrapBuffer = ByteBuffer.allocate(bufferSize) - val wrapBuffer = ByteBuffer.allocate(bufferSize) - - def unwrap(src: ByteBuffer, dsts: Array[ByteBuffer], offset: Int, length: Int): SSLEngineResult = { - val dstSet = new ByteBufferSet(dsts, offset, length) - if (!src.hasRemaining) - return new SSLEngineResult(Status.BUFFER_UNDERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0) - val unwrapSize = math.min(unwrapBuffer.capacity, src.remaining) - if (dstSet.remaining < unwrapSize) - return new SSLEngineResult(Status.BUFFER_OVERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0) - unwrapBuffer.clear() - ByteBufferUtil.copy(src, unwrapBuffer, unwrapSize) - unwrapBuffer.flip() - dstSet.putRemaining(unwrapBuffer) - new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, unwrapSize, unwrapSize) - } - - def wrap(srcs: Array[ByteBuffer], offset: Int, length: Int, dst: ByteBuffer): SSLEngineResult = { - val srcSet = new ByteBufferSet(srcs, offset, length) - if (!srcSet.hasRemaining) - return new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, 0, 0) - val wrapSize = math.min(wrapBuffer.capacity, srcSet.remaining).asInstanceOf[Int] - if (dst.remaining < wrapSize) - return new SSLEngineResult(Status.BUFFER_OVERFLOW, HandshakeStatus.NOT_HANDSHAKING, 0, 0) - wrapBuffer.clear() - srcSet.get(wrapBuffer, wrapSize) - wrapBuffer.flip() - dst.put(wrapBuffer) - new SSLEngineResult(Status.OK, HandshakeStatus.NOT_HANDSHAKING, wrapSize, wrapSize) - } - -} diff --git a/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.java b/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.java new file mode 100644 index 00000000..3eeae167 --- /dev/null +++ b/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.java @@ -0,0 +1,58 @@ +package tlschannel.helpers; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.util.function.IntSupplier; + +class RandomChunkingByteChannel implements ByteChannel { + + private final ByteChannel wrapped; + private final IntSupplier chunkSizeSupplier; + + public RandomChunkingByteChannel(ByteChannel wrapped, IntSupplier chunkSizeSupplier) { + this.wrapped = wrapped; + this.chunkSizeSupplier = chunkSizeSupplier; + } + + @Override + public void close() throws IOException { + wrapped.close(); + } + + @Override + public boolean isOpen() { + return wrapped.isOpen(); + } + + @Override + public int read(ByteBuffer in) throws IOException { + if (!in.hasRemaining()) { + return 0; + } + int oldLimit = in.limit(); + try { + int readSize = Math.min(chunkSizeSupplier.getAsInt(), in.remaining()); + in.limit(in.position() + readSize); + return wrapped.read(in); + } finally { + in.limit(oldLimit); + } + } + + @Override + public int write(ByteBuffer out) throws IOException { + if (!out.hasRemaining()) { + return 0; + } + int oldLimit = out.limit(); + try { + int writeSize = Math.min(chunkSizeSupplier.getAsInt(), out.remaining()); + out.limit(out.position() + writeSize); + return wrapped.write(out); + } finally { + out.limit(oldLimit); + } + } + +} diff --git a/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.scala b/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.scala deleted file mode 100644 index 53ff7d0d..00000000 --- a/src/test/scala/tlschannel/helpers/RandomChunkingByteChannel.scala +++ /dev/null @@ -1,37 +0,0 @@ -package tlschannel.helpers - -import java.nio.ByteBuffer -import java.nio.channels.ByteChannel - -class RandomChunkingByteChannel(val wrapped: ByteChannel, chunkSizeSupplier: () => Int) extends ByteChannel { - - def close() = wrapped.close() - def isOpen() = wrapped.isOpen() - - def read(in: ByteBuffer): Int = { - if (!in.hasRemaining) - return 0 - val oldLimit = in.limit() - try { - val readSize = math.min(chunkSizeSupplier(), in.remaining()) - in.limit(in.position() + readSize) - wrapped.read(in) - } finally { - in.limit(oldLimit) - } - } - - def write(out: ByteBuffer): Int = { - if (!out.hasRemaining) - return 0 - val oldLimit = out.limit() - try { - val writeSize = math.min(chunkSizeSupplier(), out.remaining()) - out.limit(out.position() + writeSize) - wrapped.write(out) - } finally { - out.limit(oldLimit) - } - } - -}