/*************************************************************************** * Copyright 2006-2016 by Christian Ihle * * contact@kouchat.net * * * * This file is part of KouChat. * * * * KouChat is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * KouChat is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with KouChat. * * If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ package net.usikkert.kouchat.testclient; import java.io.File; import net.usikkert.kouchat.android.settings.AndroidSettingsSaver; import net.usikkert.kouchat.message.CoreMessages; import net.usikkert.kouchat.misc.CommandException; import net.usikkert.kouchat.misc.CommandParser; import net.usikkert.kouchat.misc.Controller; import net.usikkert.kouchat.misc.ErrorHandler; import net.usikkert.kouchat.misc.User; import net.usikkert.kouchat.misc.UserList; import net.usikkert.kouchat.net.FileReceiver; import net.usikkert.kouchat.net.FileSender; import net.usikkert.kouchat.net.FileToSend; import net.usikkert.kouchat.net.TransferList; import net.usikkert.kouchat.settings.Settings; import net.usikkert.kouchat.util.Tools; import net.usikkert.kouchat.util.Validate; import org.jetbrains.annotations.NonNls; /** * A class that can be used for simulating a KouChat client in tests. * * @author Christian Ihle */ public class TestClient { private final Controller controller; private final TestClientUserInterface ui; private final TransferList transferList; private final CommandParser commandParser; private final User me; public TestClient() { this("Test", 12345678, 0); } public TestClient(final String nickName, final int userCode) { this(nickName, userCode, 0); } public TestClient(@NonNls final String nickName, final int userCode, final int ownColor) { final Settings settings = new Settings(); settings.setClient("Test"); if (ownColor != 0) { settings.setOwnColor(ownColor); } me = settings.getMe(); me.setNick(nickName); if (userCode != 0) { TestUtils.setFieldValue(me, "code", userCode); } final ErrorHandler errorHandler = new ErrorHandler(); ui = new TestClientUserInterface(settings, errorHandler); final CoreMessages coreMessages = new CoreMessages(); controller = new Controller(ui, settings, new AndroidSettingsSaver(), coreMessages, errorHandler); transferList = controller.getTransferList(); commandParser = new CommandParser(controller, ui, settings, coreMessages); } public int getUserCode() { return me.getCode(); } /** * Starts a telnet server at port 20000 and blocks until /quit. */ public void startTelnetServer() { new TestClientTelnetServer(ui, controller, commandParser); } public void logon() { controller.start(); controller.logOn(); waitForConnection(); Tools.sleep(100); } public void logoff() { if (!controller.isLoggedOn()) { return; } Tools.sleep(500); controller.logOff(true); controller.shutdown(); } public void changeTopic(final String topic) { try { controller.changeTopic(topic); } catch (final CommandException e) { throw new RuntimeException(e); } } /** * This is a hack to set the initial topic of the chat. * * @param topic The topic to set. * @param date The date the topic was set, in milliseconds. */ public void setInitialTopic(final String topic, final long date) { if (controller.isLoggedOn()) { throw new RuntimeException("Can't set initial topic when already logged on"); } controller.getTopic().changeTopic(topic, me.getNick(), date); } /** * Sends the specified chat message to the main chat. * * @param message The message to send. */ public void sendChatMessage(final String message) { try { controller.sendChatMessage(message); } catch (final CommandException e) { throw new RuntimeException(e); } } /** * Sends the specified chat message to the private chat of the specified user. * * @param message The message to send. * @param toUser The user to send the private message to. */ public void sendPrivateChatMessage(final String message, final User toUser) { try { controller.sendPrivateMessage(message, toUser); } catch (final CommandException e) { throw new RuntimeException(e); } } /** * Checks if the specified message has arrived from the specified user in the main chat. * * @param user The user who sent the message. * @param message The message the user sent. * @return If the message has arrived. */ public boolean gotMessage(final User user, final String message) { return ui.gotMessage(user, message); } /** * Gets the color of the specified message from the specified user in the main chat. * * @param user The user who sent the message. * @param message The message the user sent. * @return The color of the message. */ public int getColorOfMessage(final User user, final String message) { return ui.getColorOfMessage(user, message); } /** * Checks if the specified private message has arrived from the specified user in the private chat. * * @param user The user who sent the private message. * @param message The private message the user sent. * @return If the private message has arrived. */ public boolean gotPrivateMessage(final User user, final String message) { final User localUser = controller.getUser(user.getCode()); // Because user might be from another context final TestClientPrivateChatWindow privchat = (TestClientPrivateChatWindow) localUser.getPrivchat(); return privchat.gotPrivateMessage(localUser, message); } /** * Gets the color of the specified private message from the specified user in the private chat. * * @param user The user who sent the private message. * @param message The private message the user sent. * @return The color of the private message. */ public int getColorOfPrivateMessage(final User user, final String message) { final User localUser = controller.getUser(user.getCode()); // Because user might be from another context final TestClientPrivateChatWindow privchat = (TestClientPrivateChatWindow) localUser.getPrivchat(); return privchat.getColorOfPrivateMessage(localUser, message); } public boolean gotAnyPrivateMessages() { final UserList userList = controller.getUserList(); for (int i = 0; i < userList.size(); i++) { final User user = userList.get(i); final TestClientPrivateChatWindow privchat = (TestClientPrivateChatWindow) user.getPrivchat(); if (privchat != null && privchat.gotAnyPrivateMessages()) { return true; } } return false; } public void resetPrivateMessages() { final UserList userList = controller.getUserList(); for (int i = 0; i < userList.size(); i++) { final User user = userList.get(i); final TestClientPrivateChatWindow privchat = (TestClientPrivateChatWindow) user.getPrivchat(); if (privchat != null) { privchat.resetPrivateMessages(); } } } public void goAway(final String awayMessage) { try { controller.changeAwayStatus(me.getCode(), true, awayMessage); } catch (final CommandException e) { throw new RuntimeException(e); } } public void comeBack() { try { controller.changeAwayStatus(me.getCode(), false, ""); } catch (final CommandException e) { throw new RuntimeException(e); } } public void changeNickName(final String newNickName) { try { controller.changeMyNick(newNickName); } catch (final CommandException e) { throw new RuntimeException(e); } } public void startWriting() { controller.updateMeWriting(true); } public void stopWriting() { controller.updateMeWriting(false); } /** * Accepts a file transfer of a file with the given name from the given user. * * @param user The user who is trying to send a file. * @param fileName The name of the file that the user is trying to send. * @param newFile The full path and file name to use when saving the file. */ public void acceptFile(final User user, final String fileName, final File newFile) { final FileReceiver fileReceiver = findFileReceiver(user, fileName); fileReceiver.setFile(newFile); fileReceiver.accept(); } /** * Rejects a file transfer of a file with the given name from the given user. * * @param user The user who is trying to send a file. * @param fileName The name of the file that the user is trying to send. */ public void rejectFile(final User user, final String fileName) { final FileReceiver fileReceiver = findFileReceiver(user, fileName); fileReceiver.reject(); } /** * Sends the given file from this client to the given user. * * @param user The user to send the file to. * @param file The file to send to the user. */ public void sendFile(final User user, final File file) { final User localUser = controller.getUser(user.getCode()); // Because user might be from another context try { commandParser.sendFile(localUser, new FileToSend(file)); } catch (final CommandException e) { throw new RuntimeException(e); } } public void setFileTransferDelay(final int delay) { ui.setFileTransferDelay(delay); } /** * Cancels sending the given file to the given user. * * @param user The user the file was sent to. * @param file The file that was sent to the user. */ public void cancelFileSending(final User user, final File file) { final FileSender fileSender = findFileSender(user, file); commandParser.cancelFileTransfer(fileSender); } private FileReceiver findFileReceiver(final User user, final String fileName) { final User localUser = controller.getUser(user.getCode()); // Because user might be from another context final FileReceiver fileReceiver = transferList.getFileReceiver(localUser, fileName); Validate.notNull(fileReceiver, String.format("Unable to find the file with the name '%s' from the user '%s'", fileName, user)); return fileReceiver; } private FileSender findFileSender(final User user, final File file) { final User localUser = controller.getUser(user.getCode()); // Because user might be from another context final FileSender fileSender = transferList.getFileSender(localUser, file.getName()); Validate.notNull(fileSender, String.format("Unable to find the file with the name '%s' for the user '%s'", file.getName(), user)); return fileSender; } private void waitForConnection() { Tools.sleep(500); for (int i = 0; i < 20; i++) { if (!controller.isLoggedOn()) { Tools.sleep(100); } } if (!controller.isLoggedOn()) { throw new RuntimeException("Could not connect"); } } }