): PassKey?
+
+ /**
+ * Generates a secret symmetric key from the given passphrase.
+ *
+ * Be sure to not compromise the key! Only keep it in memory, do not write to disk. The key should
+ * only be used with the other functions in this module, as it includes a salt.
+ *
+ * Note that this function is not deterministic; to derive the same key from a password, you also
+ * must know the random salt that was used. See below.
+ *
+ * @param passphrase A non-empty byte array containing the passphrase.
+ * @return the generated symmetric key.
+ */
+ // @throws[ToxKeyDerivationException]
+ fun passKeyDerive(passphrase: ByteArray): PassKey
+
+ /**
+ * Same as above, except use the given salt for deterministic key derivation.
+ *
+ * @param passphrase A non-empty byte array containing the passphrase.
+ * @param salt Array of size [[ToxCryptoConstants.SaltLength]].
+ */
+ // @throws[ToxKeyDerivationException]
+ fun passKeyDeriveWithSalt(passphrase: ByteArray, salt: ByteArray): PassKey
+
+ /**
+ * This retrieves the salt used to encrypt the given data, which can then be passed to
+ * [[passKeyDeriveWithSalt]] to produce the same key as was previously used. Any encrypted data
+ * with this module can be used as input.
+ *
+ * Success does not say anything about the validity of the data, only that data of the appropriate
+ * size was copied.
+ *
+ * @return the salt, or an empty array if the magic number did not match.
+ */
+ // @throws[ToxGetSaltException]
+ fun getSalt(data: ByteArray): ByteArray
+
+ /* Now come the functions that are analogous to the part 2 functions. */
+
+ /**
+ * Encrypt arbitrary data with a key produced by [[passKeyDerive]] or [[passKeyDeriveWithSalt]].
+ *
+ * The output array will be [[ToxCryptoConstants.EncryptionExtraLength]] bytes longer than the
+ * input array.
+ *
+ * The result will be different on each call.
+ *
+ * @return the encrypted output array.
+ */
+ // @throws[ToxEncryptionException]
+ fun encrypt(data: ByteArray, passKey: PassKey): ByteArray
+
+ /**
+ * This is the inverse of [[encrypt]], also using only keys produced by [[passKeyDerive]].
+ *
+ * The output data has size data_length - [[ToxCryptoConstants.EncryptionExtraLength]].
+ *
+ * @return the decrypted output array.
+ */
+ // @throws[ToxDecryptionException]
+ fun decrypt(data: ByteArray, passKey: PassKey): ByteArray
+
+ /** Determines whether or not the given data is encrypted (by checking the magic number) */
+ fun isDataEncrypted(data: ByteArray): Boolean
+
+ /**
+ * Generates a cryptographic hash of the given data.
+ *
+ * This function may be used by clients for any purpose, but is provided primarily for validating
+ * cached avatars. This use is highly recommended to avoid unnecessary avatar updates.
+ *
+ * This function is a wrapper to internal message-digest functions.
+ *
+ * @param data Data to be hashed.
+ * @return hash of the data.
+ */
+ fun hash(data: ByteArray): ByteArray
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/ToxCryptoConstants.kt b/src/main/java/im/tox/tox4j/crypto/ToxCryptoConstants.kt
new file mode 100644
index 000000000..1e69eea13
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/ToxCryptoConstants.kt
@@ -0,0 +1,27 @@
+package im.tox.tox4j.crypto
+
+object ToxCryptoConstants {
+
+ /** Length of salt in bytes. */
+ val SaltLength = 32
+
+ /**
+ * The number of bytes in a serialised [[ToxCrypto.PassKey]] without salt. The serialised size is
+ * [[KeyLength]] + [[SaltLength]].
+ */
+ val KeyLength = 32
+
+ /** Number of bytes added to any encrypted data. */
+ val EncryptionExtraLength = 80
+
+ /** The number of bytes in a hash generated by tox_hash. */
+ val HashLength = 32
+
+ val PublicKeyLength = 32
+ val SecretKeyLength = 32
+ val SharedKeyLength = 32
+ val NonceLength = 24
+
+ val ZeroBytes = 32
+ val BoxZeroBytes = 16
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/Makefile b/src/main/java/im/tox/tox4j/crypto/exceptions/Makefile
new file mode 100644
index 000000000..cbc0eac30
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/Makefile
@@ -0,0 +1,2 @@
+all: ../../mkexceptions exceptions.json
+ $+
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/ToxDecryptionException.java b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxDecryptionException.java
new file mode 100644
index 000000000..a3304b3bb
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxDecryptionException.java
@@ -0,0 +1,41 @@
+package im.tox.tox4j.crypto.exceptions;
+
+import im.tox.tox4j.exceptions.ToxException;
+
+public final class ToxDecryptionException extends ToxException {
+ public enum Code {
+ /**
+ * The input data is missing the magic number (i.e. wasn't created by this
+ * module, or is corrupted)
+ */
+ BAD_FORMAT,
+ /**
+ * The encrypted byte array could not be decrypted. Either the data was
+ * corrupt or the password/key was incorrect.
+ */
+ FAILED,
+ /**
+ * The input data was shorter than {@link
+ * ToxCryptoConstants.ENCRYPTION_EXTRA_LENGTH} bytes.
+ */
+ INVALID_LENGTH,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ KEY_DERIVATION_FAILED,
+ /**
+ * The key or input data was null or empty.
+ */
+ NULL,
+ }
+
+ public ToxDecryptionException(Code code) {
+ this(code, "");
+ }
+
+ public ToxDecryptionException(Code code, String message) {
+ super(code, message);
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/ToxEncryptionException.java b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxEncryptionException.java
new file mode 100644
index 000000000..bf0ff894e
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxEncryptionException.java
@@ -0,0 +1,30 @@
+package im.tox.tox4j.crypto.exceptions;
+
+import im.tox.tox4j.exceptions.ToxException;
+
+public final class ToxEncryptionException extends ToxException {
+ public enum Code {
+ /**
+ * The encryption itself failed.
+ */
+ FAILED,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ KEY_DERIVATION_FAILED,
+ /**
+ * The key or input data was null or empty.
+ */
+ NULL,
+ }
+
+ public ToxEncryptionException(Code code) {
+ this(code, "");
+ }
+
+ public ToxEncryptionException(Code code, String message) {
+ super(code, message);
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/ToxGetSaltException.java b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxGetSaltException.java
new file mode 100644
index 000000000..7e631b47d
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxGetSaltException.java
@@ -0,0 +1,25 @@
+package im.tox.tox4j.crypto.exceptions;
+
+import im.tox.tox4j.exceptions.ToxException;
+
+public final class ToxGetSaltException extends ToxException {
+ public enum Code {
+ /**
+ * The input data is missing the magic number (i.e. wasn't created by this
+ * module, or is corrupted)
+ */
+ BAD_FORMAT,
+ /**
+ * The data or salt were null.
+ */
+ NULL,
+ }
+
+ public ToxGetSaltException(Code code) {
+ this(code, "");
+ }
+
+ public ToxGetSaltException(Code code, String message) {
+ super(code, message);
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/ToxKeyDerivationException.java b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxKeyDerivationException.java
new file mode 100644
index 000000000..00e03d1b6
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/ToxKeyDerivationException.java
@@ -0,0 +1,31 @@
+package im.tox.tox4j.crypto.exceptions;
+
+import im.tox.tox4j.exceptions.JavaOnly;
+import im.tox.tox4j.exceptions.ToxException;
+
+public final class ToxKeyDerivationException extends ToxException {
+ public enum Code {
+ /**
+ * The salt was of incorrect length.
+ */
+ @JavaOnly INVALID_LENGTH,
+ /**
+ * The crypto lib was unable to derive a key from the given passphrase,
+ * which is usually a lack of memory issue. The functions accepting keys
+ * do not produce this error.
+ */
+ FAILED,
+ /**
+ * The passphrase was null or empty.
+ */
+ NULL,
+ }
+
+ public ToxKeyDerivationException(Code code) {
+ this(code, "");
+ }
+
+ public ToxKeyDerivationException(Code code, String message) {
+ super(code, message);
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/crypto/exceptions/exceptions.json b/src/main/java/im/tox/tox4j/crypto/exceptions/exceptions.json
new file mode 100644
index 000000000..e9cb37cc8
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/crypto/exceptions/exceptions.json
@@ -0,0 +1,50 @@
+[
+ "crypto",
+ "",
+ {
+ "KeyDerivation": {
+ "NULL": ["The passphrase was null or empty."],
+ "FAILED": [
+ "The crypto lib was unable to derive a key from the given passphrase,",
+ "which is usually a lack of memory issue. The functions accepting keys",
+ "do not produce this error."
+ ],
+ "@JavaOnly INVALID_LENGTH": ["The salt was of incorrect length."]
+ },
+ "Encryption": {
+ "NULL": ["The key or input data was null or empty."],
+ "KEY_DERIVATION_FAILED": [
+ "The crypto lib was unable to derive a key from the given passphrase,",
+ "which is usually a lack of memory issue. The functions accepting keys",
+ "do not produce this error."
+ ],
+ "FAILED": ["The encryption itself failed."]
+ },
+ "Decryption": {
+ "NULL": ["The key or input data was null or empty."],
+ "INVALID_LENGTH": [
+ "The input data was shorter than {@link ToxCryptoConstants.ENCRYPTION_EXTRA_LENGTH} bytes."
+ ],
+ "BAD_FORMAT": [
+ "The input data is missing the magic number (i.e. wasn't created by this",
+ "module, or is corrupted)"
+ ],
+ "KEY_DERIVATION_FAILED": [
+ "The crypto lib was unable to derive a key from the given passphrase,",
+ "which is usually a lack of memory issue. The functions accepting keys",
+ "do not produce this error."
+ ],
+ "FAILED": [
+ "The encrypted byte array could not be decrypted. Either the data was",
+ "corrupt or the password/key was incorrect."
+ ]
+ },
+ "GetSalt": {
+ "NULL": ["The data or salt were null."],
+ "BAD_FORMAT": [
+ "The input data is missing the magic number (i.e. wasn't created by this",
+ "module, or is corrupted)"
+ ]
+ }
+ }
+]
diff --git a/src/main/java/im/tox/tox4j/exceptions/JavaOnly.java b/src/main/java/im/tox/tox4j/exceptions/JavaOnly.java
new file mode 100644
index 000000000..1da5c3670
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/exceptions/JavaOnly.java
@@ -0,0 +1,20 @@
+package im.tox.tox4j.exceptions;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark error codes in Java exception enums as Java-only, so they
+ * are not emitted as part of the error code conversion fragments in C++ (see
+ * {@link im.tox.tox4j.impl.jni.codegen.JniErrorCodes}).
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface JavaOnly {
+ /**
+ * This is just here so the annotation is retained at runtime.
+ */
+ String value() default "";
+}
diff --git a/src/main/java/im/tox/tox4j/exceptions/ToxException.kt b/src/main/java/im/tox/tox4j/exceptions/ToxException.kt
new file mode 100644
index 000000000..e0d7c5ec9
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/exceptions/ToxException.kt
@@ -0,0 +1,12 @@
+package im.tox.tox4j.exceptions
+
+abstract class ToxException constructor(val code: Enum<*>, private val extraMessage: String) :
+ Exception(extraMessage) {
+
+ final override val message: String
+ get() =
+ when (extraMessage) {
+ "" -> "Error code: " + code.name
+ else -> extraMessage + ", error code: " + code.name
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/exceptions/ToxKilledException.java b/src/main/java/im/tox/tox4j/exceptions/ToxKilledException.java
new file mode 100644
index 000000000..3212a9ce6
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/exceptions/ToxKilledException.java
@@ -0,0 +1,15 @@
+package im.tox.tox4j.exceptions;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Exception to be thrown when a method is invoked on a tox instance that has
+ * been closed.
+ *
+ * @author Simon Levermann (sonOfRa)
+ */
+public final class ToxKilledException extends RuntimeException {
+ public ToxKilledException(@NotNull String message) {
+ super(message);
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/impl/ToxImplBase.scala b/src/main/java/im/tox/tox4j/impl/ToxImplBase.scala
deleted file mode 100644
index 894cb48d3..000000000
--- a/src/main/java/im/tox/tox4j/impl/ToxImplBase.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package im.tox.tox4j.impl
-
-import com.typesafe.scalalogging.Logger
-import org.slf4j.LoggerFactory
-
-import scala.util.control.NonFatal
-
-object ToxImplBase {
-
- private val logger = Logger(LoggerFactory.getLogger(this.getClass))
-
- /**
- * Calls a callback and catches any [[NonFatal]] exceptions it throws and logs them.
- *
- * @param fatal If this is false, exceptions thrown by callbacks are caught and logged.
- * @param state State to pass through the callback.
- * @param eventHandler The callback object.
- * @param callback The method to call on the callback object.
- * @tparam T The type of the callback object.
- */
- @SuppressWarnings(Array("org.brianmckenna.wartremover.warts.Throw"))
- def tryAndLog[ToxCoreState, T](fatal: Boolean, state: ToxCoreState, eventHandler: T)(callback: T => ToxCoreState => ToxCoreState): ToxCoreState = {
- if (!fatal) {
- try {
- callback(eventHandler)(state)
- } catch {
- case NonFatal(e) =>
- logger.warn("Exception caught while executing " + eventHandler.getClass.getName, e)
- state
- }
- } else {
- callback(eventHandler)(state)
- }
- }
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/AutoGenerated.java b/src/main/java/im/tox/tox4j/impl/jni/AutoGenerated.java
deleted file mode 100644
index 5d8ff76c0..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/AutoGenerated.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package im.tox.tox4j.impl.jni;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Mark methods that are to be generated by JniMethodImpls.
- *
- * In {@link ToxCoreJni} and {@link ToxAvJni}, methods marked with this annotation do not need a manual
- * implementation in C++, as their JNI bridge implementations will be generated. This annotation exists only until the
- * majority of methods is generated, at which point there will be a "manual" override marker that inhibits
- * auto-generation. Ideally, all bridge method implementations will be generated, but in reality there are probably
- * going to be some complications that are too costly to overcome, so some manual overrides will remain.
- */
-@Retention(RetentionPolicy.RUNTIME)
-public @interface AutoGenerated {
- /**
- * Override the C function name this native method should call. By default, a method called e.g. toxFooBar will call
- * the C function tox_foo_bar. This can be overridden here.
- */
- String value() default "";
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.kt b/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.kt
new file mode 100644
index 000000000..17aad4a38
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.kt
@@ -0,0 +1,192 @@
+package im.tox.tox4j.impl.jni
+
+import com.google.protobuf.ByteString
+import im.tox.tox4j.av.callbacks.*
+import im.tox.tox4j.av.data.*
+import im.tox.tox4j.av.enums.ToxavFriendCallState
+import im.tox.tox4j.av.proto.*
+import im.tox.tox4j.core.data.ToxFriendNumber
+import java.util.EnumSet
+
+object ToxAvEventDispatch {
+
+ fun convert(channels: Int): AudioChannels =
+ when (channels) {
+ 1 -> AudioChannels.Mono
+ 2 -> AudioChannels.Stereo
+ else -> AudioChannels.Stereo
+ }
+
+ fun convert(kind: CallState.Kind): ToxavFriendCallState =
+ when (kind) {
+ CallState.Kind.ERROR -> ToxavFriendCallState.ERROR
+ CallState.Kind.FINISHED -> ToxavFriendCallState.FINISHED
+ CallState.Kind.SENDING_A -> ToxavFriendCallState.SENDING_A
+ CallState.Kind.SENDING_V -> ToxavFriendCallState.SENDING_V
+ CallState.Kind.ACCEPTING_A -> ToxavFriendCallState.ACCEPTING_A
+ CallState.Kind.ACCEPTING_V -> ToxavFriendCallState.ACCEPTING_V
+ CallState.Kind.UNRECOGNIZED -> ToxavFriendCallState.ERROR
+ }
+
+ fun convert(callState: EnumSet): Int =
+ callState.fold(
+ 0,
+ { bitMask, bit ->
+ val nextMask =
+ when (bit) {
+ ToxavFriendCallState.ERROR -> 1 shl 0
+ ToxavFriendCallState.FINISHED -> 1 shl 1
+ ToxavFriendCallState.SENDING_A -> 1 shl 2
+ ToxavFriendCallState.SENDING_V -> 1 shl 3
+ ToxavFriendCallState.ACCEPTING_A -> 1 shl 4
+ ToxavFriendCallState.ACCEPTING_V -> 1 shl 5
+ null -> 0
+ }
+ bitMask or nextMask
+ })
+
+ private fun dispatchCall(handler: CallCallback, call: List, state: S): S =
+ call.fold(
+ state,
+ { next, ev ->
+ handler.call(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ev.getAudioEnabled(),
+ ev.getVideoEnabled(),
+ next)
+ })
+
+ private fun dispatchCallState(
+ handler: CallStateCallback,
+ callState: List,
+ state: S
+ ): S =
+ callState.fold(
+ state,
+ { next, ev ->
+ val bits = ev.getCallStateList().map { convert(it) }
+ handler.callState(
+ ToxFriendNumber(ev.getFriendNumber()),
+ EnumSet.of(bits[0], *bits.drop(1).toTypedArray()),
+ next)
+ })
+
+ private fun dispatchAudioBitRate(
+ handler: AudioBitRateCallback,
+ audioBitRate: List,
+ state: S
+ ): S =
+ audioBitRate.fold(
+ state,
+ { next, ev ->
+ handler.audioBitRate(
+ ToxFriendNumber(ev.getFriendNumber()), BitRate(ev.getAudioBitRate()), next)
+ })
+
+ private fun dispatchVideoBitRate(
+ handler: VideoBitRateCallback,
+ videoBitRate: List,
+ state: S
+ ): S =
+ videoBitRate.fold(
+ state,
+ { next, ev ->
+ handler.videoBitRate(
+ ToxFriendNumber(ev.getFriendNumber()), BitRate(ev.getVideoBitRate()), next)
+ })
+
+ private fun toShortArray(bytes: ByteString): ShortArray {
+ val shortBuffer = bytes.asReadOnlyByteBuffer().asShortBuffer()
+ val shortArray = ShortArray(shortBuffer.capacity())
+ shortBuffer.get(shortArray)
+ return shortArray
+ }
+
+ private fun dispatchAudioReceiveFrame(
+ handler: AudioReceiveFrameCallback,
+ audioReceiveFrame: List,
+ state: S
+ ): S =
+ audioReceiveFrame.fold(
+ state,
+ { next, ev ->
+ handler.audioReceiveFrame(
+ ToxFriendNumber(ev.getFriendNumber()),
+ toShortArray(ev.getPcm()),
+ convert(ev.getChannels()),
+ (SamplingRate.values().filter { it.value == ev.getSamplingRate() })[0],
+ next)
+ })
+
+ private fun convert(
+ arrays: Triple?,
+ y: ByteString,
+ u: ByteString,
+ v: ByteString
+ ): Triple =
+ if (arrays == null) {
+ Triple(y.toByteArray(), u.toByteArray(), v.toByteArray())
+ } else {
+ y.copyTo(arrays.first, 0)
+ u.copyTo(arrays.second, 0)
+ v.copyTo(arrays.third, 0)
+ arrays
+ }
+
+ private fun dispatchVideoReceiveFrame(
+ handler: VideoReceiveFrameCallback,
+ videoReceiveFrame: List,
+ state: S
+ ): S =
+ videoReceiveFrame.fold(
+ state,
+ { next, ev ->
+ val w = Width(ev.getWidth())
+ val h = Height(ev.getHeight())
+ val (yArray, uArray, vArray) =
+ convert(
+ handler.videoFrameCachedYUV(
+ h, ev.getYStride(), ev.getUStride(), ev.getVStride()),
+ ev.getY(),
+ ev.getU(),
+ ev.getV())
+
+ handler.videoReceiveFrame(
+ ToxFriendNumber(ev.getFriendNumber()),
+ w,
+ h,
+ yArray,
+ uArray,
+ vArray,
+ ev.getYStride(),
+ ev.getUStride(),
+ ev.getVStride(),
+ next)
+ })
+
+ private fun dispatchEvents(handler: ToxAvEventListener, events: AvEvents, state: S): S =
+ dispatchCall(
+ handler,
+ events.getCallList(),
+ dispatchCallState(
+ handler,
+ events.getCallStateList(),
+ dispatchAudioBitRate(
+ handler,
+ events.getAudioBitRateList(),
+ dispatchVideoBitRate(
+ handler,
+ events.getVideoBitRateList(),
+ dispatchAudioReceiveFrame(
+ handler,
+ events.getAudioReceiveFrameList(),
+ dispatchVideoReceiveFrame(
+ handler, events.getVideoReceiveFrameList(), state))))))
+
+ fun dispatch(handler: ToxAvEventListener, eventData: ByteArray?, state: S): S =
+ if (eventData == null) {
+ state
+ } else {
+ dispatchEvents(handler, AvEvents.parseFrom(eventData), state)
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.scala
deleted file mode 100644
index f564b7e33..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxAvEventDispatch.scala
+++ /dev/null
@@ -1,177 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import java.util
-
-import com.google.protobuf.ByteString
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.OptimisedIdOps._
-import im.tox.tox4j.av.callbacks._
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.av.proto._
-import im.tox.tox4j.core.data.ToxFriendNumber
-import org.jetbrains.annotations.Nullable
-import org.slf4j.LoggerFactory
-
-object ToxAvEventDispatch {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- private val IntBytes = Integer.SIZE / java.lang.Byte.SIZE
-
- def convert(kind: CallState.Kind): ToxavFriendCallState = {
- kind match {
- case CallState.Kind.ERROR => ToxavFriendCallState.ERROR
- case CallState.Kind.FINISHED => ToxavFriendCallState.FINISHED
- case CallState.Kind.SENDING_A => ToxavFriendCallState.SENDING_A
- case CallState.Kind.SENDING_V => ToxavFriendCallState.SENDING_V
- case CallState.Kind.ACCEPTING_A => ToxavFriendCallState.ACCEPTING_A
- case CallState.Kind.ACCEPTING_V => ToxavFriendCallState.ACCEPTING_V
- }
- }
-
- def convert(callState: util.EnumSet[ToxavFriendCallState]): Int = {
- import scala.collection.JavaConverters._
- callState.asScala.foldLeft(0) { (bitMask, state) =>
- val nextMask = state match {
- case ToxavFriendCallState.ERROR => 1 << 0
- case ToxavFriendCallState.FINISHED => 1 << 1
- case ToxavFriendCallState.SENDING_A => 1 << 2
- case ToxavFriendCallState.SENDING_V => 1 << 3
- case ToxavFriendCallState.ACCEPTING_A => 1 << 4
- case ToxavFriendCallState.ACCEPTING_V => 1 << 5
- }
- bitMask | nextMask
- }
- }
-
- private def dispatchCall[S](handler: CallCallback[S], call: Seq[Call])(state: S): S = {
- call.foldLeft(state) {
- case (state, Call(friendNumber, audioEnabled, videoEnabled)) =>
- handler.call(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- audioEnabled,
- videoEnabled
- )(state)
- }
- }
-
- private def dispatchCallState[S](handler: CallStateCallback[S], callState: Seq[CallState])(state: S): S = {
- callState.foldLeft(state) {
- case (state, CallState(friendNumber, callStateHead +: callStateTail)) =>
- handler.callState(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- util.EnumSet.of(convert(callStateHead), callStateTail.map(convert): _*)
- )(state)
- }
- }
-
- private def dispatchAudioBitRate[S](handler: AudioBitRateCallback[S], audioBitRate: Seq[AudioBitRate])(state: S): S = {
- audioBitRate.foldLeft(state) {
- case (state, AudioBitRate(friendNumber, audioBitRate)) =>
- handler.audioBitRate(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- BitRate.unsafeFromInt(audioBitRate)
- )(state)
- }
- }
-
- private def dispatchVideoBitRate[S](handler: VideoBitRateCallback[S], videoBitRate: Seq[VideoBitRate])(state: S): S = {
- videoBitRate.foldLeft(state) {
- case (state, VideoBitRate(friendNumber, videoBitRate)) =>
- handler.videoBitRate(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- BitRate.unsafeFromInt(videoBitRate)
- )(state)
- }
- }
-
- private def toShortArray(bytes: ByteString): Array[Short] = {
- val shortBuffer = bytes.asReadOnlyByteBuffer().asShortBuffer()
- val shortArray = Array.ofDim[Short](shortBuffer.capacity)
- shortBuffer.get(shortArray)
- shortArray
- }
-
- private def dispatchAudioReceiveFrame[S](handler: AudioReceiveFrameCallback[S], audioReceiveFrame: Seq[AudioReceiveFrame])(state: S): S = {
- audioReceiveFrame.foldLeft(state) {
- case (state, AudioReceiveFrame(friendNumber, pcm, channels, samplingRate)) =>
- handler.audioReceiveFrame(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- toShortArray(pcm),
- AudioChannels.unsafeFromInt(channels),
- SamplingRate.unsafeFromInt(samplingRate)
- )(state)
- }
- }
-
- private def convert(
- arrays: Option[(Array[Byte], Array[Byte], Array[Byte])],
- y: ByteString, u: ByteString, v: ByteString
- ): (Array[Byte], Array[Byte], Array[Byte]) = {
- arrays match {
- case None =>
- (y.toByteArray, u.toByteArray, v.toByteArray)
- case Some(arrays) =>
- y.copyTo(arrays._1, 0)
- u.copyTo(arrays._2, 0)
- v.copyTo(arrays._3, 0)
- arrays
- }
- }
-
- private def dispatchVideoReceiveFrame[S](handler: VideoReceiveFrameCallback[S], videoReceiveFrame: Seq[VideoReceiveFrame])(state: S): S = {
- videoReceiveFrame.foldLeft(state) {
- case (state, VideoReceiveFrame(friendNumber, width, height, y, u, v, yStride, uStride, vStride)) =>
- val w = Width.unsafeFromInt(width)
- val h = Height.unsafeFromInt(height)
- val (yArray, uArray, vArray) = convert(handler.videoFrameCachedYUV(h, yStride, uStride, vStride), y, u, v)
-
- handler.videoReceiveFrame(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- w,
- h,
- yArray,
- uArray,
- vArray,
- yStride,
- uStride,
- vStride
- )(state)
- }
- }
-
- private def dispatchEvents[S](handler: ToxAvEventListener[S], events: AvEvents)(state: S): S = {
- (state
- |> dispatchCall(handler, events.call)
- |> dispatchCallState(handler, events.callState)
- |> dispatchAudioBitRate(handler, events.audioBitRate)
- |> dispatchVideoBitRate(handler, events.videoBitRate)
- |> dispatchAudioReceiveFrame(handler, events.audioReceiveFrame)
- |> dispatchVideoReceiveFrame(handler, events.videoReceiveFrame))
- }
-
- private def decodeInt32(eventData: Array[Byte]): Int = {
- assert(eventData.length >= IntBytes)
- (0
- | eventData(0) << (8 * 3)
- | eventData(1) << (8 * 2)
- | eventData(2) << (8 * 1)
- | eventData(3) << (8 * 0))
- }
-
- @SuppressWarnings(Array(
- "org.wartremover.warts.ArrayEquals",
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.Null"
- ))
- def dispatch[S](handler: ToxAvEventListener[S], @Nullable eventData: Array[Byte])(state: S): S = {
- if (eventData == null) { // scalastyle:ignore null
- state
- } else {
- val events = AvEvents.parseFrom(eventData)
- dispatchEvents(handler, events)(state)
- }
- }
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.kt b/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.kt
new file mode 100644
index 000000000..be7d7a375
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.kt
@@ -0,0 +1,145 @@
+package im.tox.tox4j.impl.jni
+
+import im.tox.tox4j.av.*
+import im.tox.tox4j.av.callbacks.*
+import im.tox.tox4j.av.data.*
+import im.tox.tox4j.av.enums.*
+import im.tox.tox4j.av.exceptions.*
+import im.tox.tox4j.core.ToxCore
+import im.tox.tox4j.core.data.ToxFriendNumber
+import java.util.EnumSet
+
+/**
+ * Initialise an A/V session for the existing Tox instance.
+ *
+ * @param tox An instance of the C-backed ToxCore implementation.
+ */
+// @throws[ToxavNewException]("If there was already an A/V session.")
+final class ToxAvImpl(private val tox: ToxCoreImpl) : ToxAv {
+
+ internal val instanceNumber = ToxAvJni.toxavNew(tox.instanceNumber)
+
+ override fun create(tox: ToxCore): ToxAv =
+ try {
+ ToxAvImpl(tox as ToxCoreImpl)
+ } catch (_: ClassCastException) {
+ throw ToxavNewException(
+ ToxavNewException.Code.INCOMPATIBLE, tox::class.java.getCanonicalName())
+ }
+
+ override fun close(): Unit = ToxAvJni.toxavKill(instanceNumber)
+
+ protected fun finalize(): Unit = ToxAvJni.toxavFinalize(instanceNumber)
+
+ override fun iterate(handler: ToxAvEventListener, state: S): S =
+ ToxAvEventDispatch.dispatch(handler, ToxAvJni.toxavIterate(instanceNumber), state)
+
+ override val iterationInterval: Int
+ get() = ToxAvJni.toxavIterationInterval(instanceNumber)
+
+ // @throws[ToxavCallException]
+ override fun call(
+ friendNumber: ToxFriendNumber,
+ audioBitRate: BitRate,
+ videoBitRate: BitRate
+ ): Unit =
+ ToxAvJni.toxavCall(instanceNumber, friendNumber.value, audioBitRate.value, videoBitRate.value)
+
+ // @throws[ToxavAnswerException]
+ override fun answer(
+ friendNumber: ToxFriendNumber,
+ audioBitRate: BitRate,
+ videoBitRate: BitRate
+ ): Unit =
+ ToxAvJni.toxavAnswer(
+ instanceNumber, friendNumber.value, audioBitRate.value, videoBitRate.value)
+
+ // @throws[ToxavCallControlException]
+ override fun callControl(friendNumber: ToxFriendNumber, control: ToxavCallControl): Unit =
+ ToxAvJni.toxavCallControl(instanceNumber, friendNumber.value, control.ordinal)
+
+ // @throws[ToxavBitRateSetException]
+ override fun setAudioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate): Unit =
+ ToxAvJni.toxavAudioSetBitRate(instanceNumber, friendNumber.value, audioBitRate.value)
+
+ // @throws[ToxavBitRateSetException]
+ override fun setVideoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate): Unit =
+ ToxAvJni.toxavVideoSetBitRate(instanceNumber, friendNumber.value, videoBitRate.value)
+
+ // @throws[ToxavSendFrameException]
+ override fun audioSendFrame(
+ friendNumber: ToxFriendNumber,
+ pcm: ShortArray,
+ sampleCount: SampleCount,
+ channels: AudioChannels,
+ samplingRate: SamplingRate
+ ): Unit =
+ ToxAvJni.toxavAudioSendFrame(
+ instanceNumber,
+ friendNumber.value,
+ pcm,
+ sampleCount.value,
+ channels.value,
+ samplingRate.value)
+
+ // @throws[ToxavSendFrameException]
+ override fun videoSendFrame(
+ friendNumber: ToxFriendNumber,
+ width: Int,
+ height: Int,
+ y: ByteArray,
+ u: ByteArray,
+ v: ByteArray
+ ): Unit = ToxAvJni.toxavVideoSendFrame(instanceNumber, friendNumber.value, width, height, y, u, v)
+
+ fun invokeAudioReceiveFrame(
+ friendNumber: ToxFriendNumber,
+ pcm: ShortArray,
+ channels: AudioChannels,
+ samplingRate: SamplingRate
+ ): Unit =
+ ToxAvJni.invokeAudioReceiveFrame(
+ instanceNumber, friendNumber.value, pcm, channels.value, samplingRate.value)
+
+ fun invokeAudioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate): Unit =
+ ToxAvJni.invokeAudioBitRate(instanceNumber, friendNumber.value, audioBitRate.value)
+
+ fun invokeVideoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate): Unit =
+ ToxAvJni.invokeVideoBitRate(instanceNumber, friendNumber.value, videoBitRate.value)
+
+ fun invokeCall(
+ friendNumber: ToxFriendNumber,
+ audioEnabled: Boolean,
+ videoEnabled: Boolean
+ ): Unit = ToxAvJni.invokeCall(instanceNumber, friendNumber.value, audioEnabled, videoEnabled)
+
+ fun invokeCallState(
+ friendNumber: ToxFriendNumber,
+ callState: EnumSet
+ ): Unit =
+ ToxAvJni.invokeCallState(
+ instanceNumber, friendNumber.value, ToxAvEventDispatch.convert(callState))
+
+ fun invokeVideoReceiveFrame(
+ friendNumber: ToxFriendNumber,
+ width: Width,
+ height: Height,
+ y: ByteArray,
+ u: ByteArray,
+ v: ByteArray,
+ yStride: Int,
+ uStride: Int,
+ vStride: Int
+ ): Unit =
+ ToxAvJni.invokeVideoReceiveFrame(
+ instanceNumber,
+ friendNumber.value,
+ width.value,
+ height.value,
+ y,
+ u,
+ v,
+ yStride,
+ uStride,
+ vStride)
+}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.scala
deleted file mode 100644
index 6d0b87c00..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxAvImpl.scala
+++ /dev/null
@@ -1,120 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import java.util
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.av._
-import im.tox.tox4j.av.callbacks._
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.{ ToxavCallControl, ToxavFriendCallState }
-import im.tox.tox4j.av.exceptions._
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.impl.jni.ToxAvImpl.logger
-import im.tox.tox4j.impl.jni.internal.Event
-import org.jetbrains.annotations.NotNull
-import org.slf4j.LoggerFactory
-
-private object ToxAvImpl {
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-}
-
-/**
- * Initialise an A/V session for the existing Tox instance.
- *
- * @param tox An instance of the C-backed ToxCore implementation.
- */
-// scalastyle:off no.finalize
-@throws[ToxavNewException]("If there was already an A/V session.")
-final class ToxAvImpl(@NotNull private val tox: ToxCoreImpl) extends ToxAv {
-
- private[this] val onClose: Event.Id = tox.addOnCloseCallback(close)
-
- private[jni] val instanceNumber = ToxAvJni.toxavNew(tox.instanceNumber)
-
- @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf"))
- override def create(tox: ToxCore): ToxAv = {
- try {
- new ToxAvImpl(tox.asInstanceOf[ToxCoreImpl])
- } catch {
- case _: ClassCastException =>
- throw new ToxavNewException(ToxavNewException.Code.INCOMPATIBLE, tox.getClass.getCanonicalName)
- }
- }
-
- override def close(): Unit = {
- tox.removeOnCloseCallback(onClose)
- ToxAvJni.toxavKill(instanceNumber)
- }
-
- protected override def finalize(): Unit = {
- try {
- ToxAvJni.toxavFinalize(instanceNumber)
- } catch {
- case e: Throwable =>
- logger.error("Exception caught in finalizer; this indicates a serious problem in native code", e)
- }
- super.finalize()
- }
-
- override def iterate[S](@NotNull handler: ToxAvEventListener[S])(state: S): S = {
- ToxAvEventDispatch.dispatch(handler, ToxAvJni.toxavIterate(instanceNumber))(state)
- }
-
- override def iterationInterval: Int =
- ToxAvJni.toxavIterationInterval(instanceNumber)
-
- @throws[ToxavCallException]
- override def call(friendNumber: ToxFriendNumber, audioBitRate: BitRate, videoBitRate: BitRate): Unit =
- ToxAvJni.toxavCall(instanceNumber, friendNumber.value, audioBitRate.value, videoBitRate.value)
-
- @throws[ToxavAnswerException]
- override def answer(friendNumber: ToxFriendNumber, audioBitRate: BitRate, videoBitRate: BitRate): Unit =
- ToxAvJni.toxavAnswer(instanceNumber, friendNumber.value, audioBitRate.value, videoBitRate.value)
-
- @throws[ToxavCallControlException]
- override def callControl(friendNumber: ToxFriendNumber, control: ToxavCallControl): Unit =
- ToxAvJni.toxavCallControl(instanceNumber, friendNumber.value, control.ordinal)
-
- @throws[ToxavBitRateSetException]
- override def setAudioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate): Unit =
- ToxAvJni.toxavAudioSetBitRate(instanceNumber, friendNumber.value, audioBitRate.value)
-
- @throws[ToxavBitRateSetException]
- override def setVideoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate): Unit =
- ToxAvJni.toxavVideoSetBitRate(instanceNumber, friendNumber.value, videoBitRate.value)
-
- @throws[ToxavSendFrameException]
- override def audioSendFrame(
- friendNumber: ToxFriendNumber,
- pcm: Array[Short],
- sampleCount: SampleCount,
- channels: AudioChannels,
- samplingRate: SamplingRate
- ): Unit = {
- ToxAvJni.toxavAudioSendFrame(instanceNumber, friendNumber.value, pcm, sampleCount.value, channels.value, samplingRate.value)
- }
-
- @throws[ToxavSendFrameException]
- override def videoSendFrame(
- friendNumber: ToxFriendNumber,
- width: Int, height: Int,
- y: Array[Byte], u: Array[Byte], v: Array[Byte]
- ): Unit = {
- ToxAvJni.toxavVideoSendFrame(instanceNumber, friendNumber.value, width, height, y, u, v)
- }
-
- def invokeAudioReceiveFrame(friendNumber: ToxFriendNumber, pcm: Array[Short], channels: AudioChannels, samplingRate: SamplingRate): Unit =
- ToxAvJni.invokeAudioReceiveFrame(instanceNumber, friendNumber.value, pcm, channels.value, samplingRate.value)
- def invokeAudioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate): Unit =
- ToxAvJni.invokeAudioBitRate(instanceNumber, friendNumber.value, audioBitRate.value)
- def invokeVideoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate): Unit =
- ToxAvJni.invokeVideoBitRate(instanceNumber, friendNumber.value, videoBitRate.value)
- def invokeCall(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean): Unit =
- ToxAvJni.invokeCall(instanceNumber, friendNumber.value, audioEnabled, videoEnabled)
- def invokeCallState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState]): Unit =
- ToxAvJni.invokeCallState(instanceNumber, friendNumber.value, ToxAvEventDispatch.convert(callState))
- def invokeVideoReceiveFrame(friendNumber: ToxFriendNumber, width: Width, height: Height, y: Array[Byte], u: Array[Byte], v: Array[Byte], yStride: Int, uStride: Int, vStride: Int): Unit = // scalastyle:ignore line.size.limit
- ToxAvJni.invokeVideoReceiveFrame(instanceNumber, friendNumber.value, width.value, height.value, y, u, v, yStride, uStride, vStride)
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxAvJni.java b/src/main/java/im/tox/tox4j/impl/jni/ToxAvJni.java
index 1d769c4f2..9da227883 100644
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxAvJni.java
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxAvJni.java
@@ -6,49 +6,43 @@
@SuppressWarnings({"checkstyle:emptylineseparator", "checkstyle:linelength"})
public final class ToxAvJni {
-
static {
- ToxLoadJniLibrary.load("tox4j-c");
+ System.loadLibrary("tox4j-c");
}
static native int toxavNew(int toxInstanceNumber) throws ToxavNewException;
static native void toxavKill(int instanceNumber);
static native void toxavFinalize(int instanceNumber);
static native int toxavIterationInterval(int instanceNumber);
- @Nullable
- static native byte[] toxavIterate(int instanceNumber);
- static native void toxavCall(int instanceNumber, int friendNumber, int audioBitRate, int videoBitRate) throws ToxavCallException;
- static native void toxavAnswer(int instanceNumber, int friendNumber, int audioBitRate, int videoBitRate) throws ToxavAnswerException;
- static native void toxavCallControl(int instanceNumber, int friendNumber, int control) throws ToxavCallControlException;
- static native void toxavAudioSetBitRate(int instanceNumber, int friendNumber, int audioBitRate) throws ToxavBitRateSetException;
- static native void toxavVideoSetBitRate(int instanceNumber, int friendNumber, int videoBitRate) throws ToxavBitRateSetException;
-
- static native void toxavAudioSendFrame(
- int instanceNumber,
- int friendNumber,
- @NotNull short[] pcm, int sampleCount, int channels, int samplingRate
- ) throws ToxavSendFrameException;
+ @Nullable static native byte[] toxavIterate(int instanceNumber);
+ static native void toxavCall(int instanceNumber, int friendNumber, int audioBitRate,
+ int videoBitRate) throws ToxavCallException;
+ static native void toxavAnswer(int instanceNumber, int friendNumber, int audioBitRate,
+ int videoBitRate) throws ToxavAnswerException;
+ static native void toxavCallControl(int instanceNumber, int friendNumber, int control)
+ throws ToxavCallControlException;
+ static native void toxavAudioSetBitRate(int instanceNumber, int friendNumber, int audioBitRate)
+ throws ToxavBitRateSetException;
+ static native void toxavVideoSetBitRate(int instanceNumber, int friendNumber, int videoBitRate)
+ throws ToxavBitRateSetException;
+
+ static native void toxavAudioSendFrame(int instanceNumber, int friendNumber, @NotNull short[] pcm,
+ int sampleCount, int channels, int samplingRate) throws ToxavSendFrameException;
@SuppressWarnings("checkstyle:parametername")
- static native void toxavVideoSendFrame(
- int instanceNumber,
- int friendNumber,
- int width, int height,
- @NotNull byte[] y, @NotNull byte[] u, @NotNull byte[] v
- ) throws ToxavSendFrameException;
+ static native void toxavVideoSendFrame(int instanceNumber, int friendNumber, int width,
+ int height, @NotNull byte[] y, @NotNull byte[] u, @NotNull byte[] v)
+ throws ToxavSendFrameException;
- static native void invokeAudioReceiveFrame(int instanceNumber, int friendNumber, short[] pcm, int channels, int samplingRate);
+ static native void invokeAudioReceiveFrame(
+ int instanceNumber, int friendNumber, short[] pcm, int channels, int samplingRate);
static native void invokeAudioBitRate(int instanceNumber, int friendNumber, int audioBitRate);
static native void invokeVideoBitRate(int instanceNumber, int friendNumber, int videoBitRate);
- static native void invokeCall(int instanceNumber, int friendNumber, boolean audioEnabled, boolean videoEnabled);
+ static native void invokeCall(
+ int instanceNumber, int friendNumber, boolean audioEnabled, boolean videoEnabled);
static native void invokeCallState(int instanceNumber, int friendNumber, int callState);
@SuppressWarnings("checkstyle:parametername")
- static native void invokeVideoReceiveFrame(
- int instanceNumber,
- int friendNumber,
- int width, int height,
- @NotNull byte[] y, @NotNull byte[] u, @NotNull byte[] v,
- int yStride, int uStride, int vStride
- );
-
+ static native void invokeVideoReceiveFrame(int instanceNumber, int friendNumber, int width,
+ int height, @NotNull byte[] y, @NotNull byte[] u, @NotNull byte[] v, int yStride, int uStride,
+ int vStride);
}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.kt b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.kt
new file mode 100644
index 000000000..1254def23
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.kt
@@ -0,0 +1,314 @@
+package im.tox.tox4j.impl.jni
+
+import im.tox.tox4j.core.callbacks.ToxCoreEventListener
+import im.tox.tox4j.core.data.*
+import im.tox.tox4j.core.enums.*
+import im.tox.tox4j.core.proto.*
+
+object ToxCoreEventDispatch {
+
+ fun convert(status: Connection.Type): ToxConnection =
+ when (status) {
+ Connection.Type.NONE -> ToxConnection.NONE
+ Connection.Type.TCP -> ToxConnection.TCP
+ Connection.Type.UDP -> ToxConnection.UDP
+ Connection.Type.UNRECOGNIZED -> ToxConnection.NONE
+ }
+
+ fun convert(status: UserStatus.Type): ToxUserStatus =
+ when (status) {
+ UserStatus.Type.NONE -> ToxUserStatus.NONE
+ UserStatus.Type.AWAY -> ToxUserStatus.AWAY
+ UserStatus.Type.BUSY -> ToxUserStatus.BUSY
+ UserStatus.Type.UNRECOGNIZED -> ToxUserStatus.NONE
+ }
+
+ fun convert(status: ToxUserStatus): UserStatus.Type =
+ when (status) {
+ ToxUserStatus.NONE -> UserStatus.Type.NONE
+ ToxUserStatus.AWAY -> UserStatus.Type.AWAY
+ ToxUserStatus.BUSY -> UserStatus.Type.BUSY
+ }
+
+ fun convert(control: FileControl.Type): ToxFileControl =
+ when (control) {
+ FileControl.Type.RESUME -> ToxFileControl.RESUME
+ FileControl.Type.PAUSE -> ToxFileControl.PAUSE
+ FileControl.Type.CANCEL -> ToxFileControl.CANCEL
+ FileControl.Type.UNRECOGNIZED -> ToxFileControl.CANCEL
+ }
+
+ fun convert(messageType: MessageType.Type): ToxMessageType =
+ when (messageType) {
+ MessageType.Type.NORMAL -> ToxMessageType.NORMAL
+ MessageType.Type.ACTION -> ToxMessageType.ACTION
+ MessageType.Type.UNRECOGNIZED -> ToxMessageType.NORMAL
+ }
+
+ private fun dispatchSelfConnectionStatus(
+ handler: ToxCoreEventListener,
+ selfConnectionStatus: List,
+ state: S
+ ): S =
+ selfConnectionStatus.fold(
+ state,
+ { next, ev -> handler.selfConnectionStatus(convert(ev.getConnectionStatus()), next) })
+
+ private fun dispatchFriendName(
+ handler: ToxCoreEventListener,
+ friendName: List,
+ state: S
+ ): S =
+ friendName.fold(
+ state,
+ { next, ev ->
+ handler.friendName(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ToxNickname(ev.getName().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFriendStatusMessage(
+ handler: ToxCoreEventListener,
+ friendStatusMessage: List,
+ state: S
+ ): S =
+ friendStatusMessage.fold(
+ state,
+ { next, ev ->
+ handler.friendStatusMessage(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ToxStatusMessage(ev.getMessage().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFriendStatus(
+ handler: ToxCoreEventListener,
+ friendStatus: List,
+ state: S
+ ): S =
+ friendStatus.fold(
+ state,
+ { next, ev ->
+ handler.friendStatus(
+ ToxFriendNumber(ev.getFriendNumber()), convert(ev.getStatus()), next)
+ })
+
+ private fun dispatchFriendConnectionStatus(
+ handler: ToxCoreEventListener,
+ friendConnectionStatus: List,
+ state: S
+ ): S =
+ friendConnectionStatus.fold(
+ state,
+ { next, ev ->
+ handler.friendConnectionStatus(
+ ev.getFriendNumber(), convert(ev.getConnectionStatus()), next)
+ })
+
+ private fun dispatchFriendTyping(
+ handler: ToxCoreEventListener,
+ friendTyping: List,
+ state: S
+ ): S =
+ friendTyping.fold(
+ state,
+ { next, ev ->
+ handler.friendTyping(ToxFriendNumber(ev.getFriendNumber()), ev.getIsTyping(), next)
+ })
+
+ private fun dispatchFriendReadReceipt(
+ handler: ToxCoreEventListener,
+ friendReadReceipt: List,
+ state: S
+ ): S =
+ friendReadReceipt.fold(
+ state,
+ { next, ev ->
+ handler.friendReadReceipt(
+ ToxFriendNumber(ev.getFriendNumber()), ev.getMessageId(), next)
+ })
+
+ private fun dispatchFriendRequest(
+ handler: ToxCoreEventListener,
+ friendRequest: List,
+ state: S
+ ): S =
+ friendRequest.fold(
+ state,
+ { next, ev ->
+ handler.friendRequest(
+ ToxPublicKey(ev.getPublicKey().toByteArray()),
+ ev.getTimeDelta(),
+ ToxFriendRequestMessage(ev.getMessage().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFriendMessage(
+ handler: ToxCoreEventListener,
+ friendMessage: List,
+ state: S
+ ): S =
+ friendMessage.fold(
+ state,
+ { next, ev ->
+ handler.friendMessage(
+ ToxFriendNumber(ev.getFriendNumber()),
+ convert(ev.getType()),
+ ev.getTimeDelta(),
+ ToxFriendMessage(ev.getMessage().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFileRecvControl(
+ handler: ToxCoreEventListener,
+ fileRecvControl: List,
+ state: S
+ ): S =
+ fileRecvControl.fold(
+ state,
+ { next, ev ->
+ handler.fileRecvControl(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ev.getFileNumber(),
+ convert(ev.getControl()),
+ next)
+ })
+
+ private fun dispatchFileChunkRequest(
+ handler: ToxCoreEventListener,
+ fileChunkRequest: List,
+ state: S
+ ): S =
+ fileChunkRequest.fold(
+ state,
+ { next, ev ->
+ handler.fileChunkRequest(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ev.getFileNumber(),
+ ev.getPosition(),
+ ev.getLength(),
+ next)
+ })
+
+ private fun dispatchFileRecv(
+ handler: ToxCoreEventListener,
+ fileRecv: List,
+ state: S
+ ): S =
+ fileRecv.fold(
+ state,
+ { next, ev ->
+ handler.fileRecv(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ev.getFileNumber(),
+ ev.getKind(),
+ ev.getFileSize(),
+ ToxFilename(ev.getFilename().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFileRecvChunk(
+ handler: ToxCoreEventListener,
+ fileRecvChunk: List,
+ state: S
+ ): S =
+ fileRecvChunk.fold(
+ state,
+ { next, ev ->
+ handler.fileRecvChunk(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ev.getFileNumber(),
+ ev.getPosition(),
+ ev.getData().toByteArray(),
+ next)
+ })
+
+ private fun dispatchFriendLossyPacket(
+ handler: ToxCoreEventListener,
+ friendLossyPacket: List,
+ state: S
+ ): S =
+ friendLossyPacket.fold(
+ state,
+ { next, ev ->
+ handler.friendLossyPacket(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ToxLossyPacket(ev.getData().toByteArray()),
+ next)
+ })
+
+ private fun dispatchFriendLosslessPacket(
+ handler: ToxCoreEventListener,
+ friendLosslessPacket: List,
+ state: S
+ ): S =
+ friendLosslessPacket.fold(
+ state,
+ { next, ev ->
+ handler.friendLosslessPacket(
+ ToxFriendNumber(ev.getFriendNumber()),
+ ToxLosslessPacket(ev.getData().toByteArray()),
+ next)
+ })
+
+ private fun dispatchEvents(
+ handler: ToxCoreEventListener,
+ events: CoreEvents,
+ state: S
+ ): S =
+ dispatchSelfConnectionStatus(
+ handler,
+ events.getSelfConnectionStatusList(),
+ dispatchFriendName(
+ handler,
+ events.getFriendNameList(),
+ dispatchFriendStatusMessage(
+ handler,
+ events.getFriendStatusMessageList(),
+ dispatchFriendStatus(
+ handler,
+ events.getFriendStatusList(),
+ dispatchFriendConnectionStatus(
+ handler,
+ events.getFriendConnectionStatusList(),
+ dispatchFriendTyping(
+ handler,
+ events.getFriendTypingList(),
+ dispatchFriendReadReceipt(
+ handler,
+ events.getFriendReadReceiptList(),
+ dispatchFriendRequest(
+ handler,
+ events.getFriendRequestList(),
+ dispatchFriendMessage(
+ handler,
+ events.getFriendMessageList(),
+ dispatchFileRecvControl(
+ handler,
+ events.getFileRecvControlList(),
+ dispatchFileChunkRequest(
+ handler,
+ events.getFileChunkRequestList(),
+ dispatchFileRecv(
+ handler,
+ events.getFileRecvList(),
+ dispatchFileRecvChunk(
+ handler,
+ events.getFileRecvChunkList(),
+ dispatchFriendLossyPacket(
+ handler,
+ events.getFriendLossyPacketList(),
+ dispatchFriendLosslessPacket(
+ handler,
+ events
+ .getFriendLosslessPacketList(),
+ state)))))))))))))))
+
+ fun dispatch(handler: ToxCoreEventListener, eventData: ByteArray?, state: S): S =
+ if (eventData == null) {
+ state
+ } else {
+ dispatchEvents(handler, CoreEvents.parseFrom(eventData), state)
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.scala
deleted file mode 100644
index a94892b4b..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreEventDispatch.scala
+++ /dev/null
@@ -1,244 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.OptimisedIdOps._
-import im.tox.tox4j.core.callbacks.ToxCoreEventListener
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxMessageType, ToxUserStatus }
-import im.tox.tox4j.core.proto._
-import org.jetbrains.annotations.Nullable
-
-object ToxCoreEventDispatch {
-
- def convert(status: Connection.Type): ToxConnection = {
- status match {
- case Connection.Type.NONE => ToxConnection.NONE
- case Connection.Type.TCP => ToxConnection.TCP
- case Connection.Type.UDP => ToxConnection.UDP
- }
- }
-
- def convert(status: UserStatus.Type): ToxUserStatus = {
- status match {
- case UserStatus.Type.NONE => ToxUserStatus.NONE
- case UserStatus.Type.AWAY => ToxUserStatus.AWAY
- case UserStatus.Type.BUSY => ToxUserStatus.BUSY
- }
- }
-
- def convert(status: ToxUserStatus): UserStatus.Type = {
- status match {
- case ToxUserStatus.NONE => UserStatus.Type.NONE
- case ToxUserStatus.AWAY => UserStatus.Type.AWAY
- case ToxUserStatus.BUSY => UserStatus.Type.BUSY
- }
- }
-
- def convert(control: FileControl.Type): ToxFileControl = {
- control match {
- case FileControl.Type.RESUME => ToxFileControl.RESUME
- case FileControl.Type.PAUSE => ToxFileControl.PAUSE
- case FileControl.Type.CANCEL => ToxFileControl.CANCEL
- }
- }
-
- def convert(messageType: MessageType.Type): ToxMessageType = {
- messageType match {
- case MessageType.Type.NORMAL => ToxMessageType.NORMAL
- case MessageType.Type.ACTION => ToxMessageType.ACTION
- }
- }
-
- private def dispatchSelfConnectionStatus[S](handler: ToxCoreEventListener[S], selfConnectionStatus: Seq[SelfConnectionStatus])(state: S): S = {
- selfConnectionStatus.foldLeft(state) {
- case (state, SelfConnectionStatus(status)) =>
- handler.selfConnectionStatus(
- convert(status)
- )(state)
- }
- }
-
- private def dispatchFriendName[S](handler: ToxCoreEventListener[S], friendName: Seq[FriendName])(state: S): S = {
- friendName.foldLeft(state) {
- case (state, FriendName(friendNumber, name)) =>
- handler.friendName(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- ToxNickname.unsafeFromValue(name.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFriendStatusMessage[S](handler: ToxCoreEventListener[S], friendStatusMessage: Seq[FriendStatusMessage])(state: S): S = {
- friendStatusMessage.foldLeft(state) {
- case (state, FriendStatusMessage(friendNumber, message)) =>
- handler.friendStatusMessage(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- ToxStatusMessage.unsafeFromValue(message.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFriendStatus[S](handler: ToxCoreEventListener[S], friendStatus: Seq[FriendStatus])(state: S): S = {
- friendStatus.foldLeft(state) {
- case (state, FriendStatus(friendNumber, status)) =>
- handler.friendStatus(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- convert(status)
- )(state)
- }
- }
-
- private def dispatchFriendConnectionStatus[S](handler: ToxCoreEventListener[S], friendConnectionStatus: Seq[FriendConnectionStatus])(state: S): S = {
- friendConnectionStatus.foldLeft(state) {
- case (state, FriendConnectionStatus(friendNumber, status)) =>
- handler.friendConnectionStatus(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- convert(status)
- )(state)
- }
- }
-
- private def dispatchFriendTyping[S](handler: ToxCoreEventListener[S], friendTyping: Seq[FriendTyping])(state: S): S = {
- friendTyping.foldLeft(state) {
- case (state, FriendTyping(friendNumber, isTyping)) =>
- handler.friendTyping(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- isTyping
- )(state)
- }
- }
-
- private def dispatchFriendReadReceipt[S](handler: ToxCoreEventListener[S], friendReadReceipt: Seq[FriendReadReceipt])(state: S): S = {
- friendReadReceipt.foldLeft(state) {
- case (state, FriendReadReceipt(friendNumber, messageId)) =>
- handler.friendReadReceipt(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- messageId
- )(state)
- }
- }
-
- private def dispatchFriendRequest[S](handler: ToxCoreEventListener[S], friendRequest: Seq[FriendRequest])(state: S): S = {
- friendRequest.foldLeft(state) {
- case (state, FriendRequest(publicKey, timeDelta, message)) =>
- handler.friendRequest(
- ToxPublicKey.unsafeFromValue(publicKey.toByteArray),
- timeDelta,
- ToxFriendRequestMessage.unsafeFromValue(message.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFriendMessage[S](handler: ToxCoreEventListener[S], friendMessage: Seq[FriendMessage])(state: S): S = {
- friendMessage.foldLeft(state) {
- case (state, FriendMessage(friendNumber, messageType, timeDelta, message)) =>
- handler.friendMessage(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- convert(messageType),
- timeDelta,
- ToxFriendMessage.unsafeFromValue(message.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFileRecvControl[S](handler: ToxCoreEventListener[S], fileRecvControl: Seq[FileRecvControl])(state: S): S = {
- fileRecvControl.foldLeft(state) {
- case (state, FileRecvControl(friendNumber, fileNumber, control)) =>
- handler.fileRecvControl(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- fileNumber,
- convert(control)
- )(state)
- }
- }
-
- private def dispatchFileChunkRequest[S](handler: ToxCoreEventListener[S], fileChunkRequest: Seq[FileChunkRequest])(state: S): S = {
- fileChunkRequest.foldLeft(state) {
- case (state, FileChunkRequest(friendNumber, fileNumber, position, length)) =>
- handler.fileChunkRequest(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- fileNumber,
- position,
- length
- )(state)
- }
- }
-
- private def dispatchFileRecv[S](handler: ToxCoreEventListener[S], fileRecv: Seq[FileRecv])(state: S): S = {
- fileRecv.foldLeft(state) {
- case (state, FileRecv(friendNumber, fileNumber, kind, fileSize, filename)) =>
- handler.fileRecv(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- fileNumber,
- kind,
- fileSize,
- ToxFilename.unsafeFromValue(filename.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFileRecvChunk[S](handler: ToxCoreEventListener[S], fileRecvChunk: Seq[FileRecvChunk])(state: S): S = {
- fileRecvChunk.foldLeft(state) {
- case (state, FileRecvChunk(friendNumber, fileNumber, position, data)) =>
- handler.fileRecvChunk(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- fileNumber,
- position,
- data.toByteArray
- )(state)
- }
- }
-
- private def dispatchFriendLossyPacket[S](handler: ToxCoreEventListener[S], friendLossyPacket: Seq[FriendLossyPacket])(state: S): S = {
- friendLossyPacket.foldLeft(state) {
- case (state, FriendLossyPacket(friendNumber, data)) =>
- handler.friendLossyPacket(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- ToxLossyPacket.unsafeFromValue(data.toByteArray)
- )(state)
- }
- }
-
- private def dispatchFriendLosslessPacket[S](handler: ToxCoreEventListener[S], friendLosslessPacket: Seq[FriendLosslessPacket])(state: S): S = {
- friendLosslessPacket.foldLeft(state) {
- case (state, FriendLosslessPacket(friendNumber, data)) =>
- handler.friendLosslessPacket(
- ToxFriendNumber.unsafeFromInt(friendNumber),
- ToxLosslessPacket.unsafeFromValue(data.toByteArray)
- )(state)
- }
- }
-
- private def dispatchEvents[S](handler: ToxCoreEventListener[S], events: CoreEvents)(state: S): S = {
- (state
- |> dispatchSelfConnectionStatus(handler, events.selfConnectionStatus)
- |> dispatchFriendName(handler, events.friendName)
- |> dispatchFriendStatusMessage(handler, events.friendStatusMessage)
- |> dispatchFriendStatus(handler, events.friendStatus)
- |> dispatchFriendConnectionStatus(handler, events.friendConnectionStatus)
- |> dispatchFriendTyping(handler, events.friendTyping)
- |> dispatchFriendReadReceipt(handler, events.friendReadReceipt)
- |> dispatchFriendRequest(handler, events.friendRequest)
- |> dispatchFriendMessage(handler, events.friendMessage)
- |> dispatchFileRecvControl(handler, events.fileRecvControl)
- |> dispatchFileChunkRequest(handler, events.fileChunkRequest)
- |> dispatchFileRecv(handler, events.fileRecv)
- |> dispatchFileRecvChunk(handler, events.fileRecvChunk)
- |> dispatchFriendLossyPacket(handler, events.friendLossyPacket)
- |> dispatchFriendLosslessPacket(handler, events.friendLosslessPacket))
- }
-
- @SuppressWarnings(Array(
- "org.wartremover.warts.ArrayEquals",
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.Null"
- ))
- def dispatch[S](handler: ToxCoreEventListener[S], @Nullable eventData: Array[Byte])(state: S): S = {
- if (eventData == null) { // scalastyle:ignore null
- state
- } else {
- val events = CoreEvents.parseFrom(eventData)
- dispatchEvents(handler, events)(state)
- }
- }
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.kt b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.kt
new file mode 100644
index 000000000..c4e76d23f
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.kt
@@ -0,0 +1,199 @@
+package im.tox.tox4j.impl.jni
+
+import im.tox.core.network.Port
+import im.tox.tox4j.core.*
+import im.tox.tox4j.core.callbacks.*
+import im.tox.tox4j.core.data.*
+import im.tox.tox4j.core.enums.*
+import im.tox.tox4j.core.exceptions.*
+import im.tox.tox4j.core.options.ToxOptions
+
+/**
+ * Initialises the new Tox instance with an optional save-data received from [[savedata]].
+ *
+ * @param options Connection options object with optional save-data.
+ */
+final class ToxCoreImpl(val options: ToxOptions) : ToxCore {
+
+ /** This field has package visibility for [[ToxAvImpl]]. */
+ internal val instanceNumber =
+ ToxCoreJni.toxNew(
+ options.ipv6Enabled,
+ options.udpEnabled,
+ options.localDiscoveryEnabled,
+ options.proxy.proxyType.ordinal,
+ options.proxy.proxyAddress,
+ options.proxy.proxyPort.toInt(),
+ options.startPort.toInt(),
+ options.endPort.toInt(),
+ options.tcpPort.toInt(),
+ options.saveData.kind.ordinal,
+ options.saveData.data,
+ )
+
+ override fun load(options: ToxOptions): ToxCoreImpl = ToxCoreImpl(options)
+
+ override fun close(): Unit = ToxCoreJni.toxKill(instanceNumber)
+
+ protected fun finalize(): Unit {
+ close()
+ ToxCoreJni.toxFinalize(instanceNumber)
+ }
+
+ override fun bootstrap(address: String, port: Port, publicKey: ToxPublicKey): Unit {
+ ToxCoreImpl.checkBootstrapArguments(publicKey.value)
+ ToxCoreJni.toxBootstrap(instanceNumber, address, port.value.toInt(), publicKey.value)
+ }
+
+ override fun addTcpRelay(address: String, port: Port, publicKey: ToxPublicKey): Unit {
+ ToxCoreImpl.checkBootstrapArguments(publicKey.value)
+ ToxCoreJni.toxAddTcpRelay(instanceNumber, address, port.value.toInt(), publicKey.value)
+ }
+
+ override val savedata: ByteArray
+ get() = ToxCoreJni.toxGetSavedata(instanceNumber)
+
+ override val udpPort: Port
+ get() = Port(ToxCoreJni.toxSelfGetUdpPort(instanceNumber).toUShort())
+
+ override val tcpPort: Port
+ get() = Port(ToxCoreJni.toxSelfGetTcpPort(instanceNumber).toUShort())
+
+ override val dhtId: ToxPublicKey
+ get() = ToxPublicKey(ToxCoreJni.toxSelfGetDhtId(instanceNumber))
+
+ override val iterationInterval: Int
+ get() = ToxCoreJni.toxIterationInterval(instanceNumber)
+
+ override fun iterate(handler: ToxCoreEventListener, state: S): S =
+ ToxCoreEventDispatch.dispatch(handler, ToxCoreJni.toxIterate(instanceNumber), state)
+
+ override val publicKey: ToxPublicKey
+ get() = ToxPublicKey(ToxCoreJni.toxSelfGetPublicKey(instanceNumber))
+
+ override val secretKey: ToxSecretKey
+ get() = ToxSecretKey(ToxCoreJni.toxSelfGetSecretKey(instanceNumber))
+
+ override var nospam: Int
+ get() = ToxCoreJni.toxSelfGetNospam(instanceNumber)
+ set(value) = ToxCoreJni.toxSelfSetNospam(instanceNumber, value)
+
+ override val address: ToxFriendAddress
+ get() = ToxFriendAddress(ToxCoreJni.toxSelfGetAddress(instanceNumber))
+
+ override var name: ToxNickname
+ get() = ToxNickname(ToxCoreJni.toxSelfGetName(instanceNumber))
+ set(value) = ToxCoreJni.toxSelfSetName(instanceNumber, value.value)
+
+ override var statusMessage: ToxStatusMessage
+ get() = ToxStatusMessage(ToxCoreJni.toxSelfGetStatusMessage(instanceNumber))
+ set(value) = ToxCoreJni.toxSelfSetStatusMessage(instanceNumber, value.value)
+
+ override var status: ToxUserStatus
+ get() = ToxUserStatus.values()[ToxCoreJni.toxSelfGetStatus(instanceNumber)]
+ set(value) = ToxCoreJni.toxSelfSetStatus(instanceNumber, value.ordinal)
+
+ override fun addFriend(
+ address: ToxFriendAddress,
+ message: ToxFriendRequestMessage
+ ): ToxFriendNumber {
+ ToxCoreImpl.checkLength("Friend Address", address.value, ToxCoreConstants.AddressSize)
+ return ToxFriendNumber(ToxCoreJni.toxFriendAdd(instanceNumber, address.value, message.value))
+ }
+
+ override fun addFriendNorequest(publicKey: ToxPublicKey): ToxFriendNumber {
+ ToxCoreImpl.checkLength("Public Key", publicKey.value, ToxCoreConstants.PublicKeySize)
+ return ToxFriendNumber(ToxCoreJni.toxFriendAddNorequest(instanceNumber, publicKey.value))
+ }
+
+ override fun deleteFriend(friendNumber: ToxFriendNumber): Unit =
+ ToxCoreJni.toxFriendDelete(instanceNumber, friendNumber.value)
+
+ override fun friendByPublicKey(publicKey: ToxPublicKey): ToxFriendNumber =
+ ToxFriendNumber(ToxCoreJni.toxFriendByPublicKey(instanceNumber, publicKey.value))
+
+ override fun getFriendPublicKey(friendNumber: ToxFriendNumber): ToxPublicKey =
+ ToxPublicKey(ToxCoreJni.toxFriendGetPublicKey(instanceNumber, friendNumber.value))
+
+ override fun friendExists(friendNumber: ToxFriendNumber): Boolean =
+ ToxCoreJni.toxFriendExists(instanceNumber, friendNumber.value)
+
+ override val friendList: IntArray
+ get() = ToxCoreJni.toxSelfGetFriendList(instanceNumber)
+
+ override fun setTyping(friendNumber: ToxFriendNumber, typing: Boolean): Unit =
+ ToxCoreJni.toxSelfSetTyping(instanceNumber, friendNumber.value, typing)
+
+ override fun friendSendMessage(
+ friendNumber: ToxFriendNumber,
+ messageType: ToxMessageType,
+ timeDelta: Int,
+ message: ToxFriendMessage
+ ): Int =
+ ToxCoreJni.toxFriendSendMessage(
+ instanceNumber, friendNumber.value, messageType.ordinal, timeDelta, message.value)
+
+ override fun fileControl(
+ friendNumber: ToxFriendNumber,
+ fileNumber: Int,
+ control: ToxFileControl
+ ): Unit =
+ ToxCoreJni.toxFileControl(instanceNumber, friendNumber.value, fileNumber, control.ordinal)
+
+ override fun fileSeek(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long): Unit =
+ ToxCoreJni.toxFileSeek(instanceNumber, friendNumber.value, fileNumber, position)
+
+ override fun fileSend(
+ friendNumber: ToxFriendNumber,
+ kind: Int,
+ fileSize: Long,
+ fileId: ToxFileId,
+ filename: ToxFilename
+ ): Int =
+ ToxCoreJni.toxFileSend(
+ instanceNumber, friendNumber.value, kind, fileSize, fileId.value, filename.value)
+
+ override fun fileSendChunk(
+ friendNumber: ToxFriendNumber,
+ fileNumber: Int,
+ position: Long,
+ data: ByteArray
+ ): Unit =
+ ToxCoreJni.toxFileSendChunk(instanceNumber, friendNumber.value, fileNumber, position, data)
+
+ override fun getFileFileId(friendNumber: ToxFriendNumber, fileNumber: Int): ToxFileId =
+ ToxFileId(ToxCoreJni.toxFileGetFileId(instanceNumber, friendNumber.value, fileNumber))
+
+ override fun friendSendLossyPacket(friendNumber: ToxFriendNumber, data: ToxLossyPacket): Unit =
+ ToxCoreJni.toxFriendSendLossyPacket(instanceNumber, friendNumber.value, data.value)
+
+ override fun friendSendLosslessPacket(
+ friendNumber: ToxFriendNumber,
+ data: ToxLosslessPacket
+ ): Unit = ToxCoreJni.toxFriendSendLosslessPacket(instanceNumber, friendNumber.value, data.value)
+
+ private companion object {
+
+ fun checkBootstrapArguments(publicKey: ByteArray): Unit {
+ if (publicKey.size < ToxCoreConstants.PublicKeySize) {
+ throw ToxBootstrapException(ToxBootstrapException.Code.BAD_KEY, "Key too short")
+ }
+ if (publicKey.size > ToxCoreConstants.PublicKeySize) {
+ throw ToxBootstrapException(ToxBootstrapException.Code.BAD_KEY, "Key too long")
+ }
+ }
+
+ fun throwLengthException(name: String, message: String, expectedSize: Int): Unit {
+ throw IllegalArgumentException("${name} too ${message}, must be ${expectedSize} bytes")
+ }
+
+ fun checkLength(name: String, bytes: ByteArray, expectedSize: Int): Unit {
+ if (bytes.size < expectedSize) {
+ throwLengthException(name, "short", expectedSize)
+ }
+ if (bytes.size > expectedSize) {
+ throwLengthException(name, "long", expectedSize)
+ }
+ }
+ }
+}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.scala
deleted file mode 100644
index 89a157844..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreImpl.scala
+++ /dev/null
@@ -1,295 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import com.typesafe.scalalogging.Logger
-import im.tox.core.network.Port
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.callbacks._
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxMessageType, ToxUserStatus }
-import im.tox.tox4j.core.exceptions._
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.impl.jni.ToxCoreImpl.logger
-import im.tox.tox4j.impl.jni.internal.Event
-import org.jetbrains.annotations.{ NotNull, Nullable }
-import org.slf4j.LoggerFactory
-
-// scalastyle:off null
-@SuppressWarnings(Array(
- "org.wartremover.warts.ArrayEquals",
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.Null"
-))
-object ToxCoreImpl {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- @throws[ToxBootstrapException]
- private def checkBootstrapArguments(port: Int, @Nullable publicKey: Array[Byte]): Unit = {
- if (port < 0) {
- throw new ToxBootstrapException(ToxBootstrapException.Code.BAD_PORT, "Port cannot be negative")
- }
- if (port > 65535) {
- throw new ToxBootstrapException(ToxBootstrapException.Code.BAD_PORT, "Port cannot exceed 65535")
- }
- if (publicKey ne null) {
- if (publicKey.length < ToxCoreConstants.PublicKeySize) {
- throw new ToxBootstrapException(ToxBootstrapException.Code.BAD_KEY, "Key too short")
- }
- if (publicKey.length > ToxCoreConstants.PublicKeySize) {
- throw new ToxBootstrapException(ToxBootstrapException.Code.BAD_KEY, "Key too long")
- }
- }
- }
-
- private def throwLengthException(name: String, message: String, expectedSize: Int): Unit = {
- throw new IllegalArgumentException(s"$name too $message, must be $expectedSize bytes")
- }
-
- private def checkLength(name: String, @Nullable bytes: Array[Byte], expectedSize: Int): Unit = {
- if (bytes ne null) {
- if (bytes.length < expectedSize) {
- throwLengthException(name, "short", expectedSize)
- }
- if (bytes.length > expectedSize) {
- throwLengthException(name, "long", expectedSize)
- }
- }
- }
-
- @throws[ToxSetInfoException]
- private def checkInfoNotNull(info: Array[Byte]): Unit = {
- if (info eq null) {
- throw new ToxSetInfoException(ToxSetInfoException.Code.NULL)
- }
- }
-
-}
-
-/**
- * Initialises the new Tox instance with an optional save-data received from [[getSavedata]].
- *
- * @param options Connection options object with optional save-data.
- */
-// scalastyle:off no.finalize number.of.methods
-@throws[ToxNewException]("If an error was detected in the configuration or a runtime error occurred.")
-final class ToxCoreImpl(@NotNull val options: ToxOptions) extends ToxCore {
-
- private[this] val onCloseCallbacks: Event = new Event
-
- /**
- * This field has package visibility for [[ToxAvImpl]].
- */
- private[jni] val instanceNumber =
- ToxCoreJni.toxNew(
- options.ipv6Enabled,
- options.udpEnabled,
- options.localDiscoveryEnabled,
- options.proxy.proxyType.ordinal,
- options.proxy.proxyAddress,
- options.proxy.proxyPort,
- options.startPort,
- options.endPort,
- options.tcpPort,
- options.saveData.kind.ordinal,
- options.saveData.data
- )
-
- /**
- * Add an onClose callback. This event is invoked just before the instance is closed.
- */
- def addOnCloseCallback(callback: () => Unit): Event.Id =
- onCloseCallbacks += callback
-
- def removeOnCloseCallback(id: Event.Id): Unit =
- onCloseCallbacks -= id
-
- override def load(options: ToxOptions): ToxCoreImpl =
- new ToxCoreImpl(options)
-
- override def close(): Unit = {
- onCloseCallbacks()
- ToxCoreJni.toxKill(instanceNumber)
- }
-
- protected override def finalize(): Unit = {
- try {
- close()
- ToxCoreJni.toxFinalize(instanceNumber)
- } catch {
- case e: Throwable =>
- logger.error("Exception caught in finalizer; this indicates a serious problem in native code", e)
- }
- super.finalize()
- }
-
- @throws[ToxBootstrapException]
- override def bootstrap(address: String, port: Port, publicKey: ToxPublicKey): Unit = {
- ToxCoreImpl.checkBootstrapArguments(port.value, publicKey.value)
- ToxCoreJni.toxBootstrap(instanceNumber, address, port.value, publicKey.value)
- }
-
- @throws[ToxBootstrapException]
- override def addTcpRelay(address: String, port: Port, publicKey: ToxPublicKey): Unit = {
- ToxCoreImpl.checkBootstrapArguments(port.value, publicKey.value)
- ToxCoreJni.toxAddTcpRelay(instanceNumber, address, port.value, publicKey.value)
- }
-
- override def getSavedata: Array[Byte] =
- ToxCoreJni.toxGetSavedata(instanceNumber)
-
- @throws[ToxGetPortException]
- override def getUdpPort: Port =
- Port.unsafeFromInt(ToxCoreJni.toxSelfGetUdpPort(instanceNumber))
-
- @throws[ToxGetPortException]
- override def getTcpPort: Port =
- Port.unsafeFromInt(ToxCoreJni.toxSelfGetTcpPort(instanceNumber))
-
- override def getDhtId: ToxPublicKey =
- ToxPublicKey.unsafeFromValue(ToxCoreJni.toxSelfGetDhtId(instanceNumber))
-
- override def iterationInterval: Int =
- ToxCoreJni.toxIterationInterval(instanceNumber)
-
- override def iterate[S](@NotNull handler: ToxCoreEventListener[S])(state: S): S = {
- ToxCoreEventDispatch.dispatch(handler, ToxCoreJni.toxIterate(instanceNumber))(state)
- }
-
- override def getPublicKey: ToxPublicKey =
- ToxPublicKey.unsafeFromValue(ToxCoreJni.toxSelfGetPublicKey(instanceNumber))
-
- override def getSecretKey: ToxSecretKey =
- ToxSecretKey.unsafeFromValue(ToxCoreJni.toxSelfGetSecretKey(instanceNumber))
-
- override def setNospam(nospam: Int): Unit =
- ToxCoreJni.toxSelfSetNospam(instanceNumber, nospam)
-
- override def getNospam: Int =
- ToxCoreJni.toxSelfGetNospam(instanceNumber)
-
- override def getAddress: ToxFriendAddress =
- ToxFriendAddress.unsafeFromValue(ToxCoreJni.toxSelfGetAddress(instanceNumber))
-
- @throws[ToxSetInfoException]
- override def setName(name: ToxNickname): Unit = {
- ToxCoreImpl.checkInfoNotNull(name.value)
- ToxCoreJni.toxSelfSetName(instanceNumber, name.value)
- }
-
- override def getName: ToxNickname = {
- ToxNickname.unsafeFromValue(ToxCoreJni.toxSelfGetName(instanceNumber))
- }
-
- @throws[ToxSetInfoException]
- override def setStatusMessage(message: ToxStatusMessage): Unit = {
- ToxCoreImpl.checkInfoNotNull(message.value)
- ToxCoreJni.toxSelfSetStatusMessage(instanceNumber, message.value)
- }
-
- override def getStatusMessage: ToxStatusMessage =
- ToxStatusMessage.unsafeFromValue(ToxCoreJni.toxSelfGetStatusMessage(instanceNumber))
-
- override def setStatus(status: ToxUserStatus): Unit =
- ToxCoreJni.toxSelfSetStatus(instanceNumber, status.ordinal)
-
- override def getStatus: ToxUserStatus =
- ToxUserStatus.values()(ToxCoreJni.toxSelfGetStatus(instanceNumber))
-
- @throws[ToxFriendAddException]
- override def addFriend(address: ToxFriendAddress, message: ToxFriendRequestMessage): ToxFriendNumber = {
- ToxCoreImpl.checkLength("Friend Address", address.value, ToxCoreConstants.AddressSize)
- ToxFriendNumber.unsafeFromInt(ToxCoreJni.toxFriendAdd(instanceNumber, address.value, message.value))
- }
-
- @throws[ToxFriendAddException]
- override def addFriendNorequest(publicKey: ToxPublicKey): ToxFriendNumber = {
- ToxCoreImpl.checkLength("Public Key", publicKey.value, ToxCoreConstants.PublicKeySize)
- ToxFriendNumber.unsafeFromInt(ToxCoreJni.toxFriendAddNorequest(instanceNumber, publicKey.value))
- }
-
- @throws[ToxFriendDeleteException]
- override def deleteFriend(friendNumber: ToxFriendNumber): Unit =
- ToxCoreJni.toxFriendDelete(instanceNumber, friendNumber.value)
-
- @throws[ToxFriendByPublicKeyException]
- override def friendByPublicKey(publicKey: ToxPublicKey): ToxFriendNumber =
- ToxFriendNumber.unsafeFromInt(ToxCoreJni.toxFriendByPublicKey(instanceNumber, publicKey.value))
-
- @throws[ToxFriendGetPublicKeyException]
- override def getFriendPublicKey(friendNumber: ToxFriendNumber): ToxPublicKey =
- ToxPublicKey.unsafeFromValue(ToxCoreJni.toxFriendGetPublicKey(instanceNumber, friendNumber.value))
-
- override def friendExists(friendNumber: ToxFriendNumber): Boolean =
- ToxCoreJni.toxFriendExists(instanceNumber, friendNumber.value)
-
- override def getFriendList: Array[Int] =
- ToxCoreJni.toxSelfGetFriendList(instanceNumber)
-
- @throws[ToxSetTypingException]
- override def setTyping(friendNumber: ToxFriendNumber, typing: Boolean): Unit =
- ToxCoreJni.toxSelfSetTyping(instanceNumber, friendNumber.value, typing)
-
- @throws[ToxFriendSendMessageException]
- override def friendSendMessage(friendNumber: ToxFriendNumber, messageType: ToxMessageType, timeDelta: Int, message: ToxFriendMessage): Int =
- ToxCoreJni.toxFriendSendMessage(instanceNumber, friendNumber.value, messageType.ordinal, timeDelta, message.value)
-
- @throws[ToxFileControlException]
- override def fileControl(friendNumber: ToxFriendNumber, fileNumber: Int, control: ToxFileControl): Unit =
- ToxCoreJni.toxFileControl(instanceNumber, friendNumber.value, fileNumber, control.ordinal)
-
- @throws[ToxFileSeekException]
- override def fileSeek(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long): Unit =
- ToxCoreJni.toxFileSeek(instanceNumber, friendNumber.value, fileNumber, position)
-
- @throws[ToxFileSendException]
- override def fileSend(friendNumber: ToxFriendNumber, kind: Int, fileSize: Long, @NotNull fileId: ToxFileId, filename: ToxFilename): Int =
- ToxCoreJni.toxFileSend(instanceNumber, friendNumber.value, kind, fileSize, fileId.value, filename.value)
-
- @throws[ToxFileSendChunkException]
- override def fileSendChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: Array[Byte]): Unit =
- ToxCoreJni.toxFileSendChunk(instanceNumber, friendNumber.value, fileNumber, position, data)
-
- @throws[ToxFileGetException]
- override def getFileFileId(friendNumber: ToxFriendNumber, fileNumber: Int): ToxFileId =
- ToxFileId.unsafeFromValue(ToxCoreJni.toxFileGetFileId(instanceNumber, friendNumber.value, fileNumber))
-
- @throws[ToxFriendCustomPacketException]
- override def friendSendLossyPacket(friendNumber: ToxFriendNumber, data: ToxLossyPacket): Unit =
- ToxCoreJni.toxFriendSendLossyPacket(instanceNumber, friendNumber.value, data.value)
-
- @throws[ToxFriendCustomPacketException]
- override def friendSendLosslessPacket(friendNumber: ToxFriendNumber, data: ToxLosslessPacket): Unit =
- ToxCoreJni.toxFriendSendLosslessPacket(instanceNumber, friendNumber.value, data.value)
-
- def invokeFriendName(friendNumber: ToxFriendNumber, @NotNull name: ToxNickname): Unit =
- ToxCoreJni.invokeFriendName(instanceNumber, friendNumber.value, name.value)
- def invokeFriendStatusMessage(friendNumber: ToxFriendNumber, @NotNull message: Array[Byte]): Unit =
- ToxCoreJni.invokeFriendStatusMessage(instanceNumber, friendNumber.value, message)
- def invokeFriendStatus(friendNumber: ToxFriendNumber, @NotNull status: ToxUserStatus): Unit =
- ToxCoreJni.invokeFriendStatus(instanceNumber, friendNumber.value, status.ordinal())
- def invokeFriendConnectionStatus(friendNumber: ToxFriendNumber, @NotNull connectionStatus: ToxConnection): Unit =
- ToxCoreJni.invokeFriendConnectionStatus(instanceNumber, friendNumber.value, connectionStatus.ordinal())
- def invokeFriendTyping(friendNumber: ToxFriendNumber, isTyping: Boolean): Unit =
- ToxCoreJni.invokeFriendTyping(instanceNumber, friendNumber.value, isTyping)
- def invokeFriendReadReceipt(friendNumber: ToxFriendNumber, messageId: Int): Unit =
- ToxCoreJni.invokeFriendReadReceipt(instanceNumber, friendNumber.value, messageId)
- def invokeFriendRequest(@NotNull publicKey: ToxPublicKey, timeDelta: Int, @NotNull message: Array[Byte]): Unit =
- ToxCoreJni.invokeFriendRequest(instanceNumber, publicKey.value, timeDelta, message)
- def invokeFriendMessage(friendNumber: ToxFriendNumber, @NotNull messageType: ToxMessageType, timeDelta: Int, @NotNull message: Array[Byte]): Unit =
- ToxCoreJni.invokeFriendMessage(instanceNumber, friendNumber.value, messageType.ordinal(), timeDelta, message)
- def invokeFileChunkRequest(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int): Unit =
- ToxCoreJni.invokeFileChunkRequest(instanceNumber, friendNumber.value, fileNumber, position, length)
- def invokeFileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, @NotNull filename: Array[Byte]): Unit =
- ToxCoreJni.invokeFileRecv(instanceNumber, friendNumber.value, fileNumber, kind, fileSize, filename)
- def invokeFileRecvChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, @NotNull data: Array[Byte]): Unit =
- ToxCoreJni.invokeFileRecvChunk(instanceNumber, friendNumber.value, fileNumber, position, data)
- def invokeFileRecvControl(friendNumber: ToxFriendNumber, fileNumber: Int, @NotNull control: ToxFileControl): Unit =
- ToxCoreJni.invokeFileRecvControl(instanceNumber, friendNumber.value, fileNumber, control.ordinal())
- def invokeFriendLossyPacket(friendNumber: ToxFriendNumber, @NotNull data: Array[Byte]): Unit =
- ToxCoreJni.invokeFriendLossyPacket(instanceNumber, friendNumber.value, data)
- def invokeFriendLosslessPacket(friendNumber: ToxFriendNumber, @NotNull data: Array[Byte]): Unit =
- ToxCoreJni.invokeFriendLosslessPacket(instanceNumber, friendNumber.value, data)
- def invokeSelfConnectionStatus(@NotNull connectionStatus: ToxConnection): Unit =
- ToxCoreJni.invokeSelfConnectionStatus(instanceNumber, connectionStatus.ordinal())
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreJni.java b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreJni.java
index b8151c657..ade5f93bb 100644
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxCoreJni.java
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxCoreJni.java
@@ -6,99 +6,75 @@
@SuppressWarnings({"checkstyle:emptylineseparator", "checkstyle:linelength"})
public final class ToxCoreJni {
-
static {
- ToxLoadJniLibrary.load("tox4j-c");
+ System.loadLibrary("tox4j-c");
}
- static native int toxNew(
- boolean ipv6Enabled,
- boolean udpEnabled,
- boolean localDiscoveryEnabled,
- int proxyType,
- @NotNull String proxyAddress,
- int proxyPort,
- int startPort,
- int endPort,
- int tcpPort,
- int saveDataType,
- @NotNull byte[] saveData
- ) throws ToxNewException;
+ static native int toxNew(boolean ipv6Enabled, boolean udpEnabled, boolean localDiscoveryEnabled,
+ int proxyType, @NotNull String proxyAddress, int proxyPort, int startPort, int endPort,
+ int tcpPort, int saveDataType, @NotNull byte[] saveData) throws ToxNewException;
static native void toxKill(int instanceNumber);
static native void toxFinalize(int instanceNumber);
- @NotNull
- static native byte[] toxGetSavedata(int instanceNumber);
- static native void toxBootstrap(int instanceNumber, @NotNull String address, int port, @NotNull byte[] publicKey) throws ToxBootstrapException;
- static native void toxAddTcpRelay(int instanceNumber, @NotNull String address, int port, @NotNull byte[] publicKey) throws ToxBootstrapException;
+ @NotNull static native byte[] toxGetSavedata(int instanceNumber);
+ static native void toxBootstrap(int instanceNumber, @NotNull String address, int port,
+ @NotNull byte[] publicKey) throws ToxBootstrapException;
+ static native void toxAddTcpRelay(int instanceNumber, @NotNull String address, int port,
+ @NotNull byte[] publicKey) throws ToxBootstrapException;
static native int toxSelfGetUdpPort(int instanceNumber) throws ToxGetPortException;
static native int toxSelfGetTcpPort(int instanceNumber) throws ToxGetPortException;
- @NotNull
- static native byte[] toxSelfGetDhtId(int instanceNumber);
- @AutoGenerated
+ @NotNull static native byte[] toxSelfGetDhtId(int instanceNumber);
static native int toxIterationInterval(int instanceNumber);
- @Nullable
- static native byte[] toxIterate(int instanceNumber);
- @NotNull
- static native byte[] toxSelfGetPublicKey(int instanceNumber);
- @NotNull
- static native byte[] toxSelfGetSecretKey(int instanceNumber);
- @AutoGenerated
+ @Nullable static native byte[] toxIterate(int instanceNumber);
+ @NotNull static native byte[] toxSelfGetPublicKey(int instanceNumber);
+ @NotNull static native byte[] toxSelfGetSecretKey(int instanceNumber);
static native void toxSelfSetNospam(int instanceNumber, int nospam);
- @AutoGenerated
static native int toxSelfGetNospam(int instanceNumber);
- @NotNull
- static native byte[] toxSelfGetAddress(int instanceNumber);
- static native void toxSelfSetName(int instanceNumber, @NotNull byte[] name) throws ToxSetInfoException;
- @NotNull
- static native byte[] toxSelfGetName(int instanceNumber);
- static native void toxSelfSetStatusMessage(int instanceNumber, byte[] message) throws ToxSetInfoException;
- @NotNull
- static native byte[] toxSelfGetStatusMessage(int instanceNumber);
+ @NotNull static native byte[] toxSelfGetAddress(int instanceNumber);
+ static native void toxSelfSetName(int instanceNumber, @NotNull byte[] name)
+ throws ToxSetInfoException;
+ @NotNull static native byte[] toxSelfGetName(int instanceNumber);
+ static native void toxSelfSetStatusMessage(int instanceNumber, byte[] message)
+ throws ToxSetInfoException;
+ @NotNull static native byte[] toxSelfGetStatusMessage(int instanceNumber);
static native void toxSelfSetStatus(int instanceNumber, int status);
- @AutoGenerated
static native int toxSelfGetStatus(int instanceNumber);
- static native int toxFriendAdd(int instanceNumber, @NotNull byte[] address, @NotNull byte[] message) throws ToxFriendAddException;
- static native int toxFriendAddNorequest(int instanceNumber, @NotNull byte[] publicKey) throws ToxFriendAddException;
- static native void toxFriendDelete(int instanceNumber, int friendNumber) throws ToxFriendDeleteException;
- static native int toxFriendByPublicKey(int instanceNumber, @NotNull byte[] publicKey) throws ToxFriendByPublicKeyException;
+ static native int toxFriendAdd(int instanceNumber, @NotNull byte[] address,
+ @NotNull byte[] message) throws ToxFriendAddException;
+ static native int toxFriendAddNorequest(int instanceNumber, @NotNull byte[] publicKey)
+ throws ToxFriendAddException;
+ static native void toxFriendDelete(int instanceNumber, int friendNumber)
+ throws ToxFriendDeleteException;
+ static native int toxFriendByPublicKey(int instanceNumber, @NotNull byte[] publicKey)
+ throws ToxFriendByPublicKeyException;
@NotNull
- static native byte[] toxFriendGetPublicKey(int instanceNumber, int friendNumber) throws ToxFriendGetPublicKeyException;
- @AutoGenerated
+ static native byte[] toxFriendGetPublicKey(int instanceNumber, int friendNumber)
+ throws ToxFriendGetPublicKeyException;
static native boolean toxFriendExists(int instanceNumber, int friendNumber);
+ @NotNull static native int[] toxSelfGetFriendList(int instanceNumber);
+ static native void toxSelfSetTyping(int instanceNumber, int friendNumber, boolean typing)
+ throws ToxSetTypingException;
+ static native int toxFriendSendMessage(int instanceNumber, int friendNumber, int type,
+ int timeDelta, @NotNull byte[] message) throws ToxFriendSendMessageException;
+ static native void toxFileControl(int instanceNumber, int friendNumber, int fileNumber,
+ int control) throws ToxFileControlException;
+ static native void toxFileSeek(int instanceNumber, int friendNumber, int fileNumber,
+ long position) throws ToxFileSeekException;
+ static native int toxFileSend(int instanceNumber, int friendNumber, int kind, long fileSize,
+ @NotNull byte[] fileId, @NotNull byte[] filename) throws ToxFileSendException;
+ static native void toxFileSendChunk(int instanceNumber, int friendNumber, int fileNumber,
+ long position, @NotNull byte[] data) throws ToxFileSendChunkException;
@NotNull
- static native int[] toxSelfGetFriendList(int instanceNumber);
- static native void toxSelfSetTyping(int instanceNumber, int friendNumber, boolean typing) throws ToxSetTypingException;
- static native int toxFriendSendMessage(int instanceNumber, int friendNumber, int type, int timeDelta, @NotNull byte[] message) throws ToxFriendSendMessageException;
- static native void toxFileControl(int instanceNumber, int friendNumber, int fileNumber, int control) throws ToxFileControlException;
- static native void toxFileSeek(int instanceNumber, int friendNumber, int fileNumber, long position) throws ToxFileSeekException;
- static native int toxFileSend(int instanceNumber, int friendNumber, int kind, long fileSize, @NotNull byte[] fileId, @NotNull byte[] filename) throws ToxFileSendException;
- static native void toxFileSendChunk(int instanceNumber, int friendNumber, int fileNumber, long position, @NotNull byte[] data) throws ToxFileSendChunkException;
- @NotNull
- static native byte[] toxFileGetFileId(int instanceNumber, int friendNumber, int fileNumber) throws ToxFileGetException;
- static native void toxFriendSendLossyPacket(int instanceNumber, int friendNumber, @NotNull byte[] data) throws ToxFriendCustomPacketException;
- static native void toxFriendSendLosslessPacket(int instanceNumber, int friendNumber, @NotNull byte[] data) throws ToxFriendCustomPacketException;
-
- static native void invokeSelfConnectionStatus(int instanceNumber, int connectionStatus);
- static native void invokeFileRecvControl(int instanceNumber, int friendNumber, int fileNumber, int control);
- static native void invokeFileRecv(int instanceNumber, int friendNumber, int fileNumber, int kind, long fileSize, @NotNull byte[] filename);
- static native void invokeFileRecvChunk(int instanceNumber, int friendNumber, int fileNumber, long position, @NotNull byte[] data);
- static native void invokeFileChunkRequest(int instanceNumber, int friendNumber, int fileNumber, long position, int length);
- static native void invokeFriendConnectionStatus(int instanceNumber, int friendNumber, int connectionStatus);
- static native void invokeFriendLosslessPacket(int instanceNumber, int friendNumber, @NotNull byte[] data);
- static native void invokeFriendLossyPacket(int instanceNumber, int friendNumber, @NotNull byte[] data);
- static native void invokeFriendMessage(int instanceNumber, int friendNumber, int type, int timeDelta, @NotNull byte[] message);
- static native void invokeFriendName(int instanceNumber, int friendNumber, @NotNull byte[] name);
- static native void invokeFriendRequest(int instanceNumber, @NotNull byte[] publicKey, int timeDelta, @NotNull byte[] message);
- static native void invokeFriendStatus(int instanceNumber, int friendNumber, int status);
- static native void invokeFriendStatusMessage(int instanceNumber, int friendNumber, @NotNull byte[] message);
- static native void invokeFriendTyping(int instanceNumber, int friendNumber, boolean isTyping);
- static native void invokeFriendReadReceipt(int instanceNumber, int friendNumber, int messageId);
+ static native byte[] toxFileGetFileId(int instanceNumber, int friendNumber, int fileNumber)
+ throws ToxFileGetException;
+ static native void toxFriendSendLossyPacket(int instanceNumber, int friendNumber,
+ @NotNull byte[] data) throws ToxFriendCustomPacketException;
+ static native void toxFriendSendLosslessPacket(int instanceNumber, int friendNumber,
+ @NotNull byte[] data) throws ToxFriendCustomPacketException;
static native byte[] tox4jLastLog();
static native int tox4jGetCurrentLogSize();
static native void tox4jSetMaxLogSize(int maxSize);
static native int tox4jGetMaxLogSize();
static native void tox4jSetLogFilter(String[] filter);
-
}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.kt b/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.kt
new file mode 100644
index 000000000..478a89784
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.kt
@@ -0,0 +1,38 @@
+package im.tox.tox4j.impl.jni
+
+import im.tox.tox4j.crypto.ToxCrypto
+import im.tox.tox4j.crypto.ToxCryptoConstants
+
+private typealias PassKey = ByteArray
+
+object ToxCryptoImpl : ToxCrypto {
+
+ override fun passKeyEquals(a: PassKey, b: PassKey): Boolean = a.contentEquals(b)
+
+ override fun passKeyToBytes(passKey: PassKey): List = passKey.toList()
+
+ override fun passKeyFromBytes(bytes: List): PassKey? =
+ if (bytes.size == ToxCryptoConstants.KeyLength + ToxCryptoConstants.SaltLength) {
+ bytes.toByteArray()
+ } else {
+ null
+ }
+
+ override fun encrypt(data: ByteArray, passKey: PassKey): ByteArray =
+ ToxCryptoJni.toxPassKeyEncrypt(data, passKey)
+
+ override fun getSalt(data: ByteArray): ByteArray = ToxCryptoJni.toxGetSalt(data)
+
+ override fun isDataEncrypted(data: ByteArray): Boolean = ToxCryptoJni.toxIsDataEncrypted(data)
+
+ override fun passKeyDeriveWithSalt(passphrase: ByteArray, salt: ByteArray): PassKey =
+ ToxCryptoJni.toxPassKeyDeriveWithSalt(passphrase, salt)
+
+ override fun passKeyDerive(passphrase: ByteArray): PassKey =
+ ToxCryptoJni.toxPassKeyDerive(passphrase)
+
+ override fun decrypt(data: ByteArray, passKey: PassKey): ByteArray =
+ ToxCryptoJni.toxPassKeyDecrypt(data, passKey)
+
+ override fun hash(data: ByteArray): ByteArray = ToxCryptoJni.toxHash(data)
+}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.scala
deleted file mode 100644
index fc324c193..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoImpl.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.crypto.{ ToxCrypto, ToxCryptoConstants }
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-object ToxCryptoImpl extends ToxCrypto {
-
- override type PassKey = Array[Byte]
-
- override def passKeyEquals(a: PassKey, b: PassKey): Boolean = a.deep == b.deep
- override def passKeyToBytes(passKey: PassKey): Seq[Byte] = passKey
-
- override def passKeyFromBytes(bytes: Seq[Byte]): Option[PassKey] = {
- if (bytes.length == ToxCryptoConstants.KeyLength + ToxCryptoConstants.SaltLength) {
- Some(bytes.toArray)
- } else {
- None
- }
- }
-
- override def encrypt(data: Array[Byte], passKey: PassKey): Array[Byte] =
- ToxCryptoJni.toxPassKeyEncrypt(data, passKey)
- override def getSalt(data: Array[Byte]): Array[Byte] =
- ToxCryptoJni.toxGetSalt(data)
- override def isDataEncrypted(data: Array[Byte]): Boolean =
- ToxCryptoJni.toxIsDataEncrypted(data)
- override def passKeyDeriveWithSalt(passphrase: Array[Byte], salt: Array[Byte]): PassKey =
- ToxCryptoJni.toxPassKeyDeriveWithSalt(passphrase, salt)
- override def passKeyDerive(passphrase: Array[Byte]): PassKey =
- ToxCryptoJni.toxPassKeyDerive(passphrase)
- override def decrypt(data: Array[Byte], passKey: PassKey): Array[Byte] =
- ToxCryptoJni.toxPassKeyDecrypt(data, passKey)
- override def hash(data: Array[Byte]): Array[Byte] =
- ToxCryptoJni.toxHash(data)
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoJni.java b/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoJni.java
index 6f25c765e..66cbe4cc2 100644
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoJni.java
+++ b/src/main/java/im/tox/tox4j/impl/jni/ToxCryptoJni.java
@@ -2,9 +2,8 @@
@SuppressWarnings({"checkstyle:emptylineseparator", "checkstyle:linelength"})
public final class ToxCryptoJni {
-
static {
- ToxLoadJniLibrary.load("tox4j-c");
+ System.loadLibrary("tox4j-c");
}
static native byte[] toxPassKeyEncrypt(byte[] data, byte[] passKey);
@@ -14,5 +13,4 @@ public final class ToxCryptoJni {
static native byte[] toxPassKeyDerive(byte[] passphrase);
static native byte[] toxPassKeyDecrypt(byte[] data, byte[] passKey);
static native byte[] toxHash(byte[] data);
-
}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxJniLog.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxJniLog.scala
deleted file mode 100644
index abc6fdaf4..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxJniLog.scala
+++ /dev/null
@@ -1,200 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import java.io.{ PrintWriter, StringWriter }
-
-import com.google.protobuf.InvalidProtocolBufferException
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.impl.jni.proto.Value.V
-import im.tox.tox4j.impl.jni.proto._
-import org.slf4j.LoggerFactory
-
-import scala.concurrent.duration._
-import scala.language.postfixOps
-
-/**
- * The JNI bridge logs every call made to toxcore and toxav functions along
- * with the time taken to execute in microseconds. See the message definitions
- * in ProtoLog.proto to get an idea of what can be done with this log.
- */
-// scalastyle:off non.ascii.character.disallowed
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-case object ToxJniLog {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- /**
- * By default, filter out the functions called on every iteration.
- */
- filterNot(
- "tox_iterate",
- "toxav_iterate",
- "tox_iteration_interval",
- "toxav_iteration_interval"
- )
-
- /**
- * Set the maximum number of entries in the log. After this limit is reached,
- * logging stops and ignores any further calls until the log is fetched and cleared.
- *
- * Set to 0 to disable logging.
- */
- def maxSize_=(maxSize: Int): Unit = ToxCoreJni.tox4jSetMaxLogSize(maxSize)
- def maxSize: Int = ToxCoreJni.tox4jGetMaxLogSize
-
- /**
- * The current size of the log on the native side. Can be used to determine
- * whether it needs to be fetched.
- */
- def size: Int = ToxCoreJni.tox4jGetCurrentLogSize
-
- /**
- * Set a filter to avoid logging certain calls.
- */
- def filterNot(filter: String*): Unit = ToxCoreJni.tox4jSetLogFilter(filter.toArray)
-
- /**
- * Retrieve and clear the current call log. Calling [[ToxJniLog]] twice with no
- * native calls in between will return the empty log the second time. If logging
- * is disabled, this will always return the empty log.
- */
- def apply(): JniLog = {
- fromBytes(ToxCoreJni.tox4jLastLog())
- }
-
- /**
- * Parse a protobuf message from bytes to [[JniLog]]. Logs an error and returns
- * [[JniLog.defaultInstance]] if $bytes is invalid. Returns [[JniLog.defaultInstance]]
- * if $bytes is null.
- */
- def fromBytes(bytes: Array[Byte]): JniLog = {
- try {
- Option(bytes).map(JniLog.parseFrom).getOrElse(JniLog.defaultInstance)
- } catch {
- case e: InvalidProtocolBufferException =>
- logger.error(s"${e.getMessage}; unfinished message: ${e.getUnfinishedMessage}")
- JniLog.defaultInstance
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.While"))
- private def printDelimited[A](list: Iterable[A], separator: String)(print: A => PrintWriter => Unit)(out: PrintWriter): Unit = {
- val i = list.iterator
- if (i.hasNext) {
- print(i.next())(out)
- while (i.hasNext) { // scalastyle:ignore while
- out.print(separator)
- print(i.next())(out)
- }
- }
- }
-
- /**
- * Pretty-print the log as function calls with time offset from the first message. E.g.
- * [0.000000] tox_new_unique({udp_enabled=1; ipv6_enabled=0; ...}) [20 µs, #1]
- *
- * The last part is the time spent in the native function followed by the instance number.
- */
- def print(log: JniLog)(out: PrintWriter): Unit = {
- log.entries.headOption match {
- case None =>
- case Some(first) =>
- for (entry <- log.entries) {
- print(first.timestamp.getOrElse(Timestamp.defaultInstance))(entry)(out)
- out.println()
- }
- }
- }
-
- private def printFormattedTimeDiff(a: Timestamp, b: Timestamp)(out: PrintWriter): Unit = {
- assert(a.nanos < 1000000000)
- assert(b.nanos < 1000000000)
-
- val timeDiff = {
- val seconds = a.seconds - b.seconds
- val nanos = a.nanos - b.nanos
- if (nanos < 0) {
- Timestamp(seconds - 1, nanos + (1 second).toNanos.toInt)
- } else {
- Timestamp(seconds, nanos)
- }
- }
-
- val micros = (timeDiff.nanos nanos).toMicros.toInt
- out.print(timeDiff.seconds)
- out.print('.')
- out.print {
- // scalastyle:off if.brace
- if (false) ""
- else if (micros < 10) "00000"
- else if (micros < 100) "0000"
- else if (micros < 1000) "000"
- else if (micros < 10000) "00"
- else if (micros < 100000) "0"
- else if (micros < 1000000) ""
- // scalastyle:on if.brace
- }
- out.print(micros)
- }
-
- def print(startTime: Timestamp)(entry: JniLogEntry)(out: PrintWriter): Unit = {
- out.print('[')
- printFormattedTimeDiff(entry.timestamp.getOrElse(Timestamp.defaultInstance), startTime)(out)
- out.print("] ")
- out.print(entry.name)
- out.print('(')
- printDelimited(entry.arguments, ", ")(print)(out)
- out.print(") = ")
- print(entry.result.getOrElse(Value.defaultInstance))(out)
- out.print(" [")
- val elapsedNanos = entry.elapsedNanos.nanos
- if (elapsedNanos.toMicros == 0) {
- out.print(elapsedNanos.toNanos)
- out.print(" ns")
- } else {
- out.print(elapsedNanos.toMicros)
- out.print(" µs")
- }
- entry.instanceNumber match {
- case 0 =>
- case instanceNumber =>
- out.print(", #")
- out.print(instanceNumber)
- }
- out.print("]")
- }
-
- def print(value: Value)(out: PrintWriter): Unit = {
- value.v match {
- case V.VBytes(bytes) =>
- out.print("byte[")
- if (value.truncated == 0) {
- out.print(bytes.size)
- } else {
- out.print(value.truncated)
- }
- out.print("]")
- case V.VObject(Struct(members)) =>
- out.print('{')
- printDelimited(members, "; ")(print)(out)
- out.print('}')
- case V.VSint64(sint64) => out.print(sint64)
- case V.VString(string) => out.print(string)
- case V.Empty => out.print("void")
- }
- }
-
- def print(member: (String, Value))(out: PrintWriter): Unit = {
- out.print(member._1)
- out.print('=')
- print(member._2)(out)
- }
-
- def toString(log: JniLog): String = {
- val stringWriter = new StringWriter
- val out = new PrintWriter(stringWriter)
- print(log)(out)
- out.close()
- stringWriter.toString
- }
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/ToxLoadJniLibrary.scala b/src/main/java/im/tox/tox4j/impl/jni/ToxLoadJniLibrary.scala
deleted file mode 100644
index 82a33aaf2..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/ToxLoadJniLibrary.scala
+++ /dev/null
@@ -1,127 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import java.io.File
-import java.io.InputStream
-
-import com.google.common.io.Files
-import com.typesafe.scalalogging.Logger
-import org.slf4j.LoggerFactory
-
-import scala.language.postfixOps
-
-object ToxLoadJniLibrary {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- private val AlreadyLoaded = "Native Library (.+) already loaded in another classloader".r
- private val NotFoundDalvik = "Couldn't load .+ from loader .+ findLibrary returned null".r
- private val NotFoundJvm = "no .+ in java.library.path.*".r
-
- private def withTempFile(name: String)(block: File => Boolean): Boolean = {
- val (prefix, suffix) = name.splitAt(name.lastIndexOf("."))
- val file = File.createTempFile(prefix, suffix)
- file.deleteOnExit()
- try {
- block(file)
- } finally {
- // This may fail if the OS doesn't support deleting files that are in use, but deleteOnExit
- // will ensure that it is cleaned up on normal JVM termination.
- file.delete()
- }
- }
-
- private def withResource(name: String)(block: InputStream => Boolean): Boolean = {
- val stream = getClass.getResourceAsStream(name)
- if (stream == null) {
- logger.debug(s"Resource '$name' not found")
- false
- } else {
- try {
- block(stream)
- } finally {
- stream.close()
- }
- }
- }
-
- /**
- * Load a native library from an existing location by copying it to a new, temporary location and loading
- * that new library.
- *
- * @param location A [[File]] pointing to the existing library.
- */
- private def loadFromSystem(location: File): Boolean = {
- withTempFile(location.getName) { libraryFile =>
- logger.info(s"Copying $location to $libraryFile")
- Files.copy(location, libraryFile)
-
- System.load(libraryFile.getPath)
- true
- }
- }
-
- /**
- * Load a library from a linked resource jar by copying it to a temporary location and then loading that
- * temporary file.
- *
- * @param name The library name without "dll" suffix or "lib" prefix.
- */
- private def loadFromJar(name: String): Boolean = {
- val osName = Map(
- "Mac OS X" -> "darwin"
- ).withDefault((x: String) => x.toLowerCase.split(" ").head)
- val archName = Map(
- "amd64" -> "x86_64"
- ).withDefault((x: String) => x.toLowerCase)
-
- val resourceName = "%s-%s/%s".format(
- osName(sys.props("os.name")),
- archName(sys.props("os.arch")),
- System.mapLibraryName(name)
- )
- logger.debug(s"Loading $name from resource: $resourceName")
- val location = new File(resourceName)
- withTempFile(location.getName) { libraryFile =>
- if (withResource(resourceName) { stream =>
- logger.debug(s"Copying $resourceName to ${libraryFile.getPath}")
- Files.asByteSink(libraryFile).writeFrom(stream)
- true
- }) {
- System.load(libraryFile.getPath)
- true
- } else {
- false
- }
- }
- }
-
- def load(name: String): Unit = synchronized {
- try {
- System.loadLibrary(name)
- } catch {
- case exn: UnsatisfiedLinkError =>
- logger.debug(
- s"Could not load native library '$name' (${exn.getMessage}). " +
- s"java.library.path = ${sys.props("java.library.path")}."
- )
- if (exn.getMessage match {
- case AlreadyLoaded(location) =>
- logger.warn(s"${exn.getMessage} copying file and loading again")
- loadFromSystem(new File(location))
- case NotFoundJvm() =>
- loadFromJar(name)
- case NotFoundDalvik() =>
- logger.error(s"Could not load native library '$name'; giving up.")
- false
- case msg =>
- logger.error(s"Unhandled UnsatisfiedLinkError: '$msg'.")
- false
- }) {
- logger.debug(s"Loading '$name' successful")
- } else {
- throw exn
- }
- }
- }
-
-}
diff --git a/src/main/java/im/tox/tox4j/impl/jni/internal/Event.scala b/src/main/java/im/tox/tox4j/impl/jni/internal/Event.scala
deleted file mode 100644
index f506fc6a7..000000000
--- a/src/main/java/im/tox/tox4j/impl/jni/internal/Event.scala
+++ /dev/null
@@ -1,85 +0,0 @@
-package im.tox.tox4j.impl.jni.internal
-
-import scala.annotation.tailrec
-import scala.collection.mutable.ArrayBuffer
-
-private[jni] object Event {
- private val InvalidIndex = -1
- private val EmptyCallback = () => ()
-
- trait Id {
- /**
- * @return The index in the callbacks list.
- */
- private[internal] def value: Int
-
- /**
- * Reset the index to an invalid value.
- */
- private[internal] def reset(): Unit
- }
-
- private final class IdImpl(private var index: Int) extends Id {
- override def value: Int = index
- override def reset(): Unit = index = InvalidIndex
- }
-}
-
-/**
- * Function multiplexer to turn a collection of functions into one.
- *
- * This is a collection of nullary functions returning `Unit` (`() => Unit)`) and is itself also a nullary function
- * returning unit. It can be used to implement events where one can register multiple handlers and selectively
- * unregister them.
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-private[jni] final class Event extends (() => Unit) {
- private val callbacks = new ArrayBuffer[() => Unit]
-
- /**
- * Register a callback to be called on [[apply]].
- *
- * The returned [[Event.Id]] should be considered a linear value. It should only be owned by a single owner and never
- * shared.
- *
- * @param callback A [[Runnable]] instance to be called.
- * @return An [[Event.Id]] that can be used to [[apply]] the callback again.
- */
- def +=(callback: () => Unit): Event.Id = {
- callbacks += callback
- new Event.IdImpl(callbacks.size - 1)
- }
-
- /**
- * Unregister a callback. Requires an [[Event.Id]] from [[+=]].
- *
- * After calling this method, the [[Event.Id]] should be considered consumed. Removing the same event handler twice
- * may result in erroneous behaviour. In particular, if between the two [[-=]] calls there is a [[+=]] call, the event
- * ID may have been reused, and the second call will remove the newly added handler.
- *
- * @param id The callback id object.
- */
- def -=(id: Event.Id): Unit = {
- val index = id.value
- if (index != Event.InvalidIndex) {
- id.reset()
- callbacks(index) = Event.EmptyCallback
- pruneCallbacks()
- }
- }
-
- @tailrec
- private def pruneCallbacks(): Unit = {
- callbacks.lastOption match {
- case Some(Event.EmptyCallback) =>
- callbacks.remove(callbacks.size - 1)
- pruneCallbacks()
- case _ =>
- }
- }
-
- /**
- * Invoke all callbacks.
- */
- override def apply(): Unit = callbacks.foreach(_())
-}
diff --git a/src/main/java/im/tox/tox4j/mkexceptions b/src/main/java/im/tox/tox4j/mkexceptions
new file mode 100755
index 000000000..d2a49bdfe
--- /dev/null
+++ b/src/main/java/im/tox/tox4j/mkexceptions
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings FATAL => 'all';
+use utf8;
+
+use JSON::PP;
+
+my $data = do { local $/; open my $fh, '<', 'exceptions.json' or die $!; decode_json <$fh> };
+
+my $package = $data->[0];
+my $prefix = $data->[1];
+my $exns = $data->[2];
+
+for my $type (keys %$exns) {
+ for (keys %{ $exns->{$type} }) {
+ my @lines = @{ $exns->{$type}{$_} };
+ s/^/ * / for @lines;
+ $exns->{$type}{$_} = join "\n", @lines;
+ }
+}
+
+for my $type (keys %$exns) {
+ open my $fh, '>', "Tox${prefix}${type}Exception.java"
+ or die $!;
+
+ my $codes =
+ join ",\n",
+ map { " /**\n$exns->{$type}{$_}\n */\n $_" }
+ (sort keys %{ $exns->{$type} });
+
+ my $JavaOnly =
+ $codes =~ /\@JavaOnly/
+ ? "import im.tox.tox4j.exceptions.JavaOnly;\n"
+ : "";
+
+ print $fh < Doc)(that: Doc): Doc = {
- if (this == EmptyDoc) {
- that
- } else if (that == EmptyDoc) {
- this
- } else {
- f(that)
- }
- }
-
- /**
- * Concatenates two documents.
- * Is left associative with [[gnieh.pp.empty]] as left and right unit.
- */
- def ::(that: Doc): Doc =
- withUnit(ConsDoc(_, this))(that)
-
- /** Equivalent to `that :: space :: this` */
- def :+:(that: Doc): Doc =
- withUnit(_ :: space :: this)(that)
-
- /** Equivalent to `that :: line :: this` */
- def :|:(that: Doc): Doc =
- withUnit(_ :: line :: this)(that)
-
- /** Equivalent to `that :: softline :: this` */
- def :\:(that: Doc): Doc =
- withUnit(_ :: softline :: this)(that)
-
- /** Equivalent to `that :: linebreak :: this` */
- def :||:(that: Doc): Doc =
- withUnit(_ :: linebreak :: this)(that)
-
- /** Equivalent to `that :: softbreak :: this` */
- def :\\:(that: Doc): Doc =
- withUnit(_ :: softbreak :: this)(that)
-
- /** Equivalent to `align(this :|: that)` */
- def ||(that: Doc): Doc =
- align(this :|: that)
-
- /** A flatten (no new lines) version of this document */
- def flatten: Doc
-
-}
-
-/**
- * Nest document: new lines are indented by the given indentation.
- * @author Lucas Satabin
- */
-final case class NestDoc(indent: Int, inner: Doc) extends Doc {
- override lazy val flatten = NestDoc(indent, inner.flatten)
-}
-
-/**
- * Union document: two variations of the same document.
- * '''Note''': The `long`-document's first lines must be longer that the `short`-document's ones.
- * @author Lucas Satabin
- */
-final case class UnionDoc(long: Doc, short: Doc) extends Doc {
- override lazy val flatten = long.flatten
-}
-
-/**
- * Empty document.
- * @author Lucas Satabin
- */
-case object EmptyDoc extends Doc {
- override def flatten: Doc = this
-}
-
-/**
- * Text document: shall not contain any new lines.
- * @author Lucas Satabin
- */
-final case class TextDoc(text: String) extends Doc {
- override def flatten: Doc = this
-}
-
-/**
- * Line document: renders as a new line except if discarded by a group.
- * @author Lucas Satabin
- */
-final case class LineDoc(repl: Doc) extends Doc {
- override def flatten: Doc = repl
-}
-
-/**
- * Cons document: Concatenation of two documents.
- * @author Lucas Satabin
- */
-final case class ConsDoc(first: Doc, second: Doc) extends Doc {
- override lazy val flatten = ConsDoc(first.flatten, second.flatten)
-}
-
-/**
- * Align document: aligns the document on the current column.
- * @author Lucas Satabin
- */
-final case class AlignDoc(inner: Doc) extends Doc {
- override lazy val flatten = AlignDoc(inner.flatten)
-}
-
-/**
- * Column document: creates a document depending on the current column.
- * @author Lucas Satabin
- */
-final case class ColumnDoc(f: Int => Doc) extends Doc {
- override lazy val flatten = ColumnDoc(f.andThen(_.flatten))
-}
diff --git a/src/test/java/gnieh/pp/Renderer.scala b/src/test/java/gnieh/pp/Renderer.scala
deleted file mode 100644
index 375216777..000000000
--- a/src/test/java/gnieh/pp/Renderer.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * This file is part of the gnieh-pp project.
- *
- * 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.
- */
-package gnieh.pp
-
-/**
- * A pretty printer, that tries to make the document fit in the page width
- *
- * @author Lucas Satabin
- */
-final class PrettyRenderer(width: Int) extends (Doc => SimpleDoc) {
-
- private type Docs = List[(Int, Doc)]
-
- override def apply(doc: Doc): SimpleDoc = {
- best(width, 0, List((0, doc)))
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def best(width: Int, column: Int, docs: Docs): SimpleDoc = {
- docs match {
- case Nil =>
- SEmpty
- case (_, EmptyDoc) :: tail =>
- best(width, column, tail)
- case (i, ConsDoc(first, second)) :: tail =>
- best(width, column, (i, first) :: (i, second) :: tail)
- case (i, NestDoc(j, inner)) :: tail =>
- best(width, column, (i + j, inner) :: tail)
- case (i, TextDoc(text)) :: tail =>
- SText(text, best(width, column + text.length, tail))
- case (i, LineDoc(_)) :: tail =>
- SLine(i, best(width, i, tail))
- case (i, UnionDoc(l, s)) :: tail =>
- better(width, column,
- best(width, column, (i, l) :: tail),
- best(width, column, (i, s) :: tail))
- case (i, AlignDoc(inner)) :: tail =>
- best(width, column, (column, inner) :: tail)
- case (i, ColumnDoc(f)) :: tail =>
- best(width, column, (i, f(column)) :: tail)
- }
- }
-
- private def better(width: Int, column: Int, d1: SimpleDoc, d2: => SimpleDoc): SimpleDoc = {
- if (d1.fits(width - column)) {
- d1
- } else {
- // d2 is computed only if needed...
- d2
- }
- }
-
-}
-
-/**
- * This printer is not really pretty (but should be faster than pretty printers!):
- * it does not insert any indentation and discards all groups, just renders everything as compact as possible
- *
- * @author Lucas Satabin
- */
-object CompactRenderer extends (Doc => SimpleDoc) {
-
- override def apply(doc: Doc): SimpleDoc = {
- scan(0, List(doc))
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def scan(column: Int, docs: List[Doc]): SimpleDoc = docs match { // scalastyle:ignore cyclomatic.complexity
- case Nil => SEmpty
- case doc :: docs =>
- doc match {
- case EmptyDoc => SEmpty
- case TextDoc(text) => SText(text, scan(column + text.length, docs))
- case LineDoc(_) => scan(column, doc.flatten :: docs)
- case ConsDoc(first, second) => scan(column, first :: second :: docs)
- case NestDoc(j, doc) => scan(column, doc :: docs)
- case UnionDoc(long, _) => scan(column, long :: docs)
- case AlignDoc(inner) => scan(column, inner :: docs)
- case ColumnDoc(f) => scan(column, f(column) :: docs)
- }
- }
-
-}
-
-sealed abstract class CountUnit
-/** Truncates after the count in non space characters */
-case object Characters extends CountUnit
-/** Truncates after the count in words */
-case object Words extends CountUnit
-/** Truncates after the count in lines */
-case object Lines extends CountUnit
-
-/**
- * A renderer that truncates the result (once rendered by the inner renderer) with the given
- * limit. It makes the assumption that the following invariants are respected:
- * - a [[gnieh.pp.SText]] contains either only spaces or only a word
- * - indentation characters are all modeled with the indentation in [[gnieh.pp.SLine]]
- *
- * @author Lucas Satabin
- */
-final class TruncateRenderer(max: Int, unit: CountUnit, inner: Doc => SimpleDoc) extends (Doc => SimpleDoc) {
-
- override def apply(doc: Doc): SimpleDoc = {
- truncate(inner(doc))
- }
-
- def apply(doc: SimpleDoc): SimpleDoc = {
- truncate(doc)
- }
-
- /** Truncates the simple document, depending on the constructor criterion. */
- def truncate(doc: SimpleDoc): SimpleDoc = {
- unit match {
- case Lines => firstLines(max, doc)
- case Characters => firstChars(max, doc)
- case Words => firstWords(max, doc)
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def firstLines(maxLines: Int, doc: SimpleDoc): SimpleDoc = {
- doc match {
- case SText(text, next) if maxLines >= 1 => SText(text, firstLines(maxLines, next))
- case SLine(indent, next) if maxLines > 1 => SLine(indent, firstLines(maxLines - 1, next))
- case _ => SEmpty
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def firstChars(maxChars: Int, doc: SimpleDoc): SimpleDoc = {
- doc match {
- case SText(text, next) if maxChars >= text.replaceAll(" ", "").length => SText(text, firstChars(maxChars - text.length, next))
- case SLine(indent, next) if maxChars > 0 => SLine(indent, firstChars(maxChars, next))
- case _ => SEmpty
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def firstWords(maxWords: Int, doc: SimpleDoc): SimpleDoc = {
- doc match {
- case SText(text, next) if text.trim.isEmpty && maxWords > 0 => SText(text, firstWords(maxWords, next))
- case SText(text, next) if maxWords > 0 => SText(text, firstWords(maxWords - 1, next))
- case SLine(indent, next) if maxWords > 0 => SLine(indent, firstWords(maxWords, next))
- case _ => SEmpty
- }
- }
-
-}
diff --git a/src/test/java/gnieh/pp/SimpleDoc.scala b/src/test/java/gnieh/pp/SimpleDoc.scala
deleted file mode 100644
index 7796e6ada..000000000
--- a/src/test/java/gnieh/pp/SimpleDoc.scala
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * This file is part of the gnieh-pp project.
- *
- * 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.
- */
-package gnieh.pp
-
-/**
- * A simple document is the normalized form of a document.
- *
- * This is what is produced by the renderers depending on their rendering algorithm.
- *
- * @author Lucas Satabin
- */
-sealed abstract class SimpleDoc {
-
- def fits(width: Int): Boolean
-
- def layout: String
-
- override def toString: String = layout
-
-}
-
-/**
- * An empty document.
- * @author Lucas Satabin
- */
-case object SEmpty extends SimpleDoc {
- override def fits(width: Int): Boolean = width >= 0 // always fits if there is enough place
-
- override def layout: String = ""
-}
-
-/**
- * A text document. Should never contain new lines
- * @author Lucas Satabin
- */
-final case class SText(text: String, next: SimpleDoc) extends SimpleDoc {
- def fits(width: Int): Boolean = {
- next.fits(width - text.length)
- }
-
- override def layout: String = {
- text + next.layout
- }
-}
-
-/**
- * A new line document with the indentation level to print right after.
- * If the next document is empty, the indentation is not printed.
- * @author Lucas Satabin
- */
-final case class SLine(indent: Int, next: SimpleDoc) extends SimpleDoc {
- override def fits(width: Int): Boolean = width >= 0 // always fits if there is enough place
-
- override def layout: String = {
- if (next.layout.isEmpty) {
- ""
- } else {
- "\n" + (" " * indent) + next.layout
- }
- }
-}
diff --git a/src/test/java/gnieh/pp/package.scala b/src/test/java/gnieh/pp/package.scala
deleted file mode 100644
index 91696dd6f..000000000
--- a/src/test/java/gnieh/pp/package.scala
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
-* This file is part of the gnieh-pp project.
-*
-* 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.
-*/
-package gnieh
-
-import scala.collection.TraversableLike
-import scala.language.implicitConversions
-
-/** Pretty-printer library based on the Wadler's paper "A Prettier Printer". */
-package object pp {
-
- /** Indents the document */
- def nest(indent: Int)(inner: Doc): Doc = {
- NestDoc(indent, inner)
- }
-
- /* Deindent the document */
- def unnest(indent: Int)(inner: Doc): Doc = {
- nest(-indent)(inner)
- }
-
- /** Renders as a space */
- val space: Doc = TextDoc(" ")
-
- /** Renders as a new line unless it is discarded by a group, in which case behaves like `space` */
- val line: Doc = LineDoc(TextDoc(" "))
-
- /** Renders as a new line unless it is discarded by a group, in which case behaves like `empty` */
- val linebreak: Doc = LineDoc(EmptyDoc)
-
- /** Behaves like `space` if the result fits in the page, otherwise behaves like `line` */
- val softline: Doc = group(line)
-
- /** Behaves like `empty` if the result fits in the page, otherwise behaves like `line` */
- val softbreak: Doc = group(linebreak)
-
- /** Behaves like a new line unless it is discarded by a group, in which case, behaves like the replacement document */
- def lineOr(replacement: Doc): Doc = LineDoc(replacement)
-
- /** Renders as an empty string */
- val empty: Doc = EmptyDoc
-
- /** Renders the document with nesting level set to the current column */
- def align(doc: Doc): Doc = AlignDoc(doc)
-
- /** Renders the document with nesting level set to the current column plus `indent` */
- def hang(indent: Int)(doc: Doc): Doc = align(nest(indent)(doc))
-
- /** Renders the text as is. If it contains new lines, `string` should be used. */
- def text(s: String): Doc = {
- if (s.isEmpty) {
- EmptyDoc
- } else {
- TextDoc(s)
- }
- }
-
- /** Concatenates all characters, using `line` for new lines and `text` for other blocks */
- def string(s: String): Doc = {
- if (s.contains("\n")) {
- s.split("\n").foldRight(empty) { (word, doc) =>
- text(word) :|: doc
- }
- } else {
- text(s)
- }
- }
-
- /** Splits the string into words and create a document for each word */
- def words(s: String): List[Doc] = {
- s.split("\\s+").map(text).toList
- }
-
- /** Creates a document from the given character */
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def char(c: Char): Doc = {
- if (c == '\n') {
- line
- } else {
- TextDoc(c.toString)
- }
- }
-
- /** Creates a document from the given integer */
- def int(i: Int): Doc = TextDoc(i.toString)
-
- /** Creates a document from the given long */
- def long(l: Long): Doc = TextDoc(l.toString)
-
- /** Creates a document from the given float */
- def float(f: Float): Doc = TextDoc(f.toString)
-
- /** Creates a document from the given double */
- def double(d: Double): Doc = TextDoc(d.toString)
-
- /** Discards all line breaks in the given document if the result fits in the page, otherwise, renders without any changes */
- def group(doc: Doc): Doc = UnionDoc(doc.flatten, doc)
-
- /** Renders the document as usual, and then fills until `width` with spaces if necessary */
- def fill(until: Int)(doc: Doc): Doc = {
- width { w =>
- if (w >= until) {
- empty
- } else {
- text(" " * (until - w))
- }
- }(doc)
- }
-
- /** Renders a document followed by some other document computed depending on the current width */
- def width(f: Int => Doc)(doc: Doc): Doc = {
- ColumnDoc(start => doc :: ColumnDoc(end => f(end - start)))
- }
-
- /** Renders a document in which all documents in the collection are appended horizontally, separated by a `space` */
- def hsep(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :+: _)
- }
-
- /** Renders a document in which all documents in the collection are appended vertically, separated by a `line` */
- def vsep(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :|: _)
- }
-
- /** Renders a document in which all documents in the collection are appended vertically, separated by a `softline` */
- def fillSep(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :\: _)
- }
-
- /**
- * Renders a document that tries to append the documents in the collection
- * horizontally separated by a `space` if it fits, otherwise append them
- * vertically
- */
- def sep(docs: TraversableLike[Doc, _]): Doc = {
- group(vsep(docs))
- }
-
- /** Renders a document that appends the document in the collection horizontally */
- def hcat(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :: _)
- }
-
- /** Renders a document that appends all documents in the collection vertically, separated by a `linebreak` */
- def vcat(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :||: _)
- }
-
- /** Renders a document that appends all document in the collection horizontally, separated by a `softbreak` */
- def fillCat(docs: TraversableLike[Doc, _]): Doc = {
- docs.foldRight(empty)(_ :\\: _)
- }
-
- /**
- * Renders a document that trie to append the documents in the collection
- * horizontally, otherwise append them vertically
- */
- def cat(docs: TraversableLike[Doc, _]): Doc = {
- group(vcat(docs))
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def s2doc(s: String): Doc = string(s)
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def i2doc(i: Int): Doc = int(i)
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def l2doc(l: Long): Doc = long(l)
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def f2doc(f: Float): Doc = float(f)
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def d2doc(d: Double): Doc = double(d)
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def c2doc(c: Char): Doc = char(c)
-
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def opt2doc[T](o: Option[T])(implicit ev1: T => Doc): Doc = {
- o match {
- case Some(d) => d
- case None => empty
- }
- }
-
-}
diff --git a/src/test/java/im/tox/core/random/RandomCore.scala b/src/test/java/im/tox/core/random/RandomCore.scala
deleted file mode 100644
index adabb4619..000000000
--- a/src/test/java/im/tox/core/random/RandomCore.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package im.tox.core.random
-
-import java.nio.ByteBuffer
-import im.tox.core.typesafe.Equals._
-
-import org.jetbrains.annotations.NotNull
-
-object RandomCore {
-
- def entropy(@NotNull data: Seq[Byte]): Double = {
- val frequencies = new Array[Int](-Byte.MinValue * 2)
- for (b <- data) {
- frequencies(Byte.MaxValue - b) += 1
- }
-
- val probabilities =
- for (frequency <- frequencies) yield {
- if (frequency =/= 0) {
- val probability = frequency.toDouble / data.length
- -probability * (Math.log(probability) / Math.log(-Byte.MinValue * 2))
- } else {
- 0
- }
- }
- probabilities.sum
- }
-
-}
diff --git a/src/test/java/im/tox/core/random/RandomCoreTest.scala b/src/test/java/im/tox/core/random/RandomCoreTest.scala
deleted file mode 100644
index 88eaa4951..000000000
--- a/src/test/java/im/tox/core/random/RandomCoreTest.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package im.tox.core.random
-
-import org.scalacheck.Gen
-import org.scalatest.WordSpec
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class RandomCoreTest extends WordSpec with ScalaCheckPropertyChecks {
-
- "entropy" should {
- "be 0 for the empty sequence" in {
- assert(RandomCore.entropy(Nil) == 0)
- }
-
- "be 0 for sequences of all the same element" in {
- forAll { (bytes: Seq[Byte], filler: Byte) =>
- assert(RandomCore.entropy(bytes.map(_ => filler)) == 0)
- }
- }
-
- "be near 1 for long sequences" in {
- assert(RandomCore.entropy((0 to 1000).map(_.toByte)) > 0.999)
- }
-
- "be 1 for sequences containing every byte equally often (maximum)" in {
- forAll(Gen.choose(1, 10)) { count =>
- val bytes = (1 to count).flatMap(_ => (0 to 255).map(_.toByte))
- assert(RandomCore.entropy(bytes) == 1)
- }
- }
-
- "be sorting-insensitive (symmetry)" in {
- forAll { (bytes: Seq[Byte]) =>
- assert(RandomCore.entropy(bytes) == RandomCore.entropy(bytes.sorted))
- assert(RandomCore.entropy(bytes) == RandomCore.entropy(bytes.reverse))
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/documentation/Doc.scala b/src/test/java/im/tox/documentation/Doc.scala
deleted file mode 100644
index f545b6f4a..000000000
--- a/src/test/java/im/tox/documentation/Doc.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package im.tox.documentation
-
-sealed trait Doc {
- def reference: String
-}
-
-object Doc {
- final case class Ref(reference: String) extends Doc
- final case class Text(reference: String, body: String) extends Doc
-}
diff --git a/src/test/java/im/tox/documentation/Documented.scala b/src/test/java/im/tox/documentation/Documented.scala
deleted file mode 100644
index 6d816a5c8..000000000
--- a/src/test/java/im/tox/documentation/Documented.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.documentation
-
-/**
- * Every package object with documentation must inherit from this class.
- */
-abstract class Documented {
- /**
- * Create a reference to a Java/Scala type in the documentation.
- * @tparam T The type to print in the documentation.
- */
- protected final def ref[T](implicit evidence: Manifest[T]): Doc = {
- Doc.Ref("[[" + evidence.runtimeClass.getSimpleName + "]]")
- }
-
- /**
- * Create a reference to a Scala singleton object.
- * @tparam T The type of the object to be printed.
- */
- protected final def ref[T](value: T): Doc = {
- Doc.Ref("[[" + value.getClass.getSimpleName + "]]")
- }
-
- /**
- * Initialised to just the name of the package object. Any [[DocumentationInterpolator.doc]] calls in the actual
- * package object will override this, but [[name]] will already be set then.
- */
- private var document: Doc = Doc.Ref("[[" + getClass.getName.replace(".package$", "") + "]]")
-
- /**
- * The name of the package object. Used to link to other package object documentation blocks.
- */
- final val name: Doc = document
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- implicit class DocumentationInterpolator(val sc: StringContext) {
- def doc(args: Doc*): Unit = {
- val packageName = (new Throwable).getStackTrace()(1).getClassName
- val documentation = sc.parts.zip(args.map(_.reference)).map { case (a, b) => a + b }.mkString.stripMargin
- assert(document == name)
- document = Doc.Text(packageName, documentation)
- }
- }
-
- final override def toString: String = document.toString
-}
diff --git a/src/test/java/im/tox/tox4j/ConnectedListener.scala b/src/test/java/im/tox/tox4j/ConnectedListener.scala
deleted file mode 100644
index 0f747304c..000000000
--- a/src/test/java/im/tox/tox4j/ConnectedListener.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.tox4j.core.callbacks.ToxCoreEventListener
-import im.tox.tox4j.core.enums.ToxConnection
-import org.jetbrains.annotations.NotNull
-
-final class ConnectedListener extends ToxCoreEventListener[Unit] {
-
- @NotNull private var value = ToxConnection.NONE
-
- override def selfConnectionStatus(@NotNull connectionStatus: ToxConnection)(state: Unit): Unit = {
- value = connectionStatus
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def isConnected: Boolean = value != ToxConnection.NONE
-
-}
diff --git a/src/test/java/im/tox/tox4j/DhtNode.scala b/src/test/java/im/tox/tox4j/DhtNode.scala
deleted file mode 100644
index 1efbffb18..000000000
--- a/src/test/java/im/tox/tox4j/DhtNode.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.core.network.Port
-import im.tox.tox4j.core.data.ToxPublicKey
-import im.tox.tox4j.testing.GetDisjunction._
-
-final case class DhtNode(ipv4: String, ipv6: String, udpPort: Port, tcpPort: Port, dhtId: ToxPublicKey) {
-
- def this(ipv4: String, ipv6: String, udpPort: Int, tcpPort: Int, dhtId: String) {
- this(
- ipv4, ipv6,
- Port.unsafeFromInt(udpPort),
- Port.unsafeFromInt(tcpPort),
- ToxPublicKey.fromValue(ToxCoreTestBase.parsePublicKey(dhtId)).toOption.get
- )
- }
-
- def this(ipv4: String, ipv6: String, port: Int, dhtId: String) {
- this(ipv4, ipv6, port, port, dhtId)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/DhtNodeSelector.scala b/src/test/java/im/tox/tox4j/DhtNodeSelector.scala
deleted file mode 100644
index 4fbbd2136..000000000
--- a/src/test/java/im/tox/tox4j/DhtNodeSelector.scala
+++ /dev/null
@@ -1,90 +0,0 @@
-package im.tox.tox4j
-
-import java.io.IOException
-import java.net.{ InetAddress, Socket }
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory
-import org.scalatest.Assertions
-import org.slf4j.LoggerFactory
-
-object DhtNodeSelector extends Assertions {
-
- private val logger = Logger(LoggerFactory.getLogger(this.getClass))
- private var selectedNode: Option[DhtNode] = Some(ToxCoreTestBase.nodeCandidates(0))
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- private def tryConnect(node: DhtNode): Option[DhtNode] = {
- var socket: Socket = null
- try {
- socket = new Socket(InetAddress.getByName(node.ipv4), node.udpPort.value)
- assume(socket.getInputStream != null)
- Some(node)
- } catch {
- case e: IOException =>
- logger.info(s"TCP connection failed (${e.getMessage})")
- None
- } finally {
- if (socket != null) {
- socket.close()
- }
- }
- }
-
- private def tryBootstrap(
- withTox: (Boolean, Boolean) => (ToxCore => Option[DhtNode]) => Option[DhtNode],
- node: DhtNode,
- udpEnabled: Boolean
- ): Option[DhtNode] = {
- val protocol = if (udpEnabled) "UDP" else "TCP"
- val port = if (udpEnabled) node.udpPort else node.tcpPort
- logger.info(s"Trying to bootstrap with ${node.ipv4}:$port using $protocol")
-
- withTox(true, udpEnabled) { tox =>
- val status = new ConnectedListener
- if (!udpEnabled) {
- tox.addTcpRelay(node.ipv4, port, node.dhtId)
- }
- tox.bootstrap(node.ipv4, port, node.dhtId)
-
- // Try bootstrapping for 10 seconds.
- (0 to 10000 / tox.iterationInterval) find { _ =>
- tox.iterate(status)(())
- Thread.sleep(tox.iterationInterval)
- status.isConnected
- } match {
- case Some(time) =>
- logger.info(s"Bootstrapped successfully after ${time * tox.iterationInterval}ms using $protocol")
- Some(node)
- case None =>
- logger.info(s"Unable to bootstrap with $protocol")
- None
- }
- }
- }
-
- private def findNode(withTox: (Boolean, Boolean) => (ToxCore => Option[DhtNode]) => Option[DhtNode]): DhtNode = {
- DhtNodeSelector.selectedNode match {
- case Some(node) => node
- case None =>
- logger.info("Looking for a working bootstrap node")
-
- DhtNodeSelector.selectedNode = ToxCoreTestBase.nodeCandidates find { node =>
- logger.info(s"Trying to establish a TCP connection to ${node.ipv4}")
-
- (for {
- node <- tryConnect(node)
- node <- tryBootstrap(withTox, node, udpEnabled = true)
- node <- tryBootstrap(withTox, node, udpEnabled = false)
- } yield node).isDefined
- }
-
- assume(DhtNodeSelector.selectedNode.nonEmpty, "No viable nodes for bootstrap found; cannot test")
- DhtNodeSelector.selectedNode.get
- }
- }
-
- def node: DhtNode = findNode(ToxCoreImplFactory.withToxUnit[Option[DhtNode]])
-
-}
diff --git a/src/test/java/im/tox/tox4j/SocksServer.scala b/src/test/java/im/tox/tox4j/SocksServer.scala
deleted file mode 100644
index 457f18269..000000000
--- a/src/test/java/im/tox/tox4j/SocksServer.scala
+++ /dev/null
@@ -1,245 +0,0 @@
-package im.tox.tox4j
-
-import java.io.{ Closeable, IOException, InputStream, OutputStream }
-import java.net.{ InetAddress, ServerSocket, Socket }
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.SocksServer.{ FirstPort, LastPort, logger }
-import org.jetbrains.annotations.NotNull
-import org.scalatest.Assertions
-import org.slf4j.LoggerFactory
-
-import scala.collection.mutable.ArrayBuffer
-
-object SocksServer {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- private val FirstPort = 8000
- private val LastPort = 8999
-
- /**
- * Spawn a proxy server in a thread and pass it to the function.
- *
- * @param function The function to call ot the { @link SocksServer} object.
- * @tparam R The return type of the function.
- * @return The result of calling the function on the server object.
- */
- @throws[IOException]("When a network error occurs")
- @throws[InterruptedException]("On unexpected thread interrupts")
- def withServer[R](function: SocksServer => R): R = {
- val server = new SocksServer
- val thread = new Thread(server)
- thread.start()
- try {
- function.apply(server)
- } finally {
- server.close()
- thread.join()
- }
- }
-
-}
-
-/**
- * Create a simple SOCKS5 server on a port between [[FirstPort]] and [[LastPort]].
- */
-@SuppressWarnings(Array(
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.While"
-))
-@throws[IOException]("If no port could be bound")
-final class SocksServer extends Closeable with Runnable with Assertions {
-
- private val server = connectAvailablePort()
- private val threads = new ArrayBuffer[Thread]
- private val sockets = new ArrayBuffer[Socket]
- private var running = true
- private var accepted = 0
-
- @throws[IOException]
- private def connectAvailablePort(): ServerSocket = {
- var lastException: IOException = null
- var socket: ServerSocket = null
-
- (FirstPort to LastPort) find { port =>
- try {
- socket = new ServerSocket(port)
- true
- } catch {
- case e: IOException =>
- lastException = e
- false
- }
- }
-
- if (lastException != null) {
- throw lastException
- }
-
- socket
- }
-
- @throws[IOException]
- override def close(): Unit = {
- running = false
- server.close()
- }
-
- def getPort: Int = server.getLocalPort
- def getAddress: String = server.getInetAddress.getHostAddress
-
- override def run(): Unit = {
- try {
- while (running) {
- val socket = server.accept
- sockets += socket
- val thread = new Thread(new Runnable() {
- def run(): Unit = {
- val input = socket.getInputStream
- val output = socket.getOutputStream
- try {
- greeting(input, output)
- } catch {
- case e: IOException =>
- logger.error("Exception", e)
- } finally {
- if (input != null) input.close()
- if (output != null) output.close()
- }
- }
- })
- thread.start()
- threads += thread
- accepted += 1
- }
- } catch {
- case abort: IOException =>
- running = false
- try {
- server.close()
- sockets.foreach(_.close())
- threads.foreach(_.join())
- } catch {
- case error: Throwable =>
- logger.error("Exception", error)
- }
- }
- }
-
- private def greeting(input: InputStream, output: OutputStream): Unit = {
- assert(input.read == 0x05)
- val numAuthenticationMethods = input.read
- val authenticationMethods = new Array[Int](numAuthenticationMethods)
- for (i <- 0 until numAuthenticationMethods) {
- authenticationMethods(i) = input.read
- }
-
- if (!authenticationMethods.contains(0x00)) {
- throw new IOException("Client did not support any of our authentication methods")
- }
-
- output.write(0x05)
- output.write(0x00)
- connection(input, output)
- }
-
- private def connection(@NotNull input: InputStream, @NotNull output: OutputStream): Unit = {
- assert(input.read == 0x05)
- val command = input.read
- assert(input.read == 0x00)
-
- val address =
- input.read match {
- case 0x01 =>
- val address4 = new Array[Byte](4)
- assert(input.read(address4) == address4.length)
- InetAddress.getByAddress(address4)
- case 0x03 =>
- val domain = new Array[Byte](input.read)
- assert(input.read(domain) == domain.length)
- InetAddress.getByName(new String(domain))
- case 0x04 =>
- val address6 = new Array[Byte](16)
- assert(input.read(address6) == address6.length)
- InetAddress.getByAddress(address6)
- case _ =>
- throw new IOException("Unsupported address type")
- }
-
- val portBytes = new Array[Byte](2)
- assert(input.read(portBytes) == 2)
- val port = ((portBytes(0) & 0xff) << 8) | (portBytes(1) & 0xff)
-
- command match {
- case 0x01 => establishStream(input, output, address, port)
- case 0x02 => throw new IOException("TCP/IP port binding not supported")
- case 0x03 => throw new IOException("Associating UDP port not supported")
- case _ => throw new IOException(s"Unknown command: $command")
- }
- }
-
- private def establishStream(input: InputStream, output: OutputStream, address: InetAddress, port: Int): Unit = {
- output.write(0x05)
- try {
- val target = new Socket(address, port)
- sockets += target
- pipeStream(input, output, address, port, target)
- } catch {
- case e: IOException if e.getMessage == "Network is unreachable" =>
- output.write(0x03)
- }
- }
-
- private def pipeStream(input: InputStream, output: OutputStream, address: InetAddress, port: Int, target: Socket): Unit = {
- output.write(0x00)
- output.write(0x00)
-
- val addressBytes = address.getAddress
- if (addressBytes.length == 4) {
- output.write(0x01)
- } else {
- assert(addressBytes.length == 16)
- output.write(0x04)
- }
-
- output.write(addressBytes)
- output.write(port >> 8)
- output.write(port & 0xff)
-
- val targetInput = target.getInputStream
- val targetOutput = target.getOutputStream
-
- val inputThread = new Thread(new Runnable() {
- def run(): Unit = {
- try {
- var inByte = targetInput.read
- while (inByte != -1) {
- output.write(inByte)
- inByte = targetInput.read
- }
- } catch {
- case ignored: IOException =>
- }
- }
- })
-
- inputThread.start()
- threads += inputThread
-
- try {
- var outByte = input.read
- while (outByte != -1) {
- targetOutput.write(outByte)
- outByte = input.read
- }
- } catch {
- case ignored: IOException =>
- }
- }
-
- def getAccepted: Int = {
- accepted
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/TestConstants.scala b/src/test/java/im/tox/tox4j/TestConstants.scala
deleted file mode 100644
index ab7f630d4..000000000
--- a/src/test/java/im/tox/tox4j/TestConstants.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package im.tox.tox4j
-
-import org.scalatest.time.SpanSugar._
-
-import scala.language.postfixOps
-
-@SuppressWarnings(Array("org.wartremover.warts.PublicInference"))
-object TestConstants {
- val Timeout = 60 seconds
- val Iterations = 100
-}
diff --git a/src/test/java/im/tox/tox4j/ToxCoreTestBase.scala b/src/test/java/im/tox/tox4j/ToxCoreTestBase.scala
deleted file mode 100644
index 333f1f494..000000000
--- a/src/test/java/im/tox/tox4j/ToxCoreTestBase.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-package im.tox.tox4j
-
-import java.io.IOException
-import java.net.{ InetAddress, Socket }
-import java.util.Random
-
-import org.jetbrains.annotations.NotNull
-import org.scalatest.Assertions
-
-object ToxCoreTestBase extends Assertions {
-
- private[tox4j] val nodeCandidates = Seq(
- new DhtNode("tox.initramfs.io", "tox.initramfs.io", 33445, "3F0A45A268367C1BEA652F258C85F4A66DA76BCAA667A49E770BCC4917AB6A25"),
- new DhtNode("tox.verdict.gg", null, 33445, "1C5293AEF2114717547B39DA8EA6F1E331E5E358B35F9B6B5F19317911C5F976")
- )
-
- @NotNull def randomBytes(length: Int): Array[Byte] = {
- val array = new Array[Byte](length)
- new Random().nextBytes(array)
- array
- }
-
- @NotNull
- def readablePublicKey(@NotNull id: Array[Byte]): String = {
- val str = new StringBuilder
- id foreach { c => str.append(f"$c%02X") }
- str.toString()
- }
-
- @NotNull
- def parsePublicKey(@NotNull id: String): Array[Byte] = {
- val publicKey = new Array[Byte](id.length / 2)
- publicKey.indices foreach { i =>
- publicKey(i) =
- ((fromHexDigit(id.charAt(i * 2)) << 4) +
- fromHexDigit(id.charAt(i * 2 + 1))).toByte
- }
- publicKey
- }
-
- private def fromHexDigit(c: Char): Byte = {
- val digit =
- if (false) { 0 }
- else if ('0' to '9' contains c) { c - '0' }
- else if ('A' to 'F' contains c) { c - 'A' + 10 }
- else if ('a' to 'f' contains c) { c - 'a' + 10 }
- else { throw new IllegalArgumentException(s"Non-hex digit character: $c") }
- digit.toByte
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- private def hasConnection(ip: String, port: Int): Option[String] = {
- var socket: Socket = null
- try {
- socket = new Socket(InetAddress.getByName(ip), port)
- if (socket.getInputStream == null) {
- Some("Socket input stream is null")
- } else {
- None
- }
- } catch {
- case e: IOException =>
- Some(s"A network connection can't be established to $ip:$port: ${e.getMessage}")
- } finally {
- if (socket != null) {
- socket.close()
- }
- }
- }
-
- def checkIPv4: Option[String] = {
- hasConnection("8.8.8.8", 53)
- }
-
- def checkIPv6: Option[String] = {
- hasConnection("2001:4860:4860::8888", 53)
- }
-
- protected[tox4j] def assumeIPv4(): Unit = {
- assume(checkIPv4.isEmpty)
- }
-
- protected[tox4j] def assumeIPv6(): Unit = {
- assume(checkIPv6.isEmpty)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/ToxTest.scala b/src/test/java/im/tox/tox4j/ToxTest.scala
deleted file mode 100644
index 64302a965..000000000
--- a/src/test/java/im/tox/tox4j/ToxTest.scala
+++ /dev/null
@@ -1,402 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.core.network.Port
-import im.tox.core.random.RandomCore
-import im.tox.tox4j.TestConstants.Iterations
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.callbacks.ToxCoreEventAdapter
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums.ToxUserStatus
-import im.tox.tox4j.core.options.{ ProxyOptions, ToxOptions }
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.withToxUnit
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class ToxCoreTest extends FunSuite with ToxTestMixin {
-
- val publicKey: ToxPublicKey = ToxPublicKey.fromValue(Array.ofDim(ToxCoreConstants.PublicKeySize)).toOption.get
- val eventListener: ToxCoreEventAdapter[Unit] = new ToxCoreEventAdapter[Unit]
-
- test("ToxNew") {
- withToxUnit(ToxOptions()) { _ => }
- }
-
- test("ToxNew00") {
- withToxUnit(ipv6Enabled = false, udpEnabled = false) { _ => }
- }
-
- test("ToxNew01") {
- withToxUnit(ipv6Enabled = false, udpEnabled = true) { _ => }
- }
-
- test("ToxNew10") {
- withToxUnit(ipv6Enabled = true, udpEnabled = false) { _ => }
- }
-
- test("ToxNew11") {
- withToxUnit(ipv6Enabled = true, udpEnabled = true) { _ => }
- }
-
- test("ToxNewProxyGood") {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, ProxyOptions.Socks5("localhost", 1)) { _ => }
- withToxUnit(ipv6Enabled = true, udpEnabled = true, ProxyOptions.Socks5("localhost", 0xffff)) { _ => }
- }
-
- test("ToxCreationAndImmediateDestruction") {
- (0 until Iterations) foreach { _ => withToxUnit { _ => } }
- }
-
- test("ToxCreationAndDelayedDestruction") {
- ToxCoreImplFactory.withToxes(30) { _ => }
- }
-
- test("DoubleClose") {
- withToxUnit(_.close())
- }
-
- /*
- * Can't easily test this anymore, because bootstrap now actually reports
- * success/failure immediately.
- */
- /*
- test("BootstrapBorderlinePort1") {
- withToxUnit { tox =>
- tox.bootstrap(
- DhtNodeSelector.node.ipv4,
- Port.fromInt(1).get,
- publicKey
- )
- }
- }
-
- test("BootstrapBorderlinePort2") {
- withToxUnit { tox =>
- tox.bootstrap(
- DhtNodeSelector.node.ipv4,
- Port.fromInt(65535).get,
- publicKey
- )
- }
- }
- */
-
- test("IterationInterval") {
- withToxUnit { tox =>
- assert(tox.iterationInterval > 0)
- assert(tox.iterationInterval <= 50)
- }
- }
-
- test("Close") {
- withToxUnit { _ => }
- }
-
- test("Iteration") {
- withToxUnit(_.iterate(eventListener)(()))
- }
-
- test("GetPublicKey") {
- withToxUnit { tox =>
- val id = tox.getPublicKey
- assert(id.value.length == ToxCoreConstants.PublicKeySize)
- assert(tox.getPublicKey.value sameElements id.value)
- }
- }
-
- test("GetSecretKey") {
- withToxUnit { tox =>
- val key = tox.getSecretKey
- assert(key.value.length == ToxCoreConstants.SecretKeySize)
- assert(tox.getSecretKey.value sameElements key.value)
- }
- }
-
- test("PublicKeyEntropy") {
- withToxUnit { tox =>
- val entropy = RandomCore.entropy(tox.getPublicKey.value)
- assert(entropy >= 0.5, s"Entropy of public key should be >= 0.5, but was $entropy")
- }
- }
-
- test("SecretKeyEntropy") {
- withToxUnit { tox =>
- val entropy = RandomCore.entropy(tox.getSecretKey.value)
- assert(entropy >= 0.5, s"Entropy of secret key should be >= 0.5, but was $entropy")
- }
- }
-
- test("GetAddress") {
- withToxUnit { tox =>
- assert(tox.getAddress.value.length == ToxCoreConstants.AddressSize)
- assert(tox.getAddress.value sameElements tox.getAddress.value)
- }
- }
-
- test("NoSpam") {
- val tests = Array(0x12345678, 0xffffffff, 0x00000000, 0x00000001, 0xfffffffe, 0x7fffffff)
- withToxUnit { tox =>
- assert(tox.getNospam == tox.getNospam)
- for (test <- tests) {
- tox.setNospam(test)
- assert(tox.getNospam == test)
- assert(tox.getNospam == tox.getNospam)
- val check = Array(
- (test >> 8 * 3).toByte,
- (test >> 8 * 2).toByte,
- (test >> 8 * 1).toByte,
- (test >> 8 * 0).toByte
- )
- val nospam: Array[Byte] = tox.getAddress.value.slice(ToxCoreConstants.PublicKeySize, ToxCoreConstants.PublicKeySize + 4)
- assert(nospam sameElements check)
- }
- }
- }
-
- test("GetAndSetName") {
- withToxUnit { tox =>
- assert(tox.getName.value.isEmpty)
- tox.setName(ToxNickname.fromString("myname").toOption.get)
- assert(new String(tox.getName.value) == "myname")
- }
- }
-
- test("SetNameMinSize") {
- withToxUnit { tox =>
- val array = ToxCoreTestBase.randomBytes(1)
- tox.setName(ToxNickname.fromValue(array).toOption.get)
- assert(tox.getName.value sameElements array)
- }
- }
-
- test("SetNameMaxSize") {
- withToxUnit { tox =>
- val array = ToxCoreTestBase.randomBytes(ToxCoreConstants.MaxNameLength)
- tox.setName(ToxNickname.fromValue(array).toOption.get)
- assert(tox.getName.value sameElements array)
- }
- }
-
- test("SetNameExhaustive") {
- withToxUnit { tox =>
- (1 to ToxCoreConstants.MaxNameLength) foreach { i =>
- val array = ToxCoreTestBase.randomBytes(i)
- tox.setName(ToxNickname.fromValue(array).toOption.get)
- assert(tox.getName.value sameElements array)
- }
- }
- }
-
- test("UnsetName") {
- withToxUnit { tox =>
- assert(tox.getName.value.isEmpty)
- tox.setName(ToxNickname.fromString("myname").toOption.get)
- assert(tox.getName.value.nonEmpty)
- tox.setName(ToxNickname.fromString("").toOption.get)
- assert(tox.getName.value.isEmpty)
- }
- }
-
- test("GetAndSetStatusMessage") {
- withToxUnit { tox =>
- assert(tox.getStatusMessage.value.isEmpty)
- tox.setStatusMessage(ToxStatusMessage.fromString("message").toOption.get)
- assert(new String(tox.getStatusMessage.value) == "message")
- }
- }
-
- test("SetStatusMessageMinSize") {
- withToxUnit { tox =>
- val array = ToxCoreTestBase.randomBytes(1)
- tox.setStatusMessage(ToxStatusMessage.fromValue(array).toOption.get)
- assert(tox.getStatusMessage.value sameElements array)
- }
- }
-
- test("SetStatusMessageMaxSize") {
- withToxUnit { tox =>
- val array = ToxCoreTestBase.randomBytes(ToxCoreConstants.MaxStatusMessageLength)
- tox.setStatusMessage(ToxStatusMessage.fromValue(array).toOption.get)
- assert(tox.getStatusMessage.value sameElements array)
- }
- }
-
- test("SetStatusMessageExhaustive") {
- withToxUnit { tox =>
- (1 to ToxCoreConstants.MaxStatusMessageLength) foreach { i =>
- val array = ToxCoreTestBase.randomBytes(i)
- tox.setStatusMessage(ToxStatusMessage.fromValue(array).toOption.get)
- assert(tox.getStatusMessage.value sameElements array)
- }
- }
- }
-
- test("UnsetStatusMessage") {
- withToxUnit { tox =>
- assert(tox.getStatusMessage.value.isEmpty)
- tox.setStatusMessage(ToxStatusMessage.fromString("message").toOption.get)
- assert(tox.getStatusMessage.value.nonEmpty)
- tox.setStatusMessage(ToxStatusMessage.fromString("").toOption.get)
- assert(tox.getStatusMessage.value.isEmpty)
- }
- }
-
- test("GetAndSetStatus") {
- withToxUnit { tox =>
- assert(tox.getStatus == ToxUserStatus.NONE)
- ToxUserStatus.values.foreach { status =>
- tox.setStatus(status)
- assert(tox.getStatus == status)
- }
- }
- }
-
- test("AddFriend") {
- withToxUnit { tox =>
- (0 until Iterations).map(ToxFriendNumber.fromInt(_).get) foreach { i =>
- withToxUnit { friend =>
- val friendNumber = tox.addFriend(
- friend.getAddress,
- ToxFriendRequestMessage.fromString("heyo").toOption.get
- )
- assert(friendNumber == i)
- }
- }
- assert(tox.getFriendList.length == Iterations)
- }
- }
-
- test("AddFriendNoRequest") {
- withToxUnit { tox =>
- (0 until Iterations).map(ToxFriendNumber.fromInt(_).get) foreach { i =>
- withToxUnit { friend =>
- val friendNumber = tox.addFriendNorequest(friend.getPublicKey)
- assert(friendNumber == i)
- }
- }
- assert(tox.getFriendList.length == Iterations)
- }
- }
-
- test("FriendListSize") {
- withToxUnit { tox =>
- addFriends(tox, Iterations)
- assert(tox.getFriendList.length == Iterations)
- }
- }
-
- test("FriendList") {
- withToxUnit { tox =>
- addFriends(tox, 5)
- assert(tox.getFriendList sameElements Array(0, 1, 2, 3, 4))
- }
- }
-
- test("FriendList_Empty") {
- withToxUnit { tox =>
- assert(tox.getFriendList.isEmpty)
- }
- }
-
- test("DeleteAndReAddFriend") {
- withToxUnit { tox =>
- addFriends(tox, 5)
- assert(tox.getFriendList sameElements Array[Int](0, 1, 2, 3, 4))
- tox.deleteFriend(ToxFriendNumber.fromInt(2).get)
- assert(tox.getFriendList sameElements Array[Int](0, 1, 3, 4))
- tox.deleteFriend(ToxFriendNumber.fromInt(3).get)
- assert(tox.getFriendList sameElements Array[Int](0, 1, 4))
- addFriends(tox, 1)
- assert(tox.getFriendList sameElements Array[Int](0, 1, 2, 4))
- addFriends(tox, 1)
- assert(tox.getFriendList sameElements Array[Int](0, 1, 2, 3, 4))
- }
- }
-
- test("FriendExists") {
- withToxUnit { tox =>
- addFriends(tox, 3)
- assert(tox.friendExists(ToxFriendNumber.fromInt(0).get))
- assert(tox.friendExists(ToxFriendNumber.fromInt(1).get))
- assert(tox.friendExists(ToxFriendNumber.fromInt(2).get))
- assert(!tox.friendExists(ToxFriendNumber.fromInt(3).get))
- assert(!tox.friendExists(ToxFriendNumber.fromInt(4).get))
- }
- }
-
- test("FriendExists2") {
- withToxUnit { tox =>
- addFriends(tox, 3)
- assert(tox.friendExists(ToxFriendNumber.fromInt(0).get))
- assert(tox.friendExists(ToxFriendNumber.fromInt(1).get))
- assert(tox.friendExists(ToxFriendNumber.fromInt(2).get))
- tox.deleteFriend(ToxFriendNumber.fromInt(1).get)
- assert(tox.friendExists(ToxFriendNumber.fromInt(0).get))
- assert(!tox.friendExists(ToxFriendNumber.fromInt(1).get))
- assert(tox.friendExists(ToxFriendNumber.fromInt(2).get))
- }
- }
-
- test("GetFriendPublicKey") {
- withToxUnit { tox =>
- addFriends(tox, 1)
- val friendNumber = ToxFriendNumber.fromInt(0).get
- assert(tox.getFriendPublicKey(friendNumber).value.length == ToxCoreConstants.PublicKeySize)
- assert(tox.getFriendPublicKey(friendNumber).value sameElements tox.getFriendPublicKey(friendNumber).value)
- val entropy = RandomCore.entropy(tox.getFriendPublicKey(friendNumber).value)
- assert(entropy >= 0.5, s"Entropy of friend's public key should be >= 0.5, but was $entropy")
- }
- }
-
- test("GetFriendByPublicKey") {
- withToxUnit { tox =>
- addFriends(tox, 10)
- (0 until 10).map(ToxFriendNumber.fromInt(_).get) foreach { i =>
- assert(tox.friendByPublicKey(tox.getFriendPublicKey(i)) == i)
- }
- }
- }
-
- test("SetTyping") {
- withToxUnit { tox =>
- addFriends(tox, 1)
- val friendNumber = ToxFriendNumber.fromInt(0).get
- tox.setTyping(friendNumber, false)
- tox.setTyping(friendNumber, true)
- tox.setTyping(friendNumber, false)
- tox.setTyping(friendNumber, false)
- tox.setTyping(friendNumber, true)
- tox.setTyping(friendNumber, true)
- }
- }
-
- test("GetUdpPort") {
- withToxUnit { tox =>
- assert(tox.getUdpPort.value > 0)
- assert(tox.getUdpPort.value <= 65535)
- }
- }
-
- test("GetTcpPort") {
- withToxUnit(ToxOptions(tcpPort = 33444)) { tox =>
- assert(tox.getTcpPort.value == 33444)
- }
- }
-
- test("GetDhtId") {
- withToxUnit { tox =>
- val key = tox.getDhtId
- assert(key.value.length == ToxCoreConstants.PublicKeySize)
- assert(tox.getDhtId.value sameElements key.value)
- }
- }
-
- test("DhtIdEntropy") {
- withToxUnit { tox =>
- val entropy = RandomCore.entropy(tox.getDhtId.value)
- assert(entropy >= 0.5, s"Entropy of public key should be >= 0.5, but was $entropy")
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/AvInvokeTest.scala b/src/test/java/im/tox/tox4j/av/callbacks/AvInvokeTest.scala
deleted file mode 100644
index 96ee06dba..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/AvInvokeTest.scala
+++ /dev/null
@@ -1,179 +0,0 @@
-package im.tox.tox4j.av.callbacks
-
-import java.util
-
-import im.tox.tox4j.av.callbacks.AvInvokeTest._
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.core.SmallNat
-import im.tox.tox4j.core.callbacks.InvokeTest.{ ByteArray, ShortArray }
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.impl.jni.{ ToxAvImpl, ToxCoreImpl }
-import org.scalacheck.Arbitrary.arbitrary
-import org.scalacheck.{ Arbitrary, Gen }
-import org.scalatest.FunSuite
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-import scala.collection.JavaConverters._
-import scala.language.implicitConversions
-import scala.util.Random
-
-final class AvInvokeTest extends FunSuite with ScalaCheckPropertyChecks {
-
- final class TestEventListener extends ToxAvEventListener[Option[Event]] {
- private def setEvent(event: Event)(state: Option[Event]): Option[Event] = {
- assert(state.isEmpty)
- Some(event)
- }
-
- // scalastyle:off line.size.limit
- override def audioReceiveFrame(friendNumber: ToxFriendNumber, pcm: Array[Short], channels: AudioChannels, samplingRate: SamplingRate)(state: Option[Event]): Option[Event] = setEvent(AudioReceiveFrame(friendNumber, pcm, channels, samplingRate))(state)
- override def audioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate)(state: Option[Event]): Option[Event] = setEvent(AudioBitRate(friendNumber, audioBitRate))(state)
- override def videoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate)(state: Option[Event]): Option[Event] = setEvent(VideoBitRate(friendNumber, videoBitRate))(state)
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: Option[Event]): Option[Event] = setEvent(Call(friendNumber, audioEnabled, videoEnabled))(state)
- override def callState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState])(state: Option[Event]): Option[Event] = setEvent(CallState(friendNumber, callState.asScala.toSet))(state)
- override def videoReceiveFrame(friendNumber: ToxFriendNumber, width: Width, height: Height, y: Array[Byte], u: Array[Byte], v: Array[Byte], yStride: Int, uStride: Int, vStride: Int)(state: Option[Event]): Option[Event] = setEvent(VideoReceiveFrame(friendNumber, width, height, y, u, v, yStride, uStride, vStride))(state)
- // scalastyle:on line.size.limit
- }
-
- def callbackTest(invoke: ToxAvEventSynth => Unit, expected: Event): Unit = {
- val tox = new ToxCoreImpl(ToxOptions())
- val toxav = new ToxAvImpl(tox)
-
- try {
- invoke(toxav)
- val listener = new TestEventListener
- val event = toxav.iterate(listener)(None)
- assert(event.contains(expected))
- } finally {
- toxav.close()
- tox.close()
- }
- }
-
- private val random = new Random
-
- private implicit val arbToxFriendNumber: Arbitrary[ToxFriendNumber] = {
- Arbitrary(arbitrary[Int].map(ToxFriendNumber.unsafeFromInt))
- }
-
- private implicit val arbToxavFriendCallState: Arbitrary[ToxavFriendCallState] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map { i => ToxavFriendCallState.values()(Math.abs(i % ToxavFriendCallState.values().length)) })
- }
-
- private implicit val arbWidth: Arbitrary[Width] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map(Width.clamp))
- }
-
- private implicit val arbHeight: Arbitrary[Height] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map(Height.clamp))
- }
-
- private implicit val arbSamplingRate: Arbitrary[SamplingRate] = {
- Arbitrary(Gen.oneOf(
- SamplingRate.Rate8k,
- SamplingRate.Rate12k,
- SamplingRate.Rate16k,
- SamplingRate.Rate24k,
- SamplingRate.Rate48k
- ))
- }
-
- private implicit val arbBitRate: Arbitrary[BitRate] = {
- Arbitrary(Gen.oneOf(
- Gen.const(BitRate.Unchanged),
- Gen.const(BitRate.Disabled),
- arbitrary[Int].map(BitRate.fromInt).map(_.getOrElse(BitRate.Unchanged))
- ))
- }
-
- test("Max friend number") {
- val friendNumber = ToxFriendNumber.unsafeFromInt(Int.MaxValue)
- val pcm = Array.fill(100)(1234.toShort)
- callbackTest(
- _.invokeAudioReceiveFrame(friendNumber, pcm, AudioChannels.Mono, SamplingRate.Rate24k),
- AudioReceiveFrame(friendNumber, pcm, AudioChannels.Mono, SamplingRate.Rate24k)
- )
- }
-
- test("AudioReceiveFrame") {
- forAll { (friendNumber: ToxFriendNumber, pcm: Array[Short], samplingRate: SamplingRate) =>
- val channels =
- pcm.length match {
- case length if length % 2 === 0 => AudioChannels.Stereo
- case length => AudioChannels.Mono
- }
- callbackTest(
- _.invokeAudioReceiveFrame(friendNumber, pcm, channels, samplingRate),
- AudioReceiveFrame(friendNumber, pcm, channels, samplingRate)
- )
- }
- }
-
- test("AudioBitRate") {
- forAll { (friendNumber: ToxFriendNumber, audioBitRate: BitRate) =>
- callbackTest(
- _.invokeAudioBitRate(friendNumber, audioBitRate),
- AudioBitRate(friendNumber, audioBitRate)
- )
- }
- }
-
- test("VideoBitRate") {
- forAll { (friendNumber: ToxFriendNumber, videoBitRate: BitRate) =>
- callbackTest(
- _.invokeVideoBitRate(friendNumber, videoBitRate),
- VideoBitRate(friendNumber, videoBitRate)
- )
- }
- }
-
- test("Call") {
- forAll { (friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean) =>
- callbackTest(
- _.invokeCall(friendNumber, audioEnabled, videoEnabled),
- Call(friendNumber, audioEnabled, videoEnabled)
- )
- }
- }
-
- test("CallState") {
- forAll { (friendNumber: ToxFriendNumber, callState: Set[ToxavFriendCallState]) =>
- whenever(callState.nonEmpty) {
- callbackTest(
- _.invokeCallState(friendNumber, util.EnumSet.copyOf(callState.asJavaCollection)),
- CallState(friendNumber, callState)
- )
- }
- }
- }
-
- test("VideoReceiveFrame") {
- forAll { (friendNumber: ToxFriendNumber, width: Width, height: Height, yStride: SmallNat, uStride: SmallNat, vStride: SmallNat) =>
- val w = width.value
- val h = height.value
- val y = Array.ofDim[Byte]((w max yStride) * h)
- val u = Array.ofDim[Byte](((w / 2) max Math.abs(uStride)) * (h / 2))
- val v = Array.ofDim[Byte](((w / 2) max Math.abs(vStride)) * (h / 2))
- random.nextBytes(y)
- random.nextBytes(u)
- random.nextBytes(v)
- callbackTest(
- _.invokeVideoReceiveFrame(friendNumber, width, height, y, u, v, yStride, uStride, vStride),
- VideoReceiveFrame(friendNumber, width, height, y, u, v, yStride, uStride, vStride)
- )
- }
- }
-
-}
-
-object AvInvokeTest {
- sealed trait Event
- private final case class AudioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate) extends Event
- private final case class AudioReceiveFrame(friendNumber: ToxFriendNumber, pcm: ShortArray, channels: AudioChannels, samplingRate: SamplingRate) extends Event
- private final case class Call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean) extends Event
- private final case class CallState(friendNumber: ToxFriendNumber, callState: Set[ToxavFriendCallState]) extends Event
- private final case class VideoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate) extends Event
- private final case class VideoReceiveFrame(friendNumber: ToxFriendNumber, width: Width, height: Height, y: ByteArray, u: ByteArray, v: ByteArray, yStride: Int, uStride: Int, vStride: Int) extends Event // scalastyle:ignore line.size.limit
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/CallCallbackTest.scala b/src/test/java/im/tox/tox4j/av/callbacks/CallCallbackTest.scala
deleted file mode 100644
index b47c841a9..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/CallCallbackTest.scala
+++ /dev/null
@@ -1,66 +0,0 @@
-package im.tox.tox4j.av.callbacks
-
-import im.tox.tox4j.av.data.BitRate
-import im.tox.tox4j.av.exceptions.ToxavCallException
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendMessage }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxMessageType }
-import im.tox.tox4j.testing.GetDisjunction._
-import im.tox.tox4j.testing.ToxExceptionChecks
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class CallCallbackTest extends AutoTestSuite with ToxExceptionChecks {
-
- type S = Unit
-
- object Handler extends EventListener(()) {
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state0: State): State = {
- val state = super.friendConnectionStatus(friendNumber, connectionStatus)(state0)
-
- if (connectionStatus == ToxConnection.NONE || state.id(friendNumber) != state.id.next) {
- state
- } else {
- // Call id+1.
- state.addTask { (tox, av, state) =>
- av.call(friendNumber, BitRate.fromInt(10).get, BitRate.Disabled)
- state
- }
- }
- }
-
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: State): State = {
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- // Calling them back while they are ringing is invalid.
- intercept(ToxavCallException.Code.FRIEND_ALREADY_IN_CALL) {
- av.call(friendNumber, BitRate.fromInt(10).get, BitRate.Disabled)
- }
- // Say "No thanks" and stop talking.
- debug(state, s"Got a call from ${state.id(friendNumber)}; rejecting")
- tox.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.fromString("No thanks").toOption.get)
- state.finish
- }
- } else {
- fail(s"I shouldn't have been called by friend ${state.id(friendNumber)}")
- state
- }
- }
-
- override def friendMessage(
- friendNumber: ToxFriendNumber,
- messageType: ToxMessageType,
- timeDelta: Int,
- message: ToxFriendMessage
- )(state: State): State = {
- assert(message.toString == "No thanks")
- debug(state, "Aww... I got rejected :( oh well")
- state.finish
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerator.scala b/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerator.scala
deleted file mode 100644
index 7a194ad08..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerator.scala
+++ /dev/null
@@ -1,76 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import im.tox.tox4j.av.data.{ SampleCount, AudioLength, SamplingRate }
-
-abstract class AudioGenerator {
-
- def productPrefix: String
-
- def length(samplingRate: SamplingRate): Int
- def sample(samplingRate: SamplingRate, t: Int): Int
-
- @SuppressWarnings(Array("org.wartremover.warts.While"))
- final def nextFrame16(audioLength: AudioLength, samplingRate: SamplingRate, t: Int): Array[Short] = {
- val frame = Array.ofDim[Short](SampleCount(audioLength, samplingRate).value)
- var i = 0
- while (i < frame.length) {
- frame(i) = sample(samplingRate, t + i).toShort
- i += 1
- }
- frame
- }
-
-}
-
-object AudioGenerator {
-
- sealed abstract class Oscillator {
-
- protected def f(x: Double): Double
-
- final def osc(samplingRate: SamplingRate, t: Int, frequency: Double, volume: Double): Double = {
- val samples = samplingRate.value / frequency
- f(t % samples / samples) * volume
- }
-
- }
-
- object Oscillator {
- case object Sine extends Oscillator {
- def f(x: Double): Double = Math.sin(2.0 * Math.PI * x)
- }
- case object Sawtooth extends Oscillator {
- def f(x: Double): Double = 2.0 * (x - Math.floor(x + 0.5))
- }
- }
-
- def int(boolean: Boolean): Int = if (boolean) 1 else 0
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def playTones(t: Int, tones: Array[Double], samplingRate: SamplingRate, tempo: Int): Double = {
- // The duration of the tone in number of samples.
- val duration = samplingRate.value / tempo
- // A short pause between each tone played.
- val pause = samplingRate.value / 40
-
- val index = t % (tones.length * duration) / duration
- val previous =
- if (index == 0) {
- tones.length - 1
- } else {
- index - 1
- }
- tones(index) * int(t % duration > pause || tones(previous) == tones(index))
- }
-
- def playWhiteNoise(t: Int, tones: Array[Double], samplingRate: SamplingRate, tempo: Int, duration: Double): Double = {
- playTones(t, tones, samplingRate, tempo) * Math.random() * {
- if (t % (samplingRate.value / 8) > (samplingRate.value / 8 - (samplingRate.value * duration))) {
- 1.0
- } else {
- 0.0
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerators.scala b/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerators.scala
deleted file mode 100644
index 94512e6e0..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioGenerators.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import im.tox.tox4j.av.callbacks.audio.AudioGenerator._
-import im.tox.tox4j.av.data.SamplingRate
-
-object AudioGenerators {
-
- case object ItCrowd extends AudioGenerator {
-
- def length(samplingRate: SamplingRate): Int = (samplingRate.value * 12) + (samplingRate.value / 2) * 8
-
- def sample(samplingRate: SamplingRate, t0: Int): Int = {
- // Period
- val t = t0 % length(samplingRate)
-
- val rate = samplingRate.value
-
- val a = 1 / ((rate * 16) - t)
- val b =
- if (t > (rate * 12)) {
- t % (rate / 2) * ("'&(&*$,*".charAt(t % (rate * 12) / (rate / 2)) - 32)
- } else {
- {
- t % (rate / 4) * {
- "$$$&%%%''''%%%'&".charAt(t % (rate * 4) / (rate / 4)) - 32 -
- int(t > (rate * 3 + rate / 2) && t < (rate * 4)) * 2
- }
- } / {
- int(t % rate < (rate / 2)) + 1
- }
- }
- ((a | b) / (rate / 8000) << 8).toShort / 5
- }
-
- }
-
- case object MortalKombat extends AudioGenerator {
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
-
- def sample(samplingRate: SamplingRate, t: Int): Int = {
- val rate = samplingRate.value
-
- val a = {
- 2 * t % (rate / 2) * {
- "!!#!$!%$".charAt(t % (rate * 2) / (rate / 4)) - 32 +
- int(t % (rate * 8) > (rate * 4)) * 7
- }
- } * {
- int(t % (rate * 4) > (rate * 2)) + 1
- }
- val b = int(t % (rate * 16) > (rate * 8)) * 2 * t * {
- "%%%'%+''%%%$%+))%%%%'+'%$%%%$%%%$%%".charAt(t % (rate * 8 + (rate - rate / 4)) / (rate / 4)) - 36
- }
- ((a | b) / (rate / 8000) << 8).toShort / 5
- }
- }
-
- case object Sine1 extends AudioGenerator {
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
- def sample(samplingRate: SamplingRate, t: Int): Int = (Math.sin(t / (10000d / t)) * 128).toShort << 6
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- case object Sine2 extends AudioGenerator {
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
- def sample(samplingRate: SamplingRate, t0: Int): Int = {
- val t =
- if (t0 % 2 == 0) {
- 1
- } else {
- t0
- }
- (Math.sin(t / (10000d / t)) * 128).toShort << 6
- }
- }
-
- case object Sine3 extends AudioGenerator {
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
- def sample(samplingRate: SamplingRate, t: Int): Int = {
- ((t & 0xF) * ((0 - t) & 0xF) * (((t & 0x10) >> 3) - 1) * 0x80 / 0x41 + 0x80) << 7
- }
- }
-
- final case class Sawtooth(frequency: Double) extends AudioGenerator {
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
- def sample(samplingRate: SamplingRate, t: Int): Int = {
- (Oscillator.Sine.osc(samplingRate, t, frequency, 1) * Short.MaxValue).toShort
- }
- }
-
- // https://www.youtube.com/watch?v=S7dg0X1LskI
- case object SongOfStorms extends AudioGenerator {
-
- def length(samplingRate: SamplingRate): Int = samplingRate.value * 16
-
- private val melody = (4, Array[Double](
- 146.83, 174.61, 293.66, 293.66,
- 146.83, 174.61, 293.66, 293.66,
- 329.62, 349.22, 329.62, 349.22, 329.62, 261.62, 220, 220,
-
- 220, 220, 146.83, 146.83, 174.61, 195.99, 220, 220,
- 220, 220, 146.83, 146.83, 174.61, 195.99, 164.81, 164.81,
-
- 146.83, 174.61, 293.66, 293.66,
- 146.83, 174.61, 293.66, 293.66,
- 329.62, 349.22, 329.62, 349.22, 329.62, 261.62, 220, 220,
-
- 220, 220, 146.83, 146.83, 174.61, 195.99, 220, 220,
- 220, 220, 146.83, 146.83, 146.83, 146.83, 146.83, 146.83
- ))
-
- private val bass = (1, Array[Double](
- 73.41, 82.4, 87.3, 82.4,
- 116.54, 87.3, 116.54, 110,
-
- 73.41, 82.4, 87.3, 82.4,
- 116.54, 110, 73.41, 73.41
- ))
-
- private val organ = (8, Array[Double](
- 0, 220, 0, 220,
- 0, 0, 0, 146.83,
- 246.94, 246.94, 246.94, 246.94,
- 0, 0, 0, 0,
-
- 0, 261.62, 0, 261.62,
- 0, 0, 0, 146.83,
- 246.94, 246.94, 246.94, 246.94,
- 0, 0, 0, 0,
-
- 0, 220, 0, 220,
- 0, 0, 0, 220,
- 220, 220, 220, 220,
- 0, 0, 0, 0,
-
- 0, 220, 0, 220,
- 0, 0, 0, 220,
- 220, 220, 220, 220,
- 0, 0, 0, 0
- ))
-
- private val percussions = (8, Array[Double](
- 0, 1, 0, 1,
- 0, 0, 0, 0,
- 1, 1, 1, 1,
- 0, 0, 0, 0
- ))
-
- private def playInstrument(samplingRate: SamplingRate, t: Int, input: (Int, Array[Double])): Double = {
- val (tempo, tones) = input
- playTones(t, tones, samplingRate, tempo)
- }
-
- private def playPercussions(samplingRate: SamplingRate, t: Int, input: (Int, Array[Double])): Double = {
- val (tempo, tones) = input
- playWhiteNoise(t, tones, samplingRate, tempo, 1.0 / 40)
- }
-
- def sample(samplingRate: SamplingRate, t: Int): Int = {
- val double = (0
- + Oscillator.Sine.osc(samplingRate, t, playInstrument(samplingRate, t, melody), 0.35)
- + Oscillator.Sawtooth.osc(samplingRate, t, playInstrument(samplingRate, t, bass), 0.1)
- + Oscillator.Sawtooth.osc(samplingRate, t, playInstrument(samplingRate, t, organ), 0.05)
- + Oscillator.Sawtooth.osc(samplingRate, t, playPercussions(samplingRate, t, percussions), 0.1))
- (double * Short.MaxValue).toShort
- }
-
- }
-
- // Selected audio generator for tests.
- def default: AudioGenerator = SongOfStorms
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioPlayback.scala b/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioPlayback.scala
deleted file mode 100644
index 54b00da52..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioPlayback.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import javax.sound.sampled._
-
-import im.tox.tox4j.av.data.SamplingRate
-
-import scala.util.Try
-
-object AudioPlayback {
-
- def showWave(pcm: Array[Short], width: Int): String = {
- val height = width / 10
-
- val screen = (0 until height).map(_ => Array.fill[Char](width)(' '))
-
- val maxSampleValue = -Short.MinValue
- for ((sample, x) <- pcm.zipWithIndex) {
- val y = valueToRange(sample + maxSampleValue, maxSampleValue * 2, height)
- screen(y)(valueToRange(x, pcm.length, width)) = '#'
- }
-
- screen.map(new String(_)).mkString("\n")
- }
-
- private def valueToRange(value: Double, maxValue: Int, maxRange: Int): Int = {
- (value / maxValue * maxRange).toInt
- }
-
- private def serialiseAudioFrame(pcm: Array[Short]): Array[Byte] = {
- val buffer = Array.ofDim[Byte](pcm.length * 2)
- for (i <- buffer.indices by 2) {
- buffer(i) = (pcm(i / 2) >> 8).toByte
- buffer(i + 1) = pcm(i / 2).toByte
- }
-
- buffer
- }
-
-}
-
-final class AudioPlayback(samplingRate: SamplingRate) {
-
- def play(pcm: Array[Short]): Unit = {
- soundLine.foreach { soundLine =>
- val buffer = AudioPlayback.serialiseAudioFrame(pcm)
- soundLine.write(buffer, 0, buffer.length)
- }
- }
-
- def done(length: Int): Boolean = {
- soundLine.toOption.map(_.getLongFramePosition >= length).getOrElse(true)
- }
-
- private val soundLine = Try {
- val format = new AudioFormat(samplingRate.value, 16, 1, true, true)
- val info = new DataLine.Info(classOf[SourceDataLine], format)
- val soundLine = AudioSystem.getLine(info).asInstanceOf[SourceDataLine]
- soundLine.open(format, samplingRate.value)
- soundLine.start()
- soundLine
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackTest.scala b/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackTest.scala
deleted file mode 100644
index f956ad2d9..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackTest.scala
+++ /dev/null
@@ -1,161 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import java.util
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.ToxExceptionChecks
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-import org.slf4j.LoggerFactory
-
-import scala.concurrent.duration._
-import scala.language.postfixOps
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class AudioReceiveFrameCallbackTest extends AutoTestSuite with ToxExceptionChecks {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- override def maxParticipantCount: Int = 2
-
- final case class S(t: Int = 0, frequencies: List[Double] = Nil)
-
- object Handler extends EventListener(S()) {
-
- /**
- * How much of the sent data must be received for the test to pass.
- */
- private val minCompletionRatio = 0.8
-
- private val audioFrequency = 220
- private val audio = AudioGenerators.Sawtooth(audioFrequency)
-
- private val bitRate = BitRate.fromInt(320).get
- private val audioPerFrame = AudioLength.Length60
- private val samplingRate = SamplingRate.Rate8k
- private val frameSize = SampleCount(audioPerFrame, samplingRate).value
- private val windowSize = audio.length(samplingRate) / frameSize / 2
- private val framesPerIteration = 2
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state0: State): State = {
- val state = super.friendConnectionStatus(friendNumber, connectionStatus)(state0)
-
- if (connectionStatus == ToxConnection.NONE || state.id(friendNumber) != state.id.next) {
- state
- } else {
- // Call id+1.
- state.addTask { (tox, av, state) =>
- debug(state, s"Ringing ${state.id(friendNumber)}")
- av.call(friendNumber, bitRate, BitRate.Disabled)
- state
- }
- }
- }
-
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: State): State = {
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- debug(state, s"Got a call from ${state.id(friendNumber)}; accepting")
- av.answer(friendNumber, BitRate.Disabled, BitRate.Disabled)
- state
- }
- } else {
- fail(s"I shouldn't have been called by friend ${state.id(friendNumber)}")
- state
- }
- }
-
- // There is no stack recursion here, it pushes thunks of itself for deferred execution.
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def sendFrame(friendNumber: ToxFriendNumber)(tox: ToxCore, av: ToxAv, state0: State): State = {
- val state = state0.modify(s => s.copy(t = s.t + frameSize * framesPerIteration))
-
- for (t <- state0.get.t until state.get.t by frameSize) {
- val pcm = audio.nextFrame16(audioPerFrame, samplingRate, t)
- av.audioSendFrame(
- friendNumber,
- pcm,
- SampleCount(audioPerFrame, samplingRate),
- AudioChannels.Mono,
- samplingRate
- )
- }
-
- if (state.get.t >= audio.length(samplingRate)) {
- state.finish
- } else {
- state.addTask(sendFrame(friendNumber))
- }
- }
-
- override def callState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState])(state: State): State = {
- debug(state, s"Call with ${state.id(friendNumber)} is now $callState")
- assert(callState == util.EnumSet.of(
- ToxavFriendCallState.ACCEPTING_A,
- ToxavFriendCallState.ACCEPTING_V
- ))
- state.addTask(sendFrame(friendNumber))
- }
-
- override def audioBitRate(friendNumber: ToxFriendNumber, audioBitRate: BitRate)(state: State): State = {
- debug(state, s"Bit rate in call with ${state.id(friendNumber)} should change to $audioBitRate for audio")
- state
- }
-
- override def videoBitRate(friendNumber: ToxFriendNumber, videoBitRate: BitRate)(state: State): State = {
- debug(state, s"Bit rate in call with ${state.id(friendNumber)} should change to $videoBitRate for video")
- state
- }
-
- override def audioReceiveFrame(
- friendNumber: ToxFriendNumber,
- pcm: Array[Short],
- channels: AudioChannels,
- samplingRate: SamplingRate
- )(state0: State): State = {
- val binarised = pcm.map { n =>
- if (n > 0) {
- Short.MaxValue / 2
- } else {
- Short.MinValue / 2
- }
- }
-
- val derivative = (binarised, binarised.tail).zipped.map {
- (n0, n1) => (n1 - n0).toShort
- }
-
- val vibrations = derivative.count(_ != 0)
-
- val frequency = vibrations * ((1 second) / audioPerFrame.value) / 2
-
- val state = state0.modify(s => s.copy(
- t = s.t + pcm.length,
- frequencies = (frequency :: s.frequencies).take(windowSize)
- ))
-
- val averageFrequency = state.get.frequencies.sum / state.get.frequencies.length
- debug(state, s"Received audio frame: ${state.get.t} / ${audio.length(samplingRate)} (f~=$averageFrequency (last ${state.get.frequencies.length} frames))")
- assert(channels == AudioChannels.Mono)
- assert(samplingRate == this.samplingRate)
-
- // Require at least half the frames to arrive.
- if (state.get.t >= audio.length(samplingRate) * minCompletionRatio) {
- assert(Math.round(averageFrequency) == audioFrequency)
- state.finish
- } else {
- state
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/ArithmeticVideoGenerator.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/ArithmeticVideoGenerator.scala
deleted file mode 100644
index 81d47f3cb..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/ArithmeticVideoGenerator.scala
+++ /dev/null
@@ -1,58 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-@SuppressWarnings(Array("org.wartremover.warts.While"))
-abstract class ArithmeticVideoGenerator extends VideoGenerator {
-
- def productPrefix: String
-
- override final def toString: String = s"$productPrefix($width, $height)"
-
- private val yArray = Array.ofDim[Byte](size)
- private val uArray = Array.ofDim[Byte](size / 4)
- private val vArray = Array.ofDim[Byte](size / 4)
-
- protected def y(t: Int, x: Int, y: Int): Int
- protected def u(t: Int, x: Int, y: Int): Int
- protected def v(t: Int, x: Int, y: Int): Int
-
- final def yuv(t: Int): (Array[Byte], Array[Byte], Array[Byte]) = {
- yuv(t, width.value, height.value)
- }
-
- private def yuv(t: Int, width: Int, height: Int): (Array[Byte], Array[Byte], Array[Byte]) = {
- yLoop(t, yArray, height, width)
- uvLoop(t, uArray, vArray, height / 2, width / 2)
-
- (yArray, uArray, vArray)
- }
-
- private def yLoop(t: Int, yArray: Array[Byte], height: Int, width: Int): Unit = {
- var yPos = 0
- while (yPos < height) {
- var xPos = 0
- while (xPos < width) {
- yArray(yPos * width + xPos) = y(t, xPos, yPos).toByte
-
- xPos += 1
- }
-
- yPos += 1
- }
- }
-
- private def uvLoop(t: Int, uArray: Array[Byte], vArray: Array[Byte], height: Int, width: Int): Unit = {
- var yPos = 0
- while (yPos < height) {
- var xPos = 0
- while (xPos < width) {
- uArray(yPos * width + xPos) = u(t, xPos * 2 + 1, yPos * 2 + 1).toByte
- vArray(yPos * width + xPos) = v(t, xPos * 2 + 1, yPos * 2 + 1).toByte
-
- xPos += 1
- }
-
- yPos += 1
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/RgbVideoGenerator.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/RgbVideoGenerator.scala
deleted file mode 100644
index 3938527bb..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/RgbVideoGenerator.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-abstract class RgbVideoGenerator extends ArithmeticVideoGenerator {
- def rgb(t: Int, y: Int, x: Int): Int
- protected final def y(t: Int, x: Int, y: Int): Int = VideoConversions.RGBtoY(rgb(t, y, x))
- protected final def u(t: Int, x: Int, y: Int): Int = VideoConversions.RGBtoU(rgb(t, y, x))
- protected final def v(t: Int, x: Int, y: Int): Int = VideoConversions.RGBtoV(rgb(t, y, x))
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/TextImageGenerator.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/TextImageGenerator.scala
deleted file mode 100644
index f25de5ebe..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/TextImageGenerator.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import im.tox.tox4j.av.data.{ Height, Width }
-
-abstract class TextImageGenerator(row0: String, rowN: String*) extends VideoGenerator {
-
- private def rows: Seq[String] = row0 +: rowN
-
- override final def yuv(t: Int): (Array[Byte], Array[Byte], Array[Byte]) = {
- val width = this.width.value
- val height = this.height.value
-
- val y = rows.mkString.getBytes
- val u = Array.fill((width / 2) * (height / 2))((t * 4).toByte)
- val v = Array.fill((width / 2) * (height / 2))((-t * 4 - 1).toByte)
- (y, u, v)
- }
-
- override final def resize(width: Width, height: Height): VideoGenerator = {
- VideoGenerator.resizeNearestNeighbour(width, height, this)
- }
-
- override def width: Width = Width.fromInt(row0.length).get
- override def height: Height = Height.fromInt(rows.size).get
- override def length: Int = sys.env.get("TRAVIS").map(_ => 4).getOrElse(64)
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoConversions.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/VideoConversions.scala
deleted file mode 100644
index 23ec6840f..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoConversions.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-// scalastyle:off method.name
-object VideoConversions {
-
- final case class YuvPixel(y: Byte, u: Byte, v: Byte)
-
- def RGBtoY(r: Int, g: Int, b: Int): Byte = clamp(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16)
- def RGBtoU(r: Int, g: Int, b: Int): Byte = clamp(((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128)
- def RGBtoV(r: Int, g: Int, b: Int): Byte = clamp(((112 * r - 94 * g - 18 * b + 128) >> 8) + 128)
-
- def RGBtoY(rgb: Int): Byte = RGBtoY((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff)
- def RGBtoU(rgb: Int): Byte = RGBtoU((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff)
- def RGBtoV(rgb: Int): Byte = RGBtoV((rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff)
-
- object YuvPixel {
- def ofRgb(r: Int, g: Int, b: Int): YuvPixel = {
- YuvPixel(
- y = RGBtoY(r, g, b),
- u = RGBtoU(r, g, b),
- v = RGBtoV(r, g, b)
- )
- }
-
- def ofRgb(rgb: Int): YuvPixel = {
- ofRgb(
- (rgb >> 16) & 0xff,
- (rgb >> 8) & 0xff,
- rgb & 0xff
- )
- }
- }
-
- final case class RgbPixel(r: Byte, g: Byte, b: Byte)
-
- object RgbPixel {
-
- def ofYuv(y: Int, u: Int, v: Int): RgbPixel = {
- RgbPixel(
- r = YUVtoR(y, u, v),
- g = YUVtoG(y, u, v),
- b = YUVtoB(y, u, v)
- )
- }
-
- }
-
- private def clamp(n: Int): Byte = (255 min n max 0).toByte
-
- private def C(y: Int) = y - 16
- private def D(u: Int) = u - 128
- private def E(v: Int) = v - 128
-
- private def unsigned(b: Byte): Int = b & 0xff
-
- private def YUVtoR(y: Int, u: Int, v: Int): Byte = {
- clamp((298 * C(y) + 409 * E(v) + 128) >> 8)
- }
-
- private def YUVtoG(y: Int, u: Int, v: Int): Byte = {
- clamp((298 * C(y) - 100 * D(u) - 208 * E(v) + 128) >> 8)
- }
-
- private def YUVtoB(y: Int, u: Int, v: Int): Byte = {
- clamp((298 * C(y) + 516 * D(u) + 128) >> 8)
- }
-
- def YUVtoRGB( // scalastyle:ignore parameter.number
- width: Int, height: Int,
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- ): (Array[Byte], Array[Byte], Array[Byte]) = {
- val r = Array.ofDim[Byte](width * height)
- val g = Array.ofDim[Byte](width * height)
- val b = Array.ofDim[Byte](width * height)
-
- assert(r.length >= width * height)
- assert(g.length >= width * height)
- assert(b.length >= width * height)
-
- for {
- yPos <- 0 until height
- xPos <- 0 until width
- } {
- val yx = unsigned(y((yPos * yStride) + xPos))
- val ux = unsigned(u(((yPos / 2) * uStride) + (xPos / 2)))
- val vx = unsigned(v(((yPos / 2) * vStride) + (xPos / 2)))
-
- val currPos = (yPos * width) + xPos
-
- r(currPos) = YUVtoR(yx, ux, vx)
- g(currPos) = YUVtoG(yx, ux, vx)
- b(currPos) = YUVtoB(yx, ux, vx)
- }
-
- (r, g, b)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerator.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerator.scala
deleted file mode 100644
index cb0185037..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerator.scala
+++ /dev/null
@@ -1,77 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import im.tox.tox4j.av.data.{ Height, Width }
-import org.scalatest.Assertions
-
-abstract class VideoGenerator {
-
- def width: Width
- def height: Height
- def length: Int
-
- def yuv(t: Int): (Array[Byte], Array[Byte], Array[Byte])
- def resize(width: Width, height: Height): VideoGenerator
-
- final def size: Int = width.value * height.value
-
- protected final def w: Int = width.value
- protected final def h: Int = height.value
-
-}
-
-object VideoGenerator extends Assertions {
-
- private def resizeNearestNeighbour(
- pixels: Array[Byte],
- oldWidth: Int,
- oldHeight: Int,
- newWidth: Int,
- newHeight: Int
- ): Array[Byte] = {
- val result = Array.ofDim[Byte](newWidth * newHeight)
-
- val xRatio = oldWidth / newWidth.toDouble
- val yRatio = oldHeight / newHeight.toDouble
-
- for {
- yPos <- 0 until newHeight
- xPos <- 0 until newWidth
- } {
- val px = Math.floor(xPos * xRatio)
- val py = Math.floor(yPos * yRatio)
- result((yPos * newWidth) + xPos) = pixels(((py * oldWidth) + px).toInt)
- }
-
- result
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def resizeNearestNeighbour(newWidth: Width, newHeight: Height, gen: VideoGenerator): VideoGenerator = {
- if (newWidth == gen.width && newHeight == gen.height) {
- gen
- } else {
- new VideoGenerator {
-
- override def toString: String = s"resizeNearestNeighbour($width, $height, $gen)"
-
- override def resize(width: Width, height: Height): VideoGenerator = gen.resize(width, height)
-
- override def yuv(t: Int): (Array[Byte], Array[Byte], Array[Byte]) = {
- val yuv = gen.yuv(t)
- (
- resizeNearestNeighbour(yuv._1, gen.width.value, gen.height.value, width.value, height.value),
- resizeNearestNeighbour(yuv._2, gen.width.value / 2, gen.height.value / 2, width.value / 2, height.value / 2),
- resizeNearestNeighbour(yuv._3, gen.width.value / 2, gen.height.value / 2, width.value / 2, height.value / 2)
- )
- }
-
- override def width: Width = newWidth
- override def height: Height = newHeight
- override def length: Int = gen.length
-
- }
- }
- }
-
-}
-
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerators.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerators.scala
deleted file mode 100644
index 43ff65caf..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoGenerators.scala
+++ /dev/null
@@ -1,205 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.awt.Color
-
-import im.tox.tox4j.av.data.{ Height, Width }
-import org.scalatest.Assertions
-
-object VideoGenerators extends Assertions {
-
- val DefaultWidth: Width = Width.fromInt(400).get
- val DefaultHeight: Height = Height.fromInt(400).get
- val VideoLength: Int = 100
-
- // TODO(iphydf): Several of these break with the following error in
- // libtoxcore.log, especially at higher resolutions:
- //
- // toxcore 12:13 04:53:51 3343345408 ERROR video.c:155 - Error decoding video: Unspecified internal error
-
- /**
- * Shifting colours in xor pattern.
- */
- final case class Xor1(width: Width = DefaultWidth, height: Height = DefaultHeight, length: Int = VideoLength) extends ArithmeticVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- protected def y(t: Int, x: Int, y: Int): Int = x ^ y
- protected def u(t: Int, x: Int, y: Int): Int = x ^ y + t + 1
- protected def v(t: Int, x: Int, y: Int): Int = x ^ y - t - 1
- }
-
- /**
- * Rapidly changing xor patterns.
- */
- final case class Xor2(width: Width, height: Height, length: Int = VideoLength) extends RgbVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- def rgb(t: Int, y: Int, x: Int): Int = (x ^ y) * t
- }
-
- /**
- * Slowly right-shifting and colour-shifting xor.
- */
- final case class Xor3(width: Width, height: Height, length: Int = VideoLength) extends RgbVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- def rgb(t: Int, y: Int, x: Int): Int = (x - (t * Math.log(t)).toInt ^ y + (t * Math.log(t)).toInt) * t
- }
-
- /**
- * Slowly colour-shifting xor patterns.
- */
- final case class Xor4(width: Width, height: Height, length: Int = VideoLength) extends ArithmeticVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- protected def y(t: Int, x: Int, y: Int): Int = (x ^ y) + t
- protected def u(t: Int, x: Int, y: Int): Int = t * 2
- protected def v(t: Int, x: Int, y: Int): Int = -t * 2 - 1
- }
-
- final case class Xor5(width: Width, height: Height, length: Int = VideoLength) extends ArithmeticVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- protected def y(t: Int, x: Int, y: Int): Int = t + x ^ y
- protected def u(t: Int, x: Int, y: Int): Int = x ^ y + t + 1
- protected def v(t: Int, x: Int, y: Int): Int = x ^ y - t - 1
- }
-
- private def gradient(top: Boolean, left: Boolean, x: Int, y: Int, w: Int, h: Int): Double = {
- val value =
- if (top && left) {
- (x * 512 / w) min (y * 512 / h)
- } else if (top && !left) {
- ((w - x) * 512 / w) min (y * 512 / h)
- } else if (!top && left) {
- (x * 512 / w) min ((h - y) * 512 / h)
- } else {
- ((w - x) * 512 / w) min ((h - y) * 512 / h)
- }
- assert(value >= 0)
- assert(value <= 256)
- value.toDouble / 256
- }
-
- final case class XorGradient(width: Width, height: Height, length: Int = VideoLength) extends ArithmeticVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- protected def y(t: Int, x: Int, y: Int): Int = {
- val top = y <= h / 2
- val left = x <= w / 2
-
- (gradient(top, left, x, y, w, h) * (x ^ y) + t).toInt
- }
-
- protected def u(t: Int, x: Int, y: Int): Int = t * 2
- protected def v(t: Int, x: Int, y: Int): Int = -t * 2 - 1
- }
-
- /**
- * More and more gradient boxes.
- */
- final case class GradientBoxes(width: Width, height: Height, length: Int = VideoLength) extends RgbVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- def rgb(t: Int, y: Int, x: Int): Int = (x * Math.log(t) + ((y * Math.log(t)).toInt << 8)).toInt
- }
-
- /**
- * Multiplication (x * y) pattern moving up.
- */
- final case class MultiplyUp(width: Width, height: Height, length: Int = VideoLength) extends RgbVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- def rgb(t: Int, y: Int, x: Int): Int = x * (y + t)
- }
-
- object Colors {
- /**
- * Plain colours for testing.
- */
- val values: Seq[Color] = Seq(
- Color.white,
- Color.lightGray,
- Color.gray,
- Color.darkGray,
- Color.black,
- Color.red,
- Color.pink,
- Color.orange,
- Color.yellow,
- Color.green,
- Color.magenta,
- Color.cyan,
- Color.blue
- )
-
- private val FramesPerColor = 3
- private val VideoLength = Colors.values.length * Colors.FramesPerColor
-
- def get(t: Int): Color = values(t / FramesPerColor % values.length)
- }
-
- final case class Colors(width: Width, height: Height, length: Int = Colors.VideoLength) extends RgbVideoGenerator {
- def resize(width: Width, height: Height): VideoGenerator = copy(width, height)
-
- def rgb(t: Int, y: Int, x: Int): Int = Colors.get(t).getRGB
- }
-
- case object Smiley extends TextImageGenerator(
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "00000000000011zzzzzzzzzzzzzzzzz000000000000000000000000000000000000zzzzzzzzzzzzzzzzzzz00000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "000000000000000000000000000000000000000011zzzzzzzzzzzz0000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "00000000000000001zzzzzzzz000000000000000000000000000000000000000000000000zzzzzzzzz000000000000000000",
- "000000000000000011zzzzzzzzzz000000000000000000000000000000000000000011zzzzzzzzzz00000000000000000000",
- "000000000000000000001zzzzzzzzzz00000000000000000000000000000000111zzzzzzzzzz000000000000000000000000",
- "000000000000000000000000zzzzzzzzzzzz00000000000000000000000011zzzzzzzzzzzz00000000000000000000000000",
- "0000000000000000000000000000zzzzzzzzzzzzzzzz000000001zzzzzzzzzzzzzzzzz000000000000000000000000000000",
- "00000000000000000000000000000000zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz0000000000000000000000000000000000",
- "000000000000000000000000000000000000111zzzzzzzzzzzzzzzzzzzz00000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
- )
-
- val all: Map[String, (Width, Height, Int) => VideoGenerator] = Map[String, (Width, Height, Int) => VideoGenerator](
- "xor1" -> Xor1,
- "xor2" -> Xor2,
- "xor3" -> Xor3,
- "xor4" -> Xor4,
- "xor5" -> Xor5,
- "xorgradient" -> XorGradient,
- "gradientboxes" -> GradientBoxes,
- "multiplyup" -> MultiplyUp,
- "smiley" -> { (w, h, _) => VideoGenerator.resizeNearestNeighbour(w, h, Smiley) }
- )
-
- val default: VideoGenerator = VideoGenerator.resizeNearestNeighbour(DefaultWidth, DefaultHeight, Smiley)
- // val default = XorGradient(DefaultWidth, DefaultHeight)
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackTest.scala b/src/test/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackTest.scala
deleted file mode 100644
index 5e8365708..000000000
--- a/src/test/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackTest.scala
+++ /dev/null
@@ -1,154 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.awt.Color
-import java.util
-
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.ToxExceptionChecks
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-import im.tox.tox4j.testing.autotest.AutoTestSuite.timed
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class VideoReceiveFrameCallbackTest extends AutoTestSuite with ToxExceptionChecks {
-
- /**
- * How much of the sent data must be received for the test to pass.
- */
- private val minCompletionRatio = 0.7
-
- private val video = VideoGenerators.Colors(VideoGenerators.DefaultWidth, VideoGenerators.DefaultHeight)
-
- private val bitRate = BitRate.fromInt(1).get
-
- override def maxParticipantCount: Int = 2
-
- final case class S(t: Int = 0, received: List[Color] = Nil)
-
- object Handler extends EventListener(S()) {
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state0: State): State = {
- val state = super.friendConnectionStatus(friendNumber, connectionStatus)(state0)
-
- if (connectionStatus == ToxConnection.NONE || state.id(friendNumber) != state.id.next) {
- state
- } else {
- // Call id+1.
- state.addTask { (tox, av, state) =>
- debug(state, s"Ringing ${state.id(friendNumber)} to send ${video.length} frames")
- av.call(friendNumber, BitRate.Disabled, bitRate)
- state
- }
- }
- }
-
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: State): State = {
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- debug(state, s"Got a call from ${state.id(friendNumber)}; accepting")
- av.answer(friendNumber, BitRate.Disabled, BitRate.Disabled)
- state
- }
- } else {
- fail(s"I shouldn't have been called by friend ${state.id(friendNumber)}")
- state
- }
- }
-
- // There is no stack recursion here, it pushes thunks of itself for deferred execution.
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def sendFrame(friendNumber: ToxFriendNumber)(tox: ToxCore, av: ToxAv, state0: State): State = {
- val state = state0.modify(s => s.copy(t = s.t + 1))
-
- val (y, u, v) = video.yuv(state0.get.t)
- assert(y.length == video.size)
- assert(u.length == video.size / 4)
- assert(v.length == video.size / 4)
-
- val time = timed {
- av.videoSendFrame(friendNumber, video.width.value, video.height.value, y, u, v)
- }
- debug(state, s"Sent frame ${state.get.t} of ${video.length} ($time ms)")
-
- if (state.get.t >= video.length) {
- state.finish
- } else {
- state.addTask(sendFrame(friendNumber))
- }
- }
-
- override def callState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState])(state: State): State = {
- debug(state, s"Call with ${state.id(friendNumber)} is now $callState")
- state.addTask(sendFrame(friendNumber))
- }
-
- private def approximatelyEqual(color1: Color)(color2: Color): Boolean = {
- val rgb1 = color1.getRGBColorComponents(Array.ofDim(3)).map(c => Math.round(c * 32))
- val rgb2 = color2.getRGBColorComponents(Array.ofDim(3)).map(c => Math.round(c * 32))
- (rgb1, rgb2).zipped.forall(_ == _)
- }
-
- private def average(plane: Array[Byte]): Int = {
- plane.map(_ & 0xff).sum / plane.length
- }
-
- override def videoReceiveFrame(
- friendNumber: ToxFriendNumber,
- width: Width, height: Height,
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- )(state0: State): State = {
- val (conversionTime, rgbPlanar) = timed {
- VideoConversions.YUVtoRGB(width.value, height.value, y, u, v, yStride, uStride, vStride)
- }
-
- val averageR = average(rgbPlanar._1)
- val averageG = average(rgbPlanar._2)
- val averageB = average(rgbPlanar._3)
-
- val receivedColor = new Color(averageR, averageG, averageB)
-
- val state = state0.modify(s => s.copy(
- t = s.t + 1,
- received = receivedColor :: s.received
- ))
-
- assert(state.get.t <= video.length)
-
- val minReceived = (video.length * minCompletionRatio).toInt
- val receivedMessage = s"Received frame ${state.get.t} of (minimum) $minReceived (YUVtoRGB: $conversionTime ms)"
- if (state.get.t >= minReceived) {
- val assertionTime: Int = timed {
- val received = state.get.received.distinct
- val expected = VideoGenerators.Colors.values
-
- // All received in expected.
- assert(received.forall { c => expected.exists(approximatelyEqual(c)) })
-
- if (state.get.t >= video.length) {
- // All expected in received. Only checked if every sent frame was received.
- debug(state, s"Received all ${video.length} frames")
- assert(expected.forall { c => received.exists(approximatelyEqual(c)) }): Unit
- }
- }
-
- debug(state, receivedMessage + s" (assertion time: $assertionTime ms)")
-
- state.finish
- } else {
- debug(state, receivedMessage)
-
- state
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/av/package.scala b/src/test/java/im/tox/tox4j/av/package.scala
deleted file mode 100644
index c0778f27b..000000000
--- a/src/test/java/im/tox/tox4j/av/package.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.documentation._
-
-package object av extends Documented
diff --git a/src/test/java/im/tox/tox4j/core/JToxCoreTest.java b/src/test/java/im/tox/tox4j/core/JToxCoreTest.java
deleted file mode 100644
index 477413a6c..000000000
--- a/src/test/java/im/tox/tox4j/core/JToxCoreTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package im.tox.tox4j.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import im.tox.tox4j.core.callbacks.ToxCoreEventAdapter;
-import im.tox.tox4j.core.callbacks.ToxCoreEventListener;
-import im.tox.tox4j.core.enums.ToxFileControl;
-import im.tox.tox4j.core.enums.ToxMessageType;
-import im.tox.tox4j.core.enums.ToxUserStatus;
-import im.tox.tox4j.core.exceptions.ToxFriendAddException;
-import im.tox.tox4j.core.options.ProxyOptions;
-import im.tox.tox4j.core.options.SaveDataOptions;
-import im.tox.tox4j.core.options.ToxOptions;
-import im.tox.tox4j.exceptions.ToxException;
-import im.tox.tox4j.impl.jni.ToxCoreImpl;
-import org.junit.Assert;
-import org.junit.Test;
-import org.scalatestplus.junit.JUnitSuite;
-
-public final class JToxCoreTest extends JUnitSuite {
-
- private final ToxCoreEventListener handler =
- new ToxCoreEventAdapter<>();
-
- private final ToxOptions options = new ToxOptions(
- true, true, true, new ProxyOptions.Http("localhost", 1234),
- ToxCoreConstants.DefaultStartPort(), ToxCoreConstants.DefaultEndPort(), 0,
- // TODO(iphydf): This is kind of ugly. Do we want to live with this?
- SaveDataOptions.None$.MODULE$, true);
-
- private void expectBoolean(boolean bool) {}
-
- private void expectInt(int integer) {}
-
- private void expectBytes(byte[] bytes) {}
-
- private void expectInts(int[] ints) {}
-
- @Test
- public void testJavaUsability() {
- try (ToxCore tox = new ToxCoreImpl(options)) {
- tox.iterate(handler, null);
- int friendNumber = tox.addFriend(null, null);
- Assert.fail("No exception thrown, null friend added as " + friendNumber);
- } catch (ToxFriendAddException e) {
- assertEquals(ToxFriendAddException.Code.NULL, e.code());
- }
- }
-
- /**
- * Call every ToxCore method with Java types and check whether their return
- * types conform to the expected API. This test is here to verify that the
- * Scala type changes don't break Java code.
- */
- @Test
- public void testJavaApi() {
- final byte[] bytes = "hello".getBytes();
-
- try (ToxCore tox = new ToxCoreImpl(options)) {
- expectInt(tox.addFriend(bytes, bytes));
- expectInt(tox.addFriendNorequest(bytes));
- tox.addTcpRelay("hello", 0, bytes);
- tox.bootstrap("hello", 0, bytes);
- tox.close();
- tox.deleteFriend(0);
- tox.fileControl(0, 0, ToxFileControl.CANCEL);
- tox.fileSeek(0, 0, 0L);
- expectInt(tox.fileSend(0, 0, 0L, bytes, bytes));
- tox.fileSendChunk(0, 0, 0L, bytes);
- expectInt(tox.friendByPublicKey(bytes));
- expectBoolean(tox.friendExists(0));
- tox.friendSendLosslessPacket(0, bytes);
- tox.friendSendLossyPacket(0, bytes);
- expectInt(tox.friendSendMessage(0, ToxMessageType.NORMAL, 0, bytes));
- expectBytes(tox.getAddress());
- expectBytes(tox.getDhtId());
- expectBytes(tox.getFileFileId(0, 0));
- expectInts(tox.getFriendList());
- expectBytes(tox.getFriendPublicKey(0));
- expectBytes(tox.getName());
- expectInt(tox.getNospam());
- expectBytes(tox.getPublicKey());
- expectBytes(tox.getSavedata());
- expectBytes(tox.getSecretKey());
- expectBytes(tox.getStatusMessage());
- ToxUserStatus status = tox.getStatus();
- expectInt(tox.getTcpPort());
- expectInt(tox.getUdpPort());
- Void nothing = tox.iterate(null, null);
- expectInt(tox.iterationInterval());
- ToxCore tox2 = tox.load(options);
- tox.setName(bytes);
- tox.setNospam(0);
- tox.setStatus(ToxUserStatus.AWAY);
- tox.setStatusMessage(bytes);
- tox.setTyping(0, true);
- } catch (ToxException> | IllegalArgumentException e) {
- assertNotNull(e);
- }
- }
-}
diff --git a/src/test/java/im/tox/tox4j/core/LoadSaveTest.scala b/src/test/java/im/tox/tox4j/core/LoadSaveTest.scala
deleted file mode 100644
index 1a31140ff..000000000
--- a/src/test/java/im/tox/tox4j/core/LoadSaveTest.scala
+++ /dev/null
@@ -1,198 +0,0 @@
-package im.tox.tox4j.core
-
-import im.tox.tox4j.ToxCoreTestBase
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendRequestMessage, ToxNickname, ToxStatusMessage }
-import im.tox.tox4j.core.enums.ToxUserStatus
-import im.tox.tox4j.core.options.{ SaveDataOptions, ToxOptions }
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.{ withTox, withToxUnit }
-import im.tox.tox4j.testing.GetDisjunction._
-import org.scalatest.FunSuite
-
-import scala.annotation.tailrec
-
-@SuppressWarnings(Array(
- "org.wartremover.warts.ArrayEquals",
- "org.wartremover.warts.Equals"
-))
-final class LoadSaveTest extends FunSuite {
-
- private trait Check {
- def change(tox: ToxCore): Boolean
- def check(tox: ToxCore): Unit
- }
-
- @tailrec
- private def testLoadSave(check: Check): Unit = {
- val (continue, data) = withToxUnit { tox =>
- (check.change(tox), tox.getSavedata)
- }
-
- withToxUnit(SaveDataOptions.ToxSave(data)) { tox =>
- check.check(tox)
- }
-
- if (continue) {
- testLoadSave(check)
- }
- }
-
- test("Name") {
- testLoadSave(new Check() {
- private var expected = ToxNickname.unsafeFromValue(null)
-
- override def change(tox: ToxCore): Boolean = {
- expected =
- if (expected.value == null) {
- ToxNickname.fromString("").toOption.get
- } else {
- ToxNickname.fromValue(ToxCoreTestBase.randomBytes(expected.value.length + 1)).toOption.get
- }
- tox.setName(expected)
- expected.value.length < ToxCoreConstants.MaxNameLength
- }
-
- override def check(tox: ToxCore): Unit = {
- assert(tox.getName.value sameElements expected.value)
- }
- })
- }
-
- test("StatusMessage") {
- testLoadSave(new Check() {
- private var expected = ToxStatusMessage.unsafeFromValue(null)
-
- override def change(tox: ToxCore): Boolean = {
- if (expected.value == null) {
- expected = ToxStatusMessage.fromString("").toOption.get
- } else {
- expected = ToxStatusMessage.fromValue(ToxCoreTestBase.randomBytes(expected.value.length + 1)).toOption.get
- }
- tox.setStatusMessage(expected)
- expected.value.length < ToxCoreConstants.MaxNameLength
- }
-
- override def check(tox: ToxCore): Unit = {
- assert(tox.getStatusMessage.value sameElements expected.value)
- }
- })
- }
-
- test("Status") {
- testLoadSave(new Check() {
- private var expected = ToxUserStatus.values()
-
- override def change(tox: ToxCore): Boolean = {
- tox.setStatus(expected.head)
- expected.length > 1
- }
-
- override def check(tox: ToxCore): Unit = {
- assert(tox.getStatus == expected.head)
- expected = expected.tail
- }
- })
- }
-
- test("NoSpam") {
- testLoadSave(new Check() {
- private var expected = -1
-
- override def change(tox: ToxCore): Boolean = {
- expected += 1
- tox.setNospam(expected)
- expected < 100
- }
-
- override def check(tox: ToxCore): Unit = {
- assert(tox.getNospam == expected)
- }
- })
- }
-
- test("Friend") {
- testLoadSave(new Check() {
- private var expected = ToxFriendNumber.fromInt(1).get
-
- override def change(tox: ToxCore): Boolean = {
- withToxUnit { toxFriend =>
- expected = tox.addFriend(
- toxFriend.getAddress,
- ToxFriendRequestMessage.fromString("hello").toOption.get
- )
- }
- false
- }
-
- override def check(tox: ToxCore): Unit = {
- assert(tox.getFriendNumbers.length == 1)
- assert(tox.getFriendNumbers(0) == expected)
- }
- })
- }
-
- test("SaveNotEmpty") {
- withToxUnit { tox =>
- val data = tox.getSavedata
- assert(data != null)
- assert(data.nonEmpty)
- }
- }
-
- test("SaveRepeatable") {
- withToxUnit { tox =>
- assert(tox.getSavedata sameElements tox.getSavedata)
- }
- }
-
- test("LoadSave1") {
- withToxUnit { tox =>
- val data = tox.getSavedata
- val data1 = withToxUnit(SaveDataOptions.ToxSave(data)) { tox1 =>
- tox1.getSavedata
- }
- val data2 = withToxUnit(SaveDataOptions.ToxSave(data)) { tox2 =>
- tox2.getSavedata
- }
- assert(data1 sameElements data2)
- }
- }
-
- test("LoadSave2") {
- withToxUnit { tox =>
- val data = tox.getSavedata
- withToxUnit(SaveDataOptions.ToxSave(data)) { tox1 =>
- assert(tox1.getSavedata.length == data.length)
- }
- }
- }
-
- test("LoadSave3") {
- withToxUnit { tox =>
- val data = tox.getSavedata
- withToxUnit(SaveDataOptions.ToxSave(data)) { tox1 =>
- assert(tox1.getSavedata sameElements data)
- }
- }
- }
-
- test("LoadSave4") {
- withToxUnit { tox1 =>
- val data = tox1.getSecretKey
- withToxUnit(SaveDataOptions.SecretKey(data)) { tox2 =>
- assert(tox1.getSecretKey.value sameElements tox2.getSecretKey.value)
- assert(tox1.getPublicKey.value sameElements tox2.getPublicKey.value)
- }
- }
- }
-
- test("LoadSave5") {
- withToxUnit { tox1 =>
- val data = tox1.getSecretKey
- withTox(tox1.load(ToxOptions(saveData = SaveDataOptions.SecretKey(data)))) { tox2 =>
- assert(tox1.getSecretKey.value sameElements tox2.getSecretKey.value)
- assert(tox1.getPublicKey.value sameElements tox2.getPublicKey.value)
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/NetworkTest.scala b/src/test/java/im/tox/tox4j/core/NetworkTest.scala
deleted file mode 100644
index 387f377cc..000000000
--- a/src/test/java/im/tox/tox4j/core/NetworkTest.scala
+++ /dev/null
@@ -1,123 +0,0 @@
-package im.tox.tox4j.core
-
-import im.tox.core.network.Port
-import im.tox.tox4j.DhtNodeSelector.node
-import im.tox.tox4j.TestConstants.Timeout
-import im.tox.tox4j._
-import im.tox.tox4j.core.NetworkTest.logger
-import im.tox.tox4j.core.data.ToxPublicKey
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.{ withToxUnit, withToxes }
-import org.scalatest.FlatSpec
-import org.scalatest.concurrent.TimeLimits
-import org.slf4j.LoggerFactory
-
-import scala.language.postfixOps
-
-object NetworkTest {
- private val logger = LoggerFactory.getLogger(classOf[NetworkTest])
- private val ToxCount = 10
-}
-
-@SuppressWarnings(Array("org.wartremover.warts.While"))
-final class NetworkTest extends FlatSpec with TimeLimits {
-
- // TODO(iphydf): Figure out why the bootstrap tests all fail on Travis.
- /*
- private def testBootstrap(ipv6Enabled: Boolean, udpEnabled: Boolean, ip: String, port: Port, dhtId: ToxPublicKey): Unit = {
- val action = s"bootstrap to remote node on $ip:$port with ${if (udpEnabled) "UDP" else "TCP"}${if (ipv6Enabled) 6 else 4}"
-
- withToxUnit(ipv6Enabled, udpEnabled) { tox =>
- logger.info(s"Attempting to $action")
- val start = System.currentTimeMillis
-
- if (!udpEnabled) {
- tox.addTcpRelay(ip, port, dhtId)
- }
- tox.bootstrap(ip, port, dhtId)
-
- val status = new ConnectedListener
- while (!status.isConnected) {
- tox.iterate(status)(())
- Thread.sleep(tox.iterationInterval)
- }
-
- val end = System.currentTimeMillis
-
- logger.info(s"Success: $action took ${end - start} ms")
- }
- }
-
- "bootstrap" should "connect with UDP4" in {
- assume(ToxCoreTestBase.checkIPv4.isEmpty)
- failAfter(Timeout) {
- testBootstrap(ipv6Enabled = false, udpEnabled = true, node.ipv4, node.udpPort, node.dhtId)
- }
- }
-
- it should "connect with UDP6" in {
- assume(ToxCoreTestBase.checkIPv6.isEmpty)
- failAfter(Timeout) {
- testBootstrap(ipv6Enabled = true, udpEnabled = true, node.ipv6, node.udpPort, node.dhtId)
- }
- }
-
- it should "connect with TCP4" in {
- assume(ToxCoreTestBase.checkIPv4.isEmpty)
- failAfter(Timeout) {
- testBootstrap(ipv6Enabled = false, udpEnabled = false, node.ipv4, node.tcpPort, node.dhtId)
- }
- }
-
- it should "connect with TCP6" in {
- assume(ToxCoreTestBase.checkIPv6.isEmpty)
- failAfter(Timeout) {
- testBootstrap(ipv6Enabled = true, udpEnabled = false, node.ipv6, node.tcpPort, node.dhtId)
- }
- }
- */
-
- "LAN discovery" should "connect all nodes" in {
- failAfter(Timeout) {
- withToxes(NetworkTest.ToxCount) { toxes =>
- val action = s"Connecting all of ${toxes.size} toxes with LAN discovery"
- logger.info(action)
-
- val start = System.currentTimeMillis
-
- while (!toxes.isAllConnected) {
- toxes.iterate()
- Thread.sleep(toxes.iterationInterval)
- }
-
- val end = System.currentTimeMillis
-
- logger.info(s"$action took ${end - start} ms")
- }
- }
- }
-
- it should "connect at least one instance" in {
- failAfter(Timeout) {
- withToxes(NetworkTest.ToxCount) { toxes =>
- val action = s"Connecting one of ${toxes.size} toxes with LAN discovery"
- logger.info(action)
-
- val start = System.currentTimeMillis
-
- while (!toxes.isAnyConnected) {
- toxes.iterate()
- try {
- Thread.sleep(toxes.iterationInterval)
- } catch {
- case e: InterruptedException =>
- }
- }
-
- val end = System.currentTimeMillis
-
- logger.info(s"$action took ${end - start} ms")
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/SmallNat.scala b/src/test/java/im/tox/tox4j/core/SmallNat.scala
deleted file mode 100644
index 8675913c1..000000000
--- a/src/test/java/im/tox/tox4j/core/SmallNat.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package im.tox.tox4j.core
-
-import org.scalacheck.{ Arbitrary, Gen }
-
-import scala.language.implicitConversions
-import scala.runtime.IntegralProxy
-
-/**
- * A wrapper class for [[Int]] to be used in property based testing where a
- * small positive integer is required (e.g. for array bounds).
- *
- * arbitrary[Int] generates numbers from the full range of integers, and is
- * thus unfit for allocation sizes and iteration counts.
- */
-final case class SmallNat(self: Int) extends AnyVal with IntegralProxy[Int] {
- override protected def num = scala.math.Numeric.IntIsIntegral
- override protected def ord = scala.math.Ordering.Int
- override def isWhole(): Boolean = true
-}
-
-@SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
-object SmallNat {
- val MinValue: Int = 0
- val MaxValue: Int = 100
-
- implicit val arbSmallNat: Arbitrary[SmallNat] = Arbitrary(Gen.choose(MinValue, MaxValue).map(apply))
- implicit def smallNatToInt(smallNat: SmallNat): Int = smallNat.self
-}
diff --git a/src/test/java/im/tox/tox4j/core/ToxCoreFactory.scala b/src/test/java/im/tox/tox4j/core/ToxCoreFactory.scala
deleted file mode 100644
index 34fe800e0..000000000
--- a/src/test/java/im/tox/tox4j/core/ToxCoreFactory.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package im.tox.tox4j.core
-
-import im.tox.tox4j.core.options.ToxOptions
-
-abstract class ToxCoreFactory {
-
- def withTox[R](options: ToxOptions)(f: ToxCore => R): R
-
- final def withTox[R](tox: ToxCore)(f: ToxCore => R): R = {
- try {
- f(tox)
- } finally {
- tox.close()
- }
- }
-
- @SuppressWarnings(Array(
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.Recursion"
- ))
- final def withToxN[R](
- count: Int,
- options: ToxOptions = ToxOptions(),
- initial: List[ToxCore] = Nil
- )(
- f: List[ToxCore] => R
- ): R = {
- if (count == 0) {
- f(initial)
- } else {
- withTox[R](options) { tox =>
- withToxN(count - 1, options, tox :: initial)(f)
- }
- }
- }
-
- final def withToxN[R](
- options: List[ToxOptions]
- )(
- f: List[ToxCore] => R
- ): R = {
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- def go(options: List[ToxOptions], toxes: List[ToxCore]): R = {
- options match {
- case Nil => f(toxes.reverse)
- case opts :: tail =>
- withTox[R](opts) { tox =>
- go(tail, tox :: toxes)
- }
- }
- }
- go(options, Nil)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/ToxCoreJavaTest.java b/src/test/java/im/tox/tox4j/core/ToxCoreJavaTest.java
new file mode 100644
index 000000000..84d8fe64d
--- /dev/null
+++ b/src/test/java/im/tox/tox4j/core/ToxCoreJavaTest.java
@@ -0,0 +1,42 @@
+package im.tox.tox4j.core;
+
+import im.tox.tox4j.core.callbacks.ToxCoreEventAdapter;
+import im.tox.tox4j.core.data.ToxFriendNumber;
+import im.tox.tox4j.core.enums.ToxConnection;
+import im.tox.tox4j.core.options.ToxOptions;
+import im.tox.tox4j.impl.jni.ToxCoreImpl;
+import org.junit.Test;
+
+public class ToxCoreJavaTest {
+ @Test
+ public void addFriendNorequest_shouldConnectTwoToxes() throws InterruptedException {
+ ToxCore tox1 = new ToxCoreImpl(ToxOptions.Companion.getDefaultInstance());
+ ToxCore tox2 = new ToxCoreImpl(ToxOptions.Companion.getDefaultInstance());
+
+ tox2.bootstrap("localhost", tox1.getUdpPort(), tox1.getDhtId());
+
+ tox1.addFriendNorequest(tox2.getPublicKey());
+ tox2.addFriendNorequest(tox1.getPublicKey());
+
+ boolean connected1 = false;
+ boolean connected2 = false;
+
+ while (!connected1 && !connected2) {
+ connected1 = tox1.iterate(new ToxCoreEventAdapter() {
+ @Override
+ public Boolean friendConnectionStatus(
+ int friendNumber, ToxConnection connectionStatus, Boolean state) {
+ return connectionStatus != ToxConnection.NONE;
+ }
+ }, connected1);
+ connected2 = tox2.iterate(new ToxCoreEventAdapter() {
+ @Override
+ public Boolean friendConnectionStatus(
+ int friendNumber, ToxConnection connectionStatus, Boolean state) {
+ return connectionStatus != ToxConnection.NONE;
+ }
+ }, connected2);
+ Thread.sleep(tox1.getIterationInterval());
+ }
+ }
+}
diff --git a/src/test/java/im/tox/tox4j/core/ToxCoreTest.kt b/src/test/java/im/tox/tox4j/core/ToxCoreTest.kt
new file mode 100644
index 000000000..5953c17fb
--- /dev/null
+++ b/src/test/java/im/tox/tox4j/core/ToxCoreTest.kt
@@ -0,0 +1,92 @@
+package im.tox.tox4j.core
+
+import im.tox.tox4j.core.callbacks.ToxCoreEventListener
+import im.tox.tox4j.core.data.ToxFriendNumber
+import im.tox.tox4j.core.enums.ToxConnection
+import im.tox.tox4j.core.options.ToxOptions
+import im.tox.tox4j.impl.jni.ToxCoreImpl
+import kotlin.coroutines.CoroutineContext
+import kotlin.coroutines.coroutineContext
+import kotlin.test.Test
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+
+class ToxCoreTest {
+ private class Toxes : CoroutineContext.Element {
+ private val list: MutableList = mutableListOf()
+
+ override val key = Toxes
+
+ companion object : CoroutineContext.Key {
+ suspend fun add(makeTox: () -> ToxCore): ToxCore {
+ val ctx = coroutineContext.get(Toxes)
+ if (ctx == null) {
+ throw IllegalStateException("coroutine context has no Toxes object")
+ }
+ val tox = makeTox()
+ ctx.list.add(tox)
+ return tox
+ }
+
+ suspend fun close(): Unit {
+ val ctx = coroutineContext.get(Toxes)
+ if (ctx == null) {
+ throw IllegalStateException("coroutine context has no Toxes object")
+ }
+ for (tox in ctx.list) {
+ tox.close()
+ }
+ }
+ }
+ }
+
+ private suspend fun newToxCore(options: ToxOptions): ToxCore = Toxes.add { ToxCoreImpl(options) }
+
+ private fun runTox(block: suspend CoroutineScope.() -> Unit): Unit =
+ runBlocking(Toxes()) {
+ try {
+ block()
+ } finally {
+ Toxes.close()
+ }
+ }
+
+ @Test
+ fun addFriendNorequest_shouldConnectTwoToxes() = runTox {
+ val tox1 = newToxCore(ToxOptions())
+ val tox2 = newToxCore(ToxOptions())
+
+ tox2.bootstrap("localhost", tox1.udpPort, tox1.dhtId)
+
+ tox1.addFriendNorequest(tox2.publicKey)
+ tox2.addFriendNorequest(tox1.publicKey)
+
+ var connected1 = false
+ var connected2 = false
+
+ while (!connected1 && !connected2) {
+ connected1 =
+ tox1.iterate(
+ object : ToxCoreEventListener {
+ override fun friendConnectionStatus(
+ friendNumber: ToxFriendNumber,
+ connectionStatus: ToxConnection,
+ state: Boolean,
+ ) = connectionStatus != ToxConnection.NONE
+ },
+ connected1)
+ connected2 =
+ tox2.iterate(
+ object : ToxCoreEventListener {
+ override fun friendConnectionStatus(
+ friendNumber: ToxFriendNumber,
+ connectionStatus: ToxConnection,
+ state: Boolean,
+ ) = connectionStatus != ToxConnection.NONE
+ },
+ connected2)
+ delay(tox1.iterationInterval.toLong())
+ }
+ }
+}
diff --git a/src/test/java/im/tox/tox4j/core/ToxCoreTest.scala b/src/test/java/im/tox/tox4j/core/ToxCoreTest.scala
deleted file mode 100644
index d383f6567..000000000
--- a/src/test/java/im/tox/tox4j/core/ToxCoreTest.scala
+++ /dev/null
@@ -1,67 +0,0 @@
-package im.tox.tox4j.core
-
-import im.tox.tox4j.core.SmallNat._
-import im.tox.tox4j.core.callbacks.ToxCoreEventListener
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendRequestMessage }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.impl.jni.ToxCoreImpl
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.withToxUnit
-import im.tox.tox4j.testing.GetDisjunction._
-import org.scalatest.FlatSpec
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class ToxCoreTest extends FlatSpec with ScalaCheckPropertyChecks {
-
- "addFriend" should "return increasing friend numbers and increment the friend list size" in {
- forAll { (count: SmallNat, message: Array[Byte]) =>
- whenever(message.length >= 1 && message.length <= ToxCoreConstants.MaxFriendRequestLength) {
- withToxUnit { tox =>
- (0 until count).map(ToxFriendNumber.fromInt(_).get) foreach { i =>
- withToxUnit { friend =>
- val friendNumber = tox.addFriend(
- friend.getAddress,
- ToxFriendRequestMessage.fromValue(message).toOption.get
- )
- assert(friendNumber == i)
- }
- }
- assert(tox.getFriendList.length == count.self)
- }
- }
- }
- }
-
- "onClose callbacks" should "have been called after close" in {
- var called = false
- withToxUnit { tox =>
- tox.asInstanceOf[ToxCoreImpl].addOnCloseCallback { () =>
- called = true
- }
- }
- assert(called)
- }
-
- they should "not be called before close" in {
- var called = false
- withToxUnit { tox =>
- tox.asInstanceOf[ToxCoreImpl].addOnCloseCallback { () =>
- called = true
- }
- assert(!called)
- }
- }
-
- they should "not be called if they were unregistered" in {
- var called = false
- withToxUnit { tox =>
- val toxImpl = tox.asInstanceOf[ToxCoreImpl]
- val id = toxImpl.addOnCloseCallback { () =>
- called = true
- }
- toxImpl.removeOnCloseCallback(id)
- }
- assert(!called)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/ToxList.scala b/src/test/java/im/tox/tox4j/core/ToxList.scala
deleted file mode 100644
index a07e94798..000000000
--- a/src/test/java/im/tox/tox4j/core/ToxList.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package im.tox.tox4j.core
-
-import im.tox.core.typesafe.Equals._
-import im.tox.tox4j.core.callbacks.ToxCoreEventListener
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.core.exceptions.ToxNewException
-
-import scala.collection.mutable.ArrayBuffer
-
-object ToxList {
- final case class Entry(tox: ToxCore, var connected: ToxConnection)
-}
-
-final class ToxList(newTox: () => ToxCore, count: Int) {
-
- private val handler = new ToxCoreEventListener[ToxList.Entry] {
- override def selfConnectionStatus(connectionStatus: ToxConnection)(state: ToxList.Entry): ToxList.Entry = {
- state.connected = connectionStatus
- state
- }
- }
-
- private val toxes = {
- val temporary = new ArrayBuffer[ToxCore]
- val instances = try {
- (0 until count) map { i =>
- val instance = ToxList.Entry(newTox(), ToxConnection.NONE)
- temporary += instance.tox
- instance
- }
- } catch {
- case e: ToxNewException =>
- temporary.foreach(_.close())
- throw e
- }
-
- instances
- }
-
- def close(): Unit = toxes.foreach(_.tox.close())
-
- def isAllConnected: Boolean = toxes.forall(_.connected =/= ToxConnection.NONE)
- def isAnyConnected: Boolean = toxes.exists(_.connected =/= ToxConnection.NONE)
-
- def iterate(): Unit = toxes.foreach(entry => entry.tox.iterate(handler)(entry))
-
- def iterationInterval: Int = toxes.map(_.tox.iterationInterval).max
-
- def get(index: Int): ToxCore = toxes(index).tox
- def size: Int = toxes.length
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/CoreInvokeTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/CoreInvokeTest.scala
deleted file mode 100644
index 3886d18fe..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/CoreInvokeTest.scala
+++ /dev/null
@@ -1,246 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.callbacks.CoreInvokeTest._
-import im.tox.tox4j.core.callbacks.InvokeTest.ByteArray
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxMessageType, ToxUserStatus }
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.impl.jni.ToxCoreImpl
-import im.tox.tox4j.testing.GetDisjunction._
-import org.scalacheck.Arbitrary.arbitrary
-import org.scalacheck.{ Arbitrary, Gen }
-import org.scalatest.FunSuite
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-import scala.language.implicitConversions
-import scala.util.Random
-
-final class CoreInvokeTest extends FunSuite with ScalaCheckPropertyChecks {
-
- final class TestEventListener extends ToxCoreEventListener[Option[Event]] {
- private def setEvent(event: Event)(state: Option[Event]): Option[Event] = {
- assert(state.isEmpty)
- Some(event)
- }
-
- // scalastyle:off line.size.limit
- override def friendTyping(friendNumber: ToxFriendNumber, isTyping: Boolean)(state: Option[Event]): Option[Event] = setEvent(FriendTyping(friendNumber, isTyping))(state)
- override def friendStatusMessage(friendNumber: ToxFriendNumber, message: ToxStatusMessage)(state: Option[Event]): Option[Event] = setEvent(FriendStatusMessage(friendNumber, message.value))(state)
- override def fileChunkRequest(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int)(state: Option[Event]): Option[Event] = setEvent(FileChunkRequest(friendNumber, fileNumber, position, length))(state)
- override def fileRecvChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: Array[Byte])(state: Option[Event]): Option[Event] = setEvent(FileRecvChunk(friendNumber, fileNumber, position, data))(state)
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: Option[Event]): Option[Event] = setEvent(FriendConnectionStatus(friendNumber, connectionStatus))(state)
- override def friendRequest(publicKey: ToxPublicKey, timeDelta: Int, message: ToxFriendRequestMessage)(state: Option[Event]): Option[Event] = setEvent(FriendRequest(publicKey.value, timeDelta, message.value))(state)
- override def friendLossyPacket(friendNumber: ToxFriendNumber, data: ToxLossyPacket)(state: Option[Event]): Option[Event] = setEvent(FriendLossyPacket(friendNumber, data.value))(state)
- override def friendStatus(friendNumber: ToxFriendNumber, status: ToxUserStatus)(state: Option[Event]): Option[Event] = setEvent(FriendStatus(friendNumber, status))(state)
- override def selfConnectionStatus(connectionStatus: ToxConnection)(state: Option[Event]): Option[Event] = setEvent(SelfConnectionStatus(connectionStatus))(state)
- override def friendReadReceipt(friendNumber: ToxFriendNumber, messageId: Int)(state: Option[Event]): Option[Event] = setEvent(FriendReadReceipt(friendNumber, messageId))(state)
- override def friendName(friendNumber: ToxFriendNumber, name: ToxNickname)(state: Option[Event]): Option[Event] = setEvent(FriendName(friendNumber, name.value))(state)
- override def friendLosslessPacket(friendNumber: ToxFriendNumber, data: ToxLosslessPacket)(state: Option[Event]): Option[Event] = setEvent(FriendLosslessPacket(friendNumber, data.value))(state)
- override def friendMessage(friendNumber: ToxFriendNumber, messageType: ToxMessageType, timeDelta: Int, message: ToxFriendMessage)(state: Option[Event]): Option[Event] = setEvent(FriendMessage(friendNumber, messageType, timeDelta, message.value))(state)
- override def fileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: ToxFilename)(state: Option[Event]): Option[Event] = setEvent(FileRecv(friendNumber, fileNumber, kind, fileSize, filename.value))(state)
- override def fileRecvControl(friendNumber: ToxFriendNumber, fileNumber: Int, control: ToxFileControl)(state: Option[Event]): Option[Event] = setEvent(FileRecvControl(friendNumber, fileNumber, control))(state)
- // scalastyle:on line.size.limit
- }
-
- def callbackTest(invoke: ToxCoreEventSynth => Unit, expected: Event): Unit = {
- val tox = new ToxCoreImpl(ToxOptions())
-
- try {
- invoke(tox)
- val listener = new TestEventListener
- val event = tox.iterate(listener)(None)
- assert(event.contains(expected))
- } finally {
- tox.close()
- }
- }
-
- private val random = new Random
-
- private implicit val arbToxPublicKey: Arbitrary[ToxPublicKey] = {
- Arbitrary(Gen.const(ToxPublicKey.Size).map(Array.ofDim[Byte]).map { array =>
- random.nextBytes(array)
- array(array.length - 1) = 0
- ToxPublicKey.fromValue(array).toOption.get
- })
- }
-
- private implicit val arbToxFriendNumber: Arbitrary[ToxFriendNumber] = {
- Arbitrary(arbitrary[Int].map(ToxFriendNumber.unsafeFromInt))
- }
-
- private implicit val arbToxNickname: Arbitrary[ToxNickname] = {
- Arbitrary(arbitrary[Array[Byte]].map(ToxNickname.unsafeFromValue))
- }
-
- private implicit val arbToxConnection: Arbitrary[ToxConnection] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map { i => ToxConnection.values()(Math.abs(i % ToxConnection.values().length)) })
- }
-
- private implicit val arbToxFileControl: Arbitrary[ToxFileControl] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map { i => ToxFileControl.values()(Math.abs(i % ToxFileControl.values().length)) })
- }
-
- private implicit val arbToxUserStatus: Arbitrary[ToxUserStatus] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map { i => ToxUserStatus.values()(Math.abs(i % ToxUserStatus.values().length)) })
- }
-
- private implicit val arbToxMessageType: Arbitrary[ToxMessageType] = {
- Arbitrary(Arbitrary.arbInt.arbitrary.map { i => ToxMessageType.values()(Math.abs(i % ToxMessageType.values().length)) })
- }
-
- test("FriendTyping") {
- forAll { (friendNumber: ToxFriendNumber, isTyping: Boolean) =>
- callbackTest(
- _.invokeFriendTyping(friendNumber, isTyping),
- FriendTyping(friendNumber, isTyping)
- )
- }
- }
-
- test("FriendStatusMessage") {
- forAll { (friendNumber: ToxFriendNumber, message: Array[Byte]) =>
- callbackTest(
- _.invokeFriendStatusMessage(friendNumber, message),
- FriendStatusMessage(friendNumber, message)
- )
- }
- }
-
- test("FileChunkRequest") {
- forAll { (friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int) =>
- callbackTest(
- _.invokeFileChunkRequest(friendNumber, fileNumber, position, length),
- FileChunkRequest(friendNumber, fileNumber, position, length)
- )
- }
- }
-
- test("FileRecvChunk") {
- forAll { (friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: Array[Byte]) =>
- callbackTest(
- _.invokeFileRecvChunk(friendNumber, fileNumber, position, data),
- FileRecvChunk(friendNumber, fileNumber, position, data)
- )
- }
- }
-
- test("FriendConnectionStatus") {
- forAll { (friendNumber: ToxFriendNumber, connectionStatus: ToxConnection) =>
- callbackTest(
- _.invokeFriendConnectionStatus(friendNumber, connectionStatus),
- FriendConnectionStatus(friendNumber, connectionStatus)
- )
- }
- }
-
- test("FriendRequest") {
- forAll { (publicKey: ToxPublicKey, timeDelta: Int, message: Array[Byte]) =>
- callbackTest(
- _.invokeFriendRequest(publicKey, timeDelta, message),
- FriendRequest(publicKey.value, /* timeDelta */ 0, message)
- )
- }
- }
-
- test("FriendLossyPacket") {
- forAll { (friendNumber: ToxFriendNumber, data: Array[Byte]) =>
- callbackTest(
- _.invokeFriendLossyPacket(friendNumber, data),
- FriendLossyPacket(friendNumber, data)
- )
- }
- }
-
- test("FriendStatus") {
- forAll { (friendNumber: ToxFriendNumber, status: ToxUserStatus) =>
- callbackTest(
- _.invokeFriendStatus(friendNumber, status),
- FriendStatus(friendNumber, status)
- )
- }
- }
-
- test("SelfConnectionStatus") {
- forAll { (connectionStatus: ToxConnection) =>
- callbackTest(
- _.invokeSelfConnectionStatus(connectionStatus),
- SelfConnectionStatus(connectionStatus)
- )
- }
- }
-
- test("FriendReadReceipt") {
- forAll { (friendNumber: ToxFriendNumber, messageId: Int) =>
- callbackTest(
- _.invokeFriendReadReceipt(friendNumber, messageId),
- FriendReadReceipt(friendNumber, messageId)
- )
- }
- }
-
- test("FriendName") {
- forAll { (friendNumber: ToxFriendNumber, name: ToxNickname) =>
- callbackTest(
- _.invokeFriendName(friendNumber, name),
- FriendName(friendNumber, name.value)
- )
- }
- }
-
- test("FriendLosslessPacket") {
- forAll { (friendNumber: ToxFriendNumber, data: Array[Byte]) =>
- callbackTest(
- _.invokeFriendLosslessPacket(friendNumber, data),
- FriendLosslessPacket(friendNumber, data)
- )
- }
- }
-
- test("FriendMessage") {
- forAll { (friendNumber: ToxFriendNumber, messageType: ToxMessageType, timeDelta: Int, message: Array[Byte]) =>
- callbackTest(
- _.invokeFriendMessage(friendNumber, messageType, timeDelta, message),
- FriendMessage(friendNumber, messageType, /* timeDelta */ 0, message)
- )
- }
- }
-
- test("FileRecv") {
- forAll { (friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: Array[Byte]) =>
- callbackTest(
- _.invokeFileRecv(friendNumber, fileNumber, kind, fileSize, filename),
- FileRecv(friendNumber, fileNumber, kind, fileSize, filename)
- )
- }
- }
-
- test("FileRecvControl") {
- forAll { (friendNumber: ToxFriendNumber, fileNumber: Int, control: ToxFileControl) =>
- callbackTest(
- _.invokeFileRecvControl(friendNumber, fileNumber, control),
- FileRecvControl(friendNumber, fileNumber, control)
- )
- }
- }
-
-}
-
-object CoreInvokeTest {
- sealed trait Event
- private final case class FriendTyping(friendNumber: ToxFriendNumber, isTyping: Boolean) extends Event
- private final case class FriendStatusMessage(friendNumber: ToxFriendNumber, message: ByteArray) extends Event
- private final case class FileChunkRequest(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int) extends Event
- private final case class FileRecvChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: ByteArray) extends Event
- private final case class FriendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection) extends Event
- private final case class FriendRequest(publicKey: ByteArray, timeDelta: Int, message: ByteArray) extends Event
- private final case class FriendLossyPacket(friendNumber: ToxFriendNumber, data: ByteArray) extends Event
- private final case class FriendStatus(friendNumber: ToxFriendNumber, status: ToxUserStatus) extends Event
- private final case class SelfConnectionStatus(connectionStatus: ToxConnection) extends Event
- private final case class FriendReadReceipt(friendNumber: ToxFriendNumber, messageId: Int) extends Event
- private final case class FriendName(friendNumber: ToxFriendNumber, name: ByteArray) extends Event
- private final case class FriendLosslessPacket(friendNumber: ToxFriendNumber, data: ByteArray) extends Event
- private final case class FriendMessage(friendNumber: ToxFriendNumber, messageType: ToxMessageType, timeDelta: Int, message: ByteArray) extends Event
- private final case class FileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: ByteArray) extends Event
- private final case class FileRecvControl(friendNumber: ToxFriendNumber, fileNumber: Int, control: ToxFileControl) extends Event
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeTestBase.scala b/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeTestBase.scala
deleted file mode 100644
index de40e7043..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeTestBase.scala
+++ /dev/null
@@ -1,228 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.TestConstants
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId, ToxFilename, ToxFriendMessage }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxFileKind, ToxMessageType }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-import java.util.Random
-
-/**
- * This test intends to simulate the situation of file pause
- * and resume initiated by both the sending side and the receiving side.
- * - Alice initiated the file transmission and Bob accepted
- * - After sending 1/4 of the file, Alice paused the transmission
- * - Bob saw Alice's paused transmission and sent a message to request resuming
- * - Alice resumed the transmission
- * - Bob paused the transmission after receiving 2/4 of the file
- * - Alice saw Bob paused transmission and sent a message to request resuming
- * - Bob resumed the transmission and received all the data
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-abstract class FilePauseResumeTestBase extends AliceBobTest {
-
- val fileData: Seq[Byte] = {
- val data = new Array[Byte](TestConstants.Iterations * ToxCoreConstants.MaxCustomPacketSize)
- new Random().nextBytes(data)
- data.toSeq
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals"))
- final case class State(
- aliceSentFileNumber: Int = -1,
- aliceOffset: Long = 0L,
- aliceShouldPause: Int = -1,
- fileId: ToxFileId = ToxFileId.empty,
- receivedData: Array[Byte] = Array.ofDim(fileData.length),
- bobSentFileNumber: Int = -1,
- bobOffset: Long = 0L,
- bobShouldPause: Int = -1
- )
-
- final override def initialState: State = State()
-
- abstract class Alice(name: String, expectedFriendName: String) extends ChatClient(name, expectedFriendName) {
-
- protected def addFriendMessageTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- fileId: ToxFileId,
- tox: ToxCore
- )(state: State): State
- protected def addFileRecvTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- bobOffset: Long,
- tox: ToxCore
- )(state: State): State
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connection: ToxConnection
- )(state: ChatState): ChatState = {
- if (isAlice) {
- if (connection != ToxConnection.NONE) {
- debug(s"is now connected to friend $friendNumber")
- debug(s"initiate file sending to friend $friendNumber")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- state.addTask { (tox, av, state) =>
- val aliceSentFileNumber = tox.fileSend(
- friendNumber,
- ToxFileKind.DATA,
- fileData.length,
- ToxFileId.empty,
- ToxFilename.fromValue(("file for " + expectedFriendName + ".png").getBytes).toOption.get
- )
- state.map(_.copy(
- fileId = tox.getFileFileId(friendNumber, aliceSentFileNumber),
- aliceSentFileNumber = aliceSentFileNumber
- ))
- }
- } else {
- state
- }
- } else {
- if (connection != ToxConnection.NONE) {
- debug(s"is now connected to friend $friendNumber")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- }
- state
- }
- }
-
- override def fileRecv(
- friendNumber: ToxFriendNumber,
- fileNumber: Int,
- kind: Int,
- fileSize: Long,
- filename: ToxFilename
- )(state: ChatState): ChatState = {
- assert(isBob)
- debug(s"received file send request $fileNumber from friend number $friendNumber current offset ${state.get.bobOffset}")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(kind == ToxFileKind.DATA)
- assert(new String(filename.value) == s"file for $name.png")
-
- state.addTask { (tox, av, state) =>
- assert(state.get.bobSentFileNumber == fileNumber)
- state.map(addFileRecvTask(friendNumber, state.get.bobSentFileNumber, state.get.bobOffset, tox))
- }.map(_.copy(bobSentFileNumber = fileNumber))
- }
-
- override def fileChunkRequest(
- friendNumber: ToxFriendNumber,
- fileNumber: Int,
- position: Long,
- length: Int
- )(state: ChatState): ChatState = {
- assert(isAlice)
- debug(s"got request for ${length}B from $friendNumber for file $fileNumber at $position")
- assert(length >= 0)
- if (length == 0) {
- debug("finish transmission")
- state.map(_.copy(aliceSentFileNumber = -1)).finish
- } else {
- val nextState = state.addTask { (tox, av, state) =>
- debug(s"sending ${length}B to $friendNumber from position $position")
- tox.fileSendChunk(friendNumber, fileNumber, position,
- fileData.slice(position.toInt, Math.min(position.toInt + length, fileData.length)).toArray)
- state
- }.map(state => state.copy(aliceOffset = state.aliceOffset + length))
- if (state.get.aliceOffset >= fileData.length / 4 && state.get.aliceShouldPause == -1) {
- nextState
- .map(_.copy(aliceShouldPause = 0))
- .addTask { (tox, av, state) =>
- tox.fileControl(friendNumber, fileNumber, ToxFileControl.PAUSE)
- debug("pause file transmission")
- state
- }
- } else {
- nextState
- }
- }
- }
-
- override def fileRecvControl(
- friendNumber: ToxFriendNumber,
- fileNumber: Int,
- control: ToxFileControl
- )(state: ChatState): ChatState = {
- if (isAlice) {
- debug("receive file control from Bob")
- if (control == ToxFileControl.RESUME) {
- if (state.get.aliceShouldPause != 0) {
- debug("bob accept file transmission request")
- state
- } else {
- debug("see bob resume file transmission")
- state.map(_.copy(aliceShouldPause = 1))
- }
- } else if (control == ToxFileControl.PAUSE) {
- state.addTask { (tox, av, state) =>
- tox.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0,
- ToxFriendMessage.fromValue("Please resume the file transfer".getBytes).toOption.get)
- state.map(_.copy(aliceShouldPause = 0))
- }
- } else {
- state
- }
- } else {
- if (control == ToxFileControl.PAUSE) {
- debug("see alice pause file transmission")
- state.addTask { (tox, av, state) =>
- debug("request to resume file transmission")
- tox.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0,
- ToxFriendMessage.fromValue("Please resume the file transfer".getBytes).toOption.get)
- state
- }
- } else {
- state
- }
- }
- }
-
- override def fileRecvChunk(
- friendNumber: ToxFriendNumber,
- fileNumber: Int,
- position: Long,
- data: Array[Byte]
- )(state: ChatState): ChatState = {
- assert(isBob)
- debug(s"receive file chunk from position $position of length ${data.length} shouldPause ${state.get.bobShouldPause}")
- if (data.length == 0 && state.get.bobOffset == fileData.length) {
- assert(state.get.receivedData sameElements fileData)
- debug("finish transmission")
- state.finish
- } else {
- System.arraycopy(data, 0, state.get.receivedData, position.toInt, data.length)
- val nextState = state.map(state => state.copy(bobOffset = state.bobOffset + data.length))
- if (nextState.get.bobOffset >= fileData.length * 2 / 4 && nextState.get.bobShouldPause == -1) {
- nextState
- .map(_.copy(bobShouldPause = 0))
- .addTask { (tox, av, state) =>
- debug("send file control to pause")
- tox.fileControl(friendNumber, state.get.bobSentFileNumber, ToxFileControl.PAUSE)
- state
- }
- } else {
- nextState
- }
- }
- }
-
- override def friendMessage(
- friendNumber: ToxFriendNumber,
- messageType: ToxMessageType,
- timeDelta: Int,
- message: ToxFriendMessage
- )(state: ChatState): ChatState = {
- debug(s"received a message: ${new String(message.value)}")
- assert(new String(message.value) == "Please resume the file transfer")
- state.addTask { (tox, av, state) =>
- state.map(addFriendMessageTask(friendNumber, state.get.bobSentFileNumber, state.get.fileId, tox))
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithControlTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithControlTest.scala
deleted file mode 100644
index e0d852ce6..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithControlTest.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId }
-import im.tox.tox4j.core.enums.ToxFileControl
-
-final class FilePauseResumeWithControlTest extends FilePauseResumeTestBase {
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new Alice(name, expectedFriendName)
-
- final class Alice(name: String, expectedFriendName: String) extends super.Alice(name, expectedFriendName) {
-
- protected override def addFriendMessageTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- fileId: ToxFileId,
- tox: ToxCore
- )(state: State): State = {
- debug("send resume control")
- if (isBob) {
- tox.fileControl(friendNumber, bobSentFileNumber, ToxFileControl.RESUME)
- state.copy(bobShouldPause = 1)
- } else if (isAlice) {
- tox.fileControl(friendNumber, state.aliceSentFileNumber, ToxFileControl.RESUME)
- state.copy(aliceShouldPause = 1)
- } else {
- fail("Unexpected client (not Alice or Bob)")
- state
- }
- }
-
- protected override def addFileRecvTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- bobOffset: Long,
- tox: ToxCore
- )(state: State): State = {
- debug(s"sending control RESUME for $bobSentFileNumber")
- tox.fileControl(friendNumber, bobSentFileNumber, ToxFileControl.RESUME)
- state
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithResendTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithResendTest.scala
deleted file mode 100644
index e19b5ca93..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FilePauseResumeWithResendTest.scala
+++ /dev/null
@@ -1,52 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId, ToxFilename }
-import im.tox.tox4j.core.enums.{ ToxFileControl, ToxFileKind }
-
-final class FilePauseResumeWithResendTest extends FilePauseResumeTestBase {
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new Alice(name, expectedFriendName)
-
- final class Alice(name: String, expectedFriendName: String) extends super.Alice(name, expectedFriendName) {
-
- protected override def addFriendMessageTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- fileId: ToxFileId,
- tox: ToxCore
- )(state: State): State = {
- if (isAlice) {
- state.copy(
- aliceShouldPause = 1,
- aliceSentFileNumber = tox.fileSend(
- friendNumber,
- ToxFileKind.DATA,
- fileData.length,
- fileId,
- ToxFilename.fromValue(("file for " + expectedFriendName + ".png").getBytes).toOption.get
- )
- )
- } else {
- debug("Send resume file transmission control")
- tox.fileControl(friendNumber, bobSentFileNumber, ToxFileControl.RESUME)
- state
- }
- }
-
- protected override def addFileRecvTask(
- friendNumber: ToxFriendNumber,
- bobSentFileNumber: Int,
- bobOffset: Long,
- tox: ToxCore
- )(state: State): State = {
- debug(s"seek file to $bobOffset")
- tox.fileSeek(friendNumber, bobSentFileNumber, bobOffset)
- debug(s"sending control RESUME for $bobSentFileNumber")
- tox.fileControl(friendNumber, bobSentFileNumber, ToxFileControl.RESUME)
- state.copy(bobShouldPause = 1)
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FileRecvCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FileRecvCallbackTest.scala
deleted file mode 100644
index 5fab284c2..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FileRecvCallbackTest.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId, ToxFilename }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileKind }
-import im.tox.tox4j.core.{ ToxCore, ToxCoreConstants }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class FileRecvCallbackTest extends AliceBobTest {
-
- override type State = Seq[Byte]
- override def initialState: State = Nil
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def setup(tox: ToxCore)(state: ChatState): ChatState = {
- if (isAlice) {
- state.set("This is a file for Bob".getBytes)
- } else {
- state.set("This is a file for Alice".getBytes)
- }
- }
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- state.addTask { (tox, av, state) =>
- tox.fileSend(
- friendNumber,
- ToxFileKind.DATA,
- state.get.length,
- ToxFileId.empty,
- ToxFilename.fromValue(s"file for $expectedFriendName.png".getBytes).toOption.get
- )
- state
- }
- } else {
- state
- }
- }
-
- override def fileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: ToxFilename)(state: ChatState): ChatState = {
- debug(s"received file send request $fileNumber from friend number $friendNumber")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(fileNumber == (0 | 0x10000))
- assert(kind == ToxFileKind.DATA)
- if (isAlice) {
- assert(fileSize == "This is a file for Alice".length)
- } else {
- assert(fileSize == "This is a file for Bob".length)
- }
- assert(new String(filename.value) == s"file for $selfName.png")
- state.addTask { (tox, av, state) =>
- val fileId = tox.getFileFileId(friendNumber, fileNumber)
- assert(fileId.value != null)
- assert(fileId.value.length == ToxCoreConstants.FileIdLength)
- state.finish
- }
- }
- }
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FileResumeAfterRestartTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FileResumeAfterRestartTest.scala
deleted file mode 100644
index f78eb9402..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FileResumeAfterRestartTest.scala
+++ /dev/null
@@ -1,156 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import java.util.Random
-
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxFileKind }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-/**
- * This test intends to simulate the situation of resuming a file
- * transmission after deleting and re-adding a friend.
- * - Alice initiated the file transmission and Bob accepted
- * - Alice paused the file transmission after sending 1/10 of the file
- * and deleted Bob from the friend list
- * - Bob saw Alice went offline and sent a friend request to Alice
- * - Alice accepted the friend request and resumed the file transmission
- * - Bob received all the file data
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class FileResumeAfterRestartTest extends AliceBobTest {
-
- override type State = Unit
- override def initialState: State = ()
-
- private val fileData = new Array[Byte](13710)
- private var aliceAddress = ToxFriendAddress.unsafeFromValue(Array.empty)
- new Random().nextBytes(fileData)
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new Alice(name, expectedFriendName)
-
- final class Alice(name: String, expectedFriendName: String) extends ChatClient(name, expectedFriendName) {
-
- private var aliceOffset = 0L
- private var fileId = ToxFileId.empty
- private var aliceSentFileNumber = -1
- private var aliceShouldPause = -1
- private val receivedData = new Array[Byte](fileData.length)
- private var bobSentFileNumber = -1
- private var bobOffset = 0L
- private var selfPublicKey = ToxPublicKey.unsafeFromValue(Array.empty)
-
- override def friendRequest(publicKey: ToxPublicKey, timeDelta: Int, message: ToxFriendRequestMessage)(state: ChatState): ChatState = {
- assert(isAlice)
- state.addTask { (tox, av, state) =>
- debug("accept Bob's friend request")
- tox.addFriendNorequest(publicKey)
- aliceShouldPause = 1
- state
- }
- }
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connection: ToxConnection)(state: ChatState): ChatState = {
- if (isAlice) {
- if (connection != ToxConnection.NONE) {
- debug(s"is now connected to friend $friendNumber")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- debug(s"initiate file sending to friend $friendNumber")
- state.addTask { (tox, av, state) =>
- aliceSentFileNumber = tox.fileSend(
- friendNumber,
- ToxFileKind.DATA,
- fileData.length,
- ToxFileId.empty,
- ToxFilename.fromValue(s"file for $expectedFriendName.png".getBytes).toOption.get
- )
- fileId = tox.getFileFileId(friendNumber, aliceSentFileNumber)
- aliceAddress = tox.getAddress
- state
- }
- } else {
- state
- }
- } else {
- if (connection != ToxConnection.NONE) {
- debug(s"is now connected to friend $friendNumber")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- state
- } else {
- debug("See alice go off-line")
- state.addTask { (tox, av, state) =>
- tox.deleteFriend(friendNumber)
- tox.addFriend(aliceAddress, ToxFriendRequestMessage.fromValue("Please add me back".getBytes).toOption.get)
- state
- }
- }
- }
- }
-
- override def fileChunkRequest(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int)(state: ChatState): ChatState = {
- assert(isAlice)
- debug(s"got request for ${length}B from $friendNumber for file $fileNumber at $position")
- assert(length >= 0)
- if (length == 0) {
- aliceSentFileNumber = -1
- debug("finish transmission")
- state.finish
- } else {
- if (aliceShouldPause != 0) {
- val nextState = state.addTask { (tox, av, state) =>
- debug(s"sending $length B to $friendNumber from position $position")
- tox.fileSendChunk(friendNumber, fileNumber, position,
- fileData.slice(position.toInt, Math.min(position.toInt + length, fileData.length)))
- state
- }
- aliceOffset += length
- if (aliceOffset >= fileData.length / 10 && aliceShouldPause == -1) {
- aliceShouldPause = 0
- nextState.addTask { (tox, av, state) =>
- debug("pause file transmission")
- tox.fileControl(friendNumber, fileNumber, ToxFileControl.PAUSE)
- tox.deleteFriend(friendNumber)
- state
- }
- } else {
- nextState
- }
- } else {
- state
- }
- }
- }
-
- override def fileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: ToxFilename)(state: ChatState): ChatState = {
- assert(isBob)
- debug(s"received file send request $fileNumber from friend number $friendNumber current offset $bobOffset")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(kind == ToxFileKind.DATA)
- assert(new String(filename.value) == s"file for $name.png")
- bobSentFileNumber = fileNumber
- state.addTask { (tox, av, state) =>
- selfPublicKey = tox.getPublicKey
- debug(s"sending control RESUME for $fileNumber")
- debug(s"seek file to $bobOffset")
- tox.fileSeek(friendNumber, bobSentFileNumber, bobOffset)
- tox.fileControl(friendNumber, fileNumber, ToxFileControl.RESUME)
- state
- }
- }
-
- override def fileRecvChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: Array[Byte])(state: ChatState): ChatState = {
- assert(isBob)
- debug(s"receive file chunk from position $position of length ${data.length}")
- if (data.length == 0 && receivedData.length == bobOffset) {
- assert(receivedData sameElements fileData)
- debug("finish transmission")
- state.finish
- } else {
- System.arraycopy(data, 0, receivedData, position.toInt, data.length)
- bobOffset += data.length
- state
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FileTransferTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FileTransferTest.scala
deleted file mode 100644
index 1a777692f..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FileTransferTest.scala
+++ /dev/null
@@ -1,118 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import java.util.Random
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId, ToxFilename }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxFileControl, ToxFileKind }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class FileTransferTest extends AliceBobTest {
-
- private val fileData = new Array[Byte](1500)
- new Random().nextBytes(fileData)
-
- @SuppressWarnings(Array("org.wartremover.warts.ArrayEquals"))
- sealed case class State(
- receivedData: Array[Byte] = Array.ofDim[Byte](fileData.length),
- position: Long = 0L,
- sentFileNumber: Int = -1
- ) {
- def addData(position: Long, data: Array[Byte]): State = {
- assert(data.nonEmpty)
- val nextPosition = this.position + data.length
- assert(nextPosition <= this.receivedData.length)
- System.arraycopy(data, 0, this.receivedData, position.toInt, data.length)
- copy(position = nextPosition)
- }
- }
-
- override def initialState: State = State()
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new Alice(name, expectedFriendName)
-
- class Alice(name: String, expectedFriendName: String) extends ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE && isAlice) {
- state.addTask { (tox, av, state) =>
- val sentFileNumber = tox.fileSend(
- friendNumber,
- ToxFileKind.DATA,
- fileData.length,
- ToxFileId.empty,
- ToxFilename.fromValue(s"file for $expectedFriendName.png".getBytes).toOption.get
- )
- state.map(_.copy(sentFileNumber = sentFileNumber))
- }
- } else {
- state
- }
- }
-
- override def fileRecv(friendNumber: ToxFriendNumber, fileNumber: Int, kind: Int, fileSize: Long, filename: ToxFilename)(state: ChatState): ChatState = {
- debug(s"received file send request $fileNumber from friend number $friendNumber")
- assert(isBob)
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(fileNumber == (0 | 0x10000))
- assert(kind == ToxFileKind.DATA)
- assert(fileSize == fileData.length)
- assert(new String(filename.value) == s"file for $name.png")
- state.addTask { (tox, av, state) =>
- debug(s"sending control RESUME for $fileNumber")
- tox.fileControl(friendNumber, fileNumber, ToxFileControl.RESUME)
- state
- }
- }
-
- override def fileRecvControl(friendNumber: ToxFriendNumber, fileNumber: Int, control: ToxFileControl)(state: ChatState): ChatState = {
- debug(s"file control from $friendNumber for file $fileNumber: $control")
- assert(isAlice)
- state
- }
-
- override def fileChunkRequest(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, length: Int)(state: ChatState): ChatState = {
- debug(s"got request for ${length}B from $friendNumber for file $fileNumber at $position")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(isAlice)
- assert(position >= 0)
- assert(position < Int.MaxValue)
- assert(fileNumber == state.get.sentFileNumber)
- if (length == 0) {
- state.set(state.get.copy(sentFileNumber = -1)).finish
- } else {
- state.addTask { (tox, av, state) =>
- debug(s"sending ${length}B to $friendNumber")
- tox.fileSendChunk(
- friendNumber,
- fileNumber,
- position,
- fileData.slice(
- position.toInt,
- Math.min(position.toInt + length, fileData.length)
- )
- )
- state
- }
- }
- }
-
- override def fileRecvChunk(friendNumber: ToxFriendNumber, fileNumber: Int, position: Long, data: Array[Byte])(state: ChatState): ChatState = {
- debug(s"got ${data.length}B from $friendNumber at $position")
- assert(isBob)
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(fileNumber == (0 | 0x10000))
- assert(position == state.get.position)
- assert(data != null)
- if (state.get.position == state.get.receivedData.length) {
- assert(data.isEmpty)
- assert(state.get.receivedData sameElements fileData)
- state.finish
- } else {
- state.set(state.get.addData(position, data))
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendConnectionStatusCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendConnectionStatusCallbackTest.scala
deleted file mode 100644
index cc36d2b42..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendConnectionStatusCallbackTest.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-
-final class FriendConnectionStatusCallbackTest extends AutoTestSuite {
-
- type S = Unit
-
- object Handler extends EventListener(()) {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: State): State = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.finish
- } else {
- state
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendLosslessPacketCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendLosslessPacketCallbackTest.scala
deleted file mode 100644
index 9ab39c782..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendLosslessPacketCallbackTest.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxLosslessPacket }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendLosslessPacketCallbackTest extends AliceBobTest {
-
- override type State = Unit
- override def initialState: State = ()
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- val packet = s"_My name is $selfName".getBytes
- packet(0) = 160.toByte
- tox.friendSendLosslessPacket(friendNumber, ToxLosslessPacket.fromValue(packet).toOption.get)
- state
- }
- } else {
- state
- }
- }
-
- override def friendLosslessPacket(friendNumber: ToxFriendNumber, packet: ToxLosslessPacket)(state: ChatState): ChatState = {
- val message = new String(packet.value, 1, packet.value.length - 1)
- debug(s"received a lossless packet[id=${packet.value(0)}]: $message")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(packet.value(0) == 160.toByte)
- assert(message == s"My name is $expectedFriendName")
- state.finish
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendLossyPacketCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendLossyPacketCallbackTest.scala
deleted file mode 100644
index 6a4753351..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendLossyPacketCallbackTest.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxLossyPacket }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendLossyPacketCallbackTest extends AliceBobTest {
-
- override type State = Unit
- override def initialState: State = ()
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- val packet = s"_My name is $selfName".getBytes
- packet(0) = 200.toByte
- tox.friendSendLossyPacket(friendNumber, ToxLossyPacket.fromValue(packet).toOption.get)
- state
- }
- } else {
- state
- }
- }
-
- override def friendLossyPacket(friendNumber: ToxFriendNumber, packet: ToxLossyPacket)(state: ChatState): ChatState = {
- val message = new String(packet.value, 1, packet.value.length - 1)
- debug(s"received a lossy packet[id=${packet.value(0)}]: $message")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(packet.value(0) == 200.toByte)
- assert(message == s"My name is $expectedFriendName")
- state.finish
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendMessageCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendMessageCallbackTest.scala
deleted file mode 100644
index 0ca515fa2..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendMessageCallbackTest.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendMessage }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxMessageType }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendMessageCallbackTest extends AliceBobTest {
-
- override type State = Unit
- override def initialState: State = ()
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- tox.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0,
- ToxFriendMessage.fromValue(s"My name is $selfName".getBytes).toOption.get)
- state
- }
- } else {
- state
- }
- }
-
- override def friendMessage(
- friendNumber: ToxFriendNumber,
- newType: ToxMessageType,
- timeDelta: Int,
- message: ToxFriendMessage
- )(
- state: ChatState
- ): ChatState = {
- debug("received a message: " + new String(message.value))
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- assert(newType == ToxMessageType.NORMAL)
- assert(timeDelta >= 0)
- assert(new String(message.value) == s"My name is $expectedFriendName")
- state.finish
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendNameCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendNameCallbackTest.scala
deleted file mode 100644
index face4e339..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendNameCallbackTest.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxNickname }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendNameCallbackTest extends AliceBobTest {
-
- override type State = Int
- override def initialState: State = 0
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- tox.setName(ToxNickname.fromValue(selfName.getBytes).toOption.get)
- state
- }
- } else {
- state
- }
- }
-
- override def friendName(friendNumber: ToxFriendNumber, name: ToxNickname)(state: ChatState): ChatState = {
- debug(s"friend changed name to: ${new String(name.value)}")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
-
- state.get match {
- case 0 =>
- assert(name.value.isEmpty)
- state.set(1)
- case 1 =>
- assert(new String(name.value) == expectedFriendName)
- state.finish
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendReadReceiptCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendReadReceiptCallbackTest.scala
deleted file mode 100644
index 046ff4a25..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendReadReceiptCallbackTest.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.TestConstants.Iterations
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendMessage }
-import im.tox.tox4j.core.enums.{ ToxConnection, ToxMessageType }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendReadReceiptCallbackTest extends AliceBobTest {
-
- protected override def ignoreTimeout = true
-
- override type State = Set[Int]
- override def initialState: State = Set.empty[Int]
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- debug(s"Sending $Iterations messages")
- assert(state.get.isEmpty)
- val pendingIds = (0 until Iterations).foldLeft(state.get) {
- case (receipts, i) =>
- val receipt = tox.friendSendMessage(
- friendNumber, ToxMessageType.NORMAL, 0,
- ToxFriendMessage.fromString(String.valueOf(i)).toOption.get
- )
- assert(!receipts.contains(receipt))
- receipts + receipt
- }
- assert(pendingIds.size == Iterations)
- state.set(pendingIds)
- }
- } else {
- state
- }
- }
-
- override def friendReadReceipt(friendNumber: ToxFriendNumber, messageId: Int)(state: ChatState): ChatState = {
- assert(friendNumber == AliceBobTestBase.FriendNumber)
-
- assert(state.get.contains(messageId))
- val pendingIds = state.get - messageId
- if (pendingIds.isEmpty) {
- state.finish
- } else {
- state.set(pendingIds)
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendRequestCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendRequestCallbackTest.scala
deleted file mode 100644
index 21e310f76..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendRequestCallbackTest.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendRequestMessage, ToxPublicKey }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendRequestCallbackTest extends AliceBobTest {
-
- override type State = Unit
- override def initialState: State = ()
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def setup(tox: ToxCore)(state: ChatState): ChatState = {
- tox.deleteFriend(AliceBobTestBase.FriendNumber)
- if (isAlice) {
- tox.addFriend(expectedFriendAddress, ToxFriendRequestMessage.fromString(s"Hey this is $selfName").toOption.get)
- }
- state
- }
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.finish
- } else {
- state
- }
- }
-
- override def friendRequest(publicKey: ToxPublicKey, timeDelta: Int, message: ToxFriendRequestMessage)(state: ChatState): ChatState = {
- debug(s"got friend request: ${new String(message.value)}")
- assert(isBob, "Alice shouldn't get a friend request")
- assert(publicKey.value sameElements expectedFriendPublicKey.value)
- assert(timeDelta >= 0)
- assert(new String(message.value) == s"Hey this is $expectedFriendName")
- state.addTask { (tox, av, state) =>
- tox.addFriendNorequest(publicKey)
- state
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusCallbackTest.scala
deleted file mode 100644
index 13150070e..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusCallbackTest.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxUserStatus
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-
-final class FriendStatusCallbackTest extends AutoTestSuite {
-
- type S = ToxUserStatus
-
- object Handler extends EventListener(ToxUserStatus.NONE) {
-
- private def go(status: ToxUserStatus)(state: State): State = {
- state.addTask { (tox, av, state) =>
- tox.setStatus(status)
- state.put(status)
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override def friendStatus(friendNumber: ToxFriendNumber, status: ToxUserStatus)(state: State): State = {
- debug(state, s"friend changed status to: $status")
-
- val isAlice = state.friendList(friendNumber) == state.id.next
- val isBob = state.friendList(friendNumber) == state.id.prev
-
- state.get match {
- case ToxUserStatus.NONE =>
- if (isAlice) {
- assert(status == ToxUserStatus.NONE)
- go(ToxUserStatus.AWAY)(state)
- } else {
- if (status != ToxUserStatus.NONE) {
- assert(status == ToxUserStatus.AWAY)
- go(ToxUserStatus.BUSY)(state)
- } else {
- state
- }
- }
-
- case selfStatus =>
- if (isAlice && selfStatus == ToxUserStatus.AWAY) {
- assert(status == ToxUserStatus.BUSY)
- go(ToxUserStatus.NONE)(state)
- .finish
- } else if (isBob && selfStatus == ToxUserStatus.BUSY) {
- assert(status == ToxUserStatus.NONE)
- state.finish
- } else {
- state
- }
- }
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusMessageCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusMessageCallbackTest.scala
deleted file mode 100644
index 8eb3e2b95..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendStatusMessageCallbackTest.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxStatusMessage }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class FriendStatusMessageCallbackTest extends AliceBobTest {
-
- override type State = Int
- override def initialState: State = 0
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connectionStatus: ToxConnection)(state: ChatState): ChatState = {
- super.friendConnectionStatus(friendNumber, connectionStatus)(state)
- if (connectionStatus != ToxConnection.NONE) {
- state.addTask { (tox, av, state) =>
- tox.setStatusMessage(ToxStatusMessage.fromString(s"I like $expectedFriendName").toOption.get)
- state
- }
- } else {
- state
- }
- }
-
- override def friendStatusMessage(friendNumber: ToxFriendNumber, message: ToxStatusMessage)(state: ChatState): ChatState = {
- debug(s"friend changed status message to: ${new String(message.value)}")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
-
- state.get match {
- case 0 =>
- assert(message.value.isEmpty)
- state.set(1)
- case 1 =>
- assert(new String(message.value) == s"I like $selfName")
- state.finish
- }
- }
- }
-
-}
-
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/FriendTypingCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/FriendTypingCallbackTest.scala
deleted file mode 100644
index 704b0cea7..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/FriendTypingCallbackTest.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-
-final class FriendTypingCallbackTest extends AutoTestSuite {
-
- type S = Map[ToxFriendNumber, Boolean]
-
- object Handler extends EventListener(Map.empty) {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override def friendTyping(friendNumber: ToxFriendNumber, isTyping: Boolean)(state0: State): State = {
- debug(state0, s"friend ${state0.id(friendNumber)} typing state: $isTyping")
- val state = state0.modify(_ + (friendNumber -> isTyping))
- state0.get.get(friendNumber) match {
- case None =>
- assert(!isTyping)
- state.addTask { (tox, av, state) =>
- if (state.id(friendNumber) == state.id.next) {
- debug(state, s"we start typing to ${state.id(friendNumber)}")
- tox.setTyping(friendNumber, typing = true)
- }
- state
- }
-
- case Some(false) =>
- assert(isTyping)
- if (state.id(friendNumber) == state.id.prev) {
- // id-1 started typing to us, now we also start typing to them.
- state.addTask { (tox, av, state) =>
- debug(state, s"we start typing back to ${state.id(friendNumber)}")
- tox.setTyping(friendNumber, typing = true)
- state
- }
- } else {
- assert(state.id(friendNumber) == state.id.next)
- // id+1 started typing back, so we stop typing.
- state.addTask { (tox, av, state) =>
- debug(state, s"we stop typing to ${state.id(friendNumber)}")
- tox.setTyping(friendNumber, typing = false)
- state
- }
- }
-
- case Some(true) =>
- assert(!isTyping)
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- debug(state, s"we also stop typing to ${state.id(friendNumber)}")
- tox.setTyping(friendNumber, typing = false)
- state.finish
- }
- } else {
- assert(state.id(friendNumber) == state.id.next)
- state.finish
- }
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/InvokeTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/InvokeTest.scala
deleted file mode 100644
index 5a4ffd5d1..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/InvokeTest.scala
+++ /dev/null
@@ -1,62 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.core.typesafe.Equals._
-import scala.language.implicitConversions
-
-@SuppressWarnings(Array(
- "org.wartremover.warts.Equals",
- "org.wartremover.warts.ImplicitConversion"
-))
-object InvokeTest {
-
- final case class ByteArray(private val array: Array[Byte]) {
- override def equals(rhs: Any): Boolean = {
- rhs match {
- case rhs: ByteArray => this.array.deep == rhs.array.deep
- case _ => false
- }
- }
-
- override def toString: String = {
- this.array.deep.toString()
- }
-
- override def hashCode: Int = {
- this.array.deep.hashCode()
- }
- }
-
- implicit def wrapByteArray(array: Array[Byte]): ByteArray = {
- if (array === null) {
- null
- } else {
- ByteArray(array)
- }
- }
-
- final case class ShortArray(private val array: Array[Short]) {
- override def equals(rhs: Any): Boolean = {
- rhs match {
- case rhs: ShortArray => this.array.deep == rhs.array.deep
- case _ => false
- }
- }
-
- override def toString: String = {
- this.array.deep.toString()
- }
-
- override def hashCode: Int = {
- this.array.deep.hashCode()
- }
- }
-
- implicit def wrapShortArray(array: Array[Short]): ShortArray = {
- if (array === null) {
- null
- } else {
- ShortArray(array)
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/NameEmptyTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/NameEmptyTest.scala
deleted file mode 100644
index 2ae4a6947..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/NameEmptyTest.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxNickname }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class NameEmptyTest extends AliceBobTest {
-
- override type State = Int
- override def initialState: State = 0
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override def friendName(friendNumber: ToxFriendNumber, name: ToxNickname)(state: ChatState): ChatState = {
- debug("friend changed name to: " + new String(name.value))
- assert(friendNumber == AliceBobTestBase.FriendNumber)
-
- state.get match {
- case 0 =>
- // Initial empty name
- assert(name.value.isEmpty)
-
- state.addTask { (tox, av, state) =>
- tox.setName(ToxNickname.fromString("One").toOption.get)
- state
- }.set(1)
-
- case 1 =>
- assert(new String(name.value) == "One")
-
- state.addTask { (tox, av, state) =>
- tox.setName(ToxNickname.fromString("").toOption.get)
- state
- }.set(2)
-
- case 2 =>
- assert(name.value.isEmpty)
- state.finish
- }
- }
-
- }
-
-}
-
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/SelfConnectionStatusCallbackTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/SelfConnectionStatusCallbackTest.scala
deleted file mode 100644
index e4c9a54d5..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/SelfConnectionStatusCallbackTest.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-
-final class SelfConnectionStatusCallbackTest extends AutoTestSuite {
-
- type S = ToxConnection
-
- object Handler extends EventListener(ToxConnection.NONE) {
-
- override def selfConnectionStatus(connection: ToxConnection)(state: State): State = {
- state.finish
- }
-
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/StatusMessageEmptyTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/StatusMessageEmptyTest.scala
deleted file mode 100644
index cb9e5bdc0..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/StatusMessageEmptyTest.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxStatusMessage }
-import im.tox.tox4j.testing.autotest.{ AliceBobTest, AliceBobTestBase }
-
-final class StatusMessageEmptyTest extends AliceBobTest {
-
- override type State = Int
- override def initialState: State = 0
-
- protected override def newChatClient(name: String, expectedFriendName: String) = new ChatClient(name, expectedFriendName) {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override def friendStatusMessage(friendNumber: ToxFriendNumber, message: ToxStatusMessage)(state: ChatState): ChatState = {
- debug(s"friend changed status message to: ${new String(message.value)}")
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- state.get match {
- case 0 =>
- val nextState = state.set(1)
- assert(message.value.isEmpty)
- if (isAlice) {
- nextState.addTask { (tox, av, state) =>
- tox.setStatusMessage(ToxStatusMessage.fromString("One").toOption.get)
- state
- }
- } else {
- nextState
- }
-
- case 1 =>
- val nextState = state.set(2)
- if (isAlice) {
- assert(new String(message.value) == "Two")
- nextState.addTask { (tox, av, state) =>
- tox.setStatusMessage(ToxStatusMessage.fromString("").toOption.get)
- state
- }
- } else {
- assert(new String(message.value) == "One")
- nextState.addTask { (tox, av, state) =>
- tox.setStatusMessage(ToxStatusMessage.fromString("Two").toOption.get)
- state
- }
- }
-
- case 2 =>
- val nextState = state.finish
- assert(message.value.isEmpty)
- if (isBob) {
- nextState.addTask { (tox, av, state) =>
- tox.setStatusMessage(ToxStatusMessage.fromString("").toOption.get)
- state
- }
- } else {
- nextState
- }
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/callbacks/ToxCoreEventAdapterTest.scala b/src/test/java/im/tox/tox4j/core/callbacks/ToxCoreEventAdapterTest.scala
deleted file mode 100644
index fc5330cb7..000000000
--- a/src/test/java/im/tox/tox4j/core/callbacks/ToxCoreEventAdapterTest.scala
+++ /dev/null
@@ -1,82 +0,0 @@
-package im.tox.tox4j.core.callbacks
-
-import im.tox.tox4j.core.data._
-import im.tox.tox4j.core.enums._
-import im.tox.tox4j.core.proto._
-import im.tox.tox4j.testing.GetDisjunction._
-import org.scalatest.FunSuite
-
-final class ToxCoreEventAdapterTest extends FunSuite {
-
- private val listener = new ToxCoreEventAdapter[Unit]
- private val friendNumber = ToxFriendNumber.fromInt(0).get
-
- def test[T](f: => Unit)(implicit evidence: Manifest[T]): Unit = {
- test(evidence.runtimeClass.getSimpleName)(f)
- }
-
- test[SelfConnectionStatus] {
- listener.selfConnectionStatus(ToxConnection.NONE)(())
- }
-
- test[FileRecvControl] {
- listener.fileRecvControl(friendNumber, 0, ToxFileControl.RESUME)(())
- }
-
- test[FileRecv] {
- listener.fileRecv(friendNumber, 0, ToxFileKind.DATA, 0, ToxFilename.fromString("").toOption.get)(())
- }
-
- test[FileRecvChunk] {
- listener.fileRecvChunk(friendNumber, 0, 0, Array.empty)(())
- }
-
- test[FileChunkRequest] {
- listener.fileChunkRequest(friendNumber, 0, 0, 0)(())
- }
-
- test[FriendConnectionStatus] {
- listener.friendConnectionStatus(friendNumber, ToxConnection.NONE)(())
- }
-
- test[FriendMessage] {
- listener.friendMessage(friendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.fromString("hello").toOption.get)(())
- }
-
- test[FriendName] {
- listener.friendName(friendNumber, ToxNickname.fromString("").toOption.get)(())
- }
-
- test[FriendRequest] {
- listener.friendRequest(
- ToxPublicKey.unsafeFromValue(null),
- 0,
- ToxFriendRequestMessage.fromString("").toOption.get
- )(())
- }
-
- test[FriendStatus] {
- listener.friendStatus(friendNumber, ToxUserStatus.NONE)(())
- }
-
- test[FriendStatusMessage] {
- listener.friendStatusMessage(friendNumber, ToxStatusMessage.fromString("").toOption.get)(())
- }
-
- test[FriendTyping] {
- listener.friendTyping(friendNumber, isTyping = false)(())
- }
-
- test[FriendLosslessPacket] {
- listener.friendLosslessPacket(friendNumber, ToxLosslessPacket.fromByteArray(160, Array.empty).toOption.get)(())
- }
-
- test[FriendLossyPacket] {
- listener.friendLossyPacket(friendNumber, ToxLossyPacket.fromByteArray(200, Array.empty).toOption.get)(())
- }
-
- test[FriendReadReceipt] {
- listener.friendReadReceipt(friendNumber, 0)(())
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxBootstrapExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxBootstrapExceptionTest.scala
deleted file mode 100644
index 981e2fdee..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxBootstrapExceptionTest.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.core.network.Port
-import im.tox.tox4j.core.ToxCoreConstants
-import im.tox.tox4j.core.data.ToxPublicKey
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxBootstrapExceptionTest extends FunSuite with ToxTestMixin {
-
- private val host = "192.254.75.98"
- private val publicKey = ToxPublicKey.fromValue(Array.ofDim(ToxCoreConstants.PublicKeySize)).toOption.get
- private val port = Port.fromInt(ToxCoreConstants.DefaultStartPort).get
-
- test("BootstrapBadPort1") {
- interceptWithTox(ToxBootstrapException.Code.BAD_PORT)(
- _.bootstrap(
- host,
- Port.unsafeFromInt(0),
- publicKey
- )
- )
- }
-
- test("BootstrapBadPort2") {
- interceptWithTox(ToxBootstrapException.Code.BAD_PORT)(
- _.bootstrap(
- host,
- Port.unsafeFromInt(-10),
- publicKey
- )
- )
- }
-
- test("BootstrapBadPort3") {
- interceptWithTox(ToxBootstrapException.Code.BAD_PORT)(
- _.bootstrap(
- host,
- Port.unsafeFromInt(65536),
- publicKey
- )
- )
- }
-
- test("BootstrapBadHost") {
- interceptWithTox(ToxBootstrapException.Code.BAD_HOST)(
- _.bootstrap(
- ".",
- port,
- publicKey
- )
- )
- }
-
- test("BootstrapNullHost") {
- interceptWithTox(ToxBootstrapException.Code.NULL)(
- _.bootstrap(
- null,
- port,
- publicKey
- )
- )
- }
-
- test("BootstrapNullKey") {
- interceptWithTox(ToxBootstrapException.Code.NULL)(
- _.bootstrap(
- host,
- port,
- ToxPublicKey.unsafeFromValue(null)
- )
- )
- }
-
- test("BootstrapKeyTooShort") {
- interceptWithTox(ToxBootstrapException.Code.BAD_KEY)(
- _.bootstrap(
- host,
- port,
- ToxPublicKey.unsafeFromValue(Array.ofDim(ToxCoreConstants.PublicKeySize - 1))
- )
- )
- }
-
- test("BootstrapKeyTooLong") {
- interceptWithTox(ToxBootstrapException.Code.BAD_KEY)(
- _.bootstrap(
- host,
- port,
- ToxPublicKey.unsafeFromValue(Array.ofDim(ToxCoreConstants.PublicKeySize + 1))
- )
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFileSendExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFileSendExceptionTest.scala
deleted file mode 100644
index 100c1ba70..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFileSendExceptionTest.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.ToxCoreConstants
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFileId, ToxFilename }
-import im.tox.tox4j.core.enums.ToxFileKind
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFileSendExceptionTest extends FunSuite with ToxTestMixin {
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
- private val badFriendNumber = ToxFriendNumber.fromInt(1).get
-
- test("FileSendNotConnected") {
- interceptWithTox(ToxFileSendException.Code.FRIEND_NOT_CONNECTED)(
- _.fileSend(friendNumber, ToxFileKind.DATA, 123, ToxFileId.empty,
- ToxFilename.fromString("filename").toOption.get)
- )
- }
-
- test("FileSendNotFound") {
- interceptWithTox(ToxFileSendException.Code.FRIEND_NOT_FOUND)(
- _.fileSend(badFriendNumber, ToxFileKind.DATA, 123, ToxFileId.empty,
- ToxFilename.fromString("filename").toOption.get)
- )
- }
-
- test("FileSendNameTooLong") {
- interceptWithTox(ToxFileSendException.Code.NAME_TOO_LONG)(
- _.fileSend(friendNumber, ToxFileKind.DATA, 123, ToxFileId.empty,
- ToxFilename.unsafeFromValue(Array.ofDim(ToxCoreConstants.MaxFilenameLength + 1)))
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendAddExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendAddExceptionTest.scala
deleted file mode 100644
index 431f783ad..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendAddExceptionTest.scala
+++ /dev/null
@@ -1,139 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.data.{ ToxFriendAddress, ToxFriendRequestMessage }
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendAddExceptionTest extends FunSuite with ToxTestMixin {
-
- private val validAddress = ToxCoreImplFactory.withToxUnit(_.getAddress)
-
- test("InvalidAddress1") {
- intercept[IllegalArgumentException] {
- ToxCoreImplFactory.withToxUnit(
- _.addFriend(
- ToxFriendAddress.unsafeFromValue(Array.ofDim(1)),
- ToxFriendRequestMessage.fromValue(Array.ofDim(1)).toOption.get
- )
- )
- }
- }
-
- test("InvalidAddress2") {
- intercept[IllegalArgumentException] {
- ToxCoreImplFactory.withToxUnit(
- _.addFriend(
- ToxFriendAddress.unsafeFromValue(Array.ofDim(ToxCoreConstants.AddressSize - 1)),
- ToxFriendRequestMessage.fromValue(Array.ofDim(1)).toOption.get
- )
- )
- }
- }
-
- test("InvalidAddress3") {
- intercept[IllegalArgumentException] {
- ToxCoreImplFactory.withToxUnit(
- _.addFriend(
- ToxFriendAddress.unsafeFromValue(Array.ofDim(ToxCoreConstants.AddressSize + 1)),
- ToxFriendRequestMessage.fromValue(Array.ofDim(1)).toOption.get
- )
- )
- }
- }
-
- test("Null1") {
- interceptWithTox(ToxFriendAddException.Code.NULL)(
- _.addFriend(
- ToxFriendAddress.unsafeFromValue(null),
- ToxFriendRequestMessage.fromValue(Array.ofDim(1)).toOption.get
- )
- )
- }
-
- test("Null2") {
- interceptWithTox(ToxFriendAddException.Code.NULL)(
- _.addFriend(validAddress, ToxFriendRequestMessage.unsafeFromValue(null))
- )
- }
-
- test("Not_TooLong1") {
- ToxCoreImplFactory.withToxUnit(
- _.addFriend(
- validAddress,
- ToxFriendRequestMessage.fromValue(Array.ofDim(ToxCoreConstants.MaxFriendRequestLength - 1)).toOption.get
- )
- )
- }
-
- test("Not_TooLong2") {
- ToxCoreImplFactory.withToxUnit(
- _.addFriend(
- validAddress,
- ToxFriendRequestMessage.fromValue(Array.ofDim(ToxCoreConstants.MaxFriendRequestLength)).toOption.get
- )
- )
- }
-
- test("TooLong") {
- interceptWithTox(ToxFriendAddException.Code.TOO_LONG)(
- _.addFriend(
- validAddress,
- ToxFriendRequestMessage.unsafeFromValue(Array.ofDim(ToxCoreConstants.MaxFriendRequestLength + 1))
- )
- )
- }
-
- test("NoMessage") {
- interceptWithTox(ToxFriendAddException.Code.NO_MESSAGE)(
- _.addFriend(
- validAddress,
- ToxFriendRequestMessage.fromString("").toOption.get
- )
- )
- }
-
- test("OwnKey") {
- interceptWithTox(ToxFriendAddException.Code.OWN_KEY) { tox =>
- tox.addFriend(
- tox.getAddress,
- ToxFriendRequestMessage.fromString("hello").toOption.get
- )
- }
- }
-
- test("AlreadySent") {
- interceptWithTox(ToxFriendAddException.Code.ALREADY_SENT) { tox =>
- tox.addFriend(
- validAddress,
- ToxFriendRequestMessage.fromString("hello").toOption.get
- )
- tox.addFriend(
- validAddress,
- ToxFriendRequestMessage.fromString("hello").toOption.get
- )
- }
- }
-
- test("BadChecksum") {
- interceptWithTox(ToxFriendAddException.Code.BAD_CHECKSUM)(
- _.addFriend(
- ToxFriendAddress.unsafeFromValue(validAddress.value.updated(0, (validAddress.value(0) + 1).toByte)),
- ToxFriendRequestMessage.fromString("hello").toOption.get
- )
- )
- }
-
- test("SetNewNospam") {
- interceptWithTox(ToxFriendAddException.Code.SET_NEW_NOSPAM) { tox =>
- ToxCoreImplFactory.withToxUnit { friend =>
- friend.setNospam(12345678)
- tox.addFriend(friend.getAddress, ToxFriendRequestMessage.fromString("hello").toOption.get)
- friend.setNospam(87654321)
- tox.addFriend(friend.getAddress, ToxFriendRequestMessage.fromString("hello").toOption.get)
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendByPublicKeyExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendByPublicKeyExceptionTest.scala
deleted file mode 100644
index 933e4974c..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendByPublicKeyExceptionTest.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.data.ToxPublicKey
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendByPublicKeyExceptionTest extends FunSuite with ToxTestMixin {
-
- test("Null") {
- interceptWithTox(ToxFriendByPublicKeyException.Code.NULL)(
- _.friendByPublicKey(ToxPublicKey.unsafeFromValue(null))
- )
- }
-
- test("NotFound") {
- interceptWithTox(ToxFriendByPublicKeyException.Code.NOT_FOUND) { tox =>
- tox.friendByPublicKey(tox.getPublicKey)
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendCustomPacketExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendCustomPacketExceptionTest.scala
deleted file mode 100644
index 3cbf05907..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendCustomPacketExceptionTest.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.ToxCoreConstants
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxLosslessPacket, ToxLossyPacket }
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendCustomPacketExceptionTest extends FunSuite with ToxTestMixin {
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
- private val badFriendNumber = ToxFriendNumber.fromInt(1).get
-
- test("SendLosslessPacketNotConnected") {
- interceptWithTox(ToxFriendCustomPacketException.Code.FRIEND_NOT_CONNECTED)(
- _.friendSendLosslessPacket(friendNumber, ToxLosslessPacket.fromValue(Array[Byte](160.toByte, 0, 1, 2, 3)).toOption.get)
- )
- }
-
- test("SendLossyPacketNotConnected") {
- interceptWithTox(ToxFriendCustomPacketException.Code.FRIEND_NOT_CONNECTED)(
- _.friendSendLossyPacket(friendNumber, ToxLossyPacket.fromValue(200.toByte +: Array.ofDim[Byte](4)).toOption.get)
- )
- }
-
- test("SendLosslessPacketNotFound") {
- interceptWithTox(ToxFriendCustomPacketException.Code.FRIEND_NOT_FOUND)(
- _.friendSendLosslessPacket(badFriendNumber, ToxLosslessPacket.fromValue(Array[Byte](160.toByte, 0, 1, 2, 3)).toOption.get)
- )
- }
-
- test("SendLossyPacketNotFound") {
- interceptWithTox(ToxFriendCustomPacketException.Code.FRIEND_NOT_FOUND)(
- _.friendSendLossyPacket(badFriendNumber, ToxLossyPacket.fromValue(Array[Byte](200.toByte, 0, 1, 2, 3)).toOption.get)
- )
- }
-
- test("SendLosslessPacketInvalid") {
- interceptWithTox(ToxFriendCustomPacketException.Code.INVALID)(
- _.friendSendLosslessPacket(friendNumber, ToxLosslessPacket.unsafeFromValue(Array[Byte](100.toByte)))
- )
- }
-
- test("SendLossyPacketInvalid") {
- interceptWithTox(ToxFriendCustomPacketException.Code.INVALID)(
- _.friendSendLossyPacket(friendNumber, ToxLossyPacket.unsafeFromValue(Array[Byte](100.toByte)))
- )
- }
-
- test("SendLosslessPacketEmpty") {
- interceptWithTox(ToxFriendCustomPacketException.Code.EMPTY)(
- _.friendSendLosslessPacket(friendNumber, ToxLosslessPacket.unsafeFromValue(Array[Byte]()))
- )
- }
-
- test("SendLossyPacketEmpty") {
- interceptWithTox(ToxFriendCustomPacketException.Code.EMPTY)(
- _.friendSendLossyPacket(friendNumber, ToxLossyPacket.unsafeFromValue(Array[Byte]()))
- )
- }
-
- test("SendLosslessPacketNull") {
- interceptWithTox(ToxFriendCustomPacketException.Code.NULL)(
- _.friendSendLosslessPacket(friendNumber, ToxLosslessPacket.unsafeFromValue(null))
- )
- }
-
- test("SendLossyPacketNull") {
- interceptWithTox(ToxFriendCustomPacketException.Code.NULL)(
- _.friendSendLossyPacket(friendNumber, ToxLossyPacket.unsafeFromValue(null))
- )
- }
-
- test("SendLosslessPacketTooLong") {
- interceptWithTox(ToxFriendCustomPacketException.Code.TOO_LONG)(
- _.friendSendLosslessPacket(
- friendNumber,
- ToxLosslessPacket.unsafeFromValue(160.toByte +: Array.ofDim[Byte](ToxCoreConstants.MaxCustomPacketSize))
- )
- )
- }
-
- test("SendLossyPacketTooLong") {
- interceptWithTox(ToxFriendCustomPacketException.Code.TOO_LONG)(
- _.friendSendLossyPacket(
- friendNumber,
- ToxLossyPacket.unsafeFromValue(200.toByte +: Array.ofDim[Byte](ToxCoreConstants.MaxCustomPacketSize))
- )
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendDeleteExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendDeleteExceptionTest.scala
deleted file mode 100644
index 5c3642481..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendDeleteExceptionTest.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendDeleteExceptionTest extends FunSuite with ToxTestMixin {
-
- test("DeleteFriendTwice") {
- interceptWithTox(ToxFriendDeleteException.Code.FRIEND_NOT_FOUND) { tox =>
- addFriends(tox, 4)
- assert(tox.getFriendList sameElements Array(0, 1, 2, 3, 4))
- tox.deleteFriend(ToxFriendNumber.fromInt(2).get)
- assert(tox.getFriendList sameElements Array(0, 1, 3, 4))
- tox.deleteFriend(ToxFriendNumber.fromInt(2).get)
- }
- }
-
- test("DeleteNonExistentFriend") {
- interceptWithTox(ToxFriendDeleteException.Code.FRIEND_NOT_FOUND)(
- _.deleteFriend(ToxFriendNumber.fromInt(1).get)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendGetPublicKeyExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendGetPublicKeyExceptionTest.scala
deleted file mode 100644
index aeeeef800..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendGetPublicKeyExceptionTest.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendGetPublicKeyExceptionTest extends FunSuite with ToxTestMixin {
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
- private val badFriendNumber = ToxFriendNumber.fromInt(1).get
-
- test("FriendNotFound") {
- interceptWithTox(ToxFriendGetPublicKeyException.Code.FRIEND_NOT_FOUND)(
- _.getFriendPublicKey(badFriendNumber)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendSendMessageExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendSendMessageExceptionTest.scala
deleted file mode 100644
index dccd2ba1b..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxFriendSendMessageExceptionTest.scala
+++ /dev/null
@@ -1,37 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendMessage }
-import im.tox.tox4j.core.enums.ToxMessageType
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxFriendSendMessageExceptionTest extends FunSuite with ToxTestMixin {
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
- private val badFriendNumber = ToxFriendNumber.fromInt(1).get
-
- test("SendMessageNotFound") {
- interceptWithTox(ToxFriendSendMessageException.Code.FRIEND_NOT_FOUND)(
- _.friendSendMessage(badFriendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.fromString("hello").toOption.get)
- )
- }
-
- test("SendMessageNotConnected") {
- interceptWithTox(ToxFriendSendMessageException.Code.FRIEND_NOT_CONNECTED)(
- _.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.fromString("hello").toOption.get)
- )
- }
-
- test("SendMessageNull") {
- interceptWithTox(ToxFriendSendMessageException.Code.NULL)(
- _.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.unsafeFromValue(null))
- )
- }
-
- test("SendMessageEmpty") {
- interceptWithTox(ToxFriendSendMessageException.Code.EMPTY)(
- _.friendSendMessage(friendNumber, ToxMessageType.NORMAL, 0, ToxFriendMessage.unsafeFromValue("".getBytes))
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxGetPortExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxGetPortExceptionTest.scala
deleted file mode 100644
index 687787460..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxGetPortExceptionTest.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxGetPortExceptionTest extends FunSuite with ToxTestMixin {
-
- test("GetTcpPort_NotBound") {
- interceptWithTox(ToxGetPortException.Code.NOT_BOUND)(
- _.getTcpPort
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxNewExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxNewExceptionTest.scala
deleted file mode 100644
index a03f1bcf0..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxNewExceptionTest.scala
+++ /dev/null
@@ -1,71 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.options.{ ProxyOptions, SaveDataOptions }
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.{ withToxUnit, withToxes }
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxNewExceptionTest extends FunSuite with ToxTestMixin {
-
- test("ToxNewProxyNull") {
- intercept(ToxNewException.Code.PROXY_BAD_HOST) {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5(null, 1)) { _ => }
- }
- }
-
- test("ToxNewProxyEmpty") {
- intercept(ToxNewException.Code.PROXY_BAD_HOST) {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5("", 1)) { _ => }
- }
- }
-
- test("ToxNewProxyBadPort0") {
- intercept(ToxNewException.Code.PROXY_BAD_PORT) {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5("localhost", 0)) { _ => }
- }
- }
-
- test("ToxNewProxyBadPortNegative") {
- intercept[IllegalArgumentException] {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5("localhost", -10)) { _ => }
- }
- }
-
- test("ToxNewProxyBadPortTooLarge") {
- intercept[IllegalArgumentException] {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5("localhost", 0x10000)) { _ => }
- }
- }
-
- test("ToxNewProxyBadAddress1") {
- intercept(ToxNewException.Code.PROXY_BAD_HOST) {
- val host = "\u2639" // scalastyle:ignore non.ascii.character.disallowed
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5(host, 1)) { _ => }
- }
- }
-
- test("ToxNewProxyBadAddress2") {
- intercept(ToxNewException.Code.PROXY_BAD_HOST) {
- withToxUnit(ipv6Enabled = true, udpEnabled = true, new ProxyOptions.Socks5(".", 1)) { _ => }
- }
- }
-
- test("TooManyToxCreations") {
- intercept(ToxNewException.Code.PORT_ALLOC) {
- withToxes(102) { _ => }
- }
- }
-
- test("LoadEncrypted") {
- intercept(ToxNewException.Code.LOAD_ENCRYPTED) {
- withToxUnit(SaveDataOptions.ToxSave("toxEsave blah blah blah".getBytes)) { _ => }
- }
- }
-
- test("LoadBadFormat") {
- intercept(ToxNewException.Code.LOAD_BAD_FORMAT) {
- withToxUnit(SaveDataOptions.ToxSave("blah blah blah".getBytes)) { _ => }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxSetInfoExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxSetInfoExceptionTest.scala
deleted file mode 100644
index 4209db59c..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxSetInfoExceptionTest.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.ToxCoreTestBase
-import im.tox.tox4j.core.ToxCoreConstants
-import im.tox.tox4j.core.data.{ ToxNickname, ToxStatusMessage }
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxSetInfoExceptionTest extends FunSuite with ToxTestMixin {
-
- test("SetNameTooLong") {
- val array = ToxCoreTestBase.randomBytes(ToxCoreConstants.MaxNameLength + 1)
-
- interceptWithTox(ToxSetInfoException.Code.TOO_LONG)(
- _.setName(ToxNickname.unsafeFromValue(array))
- )
- }
-
- test("SetStatusMessageTooLong") {
- val array = ToxCoreTestBase.randomBytes(ToxCoreConstants.MaxStatusMessageLength + 1)
-
- interceptWithTox(ToxSetInfoException.Code.TOO_LONG)(
- _.setStatusMessage(ToxStatusMessage.unsafeFromValue(array))
- )
- }
-
- test("SetNameNull") {
- interceptWithTox(ToxSetInfoException.Code.NULL)(
- _.setName(ToxNickname.unsafeFromValue(null))
- )
- }
-
- test("SetStatusMessageNull") {
- interceptWithTox(ToxSetInfoException.Code.NULL)(
- _.setStatusMessage(ToxStatusMessage.unsafeFromValue(null))
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/exceptions/ToxSetTypingExceptionTest.scala b/src/test/java/im/tox/tox4j/core/exceptions/ToxSetTypingExceptionTest.scala
deleted file mode 100644
index ba1ab1f0f..000000000
--- a/src/test/java/im/tox/tox4j/core/exceptions/ToxSetTypingExceptionTest.scala
+++ /dev/null
@@ -1,18 +0,0 @@
-package im.tox.tox4j.core.exceptions
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalatest.FunSuite
-
-final class ToxSetTypingExceptionTest extends FunSuite with ToxTestMixin {
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
- private val badFriendNumber = ToxFriendNumber.fromInt(1).get
-
- test("SetTypingToNonExistent") {
- interceptWithTox(ToxSetTypingException.Code.FRIEND_NOT_FOUND)(
- _.setTyping(badFriendNumber, typing = true)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/core/package.scala b/src/test/java/im/tox/tox4j/core/package.scala
deleted file mode 100644
index 34dad1856..000000000
--- a/src/test/java/im/tox/tox4j/core/package.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.documentation._
-
-package object core extends Documented
diff --git a/src/test/java/im/tox/tox4j/crypto/ToxCryptoTest.scala b/src/test/java/im/tox/tox4j/crypto/ToxCryptoTest.scala
deleted file mode 100644
index 007812d98..000000000
--- a/src/test/java/im/tox/tox4j/crypto/ToxCryptoTest.scala
+++ /dev/null
@@ -1,296 +0,0 @@
-package im.tox.tox4j.crypto
-
-import im.tox.core.random.RandomCore
-import im.tox.tox4j.crypto.ToxCryptoTest.{ EncryptedData, Salt }
-import im.tox.tox4j.crypto.exceptions.{ ToxDecryptionException, ToxEncryptionException, ToxKeyDerivationException }
-import im.tox.tox4j.testing.ToxTestMixin
-import org.scalacheck.Arbitrary.arbitrary
-import org.scalacheck.{ Arbitrary, Gen }
-import org.scalatest.WordSpec
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-import scala.language.implicitConversions
-import scala.util.Random
-
-object ToxCryptoTest {
- private final case class Salt(data: Seq[Byte]) extends AnyVal
- private final case class EncryptedData(data: Seq[Byte]) extends AnyVal
-}
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-abstract class ToxCryptoTest(private val toxCrypto: ToxCrypto) extends WordSpec with ScalaCheckPropertyChecks with ToxTestMixin {
-
- private val random = new Random
-
- private implicit val arbSalt: Arbitrary[Salt] =
- Arbitrary(Gen.const(ToxCryptoConstants.SaltLength).map(Array.ofDim[Byte]).map { array =>
- random.nextBytes(array)
- new Salt(array)
- })
-
- private implicit val arbEncryptedData: Arbitrary[EncryptedData] =
- Arbitrary(Gen.zip(arbitrary[Array[Byte]], Gen.nonEmptyContainerOf[Array, Byte](arbitrary[Byte])).map {
- case (passphrase, data) =>
- val passKey = toxCrypto.passKeyDerive(passphrase)
- new EncryptedData(toxCrypto.encrypt(data, passKey))
- })
-
- private implicit val arbPassKey: Arbitrary[toxCrypto.PassKey] =
- Arbitrary(arbitrary[Array[Byte]].map(x => toxCrypto.passKeyDerive(x)))
-
- "salt" should {
- "be contained correctly within the encrypted data" in {
- forAll { (data: Array[Byte], passphrase: Array[Byte], salt: Salt) =>
- whenever(data.nonEmpty) {
- val passKey = toxCrypto.passKeyDeriveWithSalt(passphrase, salt.data.toArray)
-
- // Check that the pass key size is reasonable.
- val serialised = toxCrypto.passKeyToBytes(passKey)
- assert(serialised.length == ToxCryptoConstants.KeyLength + ToxCryptoConstants.SaltLength)
-
- val encrypted = toxCrypto.encrypt(data, passKey)
-
- // Salt is contained within the encrypted data.
- assert(toxCrypto.getSalt(encrypted).deep == salt.data)
- }
- }
- }
-
- "be a prefix of the serialised pass key" in {
- forAll { (passphrase: Array[Byte], salt: Salt) =>
- val passKey = toxCrypto.passKeyDeriveWithSalt(passphrase, salt.data.toArray)
-
- val serialised = toxCrypto.passKeyToBytes(passKey)
- assert(serialised.slice(0, ToxCryptoConstants.SaltLength) == salt.data)
- }
- }
- }
-
- "PassKey serialisation" should {
- "produce a byte sequence of the right length" in {
- forAll { (passKey: toxCrypto.PassKey) =>
- val serialised = toxCrypto.passKeyToBytes(passKey)
- assert(serialised.length == ToxCryptoConstants.KeyLength + ToxCryptoConstants.SaltLength)
- }
- }
-
- "produce the same PassKey after deserialisation" in {
- forAll { (passKey: toxCrypto.PassKey) =>
- val serialised = toxCrypto.passKeyToBytes(passKey)
- assert(toxCrypto.passKeyFromBytes(serialised).contains(passKey))
- }
- }
- }
-
- "PassKey deserialisation" should {
- "fail for byte sequences of the wrong length" in {
- forAll { (serialised: Seq[Byte]) =>
- whenever(serialised.length != ToxCryptoConstants.KeyLength + ToxCryptoConstants.SaltLength) {
- assert(toxCrypto.passKeyFromBytes(serialised).isEmpty)
- }
- }
- }
-
- "produce the same PassKey after deserialisation" in {
- forAll { (passKey: toxCrypto.PassKey) =>
- val serialised = toxCrypto.passKeyToBytes(passKey)
- assert(toxCrypto.passKeyFromBytes(serialised).contains(passKey))
- }
- }
- }
-
- "encryption with a PassKey" should {
- import ToxEncryptionException.Code._
-
- "produce high entropy results (> 0.7)" in {
- val passKey = toxCrypto.passKeyDerive(Array.ofDim(0))
- forAll { (data: Array[Byte]) =>
- whenever(data.nonEmpty) {
- assert(RandomCore.entropy(toxCrypto.encrypt(data, passKey)) > 0.7)
- }
- }
- }
-
- "produce different data each time with the same PassKey" in {
- forAll { (data: Array[Byte], passKey: toxCrypto.PassKey) =>
- whenever(data.nonEmpty) {
- val encrypted1 = toxCrypto.encrypt(data, passKey)
- val encrypted2 = toxCrypto.encrypt(data, passKey)
- assert(encrypted1.deep != encrypted2.deep)
- }
- }
- }
-
- "produce different encrypted data with a different PassKey" in {
- forAll { (data: Array[Byte], passKey1: toxCrypto.PassKey, passKey2: toxCrypto.PassKey) =>
- whenever(data.nonEmpty && !toxCrypto.passKeyEquals(passKey1, passKey2)) {
- assert(toxCrypto.encrypt(data, passKey1).deep != toxCrypto.encrypt(data, passKey2).deep)
- }
- }
- }
-
- s"fail with $NULL for zero-length data" in {
- val passKey = toxCrypto.passKeyDerive(Array.ofDim(0))
- intercept(NULL) {
- toxCrypto.encrypt(Array.ofDim(0), passKey)
- }
- }
- }
-
- "isDataEncrypted" should {
- "identify encrypted data as such" in {
- forAll { (data: EncryptedData) =>
- assert(toxCrypto.isDataEncrypted(data.data.toArray))
- }
- }
-
- "not identify arbitrary other data as encrypted" in {
- forAll { (data: Array[Byte]) =>
- assert(!toxCrypto.isDataEncrypted(data))
- }
- }
- }
-
- "key derivation" should {
- import ToxKeyDerivationException.Code._
-
- s"fail with $INVALID_LENGTH for salt of wrong size" in {
- forAll { (salt: Array[Byte]) =>
- whenever(salt.length != ToxCryptoConstants.SaltLength) {
- intercept(INVALID_LENGTH) {
- toxCrypto.passKeyDeriveWithSalt(Array.ofDim(100), salt)
- }
- }
- }
- }
-
- "succeed for any passphrase" in {
- forAll { (passphrase: Array[Byte]) =>
- assert(Option(toxCrypto.passKeyDerive(passphrase)).nonEmpty)
- }
- }
-
- "produce the same key given the same salt" in {
- forAll { (passphrase: Array[Byte], salt: Salt) =>
- val key1 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt.data.toArray)
- val key2 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt.data.toArray)
- assert(toxCrypto.passKeyEquals(key1, key2))
- }
- }
-
- "produce a different key given a different salt" in {
- forAll { (passphrase: Array[Byte], salt1: Salt, salt2: Salt) =>
- whenever(salt1 != salt2) {
- val key1 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt1.data.toArray)
- val key2 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt2.data.toArray)
- assert(!toxCrypto.passKeyEquals(key1, key2))
- }
- }
- }
- }
-
- "decryption" should {
- import ToxDecryptionException.Code._
-
- s"fail with $INVALID_LENGTH for zero-length data" in {
- val passKey = toxCrypto.passKeyDerive(Array.ofDim(0))
- intercept(INVALID_LENGTH) {
- toxCrypto.decrypt(Array.ofDim(0), passKey)
- }
- }
-
- s"fail with $INVALID_LENGTH for 0 to ${ToxCryptoConstants.EncryptionExtraLength} bytes" in {
- val passKey = toxCrypto.passKeyDerive(Array.ofDim(0))
- (0 to ToxCryptoConstants.EncryptionExtraLength) foreach { length =>
- intercept(INVALID_LENGTH) {
- toxCrypto.decrypt(Array.ofDim(length), passKey)
- }
- }
- }
-
- s"fail with $BAD_FORMAT for an array of more than ${ToxCryptoConstants.EncryptionExtraLength} 0-bytes" in {
- val passKey = toxCrypto.passKeyDerive(Array.ofDim(0))
- intercept(BAD_FORMAT) {
- toxCrypto.decrypt(Array.ofDim(ToxCryptoConstants.EncryptionExtraLength + 1), passKey)
- }
- }
-
- "succeed with the same PassKey" in {
- forAll { (data: Array[Byte], passKey: toxCrypto.PassKey) =>
- whenever(data.nonEmpty) {
- val encrypted = toxCrypto.encrypt(data, passKey)
- val decrypted = toxCrypto.decrypt(encrypted, passKey)
- assert(data.deep == decrypted.deep)
- }
- }
- }
-
- "succeed with the same passphrase and salt" in {
- forAll { (data: Array[Byte], passphrase: Array[Byte]) =>
- whenever(data.nonEmpty) {
- val passKey1 = toxCrypto.passKeyDerive(passphrase)
- val encrypted = toxCrypto.encrypt(data, passKey1)
- val salt = toxCrypto.getSalt(encrypted)
-
- val passKey2 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt)
- val decrypted = toxCrypto.decrypt(encrypted, passKey2)
-
- assert(data.deep == decrypted.deep)
- }
- }
- }
-
- s"fail with $FAILED for the same passphrase but different salt" in {
- forAll { (data: Array[Byte], passphrase: Array[Byte], salt1: Salt, salt2: Salt) =>
- whenever(data.nonEmpty && salt1 != salt2) {
- val passKey1 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt1.data.toArray)
- val passKey2 = toxCrypto.passKeyDeriveWithSalt(passphrase, salt2.data.toArray)
- val encrypted = toxCrypto.encrypt(data, passKey1)
- intercept(FAILED) {
- toxCrypto.decrypt(encrypted, passKey2)
- }
- }
- }
- }
-
- s"fail with $FAILED for a different PassKey" in {
- forAll { (data: Array[Byte], passKey1: toxCrypto.PassKey, passKey2: toxCrypto.PassKey) =>
- whenever(data.nonEmpty && !toxCrypto.passKeyEquals(passKey1, passKey2)) {
- val encrypted = toxCrypto.encrypt(data, passKey1)
- intercept(FAILED) {
- toxCrypto.decrypt(encrypted, passKey2)
- }
- }
- }
- }
- }
-
- "hash computation" should {
- "produce the same output when called twice on the same input" in {
- forAll { (data: Array[Byte]) =>
- assert(toxCrypto.hash(data).deep == toxCrypto.hash(data).deep)
- }
- }
-
- "produce a different output for different inputs" in {
- forAll { (data1: Array[Byte], data2: Array[Byte]) =>
- whenever(data1.deep != data2.deep) {
- assert(toxCrypto.hash(data1).deep != toxCrypto.hash(data2).deep)
- }
- }
- }
-
- "create constant-length output" in {
- forAll { (data: Array[Byte]) =>
- assert(toxCrypto.hash(data).length == ToxCryptoConstants.HashLength)
- }
- }
-
- "produce high entropy results (> 0.5)" in {
- forAll { (data: Array[Byte]) =>
- assert(RandomCore.entropy(toxCrypto.hash(data)) > 0.5)
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/crypto/package.scala b/src/test/java/im/tox/tox4j/crypto/package.scala
deleted file mode 100644
index cf1563f36..000000000
--- a/src/test/java/im/tox/tox4j/crypto/package.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.documentation._
-
-package object crypto extends Documented
diff --git a/src/test/java/im/tox/tox4j/exceptions/ToxExceptionTest.scala b/src/test/java/im/tox/tox4j/exceptions/ToxExceptionTest.scala
deleted file mode 100644
index b93038864..000000000
--- a/src/test/java/im/tox/tox4j/exceptions/ToxExceptionTest.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package im.tox.tox4j.exceptions
-
-import im.tox.tox4j.core.exceptions.ToxBootstrapException
-import org.scalatest.FlatSpec
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class ToxExceptionTest extends FlatSpec with ScalaCheckPropertyChecks {
-
- "getMessage" should "contain the error code name" in {
- ToxBootstrapException.Code.values().foreach { code =>
- val exn = new ToxBootstrapException(code)
- assert(exn.getMessage.contains(code.name()))
- }
- }
-
- it should "contain the exception message" in {
- forAll { (message: String) =>
- val exn = new ToxBootstrapException(ToxBootstrapException.Code.NULL, message)
- assert(exn.getMessage.contains(message))
- }
- }
-
- "code" should "be the passed code" in {
- ToxBootstrapException.Code.values().foreach { code =>
- val exn = new ToxBootstrapException(code)
- assert(exn.code == code)
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/exceptions/ToxKilledExceptionTest.scala b/src/test/java/im/tox/tox4j/exceptions/ToxKilledExceptionTest.scala
deleted file mode 100644
index 830531bb7..000000000
--- a/src/test/java/im/tox/tox4j/exceptions/ToxKilledExceptionTest.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package im.tox.tox4j.exceptions
-
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory.withToxUnit
-import org.scalatest.FunSuite
-
-final class ToxKilledExceptionTest extends FunSuite {
-
- test("UseAfterCloseInOrder") {
- intercept[ToxKilledException] {
- withToxUnit { tox1 =>
- withToxUnit { tox2 =>
- tox1.close()
- tox1.iterationInterval
- }
- }
- }
- }
-
- test("UseAfterCloseReverseOrder") {
- intercept[ToxKilledException] {
- withToxUnit { tox1 =>
- withToxUnit { tox2 =>
- tox2.close()
- tox2.iterationInterval
- }
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/BadInstanceNumberTest.scala b/src/test/java/im/tox/tox4j/impl/jni/BadInstanceNumberTest.scala
deleted file mode 100644
index 8f63c0795..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/BadInstanceNumberTest.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.exceptions.ToxKilledException
-import org.scalacheck.Gen
-import org.scalatest.FunSuite
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-/**
- * This class tests whether the C++ code is resilient against memory corruption
- * and bad people using reflection to forge invalid Tox instances.
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class BadInstanceNumberTest extends FunSuite with ScalaCheckPropertyChecks {
-
- private def callWithInstanceNumber(instanceNumber: Int): Unit = {
- val tox = new ToxCoreImpl(ToxOptions())
-
- val field = tox.getClass.getDeclaredField("instanceNumber")
- field.setAccessible(true)
- val oldInstanceNumber = field.get(tox).asInstanceOf[Int]
- field.set(tox, instanceNumber)
-
- val exception =
- try {
- tox.iterationInterval
- null
- } catch {
- case e: Throwable => e
- }
-
- // Set it back to the good one, so close() works.
- field.set(tox, oldInstanceNumber)
- tox.close()
-
- if (exception != null) {
- throw exception
- }
- }
-
- test("negative or zero instance numbers") {
- forAll(Gen.choose(Int.MinValue, 0)) { instanceNumber =>
- intercept[IllegalStateException] {
- callWithInstanceNumber(instanceNumber)
- }
- }
- }
-
- test("very large instance numbers") {
- forAll(Gen.choose(0xffff, Int.MaxValue)) { instanceNumber =>
- intercept[IllegalStateException] {
- callWithInstanceNumber(instanceNumber)
- }
- }
- }
-
- test("any invalid instance numbers") {
- // This could be fine if there is another Tox instance lingering around, but we assume there isn't.
- // So, it's either killed (ToxKilledException) or never existed (IllegalStateException).
- System.gc() // After this, there should be no lingering instances.
-
- forAll { (instanceNumber: Int) =>
- whenever(instanceNumber != 1) {
- try {
- callWithInstanceNumber(instanceNumber)
- fail("No exception thrown. Expected IllegalStateException or ToxKilledException.")
- } catch {
- case _: IllegalStateException =>
- case _: ToxKilledException => // Both fine.
- }
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/FinalizerDoubleTest.java b/src/test/java/im/tox/tox4j/impl/jni/FinalizerDoubleTest.java
deleted file mode 100644
index 690856969..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/FinalizerDoubleTest.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package im.tox.tox4j.impl.jni;
-
-import im.tox.tox4j.core.ToxCoreConstants;
-import im.tox.tox4j.core.options.ProxyOptions;
-import im.tox.tox4j.core.options.SaveDataOptions;
-import im.tox.tox4j.core.options.ToxOptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.scalatestplus.junit.JUnitSuite;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * This test is just here to check whether calling {@link ToxCoreImpl#finalize}
- * twice causes a hard crash or not. It should be handled gracefully, although
- * it should never happen. This test should print an exception trace to the log.
- *
- *
- * Thus: This test will cause exceptions talking about a 'serious problem
- * in native code'. This is expected behaviour. It is not actually a serious
- * problem.
- */
-public class FinalizerDoubleTest extends JUnitSuite {
-
- private static final Logger logger =
- LoggerFactory.getLogger(FinalizerDoubleTest.class);
-
- private static final ToxOptions OPTIONS = new ToxOptions( //
- true, //
- true, //
- true, //
- ProxyOptions.None$.MODULE$, //
- ToxCoreConstants.DefaultStartPort(), //
- ToxCoreConstants.DefaultEndPort(), //
- ToxCoreConstants.DefaultTcpPort(), //
- SaveDataOptions.None$.MODULE$, //
- true //
- );
-
- @Before
- public void setUp() {
- logger.info(
- "Exceptions about 'a serious problem in native code' are expected.");
- }
-
- /**
- * This is ran after every test to clean up the broken Tox instances, so that
- * a future GC doesn't cause exception traces to be printed.
- */
- @After
- public void tearDown() {
- System.gc();
- }
-
- @Test
- @SuppressWarnings("FinalizeCalledExplicitly")
- public void testFinalizeTwice() {
- ToxCoreImpl tox = new ToxCoreImpl(OPTIONS);
-
- tox.finalize();
- tox.finalize();
- }
-
- @Test(expected = IllegalStateException.class)
- @SuppressWarnings("FinalizeCalledExplicitly")
- public void testCloseAfterFinalize() {
- ToxCoreImpl tox = new ToxCoreImpl(OPTIONS);
- tox.finalize();
- tox.close();
- }
-
- @Test(expected = IllegalStateException.class)
- @SuppressWarnings("FinalizeCalledExplicitly")
- public void testAnyMethodAfterFinalize() {
- ToxCoreImpl tox = new ToxCoreImpl(OPTIONS);
- tox.finalize();
- tox.iterationInterval();
- }
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/FinalizerTest.scala b/src/test/java/im/tox/tox4j/impl/jni/FinalizerTest.scala
deleted file mode 100644
index 042f4813b..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/FinalizerTest.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.core.options.ToxOptions
-import org.scalatest.FlatSpec
-
-/**
- * These tests solely exist to exercise the C++ code paths that deal with closing and finalisation. If the C++ code has
- * errors in this area, these two tests can be used to single them out and debug them.
- *
- * Although [[System.gc()]] doesn't necessarily perform a GC, on the Oracle JVM it actually does reliably do so.
- * Thus, these tests don't formally test anything, but in reality they do.
- */
-final class FinalizerTest extends FlatSpec {
-
- "Garbage collection" should "not crash the JVM when collecting a closed ToxCoreImpl" in {
- System.gc()
- new ToxCoreImpl(new ToxOptions).close()
- System.gc()
- }
-
- it should "not crash the JVM when collecting an unclosed ToxCoreImpl" in {
- System.gc()
- new ToxCoreImpl(new ToxOptions)
- System.gc()
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/MethodMap.scala b/src/test/java/im/tox/tox4j/impl/jni/MethodMap.scala
deleted file mode 100644
index d1fd3cd60..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/MethodMap.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import java.lang.reflect.{ Method, Modifier }
-
-import im.tox.tox4j.OptimisedIdOps._
-import im.tox.tox4j.impl.jni.codegen.NameConversions
-
-object MethodMap {
-
- private val actions = Seq("get", "set", "add", "delete")
-
- private def removeSelf(name: Seq[String]): Seq[String] = {
- name.headOption match {
- case Some("self") => name.drop(1)
- case _ => name
- }
- }
-
- private def moveActionToFront(name: Seq[String]): Seq[String] = {
- name.indexWhere(actions.contains) match {
- case -1 =>
- name
- case actionIndex =>
- name(actionIndex) +: (name.slice(0, actionIndex) ++ name.slice(actionIndex + 1, name.length))
- }
- }
-
- def apply(jniClass: Class[_]): Map[String, Method] = {
- jniClass
- .getDeclaredMethods.toSeq
- .filter { method =>
- Modifier.isNative(method.getModifiers) &&
- method.getName.startsWith("tox")
- }
- .map { method =>
- val expectedName = (method.getName
- |> NameConversions.cxxVarName
- |> (_.split("_").toSeq.drop(1))
- |> removeSelf
- |> moveActionToFront
- |> (_.mkString("_"))
- |> NameConversions.javaVarName)
- (expectedName, method)
- } |> { pairs => Map(pairs: _*) }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/NamingConventionsTest.scala b/src/test/java/im/tox/tox4j/impl/jni/NamingConventionsTest.scala
deleted file mode 100644
index 15ceea59b..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/NamingConventionsTest.scala
+++ /dev/null
@@ -1,21 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import org.scalatest.FunSuite
-
-abstract class NamingConventionsTest(jniClass: Class[_], traitClass: Class[_]) extends FunSuite {
-
- private val exemptions = Seq("callback", "load", "close", "create", "getFriendNumbers")
-
- test("Java method names should be derivable from JNI method names") {
- val jniMethods = MethodMap(jniClass)
-
- traitClass
- .getDeclaredMethods.toSeq
- .map(_.getName)
- .filterNot(exemptions.contains)
- .foreach { name =>
- assert(jniMethods.contains(name))
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxAvImplFactory.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxAvImplFactory.scala
deleted file mode 100644
index 400124094..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxAvImplFactory.scala
+++ /dev/null
@@ -1,17 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.av.{ ToxAv, ToxAvFactory }
-import im.tox.tox4j.core.ToxCore
-
-object ToxAvImplFactory extends ToxAvFactory {
-
- @SuppressWarnings(Array("org.wartremover.warts.AsInstanceOf"))
- private def make(tox: ToxCore): ToxAv = {
- new ToxAvImpl(tox.asInstanceOf[ToxCoreImpl])
- }
-
- def withToxAv[R](tox: ToxCore)(f: ToxAv => R): R = {
- withToxAv(make(tox))(f)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxAvNamingTest.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxAvNamingTest.scala
deleted file mode 100644
index 3c89c15a8..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxAvNamingTest.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.av.ToxAv
-
-final class ToxAvNamingTest extends NamingConventionsTest(classOf[ToxAvJni], classOf[ToxAv])
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxCoreImplFactory.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxCoreImplFactory.scala
deleted file mode 100644
index 7b04ccf26..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxCoreImplFactory.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.core.exceptions.ToxNewException
-import im.tox.tox4j.core.options.{ ProxyOptions, SaveDataOptions, ToxOptions }
-import im.tox.tox4j.core.{ ToxCore, ToxCoreFactory, ToxList }
-
-import scala.collection.mutable.ArrayBuffer
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-object ToxCoreImplFactory extends ToxCoreFactory {
-
- private val toxes = new ArrayBuffer[ToxCore]
-
- private def make(options: ToxOptions = ToxOptions()): ToxCore = {
- try {
- new ToxCoreImpl(options)
- } catch {
- case e: ToxNewException if e.code == ToxNewException.Code.PORT_ALLOC =>
- System.gc()
- new ToxCoreImpl(options)
- }
- }
-
- private def makeList(count: Int, options: ToxOptions = ToxOptions()): ToxList = {
- new ToxList(() => { this(options) }, count)
- }
-
- def destroyAll(): Unit = {
- toxes.foreach(_.close())
- toxes.clear()
- System.gc()
- }
-
- def apply(options: ToxOptions): ToxCore = {
- val tox = make(options)
- toxes += tox
- tox
- }
-
- def withToxUnit[R](options: ToxOptions)(f: ToxCore => R): R = {
- withTox(make(options))(f)
- }
-
- def withToxUnit[R](ipv6Enabled: Boolean, udpEnabled: Boolean, proxy: ProxyOptions)(f: ToxCore => R): R = {
- withToxUnit(ToxOptions(ipv6Enabled, udpEnabled, proxy = proxy))(f)
- }
-
- def withToxUnit[R](ipv6Enabled: Boolean, udpEnabled: Boolean)(f: ToxCore => R): R = {
- withToxUnit(ToxOptions(ipv6Enabled, udpEnabled))(f)
- }
-
- def withToxUnit[R](saveData: SaveDataOptions)(f: ToxCore => R): R = {
- withToxUnit(new ToxOptions(saveData = saveData))(f)
- }
-
- def withToxUnit[R](f: ToxCore => R): R = {
- withToxUnit(ipv6Enabled = true, udpEnabled = true)(f)
- }
-
- def withTox[R](options: ToxOptions)(f: ToxCore => R): R = {
- withTox(make(options))(f)
- }
-
- def withToxS[R](options: ToxOptions)(f: ToxCore => R): R = {
- withTox(make(options))(f)
- }
-
- def withToxS[R](ipv6Enabled: Boolean, udpEnabled: Boolean)(f: ToxCore => R): R = {
- withToxS(ToxOptions(ipv6Enabled, udpEnabled))(f)
- }
-
- def withToxS[R](ipv6Enabled: Boolean, udpEnabled: Boolean, proxy: ProxyOptions)(f: ToxCore => R): R = {
- withToxS(ToxOptions(ipv6Enabled, udpEnabled, proxy = proxy))(f)
- }
-
- def withToxes[R](count: Int, options: ToxOptions)(f: ToxList => R): R = {
- val toxes = makeList(count, options)
- try {
- f(toxes)
- } finally {
- toxes.close()
- }
- }
-
- def withToxes[R](count: Int)(f: ToxList => R): R = {
- withToxes(count, ToxOptions())(f)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxCoreNamingTest.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxCoreNamingTest.scala
deleted file mode 100644
index 46f96c11f..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxCoreNamingTest.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.core.ToxCore
-
-final class ToxCoreNamingTest extends NamingConventionsTest(classOf[ToxCoreJni], classOf[ToxCore])
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxCryptoImplTest.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxCryptoImplTest.scala
deleted file mode 100644
index e777762a1..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxCryptoImplTest.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.crypto.ToxCryptoTest
-
-final class ToxCryptoImplTest extends ToxCryptoTest(ToxCryptoImpl)
diff --git a/src/test/java/im/tox/tox4j/impl/jni/ToxJniLogTest.scala b/src/test/java/im/tox/tox4j/impl/jni/ToxJniLogTest.scala
deleted file mode 100644
index 532eeb189..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/ToxJniLogTest.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package im.tox.tox4j.impl.jni
-
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.impl.jni.proto.JniLog
-import org.scalacheck.Gen
-import org.scalatest.FunSuite
-import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class ToxJniLogTest extends FunSuite with ScalaCheckPropertyChecks {
-
- private val TestMaxSize = 100
-
- private val friendNumber = ToxFriendNumber.fromInt(0).get
-
- test("constructing and destroying a Tox instance with logging enabled should result in a non-empty log") {
- ToxJniLog() // clear
-
- ToxJniLog.maxSize = TestMaxSize
- assert(ToxJniLog.maxSize == TestMaxSize)
- assert(ToxJniLog().entries.isEmpty)
- // Construct and destroy a Tox instance to cause something (tox_new) to be logged and the log
- // will be non-empty.
- ToxCoreImplFactory.withToxUnit { tox => }
- assert(ToxJniLog().entries.nonEmpty)
- }
-
- test("constructing and destroying a Tox instance with logging disabled should result in an empty log") {
- ToxJniLog() // clear
-
- ToxJniLog.maxSize = 0
- assert(ToxJniLog.maxSize == 0)
- assert(ToxJniLog().entries.isEmpty)
- ToxCoreImplFactory.withToxUnit { tox => }
- assert(ToxJniLog().entries.isEmpty)
- }
-
- test("one log entry per native call") {
- ToxJniLog() // clear
-
- ToxJniLog.maxSize = TestMaxSize
- assert(ToxJniLog().entries.isEmpty)
-
- ToxCoreImplFactory.withToxUnit { tox => }
- val count1 = ToxJniLog().entries.size
-
- ToxCoreImplFactory.withToxUnit { tox => tox.friendExists(friendNumber) }
- val count2 = ToxJniLog().entries.size
-
- assert(count2 == count1 + 1)
- }
-
- test("null protobufs are ignored") {
- assert(ToxJniLog.fromBytes(null) == JniLog.defaultInstance)
- }
-
- test("invalid protobufs are ignored") {
- forAll { (bytes: Array[Byte]) =>
- assert(ToxJniLog.fromBytes(bytes) == JniLog.defaultInstance)
- }
- }
-
- test("concurrent logging works") {
- ToxJniLog() // clear
- ToxJniLog.maxSize = 10000
-
- forAll(Gen.choose(1, 99), Gen.choose(1, 100)) { (threadCount, iterations) =>
- val threads = for (_ <- 1 to threadCount) yield {
- new Thread {
- override def run(): Unit = {
- ToxCoreImplFactory.withToxUnit { tox =>
- for (_ <- 0 until iterations) {
- tox.friendExists(friendNumber)
- }
- }
- }
- }
- }
-
- threads.foreach(_.start())
- threads.foreach(_.join())
-
- val log = ToxJniLog()
- assert(log.entries.size < 10000)
- assert(log.entries.size == threadCount + threadCount * iterations)
- assert(ToxJniLog.toString(log).count(_ == '\n') == log.entries.size)
- }
-
- assert(ToxJniLog().entries.isEmpty)
- ToxJniLog.maxSize = 0
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/CodeGenerator.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/CodeGenerator.scala
deleted file mode 100644
index 9f5008691..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/CodeGenerator.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import java.io.{ File, PrintWriter }
-
-import com.google.common.base.CaseFormat
-import gnieh.pp.PrettyRenderer
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-import im.tox.tox4j.impl.jni.codegen.cxx.{ Ast, Print }
-
-object NameConversions {
-
- def cxxVarName(name: String): String = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name)
- def cxxTypeName(name: String): String = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, name)
- def javaVarName(name: String): String = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name)
- def javaTypeName(name: String): String = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name)
-
-}
-
-abstract class CodeGenerator extends App {
-
- def writeCode(path: String, sep: String = "\n\n")(code: Ast.TranslationUnit): Unit = {
- val renderer = new PrettyRenderer(130)
-
- val writer = new PrintWriter(new File("cpp/src", path))
- try {
- writer.println(code.map(Print.printDecl).map(renderer).mkString(sep))
- } finally {
- writer.close()
- }
- }
-
- def ifdef(header: String, guard: String, code: TranslationUnit*): TranslationUnit = {
- Include(header) +:
- Ifdef(guard) +:
- code.flatten :+
- Endif
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniCallbacks.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniCallbacks.scala
deleted file mode 100644
index 82b36525f..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniCallbacks.scala
+++ /dev/null
@@ -1,48 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import im.tox.core.typesafe.Equals._
-import im.tox.tox4j.av.callbacks.ToxAvEventAdapter
-import im.tox.tox4j.core.callbacks.ToxCoreEventAdapter
-import im.tox.tox4j.impl.jni.codegen.NameConversions.{ cxxTypeName, cxxVarName, javaVarName }
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-
-object JniCallbacks extends CodeGenerator {
-
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- def getAllInterfaces(clazz: Class[_]): List[Class[_]] = {
- (Option(clazz.getSuperclass).toList.flatMap(getAllInterfaces)
- ++ clazz.getInterfaces
- ++ clazz.getInterfaces.flatMap(getAllInterfaces))
- }
-
- def generateCallbacks(clazz: Class[_]): TranslationUnit = {
- getAllInterfaces(clazz).filter(_.getSimpleName.endsWith("Callback"))
- .sortBy(_.getSimpleName)
- .flatMap { interface =>
- val expectedMethodName = {
- val name = cxxTypeName(interface.getSimpleName)
- javaVarName(name.substring(0, name.lastIndexOf('_')).toLowerCase)
- }
-
- val method = interface.getDeclaredMethods.filter(_.getName === expectedMethodName) match {
- case Array() => sys.error(s"Callback interfaces $interface does not provide a method '$expectedMethodName'")
- case Array(singleMethod) => singleMethod
- case methods => sys.error(s"Callback interfaces $interface contains multiple overloads for '$expectedMethodName'")
- }
-
- Seq(
- Comment(interface.getName + "#" + expectedMethodName),
- MacroCall(FunCall(Identifier("CALLBACK"), Seq(Identifier(cxxVarName(method.getName)))))
- )
- }
- }
-
- writeCode("tox/generated/av.h", "\n") {
- generateCallbacks(classOf[ToxAvEventAdapter[_]])
- }
-
- writeCode("tox/generated/core.h", "\n") {
- generateCallbacks(classOf[ToxCoreEventAdapter[_]])
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniConstants.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniConstants.scala
deleted file mode 100644
index 2bc95524c..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniConstants.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import im.tox.tox4j.core.ToxCoreConstants
-import im.tox.tox4j.crypto.ToxCryptoConstants
-import im.tox.tox4j.impl.jni.codegen.NameConversions.cxxTypeName
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-
-object JniConstants extends CodeGenerator {
-
- def generateNativeDecls[T](prefix: String, constants: T): Decl = {
- val clazz = constants.getClass
-
- Fun(
- returnType = Static(Type.void),
- name = "check" + clazz.getSimpleName.replace("$", ""),
- params = Seq(),
- body = CompoundStmt(
- body = clazz.getDeclaredMethods
- .sortBy(method => method.getName)
- .map { method =>
- val value = method.invoke(constants).asInstanceOf[Int]
- ExprStmt(FunCall(Identifier("static_assert"), Seq(
- Equals(Identifier(prefix + cxxTypeName(method.getName)), IntegerLiteral(value)),
- StringLiteral("Java constant out of sync with C")
- )))
- }.toSeq
- )
- )
- }
-
- writeCode("ToxCore/generated/constants.h", "\n") {
- Seq(
- Comment(ToxCoreConstants.getClass.getName),
- generateNativeDecls("TOX_", ToxCoreConstants)
- )
- }
-
- writeCode("ToxCrypto/generated/constants.h", "\n") {
- Seq(
- Comment(ToxCryptoConstants.getClass.getName),
- generateNativeDecls("TOX_PASS_", ToxCryptoConstants)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniEnums.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniEnums.scala
deleted file mode 100644
index 2704e689e..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniEnums.scala
+++ /dev/null
@@ -1,113 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import com.google.common.base.CaseFormat
-import im.tox.tox4j.av.enums.{ ToxavCallControl, ToxavFriendCallState }
-import im.tox.tox4j.core.enums._
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-
-object JniEnums extends CodeGenerator {
-
- final case class Side[E <: Enum[E]](
- ty: Type,
- name: String,
- origin: String,
- expr: E => Expr
- )
-
- def enumMapping[E <: Enum[E]](values: Seq[E], cxxEnum: String, from: Side[E], to: Side[E]): Decl = {
- TemplateFun(
- typeParams = Nil,
- typeArgs = Seq(Typename(cxxEnum)),
- fun = Fun(
- returnType = to.ty,
- name = "Enum::" + to.name,
- params = Seq(
- Param(Pointer(Typename("JNIEnv")), "env"),
- Param(from.ty, from.name)
- ),
- body = CompoundStmt(
- Switch(Identifier(from.name), CompoundStmt(values.map { value =>
- Case(from.expr(value), Return(to.expr(value)))
- })),
- ExprStmt(FunCall(Identifier("tox4j_fatal"), Seq(StringLiteral(s"Invalid enumerator from ${from.origin}"))))
- )
- )
- )
- }
-
- def enumMappings[E <: Enum[E]](values: Seq[E], cxxEnum: String): TranslationUnit = {
- val from = Side[E](Typename(cxxEnum), "valueOf", "toxcore", value => Identifier(cxxEnum + "_" + value.name))
- val to = Side[E](Type.jint, "ordinal", "Java", value => IntegerLiteral(value.ordinal))
-
- Seq(
- enumMapping(values, cxxEnum, from, to),
- enumMapping(values, cxxEnum, to, from)
- )
- }
-
- def debugOut(expr: Expr): Stmt = {
- ExprStmt(
- FunCall(
- Access(Identifier("value"), "set_v_string"),
- Seq(expr)
- )
- )
- }
-
- def printArg[E <: Enum[E]](values: Seq[E], cxxEnum: String): Decl = {
- TemplateFun(
- typeParams = Nil,
- typeArgs = Seq(Typename(cxxEnum)),
- fun = Fun(
- returnType = Type.void,
- name = "print_arg",
- params = Seq(
- Param(Reference(Typename("protolog::Value")), "value"),
- Param(Reference(Const(Typename(cxxEnum))), "arg")
- ),
- body = CompoundStmt(
- Switch(Identifier("arg"), CompoundStmt(values.flatMap { value =>
- Seq(Oneliner(
- Case(
- Identifier(cxxEnum + "_" + value.name),
- debugOut(StringLiteral(cxxEnum + "_" + value.name))
- ),
- Return()
- ))
- })),
- debugOut(BinaryOperator(
- "+",
- StringLiteral(s"($cxxEnum)"),
- Identifier("std::to_string (arg)")
- ))
- )
- )
- )
- }
-
- def generateEnumConversions[E <: Enum[E]](values: Array[E]): TranslationUnit = {
- val javaEnum = values(0).getClass.getSimpleName
- val cxxEnum = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, javaEnum)
-
- enumMappings(values, cxxEnum) :+ printArg(values, cxxEnum)
- }
-
- writeCode("ToxAv/generated/enums.cpp") {
- Include("../ToxAv.h") +: (
- generateEnumConversions(ToxavCallControl.values) ++
- generateEnumConversions(ToxavFriendCallState.values)
- )
- }
-
- writeCode("ToxCore/generated/enums.cpp") {
- Include("../ToxCore.h") +: (
- generateEnumConversions(ToxConnection.values) ++
- generateEnumConversions(ToxFileControl.values) ++
- generateEnumConversions(ToxMessageType.values) ++
- generateEnumConversions(ToxProxyType.values) ++
- generateEnumConversions(ToxSavedataType.values) ++
- generateEnumConversions(ToxUserStatus.values)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniErrorCodes.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniErrorCodes.scala
deleted file mode 100644
index 8ede0e6b1..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniErrorCodes.scala
+++ /dev/null
@@ -1,93 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import im.tox.tox4j.av.exceptions._
-import im.tox.tox4j.core.exceptions._
-import im.tox.tox4j.crypto.exceptions._
-import im.tox.tox4j.exceptions.JavaOnly
-import im.tox.tox4j.impl.jni.codegen.NameConversions.{ cxxTypeName, javaTypeName }
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-
-object JniErrorCodes extends CodeGenerator {
-
- def generateErrorCode[E <: Enum[E]](values: Array[E]): Decl = {
- val exceptionClass = {
- val name = cxxTypeName(values(0).getClass.getEnclosingClass.getSimpleName)
- name.substring(name.indexOf('_') + 1, name.lastIndexOf('_'))
- }
-
- val javaEnum = values(0).getClass.getSimpleName
- val cxxEnum = cxxTypeName(javaEnum)
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- val failureCases = values filter { value =>
- value.getClass.getField(value.name).getAnnotation(classOf[JavaOnly]) == null
- } map { value =>
- FunCall(Identifier("failure_case"), Seq(Identifier(exceptionClass), Identifier(value.name)))
- } map ExprStmt
-
- MacroFun(
- init = FunCall(
- callee = Identifier("HANDLE"),
- args = Seq(
- StringLiteral(javaTypeName(exceptionClass)),
- Identifier(exceptionClass)
- )
- ),
- body = CompoundStmt(
- Switch(
- cond = Identifier("error"),
- body = CompoundStmt(
- ExprStmt(FunCall(Identifier("success_case"), Seq(Identifier(exceptionClass)))) +:
- failureCases
- )
- ),
- Return(FunCall(Identifier("unhandled"), Nil))
- )
- )
- }
-
- writeCode("ToxAv/generated/errors.cpp") {
- Include("../ToxAv.h") +:
- Seq(
- generateErrorCode(ToxavAnswerException.Code.values),
- generateErrorCode(ToxavBitRateSetException.Code.values),
- generateErrorCode(ToxavCallControlException.Code.values),
- generateErrorCode(ToxavCallException.Code.values),
- generateErrorCode(ToxavNewException.Code.values),
- generateErrorCode(ToxavSendFrameException.Code.values)
- )
- }
-
- writeCode("ToxCore/generated/errors.cpp") {
- Include("../ToxCore.h") +:
- Seq(
- generateErrorCode(ToxBootstrapException.Code.values),
- generateErrorCode(ToxFileControlException.Code.values),
- generateErrorCode(ToxFileGetException.Code.values),
- generateErrorCode(ToxFileSeekException.Code.values),
- generateErrorCode(ToxFileSendChunkException.Code.values),
- generateErrorCode(ToxFileSendException.Code.values),
- generateErrorCode(ToxFriendAddException.Code.values),
- generateErrorCode(ToxFriendByPublicKeyException.Code.values),
- generateErrorCode(ToxFriendCustomPacketException.Code.values),
- generateErrorCode(ToxFriendDeleteException.Code.values),
- generateErrorCode(ToxFriendGetPublicKeyException.Code.values),
- generateErrorCode(ToxFriendSendMessageException.Code.values),
- generateErrorCode(ToxGetPortException.Code.values),
- generateErrorCode(ToxNewException.Code.values),
- generateErrorCode(ToxSetInfoException.Code.values),
- generateErrorCode(ToxSetTypingException.Code.values)
- )
- }
-
- writeCode("ToxCrypto/generated/errors.cpp") {
- Include("../ToxCrypto.h") +:
- Seq(
- generateErrorCode(ToxDecryptionException.Code.values),
- generateErrorCode(ToxEncryptionException.Code.values),
- generateErrorCode(ToxGetSaltException.Code.values),
- generateErrorCode(ToxKeyDerivationException.Code.values)
- )
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodImpls.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodImpls.scala
deleted file mode 100644
index b799ac3e1..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodImpls.scala
+++ /dev/null
@@ -1,78 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.impl.jni.codegen.NameConversions.cxxVarName
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-import im.tox.tox4j.impl.jni.{ AutoGenerated, MethodMap, ToxAvJni, ToxCoreJni }
-
-import scala.reflect.runtime.{ universe => u }
-
-object JniMethodImpls extends CodeGenerator {
-
- private val javaTypeMap = Map(
- "void" -> Type.void,
- "int" -> Type.jint,
- "boolean" -> Type.jboolean
- )
-
- private val scalaTypeMap = Map(
- "Int" -> Type.jint,
- classOf[ToxFriendNumber].getName -> Type.jint
- )
-
- def cxxType(typeSignature: u.Type): Type = {
- scalaTypeMap(typeSignature.toString)
- }
-
- def cxxParams(params: Seq[(u.Type, u.Name)]): Seq[Param] = {
- params map {
- case (typeSignature, name) =>
- Param(cxxType(typeSignature), name.toString)
- }
- }
-
- def generateNativeCode[T](jniClass: Class[_])(implicit evidence: u.TypeTag[T]): TranslationUnit = {
- val mirror = u.runtimeMirror(jniClass.getClassLoader)
- val traitMirror = mirror.typeOf[T]
-
- MethodMap(jniClass).toSeq.flatMap {
- case (name, method) =>
- Option(method.getAnnotation(classOf[AutoGenerated])).map((name, method, _)).toIterable
- }.map {
- case (name, method, annotation) =>
- val params = traitMirror
- .member(u.TermName(name)).asMethod
- .paramLists.flatten
- .map { sym => (sym.typeSignature, sym.name) }
-
- ToxFun(
- returnType = javaTypeMap(method.getReturnType.getName),
- name = method.getName,
- params = Param(Type.jint, "instanceNumber") +: cxxParams(params),
- body = CompoundStmt(
- Return(FunCall(
- Access(Identifier("instances"), "with_instance_noerr"),
- Seq(
- Identifier("env"),
- Identifier("instanceNumber"),
- Identifier(Option(annotation.value).filter(_.nonEmpty).getOrElse(cxxVarName(method.getName)))
- ) ++ cxxParams(params).map(_.name).map(Identifier)
- ))
- )
- )
- }
- }
-
- writeCode("ToxAv/generated/impls.h") {
- Comment(classOf[ToxAvJni].getName) +:
- generateNativeCode[ToxAv](classOf[ToxAvJni])
- }
-
- writeCode("ToxCore/generated/impls.h") {
- Comment(classOf[ToxCoreJni].getName) +:
- generateNativeCode[ToxCore](classOf[ToxCoreJni])
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodRefs.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodRefs.scala
deleted file mode 100644
index 04aed3e12..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/JniMethodRefs.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen
-
-import java.lang.reflect.Modifier
-
-import im.tox.tox4j.impl.jni.codegen.NameConversions.cxxVarName
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-import im.tox.tox4j.impl.jni.{ ToxAvJni, ToxCoreJni, ToxCryptoJni }
-
-object JniMethodRefs extends CodeGenerator {
-
- def generateNativeDecls(clazz: Class[_]): TranslationUnit = {
- clazz.getDeclaredMethods
- .filter { method =>
- Modifier.isNative(method.getModifiers) &&
- !Seq("invoke", "tox4j").exists(method.getName.startsWith)
- }
- .sortBy(method => method.getName)
- .flatMap { method =>
- Seq(
- MacroCall(FunCall(Identifier("JAVA_METHOD_REF"), Seq(Identifier(method.getName)))),
- MacroCall(FunCall(Identifier("CXX_FUNCTION_REF"), Seq(Identifier(cxxVarName(method.getName)))))
- )
- }
- }
-
- writeCode("ToxAv/generated/natives.h", "\n") {
- Comment(classOf[ToxAvJni].getName) +:
- generateNativeDecls(classOf[ToxAvJni])
- }
-
- writeCode("ToxCore/generated/natives.h", "\n") {
- Comment(classOf[ToxCoreJni].getName) +:
- generateNativeDecls(classOf[ToxCoreJni])
- }
-
- writeCode("ToxCrypto/generated/natives.h", "\n") {
- Comment(classOf[ToxCryptoJni].getName) +:
- generateNativeDecls(classOf[ToxCryptoJni])
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Ast.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Ast.scala
deleted file mode 100644
index f00818350..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Ast.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen.cxx
-
-// scalastyle:ignore number.of.types
-object Ast {
-
- /**
- * Types.
- */
- sealed trait Type
-
- final case class Typename(name: String) extends Type
- final case class Static(inner: Type) extends Type
- final case class Const(inner: Type) extends Type
- final case class Pointer(inner: Type) extends Type
- final case class Reference(inner: Type) extends Type
-
- object Type {
- val void: Typename = Typename("void")
- val jint: Typename = Typename("jint")
- val jboolean: Typename = Typename("jboolean")
- }
-
- /**
- * Pre-processing directives.
- */
- sealed trait Preproc extends Decl with Stmt
-
- final case class Include(header: String) extends Preproc
- final case class Ifdef(name: String) extends Preproc
- final case class Comment(text: String) extends Preproc
- final case class MacroCall(expr: FunCall) extends Preproc
- final case class MacroFun(init: FunCall, body: CompoundStmt) extends Preproc
- final case class ToxFun(returnType: Type, name: String, params: Seq[Param], body: CompoundStmt) extends Preproc
- case object Endif extends Preproc
-
- /**
- * Statements.
- */
- sealed trait Stmt
-
- final case class Switch(cond: Expr, body: CompoundStmt) extends Stmt
- final case class Case(expr: Expr, body: Stmt) extends Stmt
- final case class Default(body: Stmt) extends Stmt
- case object Break extends Stmt
- final case class Return(expr: Option[Expr] = None) extends Stmt
- final case class ExprStmt(expr: Expr) extends Stmt
- final case class CompoundStmt(body: Seq[Stmt]) extends Stmt
- final case class Oneliner(stmts: Stmt*) extends Stmt
-
- object Return {
- def apply(expr: Expr): Return = apply(Some(expr))
- }
-
- object CompoundStmt {
- def apply(s1: Stmt): CompoundStmt = apply(Seq(s1))
- def apply(s1: Stmt, s2: Stmt): CompoundStmt = apply(Seq(s1, s2))
- def apply(s1: Stmt, s2: Stmt, s3: Stmt): CompoundStmt = apply(Seq(s1, s2, s3))
- }
-
- /**
- * Expressions.
- */
- sealed trait Expr
-
- final case class Identifier(name: String) extends Expr
- final case class IntegerLiteral(value: Int) extends Expr
- final case class StringLiteral(value: String) extends Expr
- final case class FunCall(callee: Expr, args: Seq[Expr]) extends Expr
- final case class BinaryOperator(op: String, lhs: Expr, rhs: Expr) extends Expr
-
- final case class Access(expr: Expr, name: String) extends Expr
- final case class Equals(lhs: Expr, rhs: Expr) extends Expr
-
- /**
- * Declarations.
- */
- sealed trait Decl
-
- type TranslationUnit = Seq[Decl]
- final case class Fun(returnType: Type, name: String, params: Seq[Param], body: CompoundStmt) extends Decl
- final case class TemplateFun(typeParams: Seq[String], typeArgs: Seq[Type], fun: Fun) extends Decl
- final case class Param(paramType: Type, name: String) extends Decl
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Print.scala b/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Print.scala
deleted file mode 100644
index 80a97b5fe..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/codegen/cxx/Print.scala
+++ /dev/null
@@ -1,119 +0,0 @@
-package im.tox.tox4j.impl.jni.codegen.cxx
-
-import gnieh.pp._
-import im.tox.tox4j.impl.jni.codegen.cxx.Ast._
-import org.apache.commons.lang3.StringEscapeUtils
-
-@SuppressWarnings(Array("org.wartremover.warts.Recursion"))
-object Print {
-
- private def flatten(docs: Seq[Doc], sep: Doc = empty): Doc = {
- docs match {
- case Nil => empty
- case head +: tail =>
- tail.foldLeft(head)((a, b) => a :: sep :: b)
- }
- }
-
- private def printSeq[T](nodes: Seq[T], sep: Doc = empty)(printT: T => Doc): Doc = {
- flatten(nodes.map(printT), sep)
- }
-
- /**
- * Types.
- */
- private def printTypeInner(ty: Type): Doc = {
- ty match {
- case Typename(name) => text(name) :: space
- case Static(inner) => "static " :: printTypeInner(inner)
- case Const(inner) => printTypeInner(inner) :: "const "
- case Pointer(inner) => printTypeInner(inner) :: "*"
- case Reference(inner) => printTypeInner(inner) :: "&"
- }
- }
-
- def printType(ty: Type, spacing: Doc = empty): Doc = {
- ty match {
- case Typename(name) => text(name) :: spacing
- case _ => printTypeInner(ty)
- }
- }
-
- /**
- * Pre-processing directives.
- */
- def printPreproc(pp: Preproc): Doc = {
- pp match {
- case Include(header) => "#include \"" :: header :: "\""
- case Ifdef(name) => "#ifdef " :: name
- case Comment(text) => "// " :: text
- case Endif => "#endif"
- case MacroCall(expr) => printExpr(expr)
- case MacroFun(init, body) => printExpr(init) :|: printStmt(body)
- case ToxFun(returnType, name, params, body) =>
- "JAVA_METHOD" :+: nest(2)("(" :: printType(returnType) :: "," :+: name :: "," :|:
- printSeq(params, "," :: space)(printDecl) :: ")") :|:
- printStmt(body)
- }
- }
-
- /**
- * Statements.
- */
- @SuppressWarnings(Array("org.wartremover.warts.TraversableOps"))
- def printStmt(stmt: Stmt, spacing: Doc = line): Doc = { // scalastyle:ignore cyclomatic.complexity
- stmt match {
- case Switch(cond, CompoundStmt(cases)) =>
- "switch (" :: printExpr(cond) :: nest(2)(")" :|:
- "{" :|:
- printSeq(cases)(printStmt(_)) ::
- "}") ::
- line
- case Switch(cond, body) => sys.error(s"invalid switch-body: $body")
- case Case(expr, body) => "case" :+: printExpr(expr) :: ":" :+: printStmt(body)
- case Default(body) => "default:" :+: printStmt(body)
- case Break => "break;"
- case Return(expr) => "return" :: expr.fold(empty)(expr => space :: printExpr(expr)) :: ";" :: spacing
- case ExprStmt(expr) => printExpr(expr) :: ";" :: spacing
- case CompoundStmt(Seq(stmt0)) => nest(2)("{" :|: printStmt(stmt0, empty)) :|: "}"
- case CompoundStmt(stmts) => nest(2)("{" :|: printSeq(stmts.slice(0, stmts.length - 1))(printStmt(_))) :: printStmt(stmts.last) :: "}"
- case stmt: Oneliner => group(printSeq(stmt.stmts)(printStmt(_, empty))) :: spacing
- case pp: Preproc => printPreproc(pp)
- }
- }
-
- /**
- * Expressions.
- */
- def printExpr(expr: Expr): Doc = {
- expr match {
- case Identifier(name) => name
- case IntegerLiteral(value) => value
- case StringLiteral(value) => "\"" :: StringEscapeUtils.escapeJava(value) :: "\""
- case FunCall(callee, args) => printExpr(callee) :+: "(" :: printSeq(args, "," :: space)(printExpr) :: ")"
- case BinaryOperator(op, lhs, rhs) => printExpr(lhs) :+: op :+: printExpr(rhs)
- case Equals(lhs, rhs) => printExpr(lhs) :+: "==" :+: printExpr(rhs)
- case Access(lhs, name) => printExpr(lhs) :: "." :: name
- }
- }
-
- /**
- * Declarations.
- */
- def printDecl(decl: Decl): Doc = {
- decl match {
- case Fun(ty, name, params, body) =>
- printType(ty) :|: name :+: "(" :: printSeq(params, "," :: space)(printDecl) :: ")" :|: printStmt(body)
-
- case TemplateFun(tparams, targs, Fun(ty, name, params, body)) =>
- "template<" :: flatten(tparams.map("typename" :+: _)) :: ">" :|:
- printType(ty) :|:
- name :: "<" :: flatten(targs.map(printType(_))) :: "> (" :: printSeq(params, "," :: space)(printDecl) :: ")" :|:
- printStmt(body)
-
- case Param(ty, name) => printType(ty, space) :: name
- case pp: Preproc => printPreproc(pp)
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/internal/EventTest.scala b/src/test/java/im/tox/tox4j/impl/jni/internal/EventTest.scala
deleted file mode 100644
index 8ff31ffcb..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/internal/EventTest.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package im.tox.tox4j.impl.jni.internal
-
-import org.scalatest.FlatSpec
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-class EventTest extends FlatSpec {
-
- "callback" should "be called on run()" in {
- val event = new Event
- var called = false
-
- val id = event += (() => called = true)
-
- event()
- assert(called)
- }
-
- it should "be called twice if run() is called twice" in {
- val event = new Event
- var called = 0
-
- val id = event += (() => called += 1)
-
- event()
- assert(called == 1)
- event()
- assert(called == 2)
- }
-
- it should "not be called if it was deleted" in {
- val event = new Event
- var called = false
-
- val id = event += (() => called = true)
-
- event -= id
-
- event()
- assert(!called)
- }
-
- "remove" should "be idempotent" in {
- val event = new Event
- var called = 0
-
- val id1 = event += (() => called = 1)
- val id2 = event += (() => called = 2)
-
- event -= id1
- event -= id1
-
- event()
- assert(called == 2)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/impl/jni/package.scala b/src/test/java/im/tox/tox4j/impl/jni/package.scala
deleted file mode 100644
index ebeca1606..000000000
--- a/src/test/java/im/tox/tox4j/impl/jni/package.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j.impl
-
-import im.tox.documentation._
-
-package object jni extends Documented
diff --git a/src/test/java/im/tox/tox4j/impl/package.scala b/src/test/java/im/tox/tox4j/impl/package.scala
deleted file mode 100644
index 9b496d261..000000000
--- a/src/test/java/im/tox/tox4j/impl/package.scala
+++ /dev/null
@@ -1,5 +0,0 @@
-package im.tox.tox4j
-
-import im.tox.documentation._
-
-package object impl extends Documented
diff --git a/src/test/java/im/tox/tox4j/package.scala b/src/test/java/im/tox/tox4j/package.scala
deleted file mode 100644
index 4fdff96c6..000000000
--- a/src/test/java/im/tox/tox4j/package.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-package im.tox
-
-import im.tox.documentation._
-
-package object tox4j extends Documented {
- doc"""
- |Low level Tox network interfaces.
- |
- |The packages are organised by subsystem:
- |- A/V in ${av.name}
- |- Regular text messaging and group chats in ${core.name}
- |- Cryptographic primitives in ${crypto.name}
- |
- |The subsystem packages define data structures and interfaces for all low level Tox library operations. Various
- |implementations of these interfaces is contained within subpackages of the ${impl.name} package. The native
- |interface to the C library libtoxcore is located in ${impl.jni.name}.
- |
- |Each subsystem package contains one or more of the following subpackages:
- |- callbacks: Interfaces for the callbacks (event listeners). This package provides a combined Listener interface
- | (e.g. ${ref[core.callbacks.ToxCoreEventListener[_]]} which inherits from all the single callback interfaces
- | in the package. An Adapter class (e.g. ${ref[core.callbacks.ToxCoreEventAdapter[_]]}) provides empty default
- | implementations for all callbacks. Run ${ref(impl.jni.codegen.JniCallbacks)} to update the JNI bridge.
- |- enums: Java enums mirroring the C versions exactly. The enums' ordinal does not necessarily correspond to the C
- | enum value, but the JNI bridge needs to know the ordinals, so if you reorder these, then you must update the
- | bridge, by running ${ref(impl.jni.codegen.JniEnums)}.
- |- exceptions: Exception classes corresponding to the C API's error codes. One exception class for each error enum in
- | the C API. Each exception class contains a Code enum (e.g. ${ref[core.exceptions.ToxBootstrapException.Code]})
- | with all the errors that can occur in Java. If you change these, you need to update the JNI bridge by running
- | ${ref(impl.jni.codegen.JniErrorCodes)}.
- """
-}
diff --git a/src/test/java/im/tox/tox4j/testing/CheckedOrdering.scala b/src/test/java/im/tox/tox4j/testing/CheckedOrdering.scala
deleted file mode 100644
index 44e9ba066..000000000
--- a/src/test/java/im/tox/tox4j/testing/CheckedOrdering.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package im.tox.tox4j.testing
-
-import org.scalatest.Assertions
-
-/**
- * Wrap an [[Ordering]] in another [[Ordering]] that checks whether !(a < b) && !(b < a) => a == b.
- */
-object CheckedOrdering extends Assertions {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def apply[A](ord: Ordering[A]): Ordering[A] = {
- new Ordering[A] {
- override def compare(x: A, y: A): Int = {
- val result = ord.compare(x, y)
- if (result == 0) {
- assert(x == y)
- }
- result
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/CheckedOrderingEq.scala b/src/test/java/im/tox/tox4j/testing/CheckedOrderingEq.scala
deleted file mode 100644
index 8cdb4823d..000000000
--- a/src/test/java/im/tox/tox4j/testing/CheckedOrderingEq.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package im.tox.tox4j.testing
-
-import org.scalatest.Assertions
-
-/**
- * Wrap an [[Ordering]] in another [[Ordering]] that checks whether !(a < b) && !(b < a) => a eq b.
- */
-object CheckedOrderingEq extends Assertions {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def apply[A <: AnyRef](ord: Ordering[A]): Ordering[A] = {
- new Ordering[A] {
- override def compare(x: A, y: A): Int = {
- val result = ord.compare(x, y)
- if (result == 0) {
- assert(x eq y)
- }
- result
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/CountingOrdering.scala b/src/test/java/im/tox/tox4j/testing/CountingOrdering.scala
deleted file mode 100644
index d05abf70e..000000000
--- a/src/test/java/im/tox/tox4j/testing/CountingOrdering.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package im.tox.tox4j.testing
-
-/**
- * Wrapper for an [[Ordering]] that counts the number of comparisons made.
- */
-final case class CountingOrdering[A](ord: Ordering[A]) extends Ordering[A] {
-
- var count: Int = 0
-
- override def compare(x: A, y: A): Int = {
- count += 1
- ord.compare(x, y)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/GetDisjunction.scala b/src/test/java/im/tox/tox4j/testing/GetDisjunction.scala
deleted file mode 100644
index 9b2296e5a..000000000
--- a/src/test/java/im/tox/tox4j/testing/GetDisjunction.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-package im.tox.tox4j.testing
-
-import im.tox.core.error.CoreError
-import im.tox.core.typesafe.{ -\/, \/, \/- }
-import org.scalatest.Assertions
-
-import scala.language.implicitConversions
-
-final case class GetDisjunction[T] private (disjunction: CoreError \/ T) extends Assertions {
- def get: T = {
- disjunction match {
- case -\/(error) => fail(error.toString)
- case \/-(success) => success
- }
- }
-}
-
-object GetDisjunction {
-
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit def toGetDisjunction[T](disjunction: CoreError \/ T): GetDisjunction[T] = GetDisjunction(disjunction)
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/ToxExceptionChecks.scala b/src/test/java/im/tox/tox4j/testing/ToxExceptionChecks.scala
deleted file mode 100644
index d73bb021a..000000000
--- a/src/test/java/im/tox/tox4j/testing/ToxExceptionChecks.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package im.tox.tox4j.testing
-
-import im.tox.tox4j.exceptions.ToxException
-import org.scalatest.Assertions
-
-trait ToxExceptionChecks extends Assertions {
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected def intercept[E <: Enum[E]](code: E)(f: => Unit) = {
- try {
- f
- fail(s"Expected exception with code ${code.name}")
- } catch {
- case e: ToxException[_] =>
- assert(e.code eq code)
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/ToxTestMixin.scala b/src/test/java/im/tox/tox4j/testing/ToxTestMixin.scala
deleted file mode 100644
index 4e194b844..000000000
--- a/src/test/java/im/tox/tox4j/testing/ToxTestMixin.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-package im.tox.tox4j.testing
-
-import im.tox.core.error.CoreError
-import im.tox.core.typesafe.\/
-import im.tox.tox4j.DhtNodeSelector._
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.exceptions.{ ToxBootstrapException, ToxFriendAddException, ToxNewException }
-import im.tox.tox4j.impl.jni.ToxCoreImplFactory
-import org.jetbrains.annotations.NotNull
-
-import scala.language.implicitConversions
-
-trait ToxTestMixin extends ToxExceptionChecks {
-
- protected def interceptWithTox[E <: Enum[E]](code: E)(f: ToxCore => Unit) = {
- intercept(code) {
- ToxCoreImplFactory.withToxUnit { tox =>
- addFriends(tox, 1)
- f(tox)
- }
- }
- }
-
- @throws[ToxNewException]
- @throws[ToxFriendAddException]
- protected def addFriends(@NotNull tox: ToxCore, count: Int): ToxFriendNumber = {
- (0 until count).map { (i: Int) =>
- ToxCoreImplFactory.withToxUnit { friend =>
- tox.addFriendNorequest(friend.getPublicKey)
- }
- }.lastOption match {
- case None => throw new IllegalArgumentException(s"Cannot add less than 1 friend: $count")
- case Some(num) => num
- }
- }
-
- @throws[ToxBootstrapException]
- def bootstrap(useIPv6: Boolean, udpEnabled: Boolean, @NotNull tox: ToxCore): ToxCore = {
- if (!udpEnabled) {
- tox.addTcpRelay(node.ipv4, node.tcpPort, node.dhtId)
- }
- tox.bootstrap(
- if (useIPv6) node.ipv6 else node.ipv4,
- if (udpEnabled) node.udpPort else node.tcpPort,
- node.dhtId
- )
- tox
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
- implicit final def toGetDisjunction[T](disjunction: CoreError \/ T): GetDisjunction[T] = {
- GetDisjunction.toGetDisjunction(disjunction)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTest.scala b/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTest.scala
deleted file mode 100644
index 650cbd3d0..000000000
--- a/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTest.scala
+++ /dev/null
@@ -1,136 +0,0 @@
-package im.tox.tox4j.testing.autotest
-
-import im.tox.tox4j.TestConstants._
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.options.ProxyOptions
-import im.tox.tox4j.impl.jni.{ ToxAvImplFactory, ToxCoreImplFactory }
-import im.tox.tox4j.{ SocksServer, ToxCoreTestBase }
-import org.scalatest.concurrent.TimeLimits
-import org.scalatest.exceptions.TestFailedDueToTimeoutException
-
-import scala.language.postfixOps
-
-abstract class AliceBobTest extends AliceBobTestBase with TimeLimits {
-
- protected def ignoreTimeout = false
-
- protected def enableUdp = true
- protected def enableTcp = false
- protected def enableIpv4 = true
- protected def enableIpv6 = false
- protected def enableHttp = false
- protected def enableSocks = false
-
- private def withBootstrappedTox(
- ipv6Enabled: Boolean,
- udpEnabled: Boolean,
- proxyOptions: ProxyOptions = ProxyOptions.None
- )(
- f: ToxCore => Unit
- ): Unit = {
- ToxCoreImplFactory.withToxS[Unit](ipv6Enabled, udpEnabled, proxyOptions) { tox =>
- bootstrap(ipv6Enabled, udpEnabled, tox)
- f(tox)
- }
- }
-
- private def withToxAv(tox: ToxCore)(f: ToxAv => Unit): Unit = {
- ToxAvImplFactory.withToxAv(tox)(f)
- }
-
- private def runAliceBobTest_Direct(withTox: => (ToxCore => Unit) => Unit): Unit = {
- failAfter(Timeout) {
- runAliceBobTest(
- withTox,
- withToxAv
- )
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- private def runAliceBobTest_Socks(ipv6Enabled: Boolean, udpEnabled: Boolean): Unit = {
- val proxy = SocksServer.withServer { proxy =>
- failAfter(Timeout) {
- runAliceBobTest(
- withBootstrappedTox(ipv6Enabled, udpEnabled, new ProxyOptions.Socks5(proxy.getAddress, proxy.getPort)),
- withToxAv
- )
- }
- proxy
- }
- if (!udpEnabled) {
- assert(proxy.getAccepted == 2)
- }
- }
-
- test("UDP4") {
- assume(enableUdp)
- assume(enableIpv4)
- try {
- runAliceBobTest_Direct(ToxCoreImplFactory.withToxS(ipv6Enabled = false, udpEnabled = true))
- } catch {
- case e: TestFailedDueToTimeoutException if ignoreTimeout =>
- cancel(s"Test timed out after $Timeout", e)
- }
- }
-
- test("UDP6") {
- assume(enableUdp)
- assume(enableIpv6)
- failAfter(Timeout) {
- runAliceBobTest_Direct(ToxCoreImplFactory.withToxS(ipv6Enabled = true, udpEnabled = true))
- }
- }
-
- test("TCP4") {
- assume(enableTcp)
- assume(enableIpv4)
- assume(ToxCoreTestBase.checkIPv4.isEmpty)
- failAfter(Timeout) {
- runAliceBobTest_Direct(withBootstrappedTox(ipv6Enabled = false, udpEnabled = false))
- }
- }
-
- test("TCP6") {
- assume(enableTcp)
- assume(enableIpv6)
- assume(ToxCoreTestBase.checkIPv6.isEmpty)
- failAfter(Timeout) {
- runAliceBobTest_Direct(withBootstrappedTox(ipv6Enabled = true, udpEnabled = false))
- }
- }
-
- test("UDP4+SOCKS5") {
- assume(enableUdp)
- assume(enableIpv4)
- assume(enableSocks)
- assume(ToxCoreTestBase.checkIPv4.isEmpty)
- runAliceBobTest_Socks(ipv6Enabled = false, udpEnabled = true)
- }
-
- test("UDP6+SOCKS5") {
- assume(enableUdp)
- assume(enableIpv6)
- assume(enableSocks)
- assume(ToxCoreTestBase.checkIPv6.isEmpty)
- runAliceBobTest_Socks(ipv6Enabled = true, udpEnabled = true)
- }
-
- test("TCP4+SOCKS5") {
- assume(enableTcp)
- assume(enableIpv4)
- assume(enableSocks)
- assume(ToxCoreTestBase.checkIPv4.isEmpty)
- runAliceBobTest_Socks(ipv6Enabled = false, udpEnabled = false)
- }
-
- test("TCP6+SOCKS5") {
- assume(enableTcp)
- assume(enableIpv6)
- assume(enableSocks)
- assume(ToxCoreTestBase.checkIPv6.isEmpty)
- runAliceBobTest_Socks(ipv6Enabled = true, udpEnabled = false)
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTestBase.scala b/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTestBase.scala
deleted file mode 100644
index 2fd1b2a70..000000000
--- a/src/test/java/im/tox/tox4j/testing/autotest/AliceBobTestBase.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-package im.tox.tox4j.testing.autotest
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.OptimisedIdOps._
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.testing.ToxTestMixin
-import im.tox.tox4j.testing.autotest.AliceBobTestBase.Chatter
-import org.scalatest.FunSuite
-import org.slf4j.LoggerFactory
-
-import scala.annotation.tailrec
-
-object AliceBobTestBase {
- val FriendNumber: ToxFriendNumber = ToxFriendNumber.fromInt(10).get
-
- final case class Chatter[T](
- tox: ToxCore,
- av: ToxAv,
- client: ChatClientT[T],
- state: ChatStateT[T]
- )
-}
-
-abstract class AliceBobTestBase extends FunSuite with ToxTestMixin {
-
- protected val logger = Logger(LoggerFactory.getLogger(classOf[AliceBobTestBase]))
-
- protected type State
- protected type ChatState = ChatStateT[State]
- protected type ChatClient = ChatClientT[State]
-
- protected def initialState: State
-
- protected def newChatClient(name: String, expectedFriendName: String): ChatClient
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- private def getTopLevelMethod(stackTrace: Seq[StackTraceElement]): String = {
- stackTrace
- .filter(_.getClassName == classOf[AliceBobTest].getName)
- .lastOption
- .fold("")(_.getMethodName)
- }
-
- @tailrec
- private def mainLoop(clients: Seq[Chatter[State]]): Unit = {
- val nextState = clients.map {
- case Chatter(tox, av, client, state) =>
- Chatter[State](tox, av, client, state |> tox.iterate(client) |> (_.runTasks(tox, av)))
- }
-
- val interval = (nextState.map(_.tox.iterationInterval) ++ nextState.map(_.av.iterationInterval)).min
- Thread.sleep(interval)
-
- if (nextState.exists(_.state.chatting)) {
- mainLoop(nextState)
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- protected def runAliceBobTest(
- withTox: (ToxCore => Unit) => Unit,
- withToxAv: ToxCore => (ToxAv => Unit) => Unit
- ): Unit = {
- val method = getTopLevelMethod(Thread.currentThread.getStackTrace)
- logger.info(s"[${Thread.currentThread.getId}] --- ${getClass.getSimpleName}.$method")
-
- val aliceChat = newChatClient("Alice", "Bob")
- val bobChat = newChatClient("Bob", "Alice")
-
- withTox { alice =>
- withTox { bob =>
- withToxAv(alice) { aliceAv =>
- withToxAv(bob) { bobAv =>
- assert(alice ne bob)
-
- addFriends(alice, AliceBobTestBase.FriendNumber.value)
- addFriends(bob, AliceBobTestBase.FriendNumber.value)
-
- alice.addFriendNorequest(bob.getPublicKey)
- bob.addFriendNorequest(alice.getPublicKey)
-
- aliceChat.expectedFriendAddress = bob.getAddress
- bobChat.expectedFriendAddress = alice.getAddress
-
- val aliceState = aliceChat.setup(alice)(ChatStateT[State](initialState))
- val bobState = bobChat.setup(bob)(ChatStateT[State](initialState))
-
- mainLoop(Seq(
- Chatter(alice, aliceAv, aliceChat, aliceState),
- Chatter(bob, bobAv, bobChat, bobState)
- ))
- }
- }
- }
- }
- }
-}
diff --git a/src/test/java/im/tox/tox4j/testing/autotest/AutoTest.scala b/src/test/java/im/tox/tox4j/testing/autotest/AutoTest.scala
deleted file mode 100644
index 7cd2c461e..000000000
--- a/src/test/java/im/tox/tox4j/testing/autotest/AutoTest.scala
+++ /dev/null
@@ -1,170 +0,0 @@
-package im.tox.tox4j.testing.autotest
-
-import com.typesafe.scalalogging.Logger
-import im.tox.core.typesafe.Equals._
-import im.tox.tox4j.OptimisedIdOps._
-import im.tox.tox4j.ToxEventListener
-import im.tox.tox4j.av.{ ToxAv, ToxAvFactory }
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.core.{ ToxCore, ToxCoreFactory }
-import im.tox.tox4j.testing.autotest.AutoTest._
-import im.tox.tox4j.testing.autotest.AutoTestSuite.timed
-import org.slf4j.LoggerFactory
-
-import scala.annotation.tailrec
-
-object AutoTest {
-
- type Task[S] = (ToxCore, ToxAv, ClientState[S]) => ClientState[S]
-
- /**
- * A participant in the test network. These are unique across all instances,
- * so they are useful for logging and to put oneself into relation with other
- * instances using the instance map [[ClientState.friendList]].
- */
- final case class ParticipantId(private val value: Int) extends AnyVal {
- def prev: ParticipantId = copy(value - 1)
- def next: ParticipantId = copy(value + 1)
- override def toString: String = s"#$value"
- }
-
- final case class ClientState[S](
- id: ParticipantId,
- friendList: Map[ToxFriendNumber, ParticipantId],
- state: S,
- tasks: List[(Int, Task[S])] = Nil,
- running: Boolean = true
- ) {
-
- def finish: ClientState[S] = {
- copy(running = false)
- }
-
- private[AutoTest] def updateTasks(interval: Int, tasks: List[(Int, Task[S])]): ClientState[S] = {
- copy(tasks = tasks.map {
- case (delay, task) => (delay - interval, task)
- })
- }
-
- def addTask(task: Task[S]): ClientState[S] = {
- copy(tasks = (0, task) :: tasks)
- }
-
- def addTask(delay: Int)(task: Task[S]): ClientState[S] = {
- copy(tasks = (delay, task) :: tasks)
- }
-
- def get: S = state
- def put(state: S): ClientState[S] = copy(state = state)
-
- def modify(f: S => S): ClientState[S] = {
- copy(state = f(state))
- }
-
- def id(friendNumber: ToxFriendNumber): ParticipantId = {
- friendList(friendNumber)
- }
-
- }
-
- abstract class EventListener[S] extends ToxEventListener[ClientState[S]] {
- type State = ClientState[S]
- def initial: S
- }
-
- final case class Participant[S](
- tox: ToxCore,
- av: ToxAv,
- handler: EventListener[S],
- state: ClientState[S]
- )
-
-}
-
-final case class AutoTest(
- coreFactory: ToxCoreFactory,
- avFactory: ToxAvFactory
-) {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- private def performTasks[S](
- tox: ToxCore,
- av: ToxAv,
- interval: Int
- )(state: ClientState[S]): ClientState[S] = {
- val (delayed, runnable) = state.tasks.partition(_._1 >= 0)
- logger.trace(s"Running tasks: ${runnable.size} runnable, ${delayed.size} delayed")
-
- runnable.foldRight(state.updateTasks(interval max 1, delayed)) { (task, state) =>
- assert(task._1 <= 0)
- task._2(tox, av, state)
- }
- }
-
- @tailrec
- private def mainLoop[S](clients: List[Participant[S]], iteration: Int = 0): List[S] = {
- val interval = (clients.map(_.tox.iterationInterval) ++ clients.map(_.av.iterationInterval)).min
- assert(interval >= 0)
-
- val (iterationTime, nextClients) = timed {
- clients.map {
- case Participant(tox, av, handler, state) =>
- Participant(
- tox, av, handler,
- state
- |> tox.iterate(handler)
- |> av.iterate(handler)
- |> performTasks(tox, av, interval)
- )
- }
- }
-
- val sleepTime = (interval - iterationTime) max 0
- logger.trace(s"Iteration $iteration, interval=$interval, iterationTime=$iterationTime, sleepTime=$sleepTime")
- Thread.sleep(sleepTime)
-
- if (nextClients.exists(_.state.running)) {
- mainLoop(nextClients, iteration + 1)
- } else {
- nextClients.map(_.state.state)
- }
- }
-
- def run[S](
- count: Int,
- options: ToxOptions,
- handler: EventListener[S]
- ): List[S] = {
- coreFactory.withToxN[List[S]](count, options) { toxes =>
- avFactory.withToxAvN[List[S]](toxes) { avs =>
- val states = {
- val avsWithIds =
- for (((tox, av), id) <- avs.zipWithIndex) yield {
- (tox, av, ParticipantId(id))
- }
-
- for ((tox, av, id) <- avsWithIds) yield {
- // Everybody adds everybody else as friend.
- val friendList =
- for ((friendTox, friendAv, friendId) <- avsWithIds if friendId =/= id) yield {
- tox.addFriendNorequest(friendTox.getPublicKey) -> friendId
- }
- (tox, av, id, Map(friendList: _*))
- }
- }
-
- val participants =
- for ((tox, av, id, friendList) <- states) yield {
- logger.debug(s"Participant $id's friends: $friendList")
- assert(!friendList.valuesIterator.contains(id))
- Participant(tox, av, handler, ClientState(id, friendList, handler.initial))
- }
-
- mainLoop(participants)
- }
- }
- }
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/autotest/AutoTestSuite.scala b/src/test/java/im/tox/tox4j/testing/autotest/AutoTestSuite.scala
deleted file mode 100644
index abe5e662b..000000000
--- a/src/test/java/im/tox/tox4j/testing/autotest/AutoTestSuite.scala
+++ /dev/null
@@ -1,91 +0,0 @@
-package im.tox.tox4j.testing.autotest
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.TestConstants
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.core.options.ToxOptions
-import im.tox.tox4j.impl.jni.{ ToxAvImplFactory, ToxCoreImplFactory }
-import im.tox.tox4j.testing.autotest.AutoTest.ClientState
-import org.scalatest.FunSuite
-import org.scalatest.concurrent.TimeLimits
-import org.slf4j.LoggerFactory
-import shapeless.<:!<
-
-import scala.util.Random
-
-object AutoTestSuite {
-
- sealed abstract class Timed[A, R] {
-
- protected def wrap(time: Int, result: A): R
-
- def timed(block: => A): R = {
- val start = System.currentTimeMillis()
- val result = block
- val end = System.currentTimeMillis()
- wrap((end - start).toInt, result)
- }
-
- }
-
- implicit def otherTimed[A](implicit notUnit: A <:!< Unit): Timed[A, (Int, A)] = new Timed[A, (Int, A)] {
- protected def wrap(time: Int, result: A): (Int, A) = (time, result)
- }
- implicit val unitTimed: Timed[Unit, Int] = new Timed[Unit, Int] {
- protected def wrap(time: Int, result: Unit): Int = time
- }
-
- def timed[A, R](block: => A)(implicit timed: Timed[A, R]): R = timed.timed(block)
-
-}
-
-abstract class AutoTestSuite extends FunSuite with TimeLimits {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- protected def maxParticipantCount: Int = 2
-
- type S
-
- abstract class EventListener(val initial: S) extends AutoTest.EventListener[S] {
-
- override def selfConnectionStatus(
- connectionStatus: ToxConnection
- )(state: State): State = {
- debug(state, s"Our connection: $connectionStatus")
- state
- }
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state: State): State = {
- debug(state, s"Friend ${state.id(friendNumber)}'s connection: $connectionStatus")
- state
- }
-
- }
-
- def Handler: EventListener // scalastyle:ignore method.name
-
- protected def debug(state: ClientState[S], message: String): Unit = {
- logger.debug(s"[${state.id}] $message")
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- def run(ipv6Enabled: Boolean = true, udpEnabled: Boolean = true): Unit = {
- failAfter(TestConstants.Timeout) {
- val participantCount =
- if (maxParticipantCount == 2) {
- maxParticipantCount
- } else {
- new Random().nextInt(maxParticipantCount - 2) + 2
- }
- AutoTest(ToxCoreImplFactory, ToxAvImplFactory).run(participantCount, ToxOptions(ipv6Enabled, udpEnabled), Handler)
- }
- }
-
- test("UDP")(run(ipv6Enabled = true, udpEnabled = true))
-
-}
diff --git a/src/test/java/im/tox/tox4j/testing/autotest/ChatClient.scala b/src/test/java/im/tox/tox4j/testing/autotest/ChatClient.scala
deleted file mode 100644
index 33cf662ba..000000000
--- a/src/test/java/im/tox/tox4j/testing/autotest/ChatClient.scala
+++ /dev/null
@@ -1,124 +0,0 @@
-package im.tox.tox4j.testing.autotest
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.core._
-import im.tox.tox4j.core.callbacks.ToxCoreEventAdapter
-import im.tox.tox4j.core.data.{ ToxFriendNumber, ToxFriendAddress, ToxPublicKey }
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.exceptions.ToxException
-import im.tox.tox4j.testing.GetDisjunction._
-import org.slf4j.LoggerFactory
-
-import scala.annotation.tailrec
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final case class ChatStateT[T](
- state: T,
- tasks: Seq[((ToxCore, ToxAv, ChatStateT[T]) => ChatStateT[T], Array[StackTraceElement])] = Nil,
- chatting: Boolean = true
-) {
-
- private def assembleStackTrace(e: ToxException[_], creationTrace: Array[StackTraceElement]): ToxException[_] = {
- // The stack until the performTasks method call.
- val untilPerformTasks = e.getStackTrace
- .reverse
- .dropWhile { callSite =>
- !((callSite.getClassName == classOf[ChatClientT[_]].getName) &&
- (callSite.getMethodName == "performTasks"))
- }
- .reverse
-
- // After that, add the task creation trace, minus the "addTask" method.
- val trace = untilPerformTasks ++ creationTrace
-
- // Put the assembled trace into the exception and return it.
- e.setStackTrace(trace)
-
- e
- }
-
- private[autotest] def runTasks(tox: ToxCore, av: ToxAv): ChatStateT[T] = {
- tasks.reverse.foldLeft(copy[T](tasks = Nil)) {
- case (nextState, (task, stacktrace)) =>
- try {
- task(tox, av, nextState)
- } catch {
- case e: ToxException[_] =>
- throw assembleStackTrace(e, stacktrace)
- }
- }
- }
-
- def addTask(task: (ToxCore, ToxAv, ChatStateT[T]) => ChatStateT[T]): ChatStateT[T] = {
- val creationTrace = Thread.currentThread.getStackTrace
- copy[T](tasks = (task, creationTrace.slice(2, creationTrace.length)) +: tasks)
- }
-
- def finish: ChatStateT[T] = {
- copy[T](chatting = false)
- }
-
- def get: T = state
-
- def set(value: T): ChatStateT[T] = {
- copy[T](state = value)
- }
-
- def map(f: T => T): ChatStateT[T] = {
- copy[T](state = f(state))
- }
-
- def flatMap(f: T => ChatStateT[T]): ChatStateT[T] = {
- f(state)
- }
-
-}
-
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-class ChatClientT[T](val selfName: String, val expectedFriendName: String) extends ToxCoreEventAdapter[ChatStateT[T]] {
-
- private val logger = Logger(LoggerFactory.getLogger(getOuterClass(getClass)))
-
- @tailrec
- private def getOuterClass(clazz: Class[_]): Class[_] = {
- Option(clazz.getEnclosingClass) match {
- case None => clazz
- case Some(enclosing) => getOuterClass(enclosing)
- }
- }
-
- protected def debug(message: String): Unit = {
- logger.info(s"[${Thread.currentThread.getId}] $selfName: $message")
- }
-
- var expectedFriendAddress: ToxFriendAddress = ToxFriendAddress.unsafeFromValue(null)
- protected def expectedFriendPublicKey: ToxPublicKey = {
- ToxPublicKey.fromValue(expectedFriendAddress.value.slice(0, ToxPublicKey.Size)).toOption.get
- }
-
- protected def isAlice = selfName == "Alice"
- protected def isBob = selfName == "Bob"
-
- def setup(tox: ToxCore)(state: ChatStateT[T]): ChatStateT[T] = state
-
- override def selfConnectionStatus(connectionStatus: ToxConnection)(state: ChatStateT[T]): ChatStateT[T] = {
- if (connectionStatus != ToxConnection.NONE) {
- debug(s"is now connected to the network with $connectionStatus")
- } else {
- debug("is now disconnected from the network")
- }
- state
- }
-
- override def friendConnectionStatus(friendNumber: ToxFriendNumber, connection: ToxConnection)(state: ChatStateT[T]): ChatStateT[T] = {
- assert(friendNumber == AliceBobTestBase.FriendNumber)
- if (connection != ToxConnection.NONE) {
- debug(s"is now connected to friend $friendNumber with $connection")
- } else {
- debug(s"is now disconnected from friend $friendNumber")
- }
- state
- }
-
-}
diff --git a/src/test/java/scalastyle-config.xml b/src/test/java/scalastyle-config.xml
deleted file mode 100644
index ff9cc5be8..000000000
--- a/src/test/java/scalastyle-config.xml
+++ /dev/null
@@ -1,265 +0,0 @@
-
- Scalastyle standard configuration
-
- Check the number of lines in a file
-
-
- 800
-
-
-
- Check the number of characters in a line
-
-
- 160
- 4
-
-
-
- Check that there are no tabs in a file
-
-
- Check the first lines of each file matches the text
- XXX: Disabled because we don't use file headers.
-
-
- Checks that lines are indented by a multiple of the tab size
- XXX: Disabled because we use scalariform on compile.
-
-
- Checks that a file ends with a newline character
-
-
- Checks that a file does not end with a newline character
- XXX: Disabled because it's the opposite of the one above.
-
-
- Checks that a regular expression cannot be matched, if found reports this
-
-
-
-
-
-
- Check that there is no trailing whitespace at the end of lines
-
-
- Checks that block imports are not used.
- XXX: Disabled because block imports decrease verbosity.
-
-
- Check that class names match a regular expression
-
-
-
-
-
-
- Checks that type parameter to a class matches a regular expression
-
-
-
-
-
-
- Check that classes and objects do not define equals without overriding equals(java.lang.Object).
-
-
- Checks that the cyclomatic complexity of a method does exceed a value
-
-
- 10
-
-
-
- Checks that Java @Deprecated is not used, Scala @deprecated should be used instead
-
-
- Disallow space after certain token(s)
-
-
- Disallow space before certain token(s)
-
-
- If a class/trait has no members, the braces are unnecessary
-
-
- Ensure single space after certain token(s)
-
-
- Ensure single space before certain token(s)
-
-
- Check that if a class implements either equals or hashCode, it should implement the other
-
-
- Check that field names match a regular expression
- XXX: Disabled due to https://github.com/scalastyle/scalastyle/issues/149.
-
-
-
-
-
-
- Checks that braces are used in for comprehensions.
- XXX: Disabled due to https://github.com/scalastyle/scalastyle/issues/142.
-
-
- Checks that if statements have braces
-
-
- true
- false
-
-
-
- Check that a class does not import certain classes
-
-
- android._,sun._
-
-
-
- Checks that imports are grouped together, not throughout the file
-
-
- Checks that a case statement pattern match is not lower case, as this can cause confusion
-
-
- Checks for use of magic numbers
-
-
- -1,0,1,2,3
-
-
-
- Checks that methods do not exceed a maximum length
-
-
- 50
-
-
-
- Check that method names match a regular expression
-
-
-
-
-
-
- Checks that a string literal does not appear multiple times
-
-
- Check that classes and objects do not define the clone() method
-
-
- Check that classes and objects do not define the finalize() method
-
-
- No whitespace after left bracket ‘[’
-
-
- No whitespace before left bracket ‘[’
-
-
- Some editors are unfriendly to non ascii characters.
-
-
- Checks that the code does not have ??? operators.
-
-
- Check that null is not used
-
-
- Check that a class / trait / object does not have too many methods
-
-
- 60
-
-
-
- Checks that there are not too many types declared in a file
-
-
- 30
-
-
-
- Check that object names match a regular expression
-
-
-
-
-
-
- Check that package object names match a regular expression
-
-
-
-
-
-
- Maximum number of parameters for a method
-
-
- 10
-
-
-
- Use a : Unit = for procedure declarations
- XXX: Disabled due to https://github.com/scalastyle/scalastyle/issues/145.
-
-
- Check that a method has an explicit return type, it is not inferred
-
-
- Checks that if expressions are not redundant, i.e. easily replaced by a variant of the condition
-
-
- Check that return is not used
-
-
- Checks that the ScalaDoc on documentable members is well-formed
-
-
- Boolean expression can be simplified
-
-
- Checks a space after the start of the comment.
-
-
- Check that the plus sign is followed by a space
-
-
- Check that the plus sign is preceded by a space
-
-
- Check that structural types are not used.
-
-
- Checks that a regular expression cannot be matched in a token, if found reports this
-
-
- Avoid wildcard imports
- XXX: Disabled because IDEA produces them.
-
-
- Checks that if a long literal is used, then an uppercase L is used
-
-
- Checks that classes and objects do not define mutable fields
-
-
- Checks that functions do not define mutable variables
-
-
- Checks that while is not used
-
-
- Check that XML literals are not used
-
-
- No-op checker
-
-
-
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
deleted file mode 100644
index 5d753bb6c..000000000
--- a/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-log4j.rootLogger=DEBUG, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.Target=System.out
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss.SSS}] %-5p %c{1} - %m%n
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioPlaybackShow.scala b/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioPlaybackShow.scala
deleted file mode 100644
index 56b8284f5..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioPlaybackShow.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import im.tox.tox4j.av.data.{ AudioLength, SampleCount, SamplingRate }
-
-@SuppressWarnings(Array("org.wartremover.warts.While"))
-object AudioPlaybackShow {
-
- private val audio = AudioGenerators.default
-
- private val samplingRate = SamplingRate.Rate24k
- private val audioLength = AudioLength.Length60
- private val frameSize = SampleCount(audioLength, samplingRate)
- private val playback = new AudioPlayback(samplingRate)
-
- def main(args: Array[String]) {
- val terminalWidth = 190
-
- System.out.print("\u001b[2J")
-
- for (t <- 0 to audio.length(samplingRate) by frameSize.value) {
- val frame = audio.nextFrame16(audioLength, samplingRate, t)
- System.out.print("\u001b[H")
- System.out.println(AudioPlayback.showWave(frame, terminalWidth))
- System.out.println(s"t=$t")
- System.out.flush()
- playback.play(frame)
- }
-
- while (!playback.done(audio.length(samplingRate))) {
- Thread.sleep(100)
- }
- }
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackShow.scala b/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackShow.scala
deleted file mode 100644
index 0152d8488..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/audio/AudioReceiveFrameCallbackShow.scala
+++ /dev/null
@@ -1,185 +0,0 @@
-package im.tox.tox4j.av.callbacks.audio
-
-import java.util
-import java.util.concurrent.ArrayBlockingQueue
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.ToxExceptionChecks
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-import org.slf4j.LoggerFactory
-
-import scala.annotation.tailrec
-
-/**
- * This test name does not end in "Test" so it won't be run by the CI build. This is
- * because the test is flaky by nature: it expects every lossy audio packet to arrive.
- * We keep it around, because it's fun, and because it tests something that is very
- * hard to test otherwise: the received audio sounds good. This either requires a human
- * or an algorithm we're too lazy to implement.
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class AudioReceiveFrameCallbackShow extends AutoTestSuite with ToxExceptionChecks {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
- private val terminalWidth = 190
-
- override def maxParticipantCount: Int = 2
-
- type S = Int
-
- object Handler extends EventListener(0) {
-
- private val bitRate = BitRate.fromInt(320).get
- private val audioPerFrame = AudioLength.Length40
- private val samplingRate = SamplingRate.Rate48k
- private val frameSize = SampleCount(audioPerFrame, samplingRate).value
- private val framesPerIteration = 2
-
- private val audio = AudioGenerators.default
- private val audioLength = audio.length(samplingRate)
- private val playback = new AudioPlayback(samplingRate)
- private val displayWave = !sys.env.contains("TRAVIS")
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state0: State): State = {
- val state = super.friendConnectionStatus(friendNumber, connectionStatus)(state0)
-
- if (connectionStatus == ToxConnection.NONE || state.id(friendNumber) != state.id.next) {
- state
- } else {
- // Call id+1.
- state.addTask { (tox, av, state) =>
- debug(state, s"Ringing ${state.id(friendNumber)}")
- av.call(friendNumber, bitRate, BitRate.Disabled)
- state
- }
- }
- }
-
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: State): State = {
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- debug(state, s"Got a call from ${state.id(friendNumber)}; accepting")
- av.answer(friendNumber, BitRate.Disabled, BitRate.Disabled)
- state
- }
- } else {
- fail(s"I shouldn't have been called by friend ${state.id(friendNumber)}")
- state
- }
- }
-
- // There is no stack recursion here, it pushes thunks of itself for deferred execution.
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def sendFrame(friendNumber: ToxFriendNumber)(tox: ToxCore, av: ToxAv, state0: State): State = {
- val state = state0.modify(_ + frameSize * framesPerIteration)
-
- for (t <- state0.get until state.get by frameSize) {
- val pcm = audio.nextFrame16(audioPerFrame, samplingRate, t)
- av.audioSendFrame(
- friendNumber,
- pcm,
- SampleCount(audioPerFrame, samplingRate),
- AudioChannels.Mono,
- samplingRate
- )
- }
-
- if (state.get >= audioLength) {
- state.finish
- } else {
- state.addTask(sendFrame(friendNumber))
- }
- }
-
- override def callState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState])(state: State): State = {
- debug(state, s"Call with ${state.id(friendNumber)} is now $callState")
- assert(callState == util.EnumSet.of(
- ToxavFriendCallState.ACCEPTING_A,
- ToxavFriendCallState.ACCEPTING_V
- ))
- state.addTask(sendFrame(friendNumber))
- }
-
- // There is no stack recursion here, it pushes thunks of itself for deferred execution.
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- def waitForPlayback(length: Int)(state: State): State = {
- if (!playback.done(length)) {
- state.addTask { (tox, av, state) =>
- waitForPlayback(length)(state)
- }
- } else {
- state.finish
- }
- }
-
- override def audioReceiveFrame(
- friendNumber: ToxFriendNumber,
- pcm: Array[Short],
- channels: AudioChannels,
- samplingRate: SamplingRate
- )(state0: State): State = {
- val state = state0.modify(_ + pcm.length)
-
- debug(state, s"Received audio frame: ${state.get} / ${audio.length(samplingRate)}")
- assert(channels == AudioChannels.Mono)
- assert(samplingRate == this.samplingRate)
- frameBuffer.add(Some((state0.get, pcm)))
-
- if (state.get >= audio.length(samplingRate)) {
- frameBuffer.add(None)
- waitForPlayback(audio.length(samplingRate))(state)
- } else {
- state
- }
- }
-
- @tailrec
- private def playFrames(queue: ArrayBlockingQueue[Option[(Int, Array[Short])]]): Unit = {
- queue.take() match {
- case Some((t, receivedPcm)) =>
- val expectedPcm = audio.nextFrame16(audioPerFrame, samplingRate, t)
-
- assert(receivedPcm.length == expectedPcm.length)
-
- if (displayWave) {
- if (t == 0) {
- System.out.print("\u001b[2J")
- }
- System.out.print("\u001b[H")
- System.out.println("Received:")
- System.out.println(AudioPlayback.showWave(receivedPcm, terminalWidth))
- System.out.println("Expected:")
- System.out.println(AudioPlayback.showWave(expectedPcm, terminalWidth))
- }
-
- playback.play(receivedPcm)
-
- playFrames(queue)
-
- case None =>
- logger.debug("Terminating audio playback thread")
- }
- }
-
- private lazy val frameBuffer = {
- // Make the queue large enough to hold half the audio frames.
- val queue = new ArrayBlockingQueue[Option[(Int, Array[Short])]](audioLength / frameSize / 2)
-
- // Start a thread to consume the frames.
- new Thread { override def run() { playFrames(queue) } }.start
-
- queue
- }
-
- }
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/video/ConsoleVideoDisplay.scala b/src/tools/java/im/tox/tox4j/av/callbacks/video/ConsoleVideoDisplay.scala
deleted file mode 100644
index 53bce9ef5..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/video/ConsoleVideoDisplay.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.io.PrintStream
-
-import im.tox.tox4j.av.data.{ Height, Width }
-
-import scala.util.{ Success, Try }
-
-final case class ConsoleVideoDisplay(width: Width, height: Height) extends VideoDisplay[Seq[String], PrintStream] {
-
- override protected def canvas: Try[PrintStream] = Success(System.out)
-
- override protected def displaySent(canvas: PrintStream, frameNumber: Int, senderImage: Seq[String]): Unit = {
- // Don't display the sent image in text mode.
- }
-
- override protected def displayReceived(canvas: PrintStream, frameNumber: Int, receiverImage: Seq[String]): Unit = {
- canvas.print("\u001b[H\u001b[2J")
- receiverImage.foreach(canvas.println)
- }
-
- override protected def parse(
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- ): Seq[String] = {
- val printable = ".-~:;/<>=()ot%!?@&O8SX$#"
-
- for (yPos <- 0 until height.value) yield {
- new String(y.slice(yPos * yStride, yPos * yStride + width.value).map {
- case b =>
- printable(((b & 0xff) / 255.0 * (printable.length - 1)).toInt)
- })
- }
- }
-
- override def close(): Unit = ()
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/video/GuiVideoDisplay.scala b/src/tools/java/im/tox/tox4j/av/callbacks/video/GuiVideoDisplay.scala
deleted file mode 100644
index 8ca29d3c4..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/video/GuiVideoDisplay.scala
+++ /dev/null
@@ -1,141 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.awt.Color
-import java.awt.image.{ BufferedImage, DataBufferByte }
-import java.io.File
-import javax.imageio.ImageIO
-import javax.swing.border.EtchedBorder
-import javax.swing.{ BorderFactory, ImageIcon, JDialog }
-
-import com.typesafe.scalalogging.Logger
-import im.tox.tox4j.av.callbacks.video.GuiVideoDisplay.{ UI, newImage }
-import im.tox.tox4j.av.data.{ Height, Width }
-import org.slf4j.LoggerFactory
-
-import scala.swing._
-import scala.util.Try
-
-object GuiVideoDisplay {
-
- private val capturePath = Some(new File("capture/video")).filter(_.isDirectory)
- capturePath.foreach(_.listFiles.foreach(_.delete()))
-
- private def newImage(width: Width, height: Height): BufferedImage = {
- new BufferedImage(width.value, height.value, BufferedImage.TYPE_3BYTE_BGR)
- }
-
- final class UI(width: Width, height: Height) {
-
- val senderImageView, receiverImageView: Label = new Label {
- border = BorderFactory.createEtchedBorder(EtchedBorder.RAISED)
- icon = new ImageIcon(newImage(width, height))
- }
-
- val senderLabel: Label = new Label("No frames sent yet")
- val receiverLabel: Label = new Label("No frames received yet")
-
- val dialog: Dialog = new Dialog(new Frame) {
- contents = new BoxPanel(Orientation.Vertical) {
- contents += new BoxPanel(Orientation.Horizontal) {
- contents += senderImageView
- contents += receiverImageView
- }
- contents += new BoxPanel(Orientation.Horizontal) {
- contents += Swing.HGlue
- contents += senderLabel
- contents += Swing.HGlue
- contents += Swing.HGlue
- contents += receiverLabel
- contents += Swing.HGlue
- }
- }
- }
-
- dialog.pack()
-
- /**
- * Align a width or height number to the next multiple of 2.
- * This is required so the dumped screenshots can be turned into a video by ffmpeg.
- */
- private def align(dimension: Int): Int = {
- dimension / 2 * 2 + 2
- }
-
- def screenshot(frameNumber: Int): Unit = {
- capturePath.foreach { capturePath =>
- val image = new BufferedImage(
- align(dialog.bounds.width),
- align(dialog.bounds.height),
- BufferedImage.TYPE_INT_RGB
- )
-
- dialog.self.asInstanceOf[JDialog].paint(image.getGraphics)
-
- ImageIO.write(image, "jpg", new File(capturePath, f"$frameNumber%03d.jpg"))
- }
- }
-
- }
-
-}
-
-final case class GuiVideoDisplay(width: Width, height: Height) extends RgbVideoDisplay[ImageIcon, UI] {
-
- private val logger = Logger(LoggerFactory.getLogger(getClass))
-
- override protected val canvas: Try[UI] = Try(new GuiVideoDisplay.UI(width, height))
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override protected def parse(r: Array[Byte], g: Array[Byte], b: Array[Byte]): ImageIcon = {
- val image = newImage(width, height)
-
- val data = image.getRaster.getDataBuffer.asInstanceOf[DataBufferByte].getData
- assert(data.length == r.length + g.length + b.length)
- for (index <- data.indices) {
- index % 3 match {
- case 0 => data(index) = b(index / 3)
- case 1 => data(index) = g(index / 3)
- case 2 => data(index) = r(index / 3)
- }
- }
-
- new ImageIcon(image)
- }
-
- override protected def displaySent(canvas: UI, frameNumber: Int, senderImage: ImageIcon): Unit = {
- Swing.onEDTWait {
- if (!canvas.dialog.visible) {
- canvas.dialog.visible = true
- }
- canvas.senderLabel.text = s"Sent frame #$frameNumber"
- canvas.senderImageView.icon = senderImage
-
- canvas.screenshot(frameNumber)
- }
- }
-
- @SuppressWarnings(Array("org.wartremover.warts.Equals"))
- override protected def displayReceived(canvas: UI, frameNumber: Int, receiverImage: ImageIcon): Unit = {
- Swing.onEDTWait {
- canvas.receiverLabel.text = s"Received frame #$frameNumber"
- canvas.receiverImageView.icon = receiverImage
-
- val FrameNumber = "Sent frame #(\\d+)".r
- val sentFrameNumber =
- canvas.senderLabel.text match {
- case FrameNumber(number) =>
- if (number.toInt != frameNumber) {
- canvas.receiverLabel.foreground = Color.RED
- canvas.receiverLabel.text += s" (${number.toInt - frameNumber} behind)"
- }
- number.toInt
- }
-
- // Overwrite the screenshot if this frame was received.
- canvas.screenshot(sentFrameNumber)
- }
- }
-
- override def close(): Unit = canvas.foreach(_.dialog.close())
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/video/RgbVideoDisplay.scala b/src/tools/java/im/tox/tox4j/av/callbacks/video/RgbVideoDisplay.scala
deleted file mode 100644
index 3c098ea98..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/video/RgbVideoDisplay.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-abstract class RgbVideoDisplay[Parsed, Canvas] extends VideoDisplay[Parsed, Canvas] {
-
- protected def parse(r: Array[Byte], g: Array[Byte], b: Array[Byte]): Parsed
-
- override protected final def parse(
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- ): Parsed = {
- val width = this.width.value
- val height = this.height.value
-
- val (r, g, b) = VideoConversions.YUVtoRGB(width, height, y, u, v, yStride, uStride, vStride)
- assert(r.length == width * height)
- assert(g.length == width * height)
- assert(b.length == width * height)
-
- parse(r, g, b)
- }
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoDisplay.scala b/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoDisplay.scala
deleted file mode 100644
index fdea1cf4a..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoDisplay.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.io.Closeable
-
-import im.tox.tox4j.av.data.{ Height, Width }
-import im.tox.tox4j.testing.autotest.AutoTestSuite.timed
-import org.scalatest.Assertions
-
-import scala.util.Try
-
-abstract class VideoDisplay[Parsed, Canvas] extends Assertions with Closeable {
-
- def width: Width
- def height: Height
-
- protected def canvas: Try[Canvas]
- protected def parse(
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- ): Parsed
- protected def displaySent(canvas: Canvas, frameNumber: Int, parsed: Parsed): Unit
- protected def displayReceived(canvas: Canvas, frameNumber: Int, parsed: Parsed): Unit
-
- final def displaySent(frameNumber: Int, y: Array[Byte], u: Array[Byte], v: Array[Byte]): Unit = {
- val width = this.width.value
- canvas.foreach(displaySent(_, frameNumber, parse(y, u, v, width, width / 2, width / 2)))
- }
-
- /**
- * @return (parseTime, displayTime)
- */
- final def displayReceived(
- frameNumber: Int,
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- ): Option[(Int, Int)] = {
- canvas.toOption.map { canvas =>
- val (parseTime, parsed) = timed(parse(y, u, v, yStride, uStride, vStride))
- val displayTime = timed(displayReceived(canvas, frameNumber, parsed))
-
- (parseTime, displayTime)
- }
- }
-
-}
diff --git a/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackShow.scala b/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackShow.scala
deleted file mode 100644
index 23d4b4eeb..000000000
--- a/src/tools/java/im/tox/tox4j/av/callbacks/video/VideoReceiveFrameCallbackShow.scala
+++ /dev/null
@@ -1,165 +0,0 @@
-package im.tox.tox4j.av.callbacks.video
-
-import java.io.{ DataOutputStream, File, FileOutputStream }
-import java.util
-
-import im.tox.tox4j.av.ToxAv
-import im.tox.tox4j.av.data._
-import im.tox.tox4j.av.enums.ToxavFriendCallState
-import im.tox.tox4j.core.ToxCore
-import im.tox.tox4j.core.data.ToxFriendNumber
-import im.tox.tox4j.core.enums.ToxConnection
-import im.tox.tox4j.testing.ToxExceptionChecks
-import im.tox.tox4j.testing.autotest.AutoTestSuite
-import im.tox.tox4j.testing.autotest.AutoTestSuite.timed
-
-/**
- * See [[im.tox.tox4j.av.callbacks.audio.AudioReceiveFrameCallbackShow]] for why this
- * class exists.
- */
-@SuppressWarnings(Array("org.wartremover.warts.Equals"))
-final class VideoReceiveFrameCallbackShow extends AutoTestSuite with ToxExceptionChecks {
-
- private val video = VideoGenerators.default
-
- /**
- * The time to wait for the next frame. Increase this if you need more time
- * to look at the displayed images.
- */
- private val frameDelay = 0
-
- private val bitRate = BitRate.fromInt(1).get
-
- /**
- * Base directory for sent frame capture. The files can be used to replay a
- * session in case of bugs.
- */
- private val capturePath = Some(new File("capture/videoSendFrame")).filter(_.isDirectory)
- capturePath.foreach(_.listFiles.foreach(_.delete()))
-
- override def maxParticipantCount: Int = 2
-
- type S = Int
-
- object Handler extends EventListener(0) {
-
- private lazy val displayImage = {
- if (sys.env.contains("TRAVIS")) {
- None
- } else {
- if (video.size <= 100 * 40) {
- Some(ConsoleVideoDisplay(video.width, video.height))
- } else {
- Some(GuiVideoDisplay(video.width, video.height))
- }
- }
- }
-
- override def friendConnectionStatus(
- friendNumber: ToxFriendNumber,
- connectionStatus: ToxConnection
- )(state0: State): State = {
- val state = super.friendConnectionStatus(friendNumber, connectionStatus)(state0)
-
- if (connectionStatus == ToxConnection.NONE || state.id(friendNumber) != state.id.next) {
- state
- } else {
- // Call id+1.
- state.addTask { (tox, av, state) =>
- debug(state, s"Ringing ${state.id(friendNumber)}")
- av.call(friendNumber, BitRate.Disabled, bitRate)
- state
- }
- }
- }
-
- override def call(friendNumber: ToxFriendNumber, audioEnabled: Boolean, videoEnabled: Boolean)(state: State): State = {
- if (state.id(friendNumber) == state.id.prev) {
- state.addTask { (tox, av, state) =>
- debug(state, s"Got a call from ${state.id(friendNumber)}; accepting")
- av.answer(friendNumber, BitRate.Disabled, BitRate.Disabled)
- state
- }
- } else {
- fail(s"I shouldn't have been called by friend ${state.id(friendNumber)}")
- state
- }
- }
-
- // There is no stack recursion here, it pushes thunks of itself for deferred execution.
- @SuppressWarnings(Array("org.wartremover.warts.Recursion"))
- private def sendFrame(friendNumber: ToxFriendNumber)(tox: ToxCore, av: ToxAv, state0: State): State = {
- val state = state0.modify(_ + 1)
-
- val (generationTime, (y, u, v)) = timed {
- video.yuv(state0.get)
- }
- assert(y.length == video.size)
- assert(u.length == video.size / 4)
- assert(v.length == video.size / 4)
-
- val displayTime = timed {
- displayImage.foreach { display =>
- display.displaySent(state0.get, y, u, v)
- }
- }
- val sendTime = timed {
- av.videoSendFrame(friendNumber, video.width.value, video.height.value, y, u, v)
- }
-
- capturePath.foreach { capturePath =>
- val out = new DataOutputStream(new FileOutputStream(new File(capturePath, f"${state0.get}%03d.dump")))
- out.writeInt(video.width.value)
- out.writeInt(video.height.value)
- out.write(y)
- out.write(u)
- out.write(v)
- out.close()
- }
-
- debug(
- state,
- s"Sent frame ${state0.get}: generationTime=${generationTime}ms, displayTime=${displayTime}ms, sendTime=${sendTime}ms"
- )
-
- if (state.get >= video.length) {
- state.finish
- } else {
- state.addTask(frameDelay)(sendFrame(friendNumber))
- }
- }
-
- override def callState(friendNumber: ToxFriendNumber, callState: util.EnumSet[ToxavFriendCallState])(state: State): State = {
- debug(state, s"Call with ${state.id(friendNumber)} is now $callState")
- state.addTask(sendFrame(friendNumber))
- }
-
- override def videoReceiveFrame(
- friendNumber: ToxFriendNumber,
- width: Width, height: Height,
- y: Array[Byte], u: Array[Byte], v: Array[Byte],
- yStride: Int, uStride: Int, vStride: Int
- )(state0: State): State = {
- val state = state0.modify(_ + 1)
-
- val times =
- for {
- displayImage <- displayImage
- (parseTime, displayTime) <- displayImage.displayReceived(state0.get, y, u, v, yStride, uStride, vStride)
- } yield {
- s", parseTime=${parseTime}ms, displayTime=${displayTime}ms"
- }
-
- debug(state, s"Received frame ${state0.get}: $width, $height, strides=($yStride, $uStride, $vStride)${times.getOrElse("")}")
-
- if (state.get >= video.length) {
- displayImage.foreach(_.close())
- state.finish
- } else {
- state
- }
- }
-
- }
-
-}
diff --git a/tools/cmake/FindGlog.cmake b/tools/cmake/FindGlog.cmake
deleted file mode 100644
index aa16577aa..000000000
--- a/tools/cmake/FindGlog.cmake
+++ /dev/null
@@ -1,49 +0,0 @@
-# From https://github.com/hanjianwei/cmake-modules/blob/master/FindGlog.cmake
-#
-# - Try to find Glog
-#
-# The following variables are optionally searched for defaults
-# GLOG_ROOT_DIR: Base directory where all GLOG components are found
-#
-# The following are set after configuration is done:
-# GLOG_FOUND
-# GLOG_INCLUDE_DIRS
-# GLOG_LIBRARIES
-
-include(FindPackageHandleStandardArgs)
-
-set(GLOG_ROOT_DIR "" CACHE PATH "Folder contains Google glog")
-
-if(WIN32)
- find_path(GLOG_INCLUDE_DIR glog/logging.h
- PATHS ${GLOG_ROOT_DIR}/src/windows)
-else()
- find_path(GLOG_INCLUDE_DIR glog/logging.h
- PATHS ${GLOG_ROOT_DIR})
-endif()
-
-if(MSVC)
- find_library(GLOG_LIBRARY_RELEASE libglog_static
- PATHS ${GLOG_ROOT_DIR}
- PATH_SUFFIXES Release)
-
- find_library(GLOG_LIBRARY_DEBUG libglog_static
- PATHS ${GLOG_ROOT_DIR}
- PATH_SUFFIXES Debug)
-
- set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG})
-else()
- find_library(GLOG_LIBRARY glog
- PATHS ${GLOG_ROOT_DIR}
- PATH_SUFFIXES
- lib
- lib64)
-endif()
-
-find_package_handle_standard_args(GLOG DEFAULT_MSG
- GLOG_INCLUDE_DIR GLOG_LIBRARY)
-
-if(GLOG_FOUND)
- set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
- set(GLOG_LIBRARIES ${GLOG_LIBRARY})
-endif()
diff --git a/tools/proguard.txt b/tools/proguard.txt
deleted file mode 100644
index 54d5de422..000000000
--- a/tools/proguard.txt
+++ /dev/null
@@ -1,62 +0,0 @@
--keepattributes *Annotation*,InnerClasses
-
-# Main entry point.
--keep public class im.tox.client.TestClient {
- public static void main(java.lang.String[]);
-}
-
-# Constructed from JNI.
--keep public class * extends im.tox.tox4j.exceptions.ToxException {
- public *;
-}
-
--keep public class im.tox.** extends java.lang.Enum {
- public *;
-}
-
-# Constructed through descriptor reflection.
--keep public class * implements com.google.protobuf.ProtocolMessageEnum {
- public *;
-}
-
--keep public class * implements com.google.protobuf.MessageOrBuilder {
- public *;
-}
-
-# Configured through log4j.properties.
--keep public class org.apache.log4j.ConsoleAppender {
- public *;
-}
-
--keep public class org.apache.log4j.PatternLayout {
- public *;
-}
-
--verbose
--optimizationpasses 2
--dontobfuscate
--dontnote
-
-# LVTT entry for 'entry' in class file com/google/protobuf/AbstractMessage$Builder does not match any LVT entry
--optimizations !code/allocation/variable
-
--dontwarn scala.**
--dontwarn scalax.**
--dontwarn scalaz.**
-
-# Needs javax.annotation
--dontwarn com.google.common.**
--dontwarn com.thoughtworks.paranamer.**
--dontwarn io.netty.**
--dontwarn okio.*
--dontwarn org.apache.**
--dontwarn org.fusesource.**
--dontwarn org.jdom.xpath.*
--dontwarn org.jfree.**
--dontwarn org.scalacheck.**
--dontwarn org.scalameter.**
--dontwarn org.scalatest.**
--dontwarn scodec.bits.*
-# Needs javax.crypto
--dontwarn scodec.codecs.Cipher*
--dontwarn scoverage.**