test: i hate this
This commit is contained in:
parent
c700a6c43c
commit
f00dd85502
@ -63,9 +63,6 @@ lazy val root = project
|
||||
},
|
||||
cargoBuild := {
|
||||
println(Seq("sh", "-c", "cd glue; cargo rustc -- -Awarnings") !!)
|
||||
// println(
|
||||
// Seq("sh", "-c", "cd glue; RUST_BACKTRACE=full cargo test --quiet --features e2e") !!
|
||||
// ) // very important: test suite validates interfaces
|
||||
},
|
||||
fullBuild := {
|
||||
cargoBuild.value
|
||||
|
8
glue/Cargo.lock
generated
8
glue/Cargo.lock
generated
@ -580,11 +580,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toad-jni"
|
||||
version = "0.8.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0bb1a31e7259c1338191283a47f7cb8ae7f51eb62455fd7e123d2be304f1894"
|
||||
checksum = "ef61b22c3478d481635b9eb67496d4dc18f22b8321961aca5dc2084f5253ccb7"
|
||||
dependencies = [
|
||||
"jni",
|
||||
"nb",
|
||||
"no-std-net",
|
||||
"tinyvec",
|
||||
"toad",
|
||||
"toad-array 0.5.0",
|
||||
"toad-len",
|
||||
"toad-stem",
|
||||
|
@ -15,7 +15,7 @@ e2e = []
|
||||
jni = "0.21.1"
|
||||
nb = "1"
|
||||
toad = "0.17.3"
|
||||
toad-jni = "0.8.0"
|
||||
toad-jni = "0.9.1"
|
||||
no-std-net = "0.6"
|
||||
toad-msg = "0.18.1"
|
||||
tinyvec = {version = "1.5", default_features = false, features = ["rustc_1_55"]}
|
||||
|
@ -6,8 +6,27 @@ use jni::JavaVM;
|
||||
use mem::SharedMemoryRegion;
|
||||
|
||||
mod runtime {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use toad::platform::Effect;
|
||||
use toad::std::{dtls, Platform};
|
||||
use toad::step::runtime::std::Runtime as DefaultSteps;
|
||||
use toad_jni::java::nio::channels::PeekableDatagramChannel;
|
||||
use toad_msg::{OptValue, OptNumber};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct PlatformTypes;
|
||||
|
||||
impl toad::platform::PlatformTypes for PlatformTypes {
|
||||
type MessagePayload = Vec<u8>;
|
||||
type MessageOptionBytes = Vec<u8>;
|
||||
type MessageOptionMapOptionValues = Vec<OptValue<Vec<u8>>>;
|
||||
type MessageOptions = BTreeMap<OptNumber, Vec<OptValue<Vec<u8>>>>;
|
||||
type Clock = toad::std::Clock;
|
||||
type Socket = PeekableDatagramChannel;
|
||||
type Effects = Vec<Effect<Self>>;
|
||||
}
|
||||
|
||||
pub type Runtime = Platform<dtls::N, DefaultSteps<dtls::N>>;
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
package dev.toad;
|
||||
|
||||
import dev.toad.ffi.*;
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class Toad {
|
||||
public final class Toad implements AutoCloseable {
|
||||
|
||||
static native Config defaultConfigImpl();
|
||||
|
||||
@ -26,34 +30,36 @@ public final class Toad {
|
||||
|
||||
final Ptr ptr;
|
||||
final Config config;
|
||||
final DatagramChannel channel;
|
||||
|
||||
static native long init(Config o);
|
||||
|
||||
static native Optional<dev.toad.msg.ref.Message> pollReq(long ptr);
|
||||
native Optional<dev.toad.msg.ref.Message> pollReq(long ptr);
|
||||
|
||||
static native Optional<dev.toad.msg.ref.Message> pollResp(
|
||||
native Optional<dev.toad.msg.ref.Message> pollResp(
|
||||
long ptr,
|
||||
dev.toad.msg.Token t,
|
||||
InetSocketAddress n
|
||||
);
|
||||
|
||||
Optional<dev.toad.msg.ref.Message> pollReq() {
|
||||
return Toad.pollReq(this.ptr.addr());
|
||||
return this.pollReq(this.ptr.addr());
|
||||
}
|
||||
|
||||
Optional<dev.toad.msg.ref.Message> pollResp(
|
||||
dev.toad.msg.Token regarding,
|
||||
InetSocketAddress from
|
||||
) {
|
||||
return Toad.pollResp(this.ptr.addr(), regarding, from);
|
||||
return this.pollResp(this.ptr.addr(), regarding, from);
|
||||
}
|
||||
|
||||
public static BuilderRequiresBindToAddress builder() {
|
||||
public static BuilderRequiresSocket builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
Toad(Config o) {
|
||||
Toad(Config o, DatagramChannel channel) {
|
||||
this.config = o;
|
||||
this.channel = channel;
|
||||
this.ptr = Ptr.register(this.getClass(), this.init(o));
|
||||
}
|
||||
|
||||
@ -61,22 +67,33 @@ public final class Toad {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
public interface BuilderRequiresBindToAddress {
|
||||
Toad.Builder port(short port);
|
||||
Toad.Builder address(InetSocketAddress addr);
|
||||
@Override
|
||||
public void close() {
|
||||
this.ptr.release();
|
||||
}
|
||||
|
||||
public static final class Builder implements BuilderRequiresBindToAddress {
|
||||
public interface BuilderRequiresSocket {
|
||||
Toad.Builder port(short port);
|
||||
Toad.Builder address(InetSocketAddress addr);
|
||||
Toad.Builder channel(DatagramChannel channel);
|
||||
}
|
||||
|
||||
public static final class Builder implements BuilderRequiresSocket {
|
||||
|
||||
Optional<IOException> ioException = Optional.empty();
|
||||
Config.Msg.Builder msg = Config.Msg.builder();
|
||||
Optional<InetSocketAddress> addr = Optional.empty();
|
||||
Optional<DatagramChannel> channel = Optional.empty();
|
||||
u8 concurrency = Toad.defaultConfig().concurrency;
|
||||
|
||||
Builder() {}
|
||||
|
||||
public Toad build() {
|
||||
var cfg = new Config(this.addr.get(), this.concurrency, this.msg.build());
|
||||
return new Toad(cfg);
|
||||
public Toad build() throws IOException {
|
||||
if (!this.ioException.isEmpty()) {
|
||||
var cfg = new Config(this.concurrency, this.msg.build());
|
||||
return new Toad(cfg, this.channel.get());
|
||||
} else {
|
||||
throw this.ioException.get();
|
||||
}
|
||||
}
|
||||
|
||||
public Builder msg(Function<Config.Msg.Builder, Config.Msg.Builder> f) {
|
||||
@ -89,7 +106,20 @@ public final class Toad {
|
||||
}
|
||||
|
||||
public Builder address(InetSocketAddress addr) {
|
||||
this.addr = Optional.of(addr);
|
||||
try {
|
||||
DatagramChannel channel = DatagramChannel.open(
|
||||
java.net.StandardProtocolFamily.INET
|
||||
);
|
||||
channel.bind(addr);
|
||||
return this.channel(channel);
|
||||
} catch (java.io.IOException e) {
|
||||
this.ioException = Optional.of(e);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public Builder channel(DatagramChannel channel) {
|
||||
this.channel = Optional.of(channel);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -101,12 +131,10 @@ public final class Toad {
|
||||
|
||||
public static final class Config {
|
||||
|
||||
final InetSocketAddress addr;
|
||||
final u8 concurrency;
|
||||
final Msg msg;
|
||||
|
||||
Config(InetSocketAddress addr, u8 concurrency, Msg msg) {
|
||||
this.addr = addr;
|
||||
Config(u8 concurrency, Msg msg) {
|
||||
this.concurrency = concurrency;
|
||||
this.msg = msg;
|
||||
}
|
||||
@ -114,9 +142,7 @@ public final class Toad {
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return switch (other) {
|
||||
case Config o -> o.addr == this.addr &&
|
||||
o.concurrency == this.concurrency &&
|
||||
o.msg == this.msg;
|
||||
case Config o -> o.concurrency == this.concurrency && o.msg == this.msg;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
423
src/test/java/Mock.java
Normal file
423
src/test/java/Mock.java
Normal file
@ -0,0 +1,423 @@
|
||||
package mock.java.nio.channels;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.GatheringByteChannel;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.ScatteringByteChannel;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.nio.channels.spi.AbstractSelectableChannel;
|
||||
import java.nio.channels.spi.AbstractSelectionKey;
|
||||
import java.nio.channels.spi.AbstractSelector;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Set;
|
||||
|
||||
public class Mock {
|
||||
|
||||
public static class DatagramSocket extends java.net.DatagramSocket {
|
||||
|
||||
public InetSocketAddress address;
|
||||
|
||||
public DatagramSocket(int port)
|
||||
throws SocketException, UnknownHostException {
|
||||
var addr = InetAddress.getByAddress(new byte[] { 127, 0, 0, 1 });
|
||||
this.address = new InetSocketAddress(addr, port);
|
||||
}
|
||||
|
||||
public DatagramSocket(int port, InetAddress addr) throws SocketException {
|
||||
this.address = new InetSocketAddress(addr, port);
|
||||
}
|
||||
|
||||
public InetSocketAddress address() {
|
||||
return this.address;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Channel
|
||||
extends DatagramChannel
|
||||
implements
|
||||
WritableByteChannel,
|
||||
GatheringByteChannel,
|
||||
ScatteringByteChannel,
|
||||
ReadableByteChannel {
|
||||
|
||||
public Map<SocketAddress, List<ByteBuffer>> sent = new HashMap<>();
|
||||
public Map<SocketAddress, List<ByteBuffer>> recv = new HashMap<>();
|
||||
public List<Byte> bytes = new ArrayList<>();
|
||||
public DatagramSocket sock;
|
||||
|
||||
public Channel() throws SocketException, UnknownHostException {
|
||||
this(new DatagramSocket(1234));
|
||||
}
|
||||
|
||||
public Channel(DatagramSocket sock)
|
||||
throws SocketException, UnknownHostException {
|
||||
super(new SelectorProvider());
|
||||
this.sock = sock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int send(ByteBuffer src, SocketAddress target) {
|
||||
var sent = this.sent.get(target);
|
||||
if (sent == null) {
|
||||
var list = new ArrayList<ByteBuffer>();
|
||||
this.sent.put(target, list);
|
||||
}
|
||||
|
||||
this.sent.get(target).add(src);
|
||||
|
||||
return (int) src.capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress receive(ByteBuffer dst) {
|
||||
for (Map.Entry<SocketAddress, List<ByteBuffer>> ent : this.recv.entrySet()) {
|
||||
if (ent.getValue().size() == 0) {
|
||||
this.recv.remove(ent.getKey());
|
||||
} else {
|
||||
var buf = ent.getValue().remove(0);
|
||||
dst.put(buf);
|
||||
return ent.getKey();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int write(ByteBuffer src) {
|
||||
src.rewind();
|
||||
for (int j = 0; j < src.capacity(); j++) {
|
||||
this.bytes.add(src.get(j));
|
||||
}
|
||||
|
||||
return (int) src.capacity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long write(ByteBuffer[] srcs, int offset, int length) {
|
||||
long writ = 0;
|
||||
for (ByteBuffer buf : srcs) {
|
||||
writ += this.write(buf);
|
||||
}
|
||||
return writ;
|
||||
}
|
||||
|
||||
public int read(ByteBuffer dst, int start) {
|
||||
int orig = (int) dst.position();
|
||||
for (Byte b : this.bytes.subList(start, this.bytes.size())) {
|
||||
dst.put(b);
|
||||
}
|
||||
|
||||
return (int) dst.position() - orig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(ByteBuffer dst) {
|
||||
return this.read(dst, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long read(ByteBuffer[] dsts, int off, int len) {
|
||||
long n = 0;
|
||||
for (ByteBuffer buf : dsts) {
|
||||
n += this.read(buf, (int) n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implConfigureBlocking(boolean b) {}
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() {}
|
||||
|
||||
@Override
|
||||
public SocketAddress getLocalAddress() {
|
||||
return this.sock.address();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketAddress getRemoteAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramChannel disconnect() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramChannel bind(SocketAddress local) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramChannel connect(SocketAddress remote) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnected() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatagramSocket socket() {
|
||||
return this.sock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MembershipKey join(InetAddress group, NetworkInterface interf) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MembershipKey join(
|
||||
InetAddress group,
|
||||
NetworkInterface interf,
|
||||
InetAddress source
|
||||
) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DatagramChannel setOption(SocketOption<T> name, T value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getOption(SocketOption<T> name) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SocketOption<?>> supportedOptions() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
public static class Pipe extends java.nio.channels.Pipe {
|
||||
|
||||
public SinkChannel sink;
|
||||
public SourceChannel source;
|
||||
|
||||
public Pipe() throws SocketException, UnknownHostException {
|
||||
this.sink = new SinkChannel();
|
||||
this.source = new SourceChannel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SinkChannel sink() {
|
||||
return this.sink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SourceChannel source() {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
public static class SinkChannel
|
||||
extends java.nio.channels.Pipe.SinkChannel
|
||||
implements WritableByteChannel, GatheringByteChannel {
|
||||
|
||||
public SinkChannel() throws SocketException, UnknownHostException {
|
||||
super(new SelectorProvider());
|
||||
this.channel = new Channel();
|
||||
}
|
||||
|
||||
public Channel channel;
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() {}
|
||||
|
||||
@Override
|
||||
public void implConfigureBlocking(boolean block) {}
|
||||
|
||||
@Override
|
||||
public int write(ByteBuffer src) {
|
||||
return this.channel.write(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long write(ByteBuffer[] srcs) throws IOException {
|
||||
return this.channel.write(srcs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long write(ByteBuffer[] srcs, int offset, int length) {
|
||||
return this.channel.write(srcs, offset, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceChannel
|
||||
extends java.nio.channels.Pipe.SourceChannel {
|
||||
|
||||
public Channel channel;
|
||||
|
||||
public SourceChannel() throws SocketException, UnknownHostException {
|
||||
super(new SelectorProvider());
|
||||
this.channel = new Channel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implCloseSelectableChannel() {}
|
||||
|
||||
@Override
|
||||
public void implConfigureBlocking(boolean block) {}
|
||||
|
||||
@Override
|
||||
public int read(ByteBuffer buf) {
|
||||
return this.channel.read(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long read(ByteBuffer[] dsts) throws IOException {
|
||||
return this.channel.read(dsts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long read(ByteBuffer[] dsts, int off, int len) {
|
||||
return this.channel.read(dsts, off, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SelectionKey extends AbstractSelectionKey {
|
||||
|
||||
public SelectionKey() {}
|
||||
|
||||
@Override
|
||||
public int readyOps() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int interestOps() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.SelectionKey interestOps(int o) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.Selector selector() {
|
||||
return new Selector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.SelectableChannel channel() {
|
||||
try {
|
||||
return new Channel();
|
||||
} catch (UnknownHostException e) {
|
||||
throw new Error(e);
|
||||
} catch (SocketException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Selector extends AbstractSelector {
|
||||
|
||||
public Selector() {
|
||||
super(new SelectorProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void implCloseSelector() {}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.SelectionKey register(
|
||||
AbstractSelectableChannel ch,
|
||||
int ops,
|
||||
Object att
|
||||
) {
|
||||
return new SelectionKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.Selector wakeup() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int select(long timeout) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int select() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int selectNow() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.nio.channels.SelectionKey> selectedKeys() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<java.nio.channels.SelectionKey> keys() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
}
|
||||
|
||||
public static class SelectorProvider
|
||||
extends java.nio.channels.spi.SelectorProvider {
|
||||
|
||||
@Override
|
||||
public java.nio.channels.DatagramChannel openDatagramChannel() {
|
||||
return this.openDatagramChannel(StandardProtocolFamily.INET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.nio.channels.DatagramChannel openDatagramChannel(
|
||||
ProtocolFamily proto
|
||||
) {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketChannel openSocketChannel() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerSocketChannel openServerSocketChannel() {
|
||||
throw new Error("unimplemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractSelector openSelector() {
|
||||
return new Selector();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pipe openPipe() throws SocketException, UnknownHostException {
|
||||
return new Pipe();
|
||||
}
|
||||
}
|
||||
}
|
4
src/test/scala/.Client.scala.kak.mmSB4r
Normal file
4
src/test/scala/.Client.scala.kak.mmSB4r
Normal file
@ -0,0 +1,4 @@
|
||||
class Client extends munit.FunSuite {
|
||||
test("client gets") {
|
||||
}
|
||||
}
|
8
src/test/scala/E2E.scala
Normal file
8
src/test/scala/E2E.scala
Normal file
@ -0,0 +1,8 @@
|
||||
import dev.toad.*;
|
||||
import mock.java.nio.channels.Mock;
|
||||
|
||||
class E2E extends munit.FunSuite {
|
||||
test("foo") {
|
||||
val mock = Mock.Channel();
|
||||
}
|
||||
}
|
7
src/test/scala/Glue.scala
Normal file
7
src/test/scala/Glue.scala
Normal file
@ -0,0 +1,7 @@
|
||||
import sys.process._
|
||||
|
||||
class Glue extends munit.FunSuite {
|
||||
test("cargo test") {
|
||||
Seq("sh", "-c", "cd glue; RUST_BACKTRACE=full cargo test --quiet --features e2e").!!
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
// For more information on writing tests, see
|
||||
// https://scalameta.org/munit/docs/getting-started.html
|
||||
class MySuite extends munit.FunSuite {
|
||||
test("example test that succeeds") {
|
||||
val obtained = 42
|
||||
val expected = 42
|
||||
assertEquals(obtained, expected)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user