From c727bf70170b4e6be27c85aa62f6815ce6ea33d3 Mon Sep 17 00:00:00 2001 From: Shiranuit Date: Mon, 2 Dec 2019 17:50:27 +0100 Subject: [PATCH] Revert "Revert "SDK V3 WebSocket Unit Tests"" --- .gitignore | 1 + .travis.yml | 87 ++++++--- kuzzle-sdk-java/.project | 23 +++ package.json => kuzzle-sdk-java/package.json | 0 .../test/CoreClasses/TaskTest/TaskTests.java | 151 +++++++++++++++ .../CoreClasses/TaskTest/TestableTask.java | 32 ++++ .../test/EventsTest/EventListenerTests.java | 159 ++++++++++++++++ .../EventsTest/TestableEventListener.java | 22 +++ .../io/kuzzle/test/Helpers/DefaultTests.java | 24 +++ .../test/java/io/kuzzle/test/KuzzleTests.java | 176 ++++++++++++++++++ .../test/ProtocolTest/TestableWebSocket.java | 38 ++++ .../test/ProtocolTest/WebSocketTests.java | 90 +++++++++ .../java/io/kuzzle/test/TestableKuzzle.java | 51 +++++ 13 files changed, 823 insertions(+), 31 deletions(-) create mode 100644 kuzzle-sdk-java/.project rename package.json => kuzzle-sdk-java/package.json (100%) create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TaskTests.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TestableTask.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/EventListenerTests.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/TestableEventListener.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/Helpers/DefaultTests.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/KuzzleTests.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/TestableWebSocket.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/WebSocketTests.java create mode 100644 kuzzle-sdk-java/src/test/java/io/kuzzle/test/TestableKuzzle.java diff --git a/.gitignore b/.gitignore index e4df1944..2407ed41 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ build out .idea +bin *.iml *.class bin diff --git a/.travis.yml b/.travis.yml index 7f499a00..04a06c7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,11 @@ - -env: - global: - # BINTRAY_USER - - secure: "LxONQZ8tHhxTqgu+kqx9fMCubCfTQHZsy/3ibE+l72xG8sOAYfj4hB5k1p4kklnv3skeFQEiL6B++B2qRITOEAPRdD8FExkc+UF/TM1rY5aUtjIjoA3uH4n9hYjHirTO5qNKf4KxDr1Zbcn4ISGebJ0EYwE0SG/ptrd06wPp1G8AHshc8XaZgen6gDaik66OWpQkOkmGsRz2EPmIBVgo7L2LGK21DSxE4/PTo+ou0WYCyxyyWSKLTLt1xZpt9LOtk7IckrHl+Nenl6IbV/CjHb3+5vwdifyFQd+K6AVe32iTIVjdxj7rDhEHYD0EqKb79ey+u8p9HquLnGH03gcVBeFQu/qhhQStsiwrD/S9c8jwBjWOOUnVI4bEbqjqxFaRlPfVnRaAjQZLRKHdqxyTJCdC2Ls79LmkqSCyTxM7WBwwgu4Slf6RJSbKJb5naHYlwDuKPbeyHLAYrxgjEHC28bxQiTr5wwBWxE9BLxUcnkFAXzsy3qE74FQOIjvQbtrruLIOGwRGRYtzyfygGA3MfTHug6JwZGngqFf3k+kbznE8fZe7zxMwT63P6/54rR5fU/plLoTNFqdQsZGAfGOSYuHIEzWXOkWxffqsOwxPa1VxQTLD32O95oBcrcvmw4toC2NeFTe/+zZRMfGMbu7QIi0AL3qFpky3j12zcyA/M2I=" - # BINTRAY_KEY - - secure: "Iqn4ImAwFmQeoXXDb5JOsfcunSiSeLvdp4+AEsIeniMhpIk++ZJPDSxecC+NrvndTrxOXVqHEsFUfHnZYvPHMuvg9nhXvz/rmmyYH0hZqkKg2q2qM+Sz2UJBCvs6D1sJv3ZEVi8d6fVx5bbKXMzSE023XFBBK7l8nBsG5ObXBOzTzrus9UP+fk4FXif/QKJNcUSN7rLejUIxMCk36gMQYqYGiiqL3VE60aTpaUh7Vqj/8nCEPcO3K3gXTVybcGBcmsvinV5YEc+5s5ue8eX10ONY0oYF5GFd7aEsrKEFzT2d7MVq0a29cH1rWrxt6q7vXGZNKAdAQrDyRZUz9rMFtqH+2xOgagm22UiUYNlzrn2eDYRBd08X0y043gumdgmOq/CsyaI5bcUSKMr+rsZ2XIzBjefl8MU0xBhtKMO9g9WRfGBxjRbdg0ivRQoVGJbcUXTDl2WrLMgMjt8DT4nQP+PHdIV2FjZVNioqucqmEzfHIJt+hiw7EonGDnZ9uqkW6hm6b4JpGr5QF1yY6kKVCUQxLueUBAVdiZpULdevL7uYEUzdWIES2wTFE7LaWpHqnCOHYVpkIQpdole6+R0OhINhSHK0FW858xhZ2QGjtL1SSh5yzK4th6dpGKCiwMUSGSj5frpIeWPi+GqYoUQz+TvMGLGG2XGfihx74kQE0FA=" - - AWS_ACCESS_KEY_ID=AKIAIYAXFUAHXOWP2MJA - # AWS_SECRET_ACCESS_KEY - - secure: "dIcQzFpHKRf92cAiMA+SYsudtHWNcbYadVDb7zlJayWGUGy0i4CGwwOoOOrUcWgHxYhdN9XGwvFJTSswjHLRiHEyPFBwW8x/VfaCRS+jAcblMXyWNajvm0930S/3fRv5LA+4UKNmeXMuCGSf35ZqyEIEeuThkIomYvB/tBD1wcMpBUtQfmilLm3sUTaGUnFB651jBHshlYOZ8BAGLLmX1PAfT1wCrpVcrjq5kayNOIilJkwKGSr6q9C0p7+ULNZ4bHsATKLlYNs7Xcs+9a66p1EtKetP72DQsHrr8x3wB2Hhk3U425kmjIoE3gYnF7x3h3EpO5m0rGessbgdRF1SF7XK7Bsj4ukLb4HoktA8G7734ox4848RpH60aKUHRCsiebX7JKgJe1eEwU5BZK8+PFPGH6bI1YG1HQNqthzotTHFXu058uMHnyLv2PmDWWEYMM79fCyuRo8gJJ8GJhDgaGLgtizzEb6grcNW+QwunjA6nP4o7F9o+9b3lfGlsgL595V/CeWLNnHvENkSr67RN2NkDZm6q6EHbOk8AWtQc24mVawCwCbcJjp0sPkbQdCHUXSBNXjdwrvJLA3h94A2uVEmrV7mzMdfj+i9X3IS/HXRLeQk6Ivq2s/b1W6c7rBfz4zZUO7Uu5iYpVzT71yNFra13JkW3REFgHgETEvGkko=" - - -sudo: true - +--- +# ----------------- +# YAML Templates +# ----------------- + +# ------------------------ +# Jobs configuration +# ------------------------ jobs: include: - stage: Tests @@ -21,8 +15,8 @@ jobs: node_js: 10 before_script: - - npm run doc-prepare - - npm run --prefix doc/framework clone-repos + - cd kuzzle-sdk-java && npm run doc-prepare + - npm run --prefix doc/framework clone-repos && cd - script: - gem install typhoeus - HYDRA_MAX_CONCURRENCY=20 npm run --prefix doc/framework dead-links @@ -48,17 +42,17 @@ jobs: - cd $TRAVIS_BUILD_DIR/kuzzle-sdk-java - gradle assemble script: - - npm run doc-prepare - - npm run doc-build + - cd kuzzle-sdk-java && npm run doc-prepare + - npm run doc-build && cd - deploy: provider: script script: - - npm run doc-upload + - cd kuzzle-sdk-java && npm run doc-upload && cd - skip_cleanup: true after_deploy: - - npm run doc-cloudfront + - cd kuzzle-sdk-java && npm run doc-cloudfront && cd - - stage: Deployment Doc Prod name: Deploy docs.kuzzle.io @@ -83,17 +77,48 @@ jobs: - cd $TRAVIS_BUILD_DIR/kuzzle-sdk-java - gradle assemble script: - bash gradlew test jacocoTestReport - - notifications: - email: false - + - gradle check after_success: - bash <(curl -s https://codecov.io/bash) - deploy: - provider: script - script: ./gradlew bintrayUpload - skip_cleanup: true - on: - condition: $TRAVIS_BRANCH = master + # --------------------------------------- + # Builds + # --------------------------------------- + - stage: Builds + name: Build SDK Java + language: java + jdk: oraclejdk8 + sudo: false + before_cache: + - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock + - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ + cache: + directories: + - $HOME/.gradle/caches/ + - $HOME/.gradle/wrapper/ + install: + - cd $TRAVIS_BUILD_DIR/kuzzle-sdk-java + - gradle assemble + - cd $TRAVIS_BUILD_DIR/kuzzle-sdk-java + - gradle assemble + script: + - gradle build + +# ------------------------ +# Stages configuration +# ------------------------ +stages: + - name: Unit Tests + if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-(dev|stable)$/ + - name: Builds + if: type =~ /(cron|push|pull_request)/ AND branch =~ /^master|[0-9]+-(dev|stable)$/ + +# --------------------------------------- +# Notifications +# --------------------------------------- +notifications: + slack: + rooms: + - secure: "ACjz4TJEYBEzmwVOYrCNnr4+jC0FaX+qh150QacYGIgaQYL+U3xLEQmWNlZ3oxaPPMDAk42m+diHolqNwh6qsOWaPSWRlGfLKhHLSzRI98bhF7HQ+3eLMYmx7y7SKwRzyRjus0jgxp0Kc2mq0nhKqv+7rarQtIgWlC1PLrzZ35CUbUlqYSoeYAlXoyDB1eZgYsvjt+eC5yCvGePsfKbupWC2/hIVl+qZ+9AhVmOfiMv7daFW29Vu300aoY+0IqwX7jHGcmHn/7QCRsx0IBy/SL24TzfSV9SUSnbjK4fTrcrhjYDEZdH1lpvDtvr50GgkrTjy1wPVz8XIyCZ7LZolylkx+nR1MWyvum20QRFub2Qhz/+rS+OFiQZ8H01BPuklLUTSQhBksfpGBck3d2yNLiTqGEVWYTnZ9mkCnMQ3BzJXEF04KLHG7wYn2rk6wjPghVmFQH5GMsxM5v33CFgcNzp6lRJOX9CmjZosck6o9SA0WlazHH/CLWWKk1wrQ1ygDayW5m+N/o58UIxgW2LIUlp4tV1z/bRtO2yTd020yWchlKPVmf1A5OMfigJNMRsQGNZNadS7qA2M394OJw3/Hg+0EVF8gai/V8FRijmkxmhYyCIYMcjaGwx8JxfoMrRKcM76haBAhg0JQxsSVKzyXfONGzd5DXjcxSGZ2wuEdu0=" + on_success: never + on_failure: always diff --git a/kuzzle-sdk-java/.project b/kuzzle-sdk-java/.project new file mode 100644 index 00000000..1a097e23 --- /dev/null +++ b/kuzzle-sdk-java/.project @@ -0,0 +1,23 @@ + + + kuzzle-sdk-java + Project kuzzle-sdk-java created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/package.json b/kuzzle-sdk-java/package.json similarity index 100% rename from package.json rename to kuzzle-sdk-java/package.json diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TaskTests.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TaskTests.java new file mode 100644 index 00000000..21c6d0c9 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TaskTests.java @@ -0,0 +1,151 @@ +package io.kuzzle.test.CoreClasses.TaskTest; + +import io.kuzzle.sdk.CoreClasses.Task; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; + +public class TaskTests { + + @Test + public void constructorTest() { + TestableTask task = new TestableTask<>(); + Assert.assertNotNull(task.getAtomicReference()); + Assert.assertEquals( + AtomicReference.class, + task.getAtomicReference().getClass() + ); + Assert.assertNotNull(task.getCountDownLatch()); + Assert.assertEquals( + CountDownLatch.class, + task.getCountDownLatch().getClass() + ); + Assert.assertNotNull(task.getFuture()); + } + + @Test + public void getFutureTest() { + Task task = new Task<>(); + + Assert.assertEquals( + CompletableFuture.class, + task.getFuture().getClass() + ); + } + + @Test + public void setExceptionTest() { + TestableTask task = new TestableTask<>(); + task.applyMockFuture(); + + task.setException(new Exception("foobar")); + + verify( + task.mockedFuture, + times(1) + ).completeExceptionally(any(Exception.class)); + } + + @Test + public void isCancelledTest() { + TestableTask task = new TestableTask<>(); + task.applyMockFuture(); + + when(task.mockedFuture.isCancelled()) + .thenReturn(true); + + Assert.assertTrue(task.isCancelled()); + + verify( + task.mockedFuture, + times(1) + ).isCancelled(); + } + + @Test + public void isDoneTest() { + TestableTask task = new TestableTask<>(); + task.applyMockFuture(); + + when(task.mockedFuture.isDone()) + .thenReturn(true); + + Assert.assertTrue(task.isDone()); + + verify( + task.mockedFuture, + times(1) + ).isDone(); + } + + @Test + public void isCompletedExceptionallyTest() { + TestableTask task = new TestableTask<>(); + task.applyMockFuture(); + + when(task.mockedFuture.isCompletedExceptionally()) + .thenReturn(true); + + Assert.assertTrue(task.isCompletedExceptionally()); + + verify( + task.mockedFuture, + times(1) + ).isCompletedExceptionally(); + } + + @Test + public void setCancelledTest() { + TestableTask task = new TestableTask<>(); + task.applyMockFuture(); + + task.setCancelled(true); + + verify( + task.mockedFuture, + times(1) + ).cancel(anyBoolean()); + } + + @Test + public void triggerTest() { + Task task = new Task(); + + final AtomicBoolean success = new AtomicBoolean(false); + + CompletableFuture taskChain = task.getFuture().thenRun(() -> { + success.set(true); + }); + + task.trigger(); + + taskChain.join(); + + Assert.assertTrue(success.get()); + + } + + @Test + public void triggerWithObjectTest() { + Task task = new Task(); + + final AtomicBoolean success = new AtomicBoolean(false); + + CompletableFuture taskChain = task.getFuture().thenAccept((str) -> { + success.set(str.equals("foobar")); + }); + + task.trigger("foobar"); + + taskChain.join(); + + Assert.assertTrue(success.get()); + } +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TestableTask.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TestableTask.java new file mode 100644 index 00000000..51852112 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/CoreClasses/TaskTest/TestableTask.java @@ -0,0 +1,32 @@ +package io.kuzzle.test.CoreClasses.TaskTest; + +import io.kuzzle.sdk.CoreClasses.Task; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicReference; + +import static org.mockito.Mockito.mock; + +public class TestableTask extends Task { + public CountDownLatch mockedCountDownLatch = mock(CountDownLatch.class); + public CompletableFuture mockedFuture = mock(CompletableFuture.class); + + public TestableTask() { + super(); + } + + public void applyMockFuture() { + super.future = mockedFuture; + } + + public CountDownLatch getCountDownLatch() { + return super.countDownLatch; + } + + public AtomicReference getAtomicReference() { + return super.atomicReference; + } + + +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/EventListenerTests.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/EventListenerTests.java new file mode 100644 index 00000000..ec22a31f --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/EventListenerTests.java @@ -0,0 +1,159 @@ +package io.kuzzle.test.EventsTest; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class EventListenerTests { + + @Test + public void registerRunnableTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + eventListener.applyMock(); + + eventListener.register(() -> {}); + + verify( + eventListener.mockedCallbacks, + times(1) + ).add(any(Runnable.class)); + } + + @Test + public void unregisterRunnableTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + eventListener.applyMock(); + + eventListener.unregister(() -> {}); + + verify( + eventListener.mockedCallbacks, + times(1) + ).remove(any(Runnable.class)); + } + + @Test + public void registerConsumerTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + eventListener.applyMock(); + + eventListener.register((obj) -> {}); + + verify( + eventListener.mockedCallbacks, + times(1) + ).add(any(Consumer.class)); + } + + @Test + public void unregisterConsumerTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + eventListener.applyMock(); + + eventListener.unregister((obj) -> {}); + + verify( + eventListener.mockedCallbacks, + times(1) + ).remove(any(Consumer.class)); + } + + @Test + public void registerDuplicateTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + + Runnable runnable1 = () -> {}; + eventListener.register(runnable1); + eventListener.register(runnable1); + eventListener.register(runnable1); + eventListener.register(runnable1); + eventListener.register(runnable1); + eventListener.register(() -> {}); + + Assert.assertEquals(2, eventListener.getCallbacks().size()); + } + + @Test + public void triggerRunnableTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + + AtomicBoolean success = new AtomicBoolean(false); + eventListener.register(() -> success.set(true)); + + Assert.assertFalse(success.get()); + + eventListener.trigger(); + + Assert.assertTrue(success.get()); + } + + @Test + public void triggerConsumerTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + + AtomicBoolean success = new AtomicBoolean(false); + eventListener.register((str) -> success.set(str.equals("foobar"))); + + Assert.assertFalse(success.get()); + + eventListener.trigger("foobar"); + + Assert.assertTrue(success.get()); + } + + @Test + public void triggerOnlyConsumerTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + + AtomicBoolean consumerSuccess = new AtomicBoolean(false); + AtomicBoolean runnableSuccess = new AtomicBoolean(false); + + eventListener.register((str) -> consumerSuccess.set(str.equals("foobar"))); + eventListener.register(() -> runnableSuccess.set(true)); + + Assert.assertFalse(consumerSuccess.get()); + Assert.assertFalse(runnableSuccess.get()); + + eventListener.trigger("foobar"); + + Assert.assertTrue(consumerSuccess.get()); + Assert.assertFalse(runnableSuccess.get()); + } + + @Test + public void triggerOnlyRunnableTest() { + TestableEventListener + eventListener = new TestableEventListener<>(); + + AtomicBoolean consumerSuccess = new AtomicBoolean(false); + AtomicBoolean runnableSuccess = new AtomicBoolean(false); + + eventListener.register( + (str) -> consumerSuccess.set(str.equals("foobar")) + ); + eventListener.register(() -> runnableSuccess.set(true)); + + Assert.assertFalse(consumerSuccess.get()); + Assert.assertFalse(runnableSuccess.get()); + + eventListener.trigger(); + + Assert.assertFalse(consumerSuccess.get()); + Assert.assertTrue(runnableSuccess.get()); + } + +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/TestableEventListener.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/TestableEventListener.java new file mode 100644 index 00000000..3d1af9e3 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/EventsTest/TestableEventListener.java @@ -0,0 +1,22 @@ +package io.kuzzle.test.EventsTest; + +import io.kuzzle.sdk.Events.EventListener; + +import java.util.Set; + +import static org.mockito.Mockito.mock; + +public class TestableEventListener extends EventListener { + public Set mockedCallbacks = mock(Set.class); + public TestableEventListener() { + super(); + } + + public void applyMock() { + super.callbacks = mockedCallbacks; + } + + public Set getCallbacks() { + return super.callbacks; + } +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/Helpers/DefaultTests.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/Helpers/DefaultTests.java new file mode 100644 index 00000000..a54da7fc --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/Helpers/DefaultTests.java @@ -0,0 +1,24 @@ +package io.kuzzle.test.Helpers; + +import io.kuzzle.sdk.Helpers.Default; +import org.junit.Assert; +import org.junit.Test; + +public class DefaultTests { + + @Test + public void notNullTest() { + String str1 = Default.notNull(null, "foobar"); + String str2 = Default.notNull("SomeString", "foobar"); + + Integer int1 = Default.notNull(null, 42); + Integer int2 = Default.notNull(10, 42); + + Assert.assertEquals("foobar", str1); + Assert.assertEquals("SomeString", str2); + + Assert.assertEquals(42, int1.intValue()); + Assert.assertEquals(10, int2.intValue()); + } + +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/KuzzleTests.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/KuzzleTests.java new file mode 100644 index 00000000..decab2d6 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/KuzzleTests.java @@ -0,0 +1,176 @@ +package io.kuzzle.test; + +import io.kuzzle.sdk.CoreClasses.Json.JsonSerializer; +import io.kuzzle.sdk.CoreClasses.Task; +import io.kuzzle.sdk.Events.EventListener; +import io.kuzzle.sdk.Exceptions.InternalException; +import io.kuzzle.sdk.Exceptions.NotConnectedException; +import io.kuzzle.sdk.Protocol.AbstractProtocol; +import io.kuzzle.sdk.Protocol.ProtocolState; +import io.kuzzle.sdk.CoreClasses.Responses.ErrorResponse; +import io.kuzzle.sdk.CoreClasses.Responses.Response; +import io.kuzzle.sdk.Protocol.WebSocket; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Matchers; +import org.mockito.Mockito; +import org.mockito.stubbing.Answer; + +import java.net.URISyntaxException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; + +public class KuzzleTests { + private AbstractProtocol networkProtocol = Mockito.mock(WebSocket.class); + private EventListener + tokenExpiredEventListener = Mockito.mock(EventListener.class); + private EventListener + unhandledResponseEventListener = Mockito.mock(EventListener.class); + private TestableKuzzle kuzzle; + + @Before + public void setup() throws URISyntaxException { + kuzzle = new TestableKuzzle(networkProtocol); + kuzzle.setTokenExpiredEventListener(tokenExpiredEventListener); + kuzzle.setUnhandledResponseEventListener(unhandledResponseEventListener); + } + + @Test + public void connect() throws Exception { + kuzzle.connect(); + Mockito.verify( + networkProtocol, + Mockito.times(1) + ).connect(); + } + + @Test + public void disconnect() throws Exception { + kuzzle.disconnect(); + Mockito.verify( + networkProtocol, + Mockito.times(1) + ).disconnect(); + } + + + @Test + public void registerTokenExpiredEvent() throws Exception { + kuzzle.registerTokenExpiredEvent(() -> {}); + Mockito.verify(tokenExpiredEventListener, + Mockito.times(1) + ).register(Matchers.any(Runnable.class)); + } + + @Test + public void unregisterTokenExpiredEvent() throws Exception { + kuzzle.unregisterTokenExpiredEvent(() -> {}); + Mockito.verify( + tokenExpiredEventListener, + Mockito.times(1) + ).unregister(Matchers.any(Runnable.class)); + } + + @Test + public void onStateChanged() { + ConcurrentHashMap> + requests = kuzzle.getRequests(); + + Task response = new Task<>(); + requests.put("foobar", response); + kuzzle.onStateChanged(ProtocolState.CLOSE); + Assert.assertEquals(0, requests.size()); + Assert.assertTrue(response.isCompletedExceptionally()); + } + + @Test(expected = NotConnectedException.class) + public void queryShouldThrowWhenNotConnected() + throws NotConnectedException, InternalException { + Mockito.when(networkProtocol.getState()) + .thenAnswer( + (Answer) invocation -> ProtocolState.CLOSE + ); + + kuzzle.query(new ConcurrentHashMap<>()); + } + + @Test + public void querySuccess() throws NotConnectedException, InternalException { + Mockito.when(networkProtocol.getState()) + .thenAnswer( + (Answer) invocation -> ProtocolState.OPEN + ); + + CompletableFuture + response = kuzzle.query( + new ConcurrentHashMap<>() + ); + + Assert.assertNotNull(response); + Mockito.verify( + networkProtocol, + Mockito.times(1) + ).send(Matchers.any(ConcurrentHashMap.class)); + } + + @Test(expected = InternalException.class) + public void queryShouldThrowWhenVolatileIsNotConcurrentHashMap() + throws NotConnectedException, InternalException { + Mockito.when(networkProtocol.getState()) + .thenAnswer( + (Answer) invocation -> ProtocolState.OPEN + ); + + ConcurrentHashMap payload = new ConcurrentHashMap<>(); + payload.put("volatile", "foobar"); + + kuzzle.query(payload); + } + + @Test + public void onResponseReceivedAndTokenIsExpired() { + ConcurrentHashMap> + requests = kuzzle.getRequests(); + + Response response = new Response(); + response.error = new ErrorResponse(); + response.error.message = "Token expired"; + response.error.status = 42; + response.room = "room-id"; + + Task task = new Task<>(); + + requests.put("room-id", task); + + kuzzle.onResponseReceived(JsonSerializer.serialize(response.toMap())); + + Mockito.verify( + tokenExpiredEventListener, + Mockito.times(1) + ).trigger(); + } + + @Test + public void onResponseReceivedAndResponseIsUnhandled() { + ConcurrentHashMap> + requests = kuzzle.getRequests(); + + AtomicBoolean success = new AtomicBoolean(false); + Response response = new Response(); + response.requestId = "foobar"; + + Task task = new Task<>(); + + requests.put("request-id", task); + + kuzzle.onResponseReceived(JsonSerializer.serialize(response.toMap())); + + Mockito.verify( + unhandledResponseEventListener, + Mockito.times(1) + ).trigger(Matchers.any(Response.class)); + } + +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/TestableWebSocket.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/TestableWebSocket.java new file mode 100644 index 00000000..daae19df --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/TestableWebSocket.java @@ -0,0 +1,38 @@ +package io.kuzzle.test.ProtocolTest; + +import io.kuzzle.sdk.Options.Protocol.WebSocketOptions; +import io.kuzzle.sdk.Protocol.ProtocolState; +import io.kuzzle.sdk.Protocol.WebSocket; +import java.net.URISyntaxException; + +import static org.mockito.Mockito.mock; + +public class TestableWebSocket extends WebSocket { + public int stateChangedCount = 0; + public ProtocolState lastStateDispatched = ProtocolState.CLOSE; + public com.neovisionaries.ws.client.WebSocket + mockedSocket = mock(com.neovisionaries.ws.client.WebSocket.class); + + public TestableWebSocket(String host) + throws URISyntaxException, IllegalArgumentException { + super(host); + } + + public TestableWebSocket(String host, WebSocketOptions options) + throws URISyntaxException, IllegalArgumentException { + super(host, options); + super.stateChanged.register((ProtocolState state) -> { + stateChangedCount += 1; + lastStateDispatched = state; + }); + } + + public com.neovisionaries.ws.client.WebSocket getSocket() { + return super.socket; + } + + @Override + protected com.neovisionaries.ws.client.WebSocket createClientSocket() { + return mockedSocket; + } +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/WebSocketTests.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/WebSocketTests.java new file mode 100644 index 00000000..ed6e1252 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/ProtocolTest/WebSocketTests.java @@ -0,0 +1,90 @@ +package io.kuzzle.test.ProtocolTest; + +import io.kuzzle.sdk.Options.Protocol.WebSocketOptions; +import io.kuzzle.sdk.Protocol.ProtocolState; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.net.URISyntaxException; + +import static org.mockito.Mockito.*; + +public class WebSocketTests { + + private TestableWebSocket socket; + private String host; + private WebSocketOptions options; + + @Before + public void setup() throws URISyntaxException { + host = "foo"; + options = new WebSocketOptions() + .withPort(1234) + .withSsl(true); + socket = new TestableWebSocket(host, options); + } + + @Test + public void constructorNotConnected() throws URISyntaxException { + TestableWebSocket ws = new TestableWebSocket(host, options); + + Assert.assertEquals(ProtocolState.CLOSE, ws.getState()); + Assert.assertNull(ws.getSocket()); + } + + @Test(expected = IllegalArgumentException.class) + public void constructorRejectsNullHost() throws URISyntaxException { + TestableWebSocket ws = new TestableWebSocket(null, options); + } + + @Test + public void connectTest() throws Exception { + when(socket.mockedSocket.connect()).thenAnswer(invocation -> null); + + socket.connect(); + + Assert.assertNotNull(socket.getSocket()); + + socket.connect(); + socket.connect(); + socket.connect(); + + verify(socket.mockedSocket, times(1)).connect(); + + Assert.assertEquals(ProtocolState.OPEN, socket.getState()); + Assert.assertEquals(1, socket.stateChangedCount); + Assert.assertEquals(ProtocolState.OPEN, socket.lastStateDispatched); + } + + @Test + public void disconnectTest() throws Exception { + when(socket.mockedSocket.connect()).thenAnswer(invocation -> null); + + socket.connect(); + + Assert.assertEquals(ProtocolState.OPEN, socket.getState()); + Assert.assertEquals(1, socket.stateChangedCount); + Assert.assertEquals(ProtocolState.OPEN, socket.lastStateDispatched); + + socket.disconnect(); + socket.disconnect(); + socket.disconnect(); + + verify( + socket.mockedSocket, + times(1) + ).disconnect(); + } + + @Test + public void disconnectWithoutEverConnecting() throws Exception { + Assert.assertEquals(ProtocolState.CLOSE, socket.getState()); + Assert.assertEquals(0, socket.stateChangedCount); + + socket.disconnect(); + + Assert.assertEquals(ProtocolState.CLOSE, socket.getState()); + Assert.assertEquals(0, socket.stateChangedCount); + } +} diff --git a/kuzzle-sdk-java/src/test/java/io/kuzzle/test/TestableKuzzle.java b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/TestableKuzzle.java new file mode 100644 index 00000000..f42d8137 --- /dev/null +++ b/kuzzle-sdk-java/src/test/java/io/kuzzle/test/TestableKuzzle.java @@ -0,0 +1,51 @@ +package io.kuzzle.test; + +import io.kuzzle.sdk.CoreClasses.Responses.Response; +import io.kuzzle.sdk.CoreClasses.Task; +import io.kuzzle.sdk.Events.EventListener; +import io.kuzzle.sdk.Kuzzle; +import io.kuzzle.sdk.Options.KuzzleOptions; +import io.kuzzle.sdk.Protocol.AbstractProtocol; +import io.kuzzle.sdk.Protocol.ProtocolState; + +import java.net.URISyntaxException; +import java.util.concurrent.ConcurrentHashMap; + +public class TestableKuzzle extends Kuzzle { + + public TestableKuzzle(AbstractProtocol networkProtocol) throws URISyntaxException, IllegalArgumentException { + super(networkProtocol); + } + + public TestableKuzzle(AbstractProtocol networkProtocol, KuzzleOptions options) throws IllegalArgumentException { + super(networkProtocol, options); + } + + public void setTokenExpiredEventListener(EventListener eventListener) { + super.tokenExpiredEvent = eventListener; + } + + public EventListener getTokenExpiredEventListener() { + return super.tokenExpiredEvent; + } + + public void setUnhandledResponseEventListener(EventListener eventListener) { + super.unhandledResponseEvent = eventListener; + } + + public EventListener getUnhandledResponseEventListener() { + return super.unhandledResponseEvent; + } + + public void onStateChanged(ProtocolState state) { + super.onStateChanged(state); + } + + public void onResponseReceived(String payload) { + super.onResponseReceived(payload); + } + + public ConcurrentHashMap> getRequests() { + return super.requests; + } +}