diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml index 8d27bf6..0d30f76 100644 --- a/.github/workflows/maven-publish.yml +++ b/.github/workflows/maven-publish.yml @@ -11,8 +11,7 @@ jobs: strategy: matrix: include: - - { os: ubuntu-20.04, arch: "linux/amd64", implementation: "tdlight" } - #- { os: ubuntu-20.04, arch: "linux/amd64", implementation: "tdlib" } + - { os: ubuntu-20.04, arch: "linux/amd64" } runs-on: ${{ matrix.os }} steps: - name: Branch name @@ -30,10 +29,8 @@ jobs: run: | # ====== Variables export REVISION=${{ steps.branch_name.outputs.SOURCE_TAG_VERSION }} - export IMPLEMENTATION_NAME=${{ matrix.implementation }} echo "REVISION=$REVISION" >> $GITHUB_ENV - echo "IMPLEMENTATION_NAME=$IMPLEMENTATION_NAME" >> $GITHUB_ENV - name: Set up JDK 17 (Snapshot) if: ${{ !startsWith(github.ref, 'refs/tags/v') }} uses: actions/setup-java@v1 @@ -46,8 +43,6 @@ jobs: if: ${{ !startsWith(github.ref, 'refs/tags/v') }} shell: bash run: | - echo "IMPLEMENTATION_NAME: $IMPLEMENTATION_NAME" - source ./scripts/continuous-integration/github-workflows/deploy-snapshot.sh env: MAVEN_USERNAME: ${{ secrets.MCHV_USERNAME }} @@ -65,7 +60,6 @@ jobs: shell: bash run: | echo "REVISION: $REVISION" - echo "IMPLEMENTATION_NAME: $IMPLEMENTATION_NAME" source ./scripts/continuous-integration/github-workflows/deploy-release.sh env: diff --git a/README.md b/README.md index 55a69c8..e4df735 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,10 @@ - s390x (Linux) - ppc64el/ppc64le (Linux) -**Required libraries for Linux: OpenSSL and zlib** +## 📚 Required libraries +- **Linux: OpenSSL, zlib** +- **MacOS: OpenSSL** +- **Windows: [Microsoft Visual C++ Redistributable](https://aka.ms/vs/17/release/vc_redist.x64.exe)** ### Install OpenSSL on macOS @@ -62,18 +65,32 @@ If you are using Maven, edit your `pom.xml` file as below: + + + + + + it.tdlight + tdlight-java-bom + VERSION + pom + import + + + + it.tdlight tdlight-java - VERSION + it.tdlight tdlight-natives-linux-amd64 - NATIVES_VERSION + @@ -84,9 +101,6 @@ If you are using Maven, edit your `pom.xml` file as below: Replace `VERSION` with the latest release version, you can find it [here](https://github.com/tdlight-team/tdlight-java/releases). -Replace `NATIVES_VERSION` with the latest native version. Make sure that you are using the correct natives version for -the release that you are using. - ## Setting up the library using Gradle If you are using Gradle, add the following lines into your `build.gradle` file @@ -95,9 +109,18 @@ If you are using Gradle, add the following lines into your `build.gradle` file repositories { maven { url "https://mvn.mchv.eu/repository/mchv/" } } +dependencyManagement { + imports { + mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Edgware.SR4' + } +} dependencies { - implementation 'it.tdlight:tdlight-java:LATEST_VERSION' - implementation 'it.tdlight:tdlight-natives-linux-amd64:NATIVES_VERSION' + // import the BOM + implementation platform('it.tdlight:tdlight-java-bom:VERSION') + + // do not specify the versions on the dependencies below! + implementation 'it.tdlight:tdlight-java' + implementation 'it.tdlight:tdlight-natives-linux-amd64' // Include other native versions that you want, for example for windows, osx, ... } ``` @@ -105,9 +128,6 @@ dependencies { Replace `VERSION` with the latest release version, you can find it [here](https://github.com/tdlight-team/tdlight-java/releases). -Replace `NATIVES_VERSION` with the latest native version. Make sure that you are using the correct natives version for -the release that you are using. - ## ⚒ Native dependencies To use TDLight Java you need to include one or more native dependencies: diff --git a/bom/pom.xml b/bom/pom.xml new file mode 100644 index 0000000..da4be65 --- /dev/null +++ b/bom/pom.xml @@ -0,0 +1,198 @@ + + 4.0.0 + it.tdlight + tdlight-java-bom + ${revision} + pom + TDLight Java BOM + + 1.0.0.0-SNAPSHOT + 194 + + 4.0.${nativesRevisionNumber}${nativesRevisionSuffix} + 193 + + 4.0.${apiRevisionNumber}${apiRevisionSuffix} + + + + mchv-release + MCHV Release Apache Maven Packages + https://mvn.mchv.eu/repository/mchv + + + mchv-snapshot + MCHV Snapshot Apache Maven Packages + https://mvn.mchv.eu/repository/mchv-snapshot + + + + + mchv-release-distribution + MCHV Release Apache Maven Packages Distribution + https://mvn.mchv.eu/repository/mchv + + + mchv-snapshot-distribution + MCHV Snapshot Apache Maven Packages Distribution + https://mvn.mchv.eu/repository/mchv-snapshot + + + + scm:git:https://git.ignuranza.net/tdlight-team/tdlight-java.git + scm:git:https://git.ignuranza.net/tdlight-team/tdlight-java.git + HEAD + + + + + + it.unimi.dsi + fastutil + 8.5.6 + + + net.harawata + appdirs + 1.2.1 + + + com.google.zxing + core + 3.4.1 + + + it.tdlight + tdlight-api-legacy + ${tdlight.api.version} + + + it.tdlight + tdlight-api-sealed + ${tdlight.api.version} + + + it.tdlight + tdlib-api-legacy + ${tdlight.api.version} + + + it.tdlight + tdlib-api-sealed + ${tdlight.api.version} + + + it.tdlight + tdlight-java + ${revision} + + + it.tdlight + tdlib-java + ${revision} + + + it.tdlight + tdlight-java-parent + ${revision} + + + it.tdlight + tdlib-java-parent + ${revision} + + + + + + it.tdlight + tdlight-natives-linux-amd64 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-linux-aarch64 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-linux-x86 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-linux-armv6 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-linux-armv7 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-linux-ppc64le + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-windows-amd64 + ${tdlight.natives.version} + + + it.tdlight + tdlight-natives-osx-amd64 + ${tdlight.natives.version} + + + + + + it.tdlight + tdlib-natives-linux-amd64 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-linux-aarch64 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-linux-x86 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-linux-armv6 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-linux-armv7 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-linux-ppc64le + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-windows-amd64 + ${tdlight.natives.version} + + + it.tdlight + tdlib-natives-osx-amd64 + ${tdlight.natives.version} + + + + + + + ../parent + + diff --git a/example/pom.xml b/example/pom.xml index efa6bf2..acbe427 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -8,8 +8,6 @@ jar UTF-8 - 2.7.9.5 - 4.0.186 @@ -23,29 +21,36 @@ https://mvn.mchv.eu/repository/mchv-snapshot + + + + it.tdlight + tdlight-java-bom + 2.7.10.0 + pom + import + + + it.tdlight tdlight-java - ${tdlight.java.version} it.tdlight tdlight-natives-linux-amd64 - ${tdlight.natives.version} it.tdlight tdlight-natives-windows-amd64 - ${tdlight.natives.version} it.tdlight tdlight-natives-osx-amd64 - ${tdlight.natives.version} diff --git a/parent/pom.xml b/parent/pom.xml new file mode 100644 index 0000000..5248212 --- /dev/null +++ b/parent/pom.xml @@ -0,0 +1,21 @@ + + + 4.0.0 + tdlight-java-parent + ${revision} + pom + + it.tdlight + ${revision} + tdlight-java-bom + ../bom/pom.xml + + + 1.0.0.0-SNAPSHOT + + + + ../tdlight + + diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 0c62515..0000000 --- a/pom.xml +++ /dev/null @@ -1,68 +0,0 @@ - - 4.0.0 - it.tdlight - tdlight-java-parent - ${revision} - pom - TDLight Java Parent - - 1.0.0.0-SNAPSHOT - 187 - - 185 - - - - - mchv-release - MCHV Release Apache Maven Packages - https://mvn.mchv.eu/repository/mchv - - - mchv-snapshot - MCHV Snapshot Apache Maven Packages - https://mvn.mchv.eu/repository/mchv-snapshot - - - - - mchv-release-distribution - MCHV Release Apache Maven Packages Distribution - https://mvn.mchv.eu/repository/mchv - - - mchv-snapshot-distribution - MCHV Snapshot Apache Maven Packages Distribution - https://mvn.mchv.eu/repository/mchv-snapshot - - - - scm:git:https://git.ignuranza.net/tdlight-team/tdlight-java.git - scm:git:https://git.ignuranza.net/tdlight-team/tdlight-java.git - HEAD - - - - - - - tdlib - - false - - - tdlib - - - - tdlight - - false - - - tdlight - - - - diff --git a/scripts/continuous-integration/github-workflows/deploy-release.sh b/scripts/continuous-integration/github-workflows/deploy-release.sh index be8c560..61ffe21 100755 --- a/scripts/continuous-integration/github-workflows/deploy-release.sh +++ b/scripts/continuous-integration/github-workflows/deploy-release.sh @@ -2,7 +2,6 @@ set -e # OTHER REQUIRED ENVIRONMENT VARIABLES: # REVISION = -# IMPLEMENTATION_NAME = cd ./scripts/core/ ./deploy_release.sh diff --git a/scripts/continuous-integration/github-workflows/deploy-snapshot.sh b/scripts/continuous-integration/github-workflows/deploy-snapshot.sh index 14b060f..f40ca02 100644 --- a/scripts/continuous-integration/github-workflows/deploy-snapshot.sh +++ b/scripts/continuous-integration/github-workflows/deploy-snapshot.sh @@ -1,7 +1,6 @@ #!/bin/bash -e set -e # OTHER REQUIRED ENVIRONMENT VARIABLES: -# IMPLEMENTATION_NAME = cd ./scripts/core/ ./deploy_snapshot.sh diff --git a/scripts/continuous-integration/github-workflows/only-compile-release.sh b/scripts/continuous-integration/github-workflows/only-compile-release.sh index 08b0d46..765f241 100755 --- a/scripts/continuous-integration/github-workflows/only-compile-release.sh +++ b/scripts/continuous-integration/github-workflows/only-compile-release.sh @@ -1,7 +1,6 @@ #!/bin/bash -e set -e # OTHER REQUIRED ENVIRONMENT VARIABLES: -# IMPLEMENTATION_NAME = cd ./scripts/core/ ./only_compile_release.sh diff --git a/scripts/core/deploy_release.sh b/scripts/core/deploy_release.sh index e7a516f..10d5014 100755 --- a/scripts/core/deploy_release.sh +++ b/scripts/core/deploy_release.sh @@ -1,21 +1,18 @@ #!/bin/bash -e # OTHER REQUIRED ENVIRONMENT VARIABLES: # REVISION = -# IMPLEMENTATION_NAME = # Check variables correctness if [ -z "${REVISION}" ]; then echo "Missing parameter: REVISION" exit 1 fi -if [ -z "${IMPLEMENTATION_NAME}" ]; then - echo "Missing parameter: IMPLEMENTATION_NAME" - exit 1 -fi -cd ../../ +cd "../../" -mvn -B -P "${IMPLEMENTATION_NAME}" -Drevision="${REVISION}" clean deploy +cd "bom" +mvn -B -Drevision="${REVISION}" clean deploy +cd "../" echo "Done." exit 0 diff --git a/scripts/core/deploy_snapshot.sh b/scripts/core/deploy_snapshot.sh index 2bfadd3..4a3d805 100755 --- a/scripts/core/deploy_snapshot.sh +++ b/scripts/core/deploy_snapshot.sh @@ -1,16 +1,11 @@ #!/bin/bash -e # OTHER REQUIRED ENVIRONMENT VARIABLES: -# IMPLEMENTATION_NAME = -# Check variables correctness -if [ -z "${IMPLEMENTATION_NAME}" ]; then - echo "Missing parameter: IMPLEMENTATION_NAME" - exit 1 -fi +cd "../../" -cd ../../ - -mvn -B -P "${IMPLEMENTATION_NAME}" clean deploy +cd "bom" +mvn -B clean deploy +cd "../" echo "Done." exit 0 diff --git a/scripts/core/only_compile_release.sh b/scripts/core/only_compile_release.sh index 83fe3e1..1fdcfc6 100755 --- a/scripts/core/only_compile_release.sh +++ b/scripts/core/only_compile_release.sh @@ -1,16 +1,11 @@ #!/bin/bash -e # OTHER REQUIRED ENVIRONMENT VARIABLES: -# IMPLEMENTATION_NAME = - -# Check variables correctness -if [ -z "${IMPLEMENTATION_NAME}" ]; then - echo "Missing parameter: IMPLEMENTATION_NAME" - exit 1 -fi cd "../../" -mvn -B -P "${IMPLEMENTATION_NAME}" clean package +cd "bom" +mvn -B clean package +cd "../" echo "Done." exit 0 diff --git a/src/main/java/it/tdlight/client/AuthorizationStateWaitAuthenticationDataHandler.java b/src/main/java/it/tdlight/client/AuthorizationStateWaitAuthenticationDataHandler.java index 27c8530..333fd75 100644 --- a/src/main/java/it/tdlight/client/AuthorizationStateWaitAuthenticationDataHandler.java +++ b/src/main/java/it/tdlight/client/AuthorizationStateWaitAuthenticationDataHandler.java @@ -45,7 +45,7 @@ final class AuthorizationStateWaitAuthenticationDataHandler implements GenericUp } }, exceptionHandler); } else { - PhoneNumberAuthenticationSettings phoneSettings = new PhoneNumberAuthenticationSettings(false, false, false); + PhoneNumberAuthenticationSettings phoneSettings = new PhoneNumberAuthenticationSettings(false, false, false, false, null); String phoneNumber = String.valueOf(authenticationData.getUserPhoneNumber()); SetAuthenticationPhoneNumber response = new SetAuthenticationPhoneNumber(phoneNumber, phoneSettings); diff --git a/src/main/java/it/tdlight/client/CommandsHandler.java b/src/main/java/it/tdlight/client/CommandsHandler.java index ff4a173..ab707a1 100644 --- a/src/main/java/it/tdlight/client/CommandsHandler.java +++ b/src/main/java/it/tdlight/client/CommandsHandler.java @@ -73,7 +73,7 @@ final class CommandsHandler implements GenericUpdateHandler { if (response.getConstructor() == TdApi.Error.CONSTRUCTOR) { throw new TelegramError((TdApi.Error) response); } - handler.onCommand((Chat) response, message.sender, arguments); + handler.onCommand((Chat) response, message.senderId, arguments); }, error -> logger.warn("Error when handling the command {}", commandName, error)); } } diff --git a/src/main/java/it/tdlight/common/internal/InternalClient.java b/src/main/java/it/tdlight/common/internal/InternalClient.java index ac3939c..e2c13ef 100644 --- a/src/main/java/it/tdlight/common/internal/InternalClient.java +++ b/src/main/java/it/tdlight/common/internal/InternalClient.java @@ -47,24 +47,22 @@ public final class InternalClient implements ClientEventsHandler, TelegramClient @Override public void handleEvents(boolean isClosed, long[] eventIds, TdApi.Object[] events, int arrayOffset, int arrayLength) { if (updatesHandler != null) { - LongArrayList idsToFilter = new LongArrayList(eventIds); - ObjectArrayList eventsToFilter = new ObjectArrayList<>(events); + ObjectArrayList updatesList = new ObjectArrayList<>(arrayLength); for (int i = (arrayOffset + arrayLength) - 1; i >= arrayOffset; i--) { if (eventIds[i] != 0) { - idsToFilter.removeLong(i); - eventsToFilter.remove(i); - long eventId = eventIds[i]; TdApi.Object event = events[i]; Handler handler = handlers.remove(eventId); handleResponse(eventId, event, handler); + } else { + updatesList.add(events[i]); } } try { - updatesHandler.getUpdatesHandler().onUpdates(eventsToFilter); + updatesHandler.getUpdatesHandler().onUpdates(updatesList); } catch (Throwable cause) { handleException(updatesHandler.getExceptionHandler(), cause); } diff --git a/src/main/java/it/tdlight/common/internal/InternalClientManager.java b/src/main/java/it/tdlight/common/internal/InternalClientManager.java index cb46231..d9351b5 100644 --- a/src/main/java/it/tdlight/common/internal/InternalClientManager.java +++ b/src/main/java/it/tdlight/common/internal/InternalClientManager.java @@ -35,7 +35,7 @@ public final class InternalClientManager implements AutoCloseable { System.exit(1); } this.implementationName = implementationName; - responseReceiver = new ResponseReceiver(this::handleClientEvents); + responseReceiver = new NativeResponseReceiver(this::handleClientEvents); } /** diff --git a/src/main/java/it/tdlight/common/internal/NativeResponseReceiver.java b/src/main/java/it/tdlight/common/internal/NativeResponseReceiver.java new file mode 100644 index 0000000..caa9d29 --- /dev/null +++ b/src/main/java/it/tdlight/common/internal/NativeResponseReceiver.java @@ -0,0 +1,16 @@ +package it.tdlight.common.internal; + +import it.tdlight.common.EventsHandler; +import it.tdlight.jni.TdApi.Object; + +public class NativeResponseReceiver extends ResponseReceiver { + + public NativeResponseReceiver(EventsHandler eventsHandler) { + super(eventsHandler); + } + + @Override + public int receive(int[] clientIds, long[] eventIds, Object[] events, double timeout) { + return NativeClientAccess.receive(clientIds, eventIds, events, timeout); + } +} diff --git a/src/main/java/it/tdlight/common/internal/ResponseReceiver.java b/src/main/java/it/tdlight/common/internal/ResponseReceiver.java index efc9996..eb3f339 100644 --- a/src/main/java/it/tdlight/common/internal/ResponseReceiver.java +++ b/src/main/java/it/tdlight/common/internal/ResponseReceiver.java @@ -7,18 +7,19 @@ import it.tdlight.common.EventsHandler; import it.tdlight.common.utils.IntSwapper; import it.tdlight.common.utils.SpinWaitSupport; import it.tdlight.jni.TdApi; -import it.tdlight.jni.TdApi.Object; import it.tdlight.jni.TdApi.UpdateAuthorizationState; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Set; +import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; -public final class ResponseReceiver extends Thread implements AutoCloseable { +abstract class ResponseReceiver extends Thread implements AutoCloseable { private static final String FLAG_PAUSE_SHUTDOWN_UNTIL_ALL_CLOSED = "it.tdlight.pauseShutdownUntilAllClosed"; private static final String FLAG_USE_OPTIMIZED_DISPATCHER = "tdlight.dispatcher.use_optimized_dispatcher"; @@ -58,30 +59,34 @@ public final class ResponseReceiver extends Thread implements AutoCloseable { this.setDaemon(true); } + /** + * @return results count + */ + public abstract int receive(int[] clientIds, long[] eventIds, TdApi.Object[] events, double timeout); + @Override - public synchronized void start() { + public void run() { if (closeCalled.get()) { throw new IllegalStateException("Closed"); } if (startCalled.compareAndSet(false, true)) { - super.start(); + this.runInternal(); } else { throw new IllegalStateException("Start already called"); } } - @Override - public void run() { + private void runInternal() { int[] sortIndex; try { boolean interrupted; while ( !(interrupted = Thread.interrupted()) - && !jvmShutdown.get() - && (!closeCalled.get() || !registeredClients.isEmpty()) + && !jvmShutdown.get() + && (!closeCalled.get() || !registeredClients.isEmpty()) ) { // Timeout is expressed in seconds - int resultsCount = NativeClientAccess.receive(clientIds, eventIds, events, 2.0); + int resultsCount = receive(clientIds, eventIds, events, 2.0); if (resultsCount <= 0) { SpinWaitSupport.onSpinWait(); @@ -145,13 +150,39 @@ public final class ResponseReceiver extends Thread implements AutoCloseable { public final int clientId; public final long eventId; - public final Object event; + public final TdApi.Object event; - public Event(int clientId, long eventId, Object event) { + public Event(int clientId, long eventId, TdApi.Object event) { this.clientId = clientId; this.eventId = eventId; this.event = event; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Event event1 = (Event) o; + return clientId == event1.clientId && eventId == event1.eventId && Objects.equals(event, event1.event); + } + + @Override + public int hashCode() { + return Objects.hash(clientId, eventId, event); + } + + @Override + public String toString() { + return new StringJoiner(", ", Event.class.getSimpleName() + "[", "]") + .add("clientId=" + clientId) + .add("eventId=" + eventId) + .add("event=" + event) + .toString(); + } } List eventsList = new ArrayList<>(resultsCount); diff --git a/src/test/java/it/tdlight/common/internal/Event.java b/src/test/java/it/tdlight/common/internal/Event.java new file mode 100644 index 0000000..90a5018 --- /dev/null +++ b/src/test/java/it/tdlight/common/internal/Event.java @@ -0,0 +1,51 @@ +package it.tdlight.common.internal; + +import it.tdlight.jni.TdApi; +import java.util.Objects; + +public final class Event { + + private final int clientId; + private final long eventId; + private final TdApi.Object event; + + Event(int clientId, long eventId, TdApi.Object event) { + this.clientId = clientId; + this.eventId = eventId; + this.event = event; + } + + public int clientId() { + return clientId; + } + + public long eventId() { + return eventId; + } + + public TdApi.Object event() { + return event; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + Event that = (Event) obj; + return this.clientId == that.clientId && this.eventId == that.eventId && Objects.equals(this.event, that.event); + } + + @Override + public int hashCode() { + return Objects.hash(clientId, eventId, event); + } + + @Override + public String toString() { + return "Event[" + "clientId=" + clientId + ", " + "eventId=" + eventId + ", " + "event=" + event + ']'; + } +} diff --git a/src/test/java/it/tdlight/common/internal/HandleEventsTest.java b/src/test/java/it/tdlight/common/internal/HandleEventsTest.java new file mode 100644 index 0000000..75d81c7 --- /dev/null +++ b/src/test/java/it/tdlight/common/internal/HandleEventsTest.java @@ -0,0 +1,124 @@ +package it.tdlight.common.internal; + +import static org.junit.jupiter.api.Assertions.*; + +import it.tdlight.common.EventsHandler; +import it.tdlight.jni.TdApi; +import it.tdlight.jni.TdApi.Object; +import it.unimi.dsi.fastutil.longs.LongArraySet; +import it.unimi.dsi.fastutil.longs.LongSets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class HandleEventsTest { + + @Test + public void test() throws InterruptedException { + System.setProperty("tdlight.dispatcher.use_optimized_dispatcher", "false"); + List initialEvents = new ArrayList<>(); + initialEvents.add(new Event(2, 0, new TdApi.LogVerbosityLevel(0))); + initialEvents.add(new Event(1, 1, new TdApi.LogVerbosityLevel(1))); + initialEvents.add(new Event(7, 3, new TdApi.LogVerbosityLevel(2))); + initialEvents.add(new Event(7, 0, new TdApi.LogVerbosityLevel(3))); + initialEvents.add(new Event(1, 7, new TdApi.LogVerbosityLevel(4))); + initialEvents.add(new Event(2, 398, new TdApi.LogVerbosityLevel(5))); + initialEvents.add(new Event(7, 98832, new TdApi.LogVerbosityLevel(6))); + initialEvents.add(new Event(2, 32832, new TdApi.LogVerbosityLevel(7))); + initialEvents.add(new Event(1, 39484, new TdApi.LogVerbosityLevel(8))); + initialEvents.add(new Event(1, 39485, new TdApi.LogVerbosityLevel(9))); + initialEvents.add(new Event(1, 39486, new TdApi.LogVerbosityLevel(10))); + initialEvents.add(new Event(1, 39487, new TdApi.LogVerbosityLevel(11))); + initialEvents.add(new Event(1, 39488, new TdApi.LogVerbosityLevel(12))); + CountDownLatch eventsQueueEmptied = new CountDownLatch(1); + ArrayBlockingQueue eventsQueue = new ArrayBlockingQueue<>(1024); + eventsQueue.addAll(initialEvents); + ArrayBlockingQueue results = new ArrayBlockingQueue<>(1024); + ResponseReceiver responseReceiver = new ResponseReceiver((clientId, isClosed, clientEventIds, clientEvents, arrayOffset, arrayLength) -> { + results.add(new Result(clientId, + isClosed, + Arrays.copyOf(clientEventIds, clientEventIds.length), + Arrays.copyOf(clientEvents, clientEvents.length), + arrayOffset, + arrayLength + )); + }) { + @Override + public int receive(int[] clientIds, long[] eventIds, Object[] events, double timeout) { + int i = 0; + while (!eventsQueue.isEmpty() && i < clientIds.length) { + Event event = eventsQueue.poll(); + clientIds[i] = event.clientId(); + eventIds[i] = event.eventId(); + events[i] = event.event(); + i++; + } + if (eventsQueue.isEmpty()) { + eventsQueueEmptied.countDown(); + } + return i; + } + }; + responseReceiver.registerClient(2); + responseReceiver.registerClient(1); + responseReceiver.registerClient(7); + responseReceiver.start(); + eventsQueueEmptied.await(); + responseReceiver.interrupt(); + responseReceiver.close(); + HashMap resultsMap = new HashMap<>(); + while (!results.isEmpty()) { + Result part = results.poll(); + if (part.arrayLength() > 0) { + Result prev = resultsMap.get(part.clientId()); + if (prev == null) { + prev = new Result(part.clientId(), false, new long[0], new TdApi.Object[0], 0, 0); + } + int newSize = part.arrayLength() + prev.arrayLength(); + long[] newIds = new long[newSize]; + TdApi.Object[] newEvents = new TdApi.Object[newSize]; + int i = 0; + for (int i1 = 0; i1 < prev.arrayLength(); i1++, i++) { + newIds[i] = prev.clientEventIds()[i1 + prev.arrayOffset()]; + newEvents[i] = prev.clientEvents()[i1 + prev.arrayOffset()]; + } + for (int i1 = 0; i1 < part.arrayLength(); i1++, i++) { + newIds[i] = part.clientEventIds()[i1 + part.arrayOffset()]; + newEvents[i] = part.clientEvents()[i1 + part.arrayOffset()]; + } + resultsMap.put(part.clientId(), new Result(part.clientId(), part.isClosed() || prev.isClosed(), newIds, newEvents, 0, newSize)); + } + } + Result client2Results = resultsMap.remove(2); + Result client1Results = resultsMap.remove(1); + Result client7Results = resultsMap.remove(7); + assertTrue(resultsMap.isEmpty()); + assertEquals(0, results.size()); + + assertEquals(2, client2Results.clientId()); + assertEquals(1, client1Results.clientId()); + assertEquals(7, client7Results.clientId()); + + assertEquals(getClientEventIds(initialEvents, 2), LongArraySet.of(Arrays.copyOfRange(client2Results.clientEventIds(), client2Results.arrayOffset(), client2Results.arrayOffset() + client2Results.arrayLength()))); + assertEquals(getClientEventIds(initialEvents, 1), LongArraySet.of(Arrays.copyOfRange(client1Results.clientEventIds(), client1Results.arrayOffset(), client1Results.arrayOffset() + client1Results.arrayLength()))); + assertEquals(getClientEventIds(initialEvents, 7), LongArraySet.of(Arrays.copyOfRange(client7Results.clientEventIds(), client7Results.arrayOffset(), client7Results.arrayOffset() + client7Results.arrayLength()))); + + assertEquals(initialEvents.size(), client2Results.arrayLength() + client1Results.arrayLength() + client7Results.arrayLength()); + + assertEquals(3, client2Results.arrayLength()); + assertEquals(7, client1Results.arrayLength()); + assertEquals(3, client7Results.arrayLength()); + } + + private Set getClientEventIds(List initialEvents, long clientId) { + return initialEvents.stream().filter(e -> e.clientId() == clientId).map(Event::eventId).collect(Collectors.toSet()); + } +} diff --git a/src/test/java/it/tdlight/common/internal/Result.java b/src/test/java/it/tdlight/common/internal/Result.java new file mode 100644 index 0000000..99fada0 --- /dev/null +++ b/src/test/java/it/tdlight/common/internal/Result.java @@ -0,0 +1,80 @@ +package it.tdlight.common.internal; + +import it.tdlight.jni.TdApi; +import java.util.List; +import java.util.Objects; + +public final class Result { + + private final int clientId; + private final boolean isClosed; + private final long[] clientEventIds; + private final TdApi.Object[] clientEvents; + private final int arrayOffset; + private final int arrayLength; + + public Result(int clientId, + boolean isClosed, + long[] clientEventIds, + TdApi.Object[] clientEvents, + int arrayOffset, + int arrayLength) { + this.clientId = clientId; + this.isClosed = isClosed; + this.clientEventIds = clientEventIds; + this.clientEvents = clientEvents; + this.arrayOffset = arrayOffset; + this.arrayLength = arrayLength; + } + + public int clientId() { + return clientId; + } + + public boolean isClosed() { + return isClosed; + } + + public long[] clientEventIds() { + return clientEventIds; + } + + public TdApi.Object[] clientEvents() { + return clientEvents; + } + + public int arrayOffset() { + return arrayOffset; + } + + public int arrayLength() { + return arrayLength; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj == null || obj.getClass() != this.getClass()) { + return false; + } + Result that = (Result) obj; + return this.clientId == that.clientId && this.isClosed == that.isClosed && Objects.equals(this.clientEventIds, + that.clientEventIds + ) && Objects.equals(this.clientEvents, that.clientEvents) && this.arrayOffset == that.arrayOffset + && this.arrayLength == that.arrayLength; + } + + @Override + public int hashCode() { + return Objects.hash(clientId, isClosed, clientEventIds, clientEvents, arrayOffset, arrayLength); + } + + @Override + public String toString() { + return "Result[" + "clientId=" + clientId + ", " + "isClosed=" + isClosed + ", " + "clientEventIds=" + + clientEventIds + ", " + "clientEvents=" + clientEvents + ", " + "arrayOffset=" + arrayOffset + ", " + + "arrayLength=" + arrayLength + ']'; + } +} diff --git a/tdlib/pom.xml b/tdlib/pom.xml index 2953759..3415d2e 100644 --- a/tdlib/pom.xml +++ b/tdlib/pom.xml @@ -9,11 +9,12 @@ it.tdlight ${revision} tdlight-java-parent - ../pom.xml + ../parent/pom.xml UTF-8 1.0.0.0-SNAPSHOT + tdlib-api-legacy @@ -47,13 +48,7 @@ it.tdlight - tdlib-api - 4.0.${apiRevisionNumber}${apiRevisionSuffix} - - - it.cavallium - concurrent-locks - 1.0.8 + ${tdlib.api.artifact.id} it.unimi.dsi @@ -77,23 +72,21 @@ com.google.zxing core + + org.junit.jupiter + junit-jupiter-engine + 5.8.0 + test + - it.unimi.dsi - fastutil - 8.5.6 - - - net.harawata - appdirs - 1.2.1 - - - com.google.zxing - core - 3.4.1 + it.tdlight + tdlight-java-bom + ${revision} + pom + import @@ -110,9 +103,28 @@ target-snapshot + + jdk-with-sealed-interfaces + + [17,) + + + tdlib-api-sealed + + + + jdk-with-legacy-interfaces + + (,17) + + + tdlib-api-legacy + + ${project.basedir}/../src/main/java + ${project.basedir}/../src/test/java maven-clean-plugin @@ -243,12 +255,11 @@ org.codehaus.mojo flatten-maven-plugin - 1.1.0 + 1.2.2 - true - resolveCiFriendliesOnly + flatten process-resources @@ -256,6 +267,7 @@ flatten + flatten.clean clean @@ -284,6 +296,18 @@ maven-deploy-plugin 2.8.2 + + org.apache.maven.surefire + surefire + 3.0.0-M5 + + + org.junit.jupiter + junit-jupiter-engine + 5.8.0 + + + diff --git a/tdlight/pom.xml b/tdlight/pom.xml index 4b7b1fe..2bec979 100644 --- a/tdlight/pom.xml +++ b/tdlight/pom.xml @@ -9,11 +9,12 @@ it.tdlight ${revision} tdlight-java-parent - ../pom.xml + ../parent/pom.xml UTF-8 1.0.0.0-SNAPSHOT + tdlight-api-legacy @@ -47,13 +48,7 @@ it.tdlight - tdlight-api - 4.0.${apiRevisionNumber}${apiRevisionSuffix} - - - it.cavallium - concurrent-locks - 1.0.8 + ${tdlight.api.artifact.id} it.unimi.dsi @@ -77,23 +72,21 @@ com.google.zxing core + + org.junit.jupiter + junit-jupiter-engine + 5.8.0 + test + - it.unimi.dsi - fastutil - 8.5.6 - - - net.harawata - appdirs - 1.2.1 - - - com.google.zxing - core - 3.4.1 + it.tdlight + tdlight-java-bom + ${revision} + pom + import @@ -110,9 +103,28 @@ target-snapshot + + jdk-with-sealed-interfaces + + [17,) + + + tdlight-api-sealed + + + + jdk-with-legacy-interfaces + + (,17) + + + tdlight-api-legacy + + ${project.basedir}/../src/main/java + ${project.basedir}/../src/test/java maven-clean-plugin @@ -187,6 +199,7 @@ it/tdlight/tdlib/ClientManager.java + 8 @@ -243,12 +256,11 @@ org.codehaus.mojo flatten-maven-plugin - 1.1.0 + 1.2.2 - true - resolveCiFriendliesOnly + flatten process-resources @@ -256,6 +268,7 @@ flatten + flatten.clean clean @@ -300,6 +313,18 @@ + + org.apache.maven.surefire + surefire + 3.0.0-M5 + + + org.junit.jupiter + junit-jupiter-engine + 5.8.0 + + +