diff --git a/.github/workflows/chat.yml b/.github/workflows/chat.yml index 8522427..0d1ce3c 100644 --- a/.github/workflows/chat.yml +++ b/.github/workflows/chat.yml @@ -21,4 +21,5 @@ jobs: if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.action == 'opened') env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: mvn sonar:sonar -Dsonar.projectKey=cryptic-game_cryptic-chat -Dsonar.organization=cryptic-game -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=${{ secrets.SONAR_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: ./sonar-scanner.sh \ No newline at end of file diff --git a/pom.xml b/pom.xml index ac8f3f9..142dbb8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,70 +1,91 @@ - 4.0.0 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - net.cryptic_game.microservice - chat - 0.0.3-SNAPSHOT - jar + net.cryptic_game.microservice + chat + 0.0.3-SNAPSHOT + jar - cryptic-game-chat - offical chat microservice of cryptic-game - https://cryptic-game.net + cryptic-game-chat + offical chat microservice of cryptic-game + https://cryptic-game.net - - - - maven-assembly-plugin - 3.1.0 - - - - net.cryptic_game.microservice.chat.App - - - - jar-with-dependencies - - - - - make-assembly - package - - single - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - 1.8 - 1.8 - - - - + + + + maven-assembly-plugin + 3.1.0 + + + + net.cryptic_game.microservice.chat.App + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + - - UTF-8 - + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M3 + - - - jitpack.io - https://jitpack.io - - + + - - - com.github.cryptic-game - java-lib - master-SNAPSHOT - - + + UTF-8 + + + + + jitpack.io + https://jitpack.io + + + + + + com.github.cryptic-game + java-lib + experimental-SNAPSHOT + + + + org.powermock + powermock-module-junit4 + 2.0.2 + test + + + org.powermock + powermock-api-mockito2 + 2.0.2 + test + + diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..779c751 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,7 @@ +sonar.organization=cryptic-game +sonar.projectKey=cryptic-game_cryptic-chat +sonar.projectName=cryptic-chat +sonar.projectVersion=1.0 +sonar.sources=src/main/java/ +sonar.java.binaries=target/classes/ +sonar.coverage.exclusions=src/test/*,src/main/java/net/cryptic_game/microservice/chat/App.java diff --git a/sonar-scanner.sh b/sonar-scanner.sh new file mode 100755 index 0000000..8167f6f --- /dev/null +++ b/sonar-scanner.sh @@ -0,0 +1,13 @@ +#!/bin/sh + +export SONAR_SCANNER_VERSION=4.0.0.1744 +export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux +rm -rf $SONAR_SCANNER_HOME +mkdir -p $SONAR_SCANNER_HOME +curl -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip +unzip $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ +rm $HOME/.sonar/sonar-scanner.zip +export PATH=$SONAR_SCANNER_HOME/bin:$PATH +export SONAR_SCANNER_OPTS="-server" + +sonar-scanner -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=$SONAR_TOKEN \ No newline at end of file diff --git a/src/main/java/net/cryptic_game/microservice/chat/App.java b/src/main/java/net/cryptic_game/microservice/chat/App.java index 8771701..e38f1d0 100644 --- a/src/main/java/net/cryptic_game/microservice/chat/App.java +++ b/src/main/java/net/cryptic_game/microservice/chat/App.java @@ -1,19 +1,27 @@ package net.cryptic_game.microservice.chat; -import org.apache.log4j.BasicConfigurator; - import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.chat.channel.ChannelHandler; +import org.apache.log4j.BasicConfigurator; public class App extends MicroService { - public App() { - super("chat"); - } + private static ChannelHandler channelHandler; + + private App() { + super("chat"); + } + + public static void main(String[] args) { + BasicConfigurator.configure(); - public static void main(String[] args) { - BasicConfigurator.configure(); + channelHandler = new ChannelHandler(); + channelHandler.addChanel("global"); - new App(); - } + new App(); + } + public static ChannelHandler getChannelHandler() { + return channelHandler; + } } diff --git a/src/main/java/net/cryptic_game/microservice/chat/channel/Channel.java b/src/main/java/net/cryptic_game/microservice/chat/channel/Channel.java new file mode 100644 index 0000000..487d95f --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/channel/Channel.java @@ -0,0 +1,66 @@ +package net.cryptic_game.microservice.chat.channel; + +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.wrapper.User; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class Channel { + + private final UUID uuid; + private final List users; + private String name; + + public Channel(final String name) { + this.uuid = UUID.randomUUID(); + this.name = name; + this.users = new ArrayList<>(); + } + + public UUID getUuid() { + return this.uuid; + } + + public String getName() { + return this.name; + } + + public void setName(final String name) { + this.name = name; + } + + public List getUsers() { + return this.users; + } + + public boolean addUser(final User user) { + for (final User u : this.users) { + if (u.getUUID().equals(user.getUUID())) { + return false; + } + } + App.getChannelHandler().notifyAllChannelUsers(ChatAction.MEMBER_JOIN, this, user.getName()); + this.users.add(user); + return true; + } + + public boolean removeUser(final User user) { + for (final User u : this.users) { + if (u.getUUID().equals(user.getUUID())) { + this.users.remove(user); + App.getChannelHandler().notifyAllChannelUsers(ChatAction.MEMBER_LEAVE, this, user.getName()); + return true; + } + } + return false; + } + + public User getUserByName(final String name) { + for (final User user : this.users) { + if (user.getName().equals(name)) return user; + } + return null; + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/channel/ChannelHandler.java b/src/main/java/net/cryptic_game/microservice/chat/channel/ChannelHandler.java new file mode 100644 index 0000000..45ea29c --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/channel/ChannelHandler.java @@ -0,0 +1,82 @@ +package net.cryptic_game.microservice.chat.channel; + +import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.utils.JSONBuilder; +import net.cryptic_game.microservice.wrapper.User; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import static net.cryptic_game.microservice.utils.JSONBuilder.anJSON; + +public class ChannelHandler { + + private final List channels; + + public ChannelHandler() { + this.channels = new ArrayList<>(); + } + + public Channel addChanel(final String name) { + final Channel channel = new Channel(name); + this.channels.add(channel); + return channel; + } + + public void removeChannel(final UUID channelUuid, final String userUuid) { + final Channel channel = this.getChannelByUUID(channelUuid); + this.notifyAllChannelUsers(ChatAction.CHANNEL_DELETE, channel, userUuid); + this.channels.remove(channel); + } + + public Channel getChannelByUUID(final UUID uuid) { + for (final Channel channel : this.channels) if (channel.getUuid().equals(uuid)) return channel; + return null; + } + + public List getChannels() { + return this.channels; + } + + public void notifyUser(final User user, final ChatAction action, final Channel channel, final String target) { + this.notifyUsers(new ArrayList<>(Collections.singletonList(user)), action, channel, target); + } + + public void notifyUser(final User user, final ChatAction action, final Channel channel, final String target, final JSONObject content) { + this.notifyUsers(new ArrayList<>(Collections.singletonList(user)), action, channel, target, content); + } + + public void notifyUsers(final List users, final ChatAction action, final Channel channel, final String target) { + this.notifyUsers(users, action, channel, target, null); + } + + public void notifyAllChannelUsers(final ChatAction action, final Channel channel, final String target) { + this.notifyUsers(channel.getUsers(), action, channel, target, null); + } + + public void notifyAllChannelUsers(final ChatAction action, final Channel channel, final String target, final JSONObject content) { + this.notifyUsers(channel.getUsers(), action, channel, target, content); + } + + public void notifyUsers(final List users, ChatAction action, final Channel channel, final String target, final JSONObject content) { + final JSONBuilder data = anJSON() + .add("action", action.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target); + + if (content != null) { + data.add("content", content); + } + + final JSONObject json = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", data.build() + ).build(); + + users.forEach(user -> MicroService.getInstance().sendToUser(user.getUUID(), json)); + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/channel/ChatAction.java b/src/main/java/net/cryptic_game/microservice/chat/channel/ChatAction.java new file mode 100644 index 0000000..3e4426b --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/channel/ChatAction.java @@ -0,0 +1,21 @@ +package net.cryptic_game.microservice.chat.channel; + +public enum ChatAction { + MEMBER_JOIN("member-join"), + MEMBER_LEAVE("member-leave"), + + SEND_MESSAGE("send-message"), + WHISPER_MESSAGE("whisper-message"), + + CHANNEL_DELETE("channel-delete"); + + final String value; + + ChatAction(final String value) { + this.value = value; + } + + public String getValue() { + return this.value; + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/endpoint/.gitkeep b/src/main/java/net/cryptic_game/microservice/chat/endpoint/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpoints.java b/src/main/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpoints.java new file mode 100644 index 0000000..4595d9d --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpoints.java @@ -0,0 +1,101 @@ +package net.cryptic_game.microservice.chat.endpoint; + +import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.chat.channel.Channel; +import net.cryptic_game.microservice.chat.channel.ChannelHandler; +import net.cryptic_game.microservice.endpoint.UserEndpoint; +import net.cryptic_game.microservice.utils.JSON; +import net.cryptic_game.microservice.wrapper.User; +import org.json.simple.JSONObject; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static net.cryptic_game.microservice.chat.endpoint.EndpointResponse.*; +import static net.cryptic_game.microservice.utils.JSONBuilder.anJSON; +import static net.cryptic_game.microservice.utils.JSONBuilder.simple; + +public class ChannelEndpoints { + + private ChannelEndpoints() { + } + + @UserEndpoint(path = {"channel", "list"}, keys = {}, types = {}) + public static JSONObject getChannel(final JSON data, final UUID uuid) { + final ChannelHandler channelHandler = App.getChannelHandler(); + + final List channelsJson = new ArrayList<>(); + + for (final Channel channel : channelHandler.getChannels()) { + channelsJson.add(anJSON() + .add("uuid", channel.getUuid().toString()) + .add("name", channel.getName()) + .build()); + } + + return simple("channels", channelsJson); + } + + @UserEndpoint(path = {"channel", "members"}, keys = {"channel"}, types = {String.class}) + public static JSONObject getChannelMembers(final JSON data, final UUID uuid) { + final ChannelHandler channelHandler = App.getChannelHandler(); + + final Channel channel = channelHandler.getChannelByUUID(data.getUUID("channel")); + + if (channel == null) { + return CHANNEL_NOT_FOUND.getJson(); + } + + final List userJson = new ArrayList<>(); + + for (final User user : channel.getUsers()) { + userJson.add(simple("name", user.getName())); + } + + return simple("users", userJson); + } + + @UserEndpoint(path = {"channel", "join"}, keys = {"channel"}, types = {String.class}) + public static JSONObject joinChannel(final JSON data, final UUID uuid) { + final ChannelHandler channelHandler = App.getChannelHandler(); + + final User user = MicroService.getInstance().getUser(uuid); + final Channel channel = channelHandler.getChannelByUUID(data.getUUID("channel")); + + if (user == null) { + return USER_NOT_FOUND.getJson(); + } + if (channel == null) { + return CHANNEL_NOT_FOUND.getJson(); + } + + if (channel.addUser(user)) { + return SUCCESS.getJson(); + } + + return FAIL.getJson(); + } + + @UserEndpoint(path = {"channel", "leave"}, keys = {"channel"}, types = {String.class}) + public static JSONObject leaveChannel(final JSON data, final UUID uuid) { + final ChannelHandler channelHandler = App.getChannelHandler(); + + final User user = MicroService.getInstance().getUser(uuid); + final Channel channel = channelHandler.getChannelByUUID(data.getUUID("channel")); + + if (user == null) { + return USER_NOT_FOUND.getJson(); + } + if (channel == null) { + return CHANNEL_NOT_FOUND.getJson(); + } + + if (channel.removeUser(user)) { + return SUCCESS.getJson(); + } + + return FAIL.getJson(); + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/endpoint/EndpointResponse.java b/src/main/java/net/cryptic_game/microservice/chat/endpoint/EndpointResponse.java new file mode 100644 index 0000000..b00defe --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/endpoint/EndpointResponse.java @@ -0,0 +1,24 @@ +package net.cryptic_game.microservice.chat.endpoint; + +import org.json.simple.JSONObject; + +import static net.cryptic_game.microservice.utils.JSONBuilder.simple; + +public enum EndpointResponse { + + USER_NOT_FOUND(simple("error", "user_not_found")), + CHANNEL_NOT_FOUND(simple("error", "channel_not_found")), + USER_NOT_IN_CHANNEL(simple("error", "user_not_in_channel")), + FAIL(simple("success", false)), + SUCCESS(simple("success", true)); + + final JSONObject json; + + EndpointResponse(final JSONObject json) { + this.json = json; + } + + public JSONObject getJson() { + return this.json; + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/endpoint/MessageEndpoints.java b/src/main/java/net/cryptic_game/microservice/chat/endpoint/MessageEndpoints.java new file mode 100644 index 0000000..030cef9 --- /dev/null +++ b/src/main/java/net/cryptic_game/microservice/chat/endpoint/MessageEndpoints.java @@ -0,0 +1,79 @@ +package net.cryptic_game.microservice.chat.endpoint; + +import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.chat.channel.Channel; +import net.cryptic_game.microservice.chat.channel.ChatAction; +import net.cryptic_game.microservice.endpoint.UserEndpoint; +import net.cryptic_game.microservice.utils.JSON; +import net.cryptic_game.microservice.wrapper.User; +import org.json.simple.JSONObject; + +import java.util.Date; +import java.util.UUID; + +import static net.cryptic_game.microservice.chat.endpoint.EndpointResponse.*; +import static net.cryptic_game.microservice.utils.JSONBuilder.anJSON; +import static net.cryptic_game.microservice.utils.JSONBuilder.simple; + +public class MessageEndpoints { + + private MessageEndpoints() { + } + + @UserEndpoint(path = {"message", "send"}, keys = {"channel", "message"}, types = {String.class, String.class}) + public static JSONObject sendMessage(final JSON data, final UUID userUuid) { + final UUID channelUuid = data.getUUID("channel"); + final String messageContent = data.get("message"); + final User user = MicroService.getInstance().getUser(userUuid); + + if (user == null) { + return USER_NOT_FOUND.getJson(); + } + + final Channel channel = App.getChannelHandler().getChannelByUUID(channelUuid); + if (channel == null) { + return CHANNEL_NOT_FOUND.getJson(); + } + + final JSONObject content = anJSON() + .add("message", messageContent) + .add("send-date", new Date().getTime()) + .build(); + + App.getChannelHandler().notifyAllChannelUsers(ChatAction.SEND_MESSAGE, channel, user.getName(), content); + + return simple("success", true); + } + + @UserEndpoint(path = {"message", "whisper"}, keys = {"channel", "message", "target"}, types = {String.class, String.class, String.class}) + public static JSONObject whisperMessage(final JSON data, final UUID userUuid) { + final UUID channelUuid = data.getUUID("channel"); + final String messageContent = data.get("message"); + final String targetName = data.get("target"); + final User user = MicroService.getInstance().getUser(userUuid); + + if (user == null) { + return USER_NOT_FOUND.getJson(); + } + + final Channel channel = App.getChannelHandler().getChannelByUUID(channelUuid); + if (channel == null) { + return CHANNEL_NOT_FOUND.getJson(); + } + + final User target = channel.getUserByName(targetName); + if (target == null) { + return USER_NOT_IN_CHANNEL.getJson(); + } + + final JSONObject content = anJSON() + .add("message", messageContent) + .add("send-date", new Date().getTime()) + .build(); + + App.getChannelHandler().notifyUser(target, ChatAction.WHISPER_MESSAGE, channel, user.getName(), content); + + return simple("success", true); + } +} diff --git a/src/main/java/net/cryptic_game/microservice/chat/model/.gitkeep b/src/main/java/net/cryptic_game/microservice/chat/model/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelHandlerTests.java b/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelHandlerTests.java new file mode 100644 index 0000000..7050eae --- /dev/null +++ b/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelHandlerTests.java @@ -0,0 +1,247 @@ +package net.cryptic_game.microservice.chat.channel; + +import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.wrapper.User; +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static net.cryptic_game.microservice.utils.JSONBuilder.anJSON; +import static net.cryptic_game.microservice.utils.JSONBuilder.simple; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.*; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MicroService.class, App.class}) +public class ChannelHandlerTests { + + @Mock + MicroService microService; + + @Mock + ChannelHandler channelHandler; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mockStatic(MicroService.class); + mockStatic(App.class); + when(MicroService.getInstance()).thenReturn(microService); + when(App.getChannelHandler()).thenReturn(channelHandler); + } + + @Test + public void testChannelHandlerAddChannel() { + final ChannelHandler channelHandler = new ChannelHandler(); + + channelHandler.addChanel("test"); + + assertEquals("test", channelHandler.getChannels().get(0).getName()); + } + + @Test + public void testChannelHandlerRemoveChannel() { + final ChannelHandler channelHandler = new ChannelHandler(); + + channelHandler.addChanel("test"); + + final Channel testChannel = channelHandler.getChannels().get(0); + if (!channelHandler.getChannels().get(0).getName().equals("test")) { + fail(); + } + + channelHandler.removeChannel(testChannel.getUuid(), null); + + assertNull(channelHandler.getChannelByUUID(testChannel.getUuid())); + } + + @Test + public void testChannelHandlerGetChannelByUuid() { + final ChannelHandler channelHandler = new ChannelHandler(); + + channelHandler.addChanel("test"); + final Channel testChannel = channelHandler.getChannels().get(0); + + assertNotNull(channelHandler.getChannelByUUID(testChannel.getUuid())); + } + + @Test + public void testNotifyUserWithOutJson() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final User user = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final Channel channel = new Channel(""); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyUser(user, ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString()); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .build() + ).build(); + + verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject); + } + + @Test + public void testNotifyUser() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final User user = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final Channel channel = new Channel(""); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyUser(user, ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString(), simple("abc", "cba")); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .add("content", simple("abc", "cba")) + .build() + ).build(); + + verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject); + } + + @Test + public void testNotifyAllChannelUsersWithOutJson() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final List users = new ArrayList<>(); + users.add(new User(UUID.randomUUID(), "", "", new Date(), new Date())); + + final Channel channel = new Channel(""); + users.forEach(channel::addUser); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyAllChannelUsers(ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString()); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .build() + ).build(); + + users.forEach(user -> verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject)); + } + + @Test + public void testNotifyAllChannelUsers() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final List users = new ArrayList<>(); + users.add(new User(UUID.randomUUID(), "", "", new Date(), new Date())); + + final Channel channel = new Channel(""); + users.forEach(channel::addUser); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyAllChannelUsers(ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString(), simple("abc", "cba")); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .add("content", simple("abc", "cba")) + .build() + ).build(); + + users.forEach(user -> verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject)); + } + + @Test + public void testNotifyUsersWithOutJson() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final List users = new ArrayList<>(); + users.add(new User(UUID.randomUUID(), "", "", new Date(), new Date())); + + final Channel channel = new Channel(""); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyUsers(users, ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString()); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .build() + ).build(); + + users.forEach(user -> verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject)); + } + + @Test + public void testNotifyUsers() { + doNothing().when(microService).sendToUser(any(UUID.class), any(JSONObject.class)); + + final User target = new User(UUID.randomUUID(), "", "", new Date(), new Date()); + + final List users = new ArrayList<>(); + users.add(new User(UUID.randomUUID(), "", "", new Date(), new Date())); + + final Channel channel = new Channel(""); + + final ChannelHandler channelHandler = new ChannelHandler(); + channelHandler.notifyUsers(users, ChatAction.CHANNEL_DELETE, channel, target.getUUID().toString(), simple("abc", "cba")); + + final JSONObject jsonObject = anJSON() + .add("notify-id", "chat-update") + .add("origin", "chat") + .add("data", anJSON() + .add("action", ChatAction.CHANNEL_DELETE.getValue()) + .add("channel", channel.getUuid().toString()) + .add("user", target.getUUID().toString()) + .add("content", simple("abc", "cba")) + .build() + ).build(); + + users.forEach(user -> verify(microService, times(1)).sendToUser(user.getUUID(), jsonObject)); + } +} + diff --git a/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelTests.java b/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelTests.java new file mode 100644 index 0000000..f6b04eb --- /dev/null +++ b/src/test/java/net/cryptic_game/microservice/chat/channel/ChannelTests.java @@ -0,0 +1,136 @@ +package net.cryptic_game.microservice.chat.channel; + +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.wrapper.User; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.Date; +import java.util.UUID; + +import static org.junit.Assert.*; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(App.class) +public class ChannelTests { + + @Mock + ChannelHandler channelHandler; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mockStatic(App.class); + when(App.getChannelHandler()).thenReturn(channelHandler); + } + + @Test + public void testGetUuid() { + final Channel channel = new Channel("test"); + assertNotNull(channel.getUuid()); + } + + @Test + public void testGetName() { + final Channel channel = new Channel("test"); + assertEquals("test", channel.getName()); + } + + @Test + public void testSetName() { + final Channel channel = new Channel("test"); + channel.setName("test123"); + + assertEquals("test123", channel.getName()); + } + + @Test + public void testAddUser() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + channel.addUser(testUser); + channel.addUser(new User(UUID.randomUUID(), "test123", "test@test.test", new Date(), new Date())); + + assertTrue(channel.getUsers().contains(testUser)); + } + + @Test + public void testAddUserReturn() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + assertTrue(channel.addUser(testUser)); + } + + @Test + public void testDupedAddUser() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + channel.addUser(testUser); + assertFalse(channel.addUser(testUser)); + } + + @Test + public void testRemoveUser() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + channel.addUser(testUser); + channel.addUser(new User(UUID.randomUUID(), "test123", "test@test.test", new Date(), new Date())); + + if (!channel.getUsers().contains(testUser)) { + fail(); + } + + channel.removeUser(testUser); + + assertFalse(channel.getUsers().contains(testUser)); + } + + @Test + public void testRemoveUserReturn() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + channel.addUser(testUser); + channel.addUser(new User(UUID.randomUUID(), "test123", "test@test.test", new Date(), new Date())); + + if (!channel.getUsers().contains(testUser)) { + fail(); + } + + assertTrue(channel.removeUser(testUser)); + } + + @Test + public void testRemoveUserWithoutExist() { + final Channel channel = new Channel("test"); + channel.addUser(new User(UUID.randomUUID(), "test123", "test@test.test", new Date(), new Date())); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + assertFalse(channel.removeUser(testUser)); + } + + @Test + public void testGetUserByName() { + final Channel channel = new Channel("test"); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + channel.addUser(testUser); + + assertEquals(testUser, channel.getUserByName(testUser.getName())); + } + + @Test + public void testGetUserByNameWithoutExist() { + final Channel channel = new Channel("test"); + channel.addUser(new User(UUID.randomUUID(), "test123", "test@test.test", new Date(), new Date())); + final User testUser = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + assertNull(channel.getUserByName(testUser.getName())); + } +} diff --git a/src/test/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpointsTests.java b/src/test/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpointsTests.java new file mode 100644 index 0000000..fa4d0e0 --- /dev/null +++ b/src/test/java/net/cryptic_game/microservice/chat/endpoint/ChannelEndpointsTests.java @@ -0,0 +1,176 @@ +package net.cryptic_game.microservice.chat.endpoint; + +import net.cryptic_game.microservice.MicroService; +import net.cryptic_game.microservice.chat.App; +import net.cryptic_game.microservice.chat.channel.Channel; +import net.cryptic_game.microservice.chat.channel.ChannelHandler; +import net.cryptic_game.microservice.chat.channel.ChatAction; +import net.cryptic_game.microservice.utils.JSON; +import net.cryptic_game.microservice.wrapper.User; +import org.json.simple.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static net.cryptic_game.microservice.utils.JSONBuilder.anJSON; +import static net.cryptic_game.microservice.utils.JSONBuilder.simple; +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.isA; +import static org.powermock.api.mockito.PowerMockito.*; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({App.class, MicroService.class}) +public class ChannelEndpointsTests { + + private ChannelHandler channelHandler; + private MicroService microService; + + @Before + public void setUp() { + mockStatic(App.class); + mockStatic(MicroService.class); + this.channelHandler = new ChannelHandler(); + this.microService = mock(MicroService.class); + when(App.getChannelHandler()).thenReturn(this.channelHandler); + when(MicroService.getInstance()).thenReturn(this.microService); + } + + @Test + public void getChannel() { + final Channel[] channels = new Channel[2]; + channels[0] = this.channelHandler.addChanel("test"); + channels[1] = this.channelHandler.addChanel("test123"); + + final List resultChannels = (List) ChannelEndpoints.getChannel(new JSON(new JSONObject()), UUID.randomUUID()).get("channels"); + + assertEquals(channels.length, resultChannels.size()); + + for (int i = 0; i < resultChannels.size(); i++) { + final Channel channel = channels[i]; + assertEquals(anJSON() + .add("uuid", channel.getUuid().toString()) + .add("name", channel.getName()) + .build(), resultChannels.get(i)); + } + } + + @Test + public void getChannelEmpty() { + final List resultChannels = (List) ChannelEndpoints.getChannel(new JSON(new JSONObject()), UUID.randomUUID()).get("channels"); + assertEquals(resultChannels.size(), 0); + } + + @Test + public void getChannelMembersWithoutChannel() { + assertEquals(simple("error", "channel_not_found").toString(), ChannelEndpoints.getChannelMembers(new JSON(simple("channel", UUID.randomUUID().toString())), UUID.randomUUID()).toString()); + } + + @Test + public void getChannelMembers() { + this.channelHandler = mock(ChannelHandler.class); + when(App.getChannelHandler()).thenReturn(this.channelHandler); + doNothing().when(this.channelHandler).notifyAllChannelUsers(isA(ChatAction.class), isA(Channel.class), isA(String.class)); + + final Channel channel = new Channel("test123"); + final User[] users = new User[2]; + users[0] = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + users[1] = new User(UUID.randomUUID(), "test1", "tes1t@test1.test1", new Date(), new Date()); + for (final User user : users) { + channel.addUser(user); + } + + when(this.channelHandler.getChannelByUUID(channel.getUuid())).thenReturn(channel); + + final List resultUsers = (List) ChannelEndpoints.getChannelMembers( + new JSON(simple("channel", channel.getUuid().toString())), + UUID.randomUUID()) + .get("users"); + + assertEquals(users.length, resultUsers.size()); + + for (int i = 0; i < resultUsers.size(); i++) { + assertEquals(users[i].getName(), resultUsers.get(i).get("name")); + } + } + + @Test + public void joinChannelEmptyUser() { + assertEquals(simple("error", "user_not_found").toString(), ChannelEndpoints.leaveChannel(new JSON(simple("channel", UUID.randomUUID())), UUID.randomUUID()).toString()); + } + + @Test + public void joinChannelEmptyChannel() { + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("error", "channel_not_found").toString(), ChannelEndpoints.leaveChannel(new JSON(simple("channel", UUID.randomUUID())), user.getUUID()).toString()); + } + + @Test + public void joinChannelAlreadyJoined() { + final Channel channel = this.channelHandler.addChanel("test123"); + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + this.channelHandler = mock(ChannelHandler.class); + when(App.getChannelHandler()).thenReturn(this.channelHandler); + doNothing().when(this.channelHandler).notifyAllChannelUsers(isA(ChatAction.class), isA(Channel.class), isA(String.class)); + when(this.channelHandler.getChannelByUUID(channel.getUuid())).thenReturn(channel); + + channel.addUser(user); + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("success", false).toString(), ChannelEndpoints.joinChannel(new JSON(simple("channel", channel.getUuid().toString())), user.getUUID()).toString()); + } + + @Test + public void joinChannel() { + final Channel channel = this.channelHandler.addChanel("test123"); + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("success", true).toString(), ChannelEndpoints.joinChannel(new JSON(simple("channel", channel.getUuid().toString())), user.getUUID()).toString()); + } + + @Test + public void leaveChannelEmptyUser() { + assertEquals(simple("error", "user_not_found").toString(), ChannelEndpoints.joinChannel(new JSON(simple("channel", UUID.randomUUID())), UUID.randomUUID()).toString()); + } + + @Test + public void leaveChannelEmptyChannel() { + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("error", "channel_not_found").toString(), ChannelEndpoints.joinChannel(new JSON(simple("channel", UUID.randomUUID())), user.getUUID()).toString()); + } + + @Test + public void leaveChannelWithoutUser() { + final Channel channel = this.channelHandler.addChanel("test123"); + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + this.channelHandler = mock(ChannelHandler.class); + when(App.getChannelHandler()).thenReturn(this.channelHandler); + when(this.channelHandler.getChannelByUUID(channel.getUuid())).thenReturn(channel); + + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("success", false).toString(), ChannelEndpoints.leaveChannel(new JSON(simple("channel", channel.getUuid().toString())), user.getUUID()).toString()); + } + + @Test + public void leaveChannel() { + final Channel channel = this.channelHandler.addChanel("test123"); + final User user = new User(UUID.randomUUID(), "test", "test@test.test", new Date(), new Date()); + + this.channelHandler = mock(ChannelHandler.class); + when(App.getChannelHandler()).thenReturn(this.channelHandler); + doNothing().when(this.channelHandler).notifyAllChannelUsers(isA(ChatAction.class), isA(Channel.class), isA(String.class)); + when(this.channelHandler.getChannelByUUID(channel.getUuid())).thenReturn(channel); + + channel.addUser(user); + when(this.microService.getUser(isA(UUID.class))).thenReturn(user); + assertEquals(simple("success", true).toString(), ChannelEndpoints.leaveChannel(new JSON(simple("channel", channel.getUuid().toString())), user.getUUID()).toString()); + } +}