diff --git a/resources/log4j2.xml b/resources/log4j2.xml
new file mode 100644
index 0000000..ea50218
--- /dev/null
+++ b/resources/log4j2.xml
@@ -0,0 +1,23 @@
+
+
+
+ logs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/lesson7/TestEx.java b/src/lesson7/TestEx.java
new file mode 100644
index 0000000..ba4eb30
--- /dev/null
+++ b/src/lesson7/TestEx.java
@@ -0,0 +1,34 @@
+package lesson7;
+
+import java.util.Arrays;
+
+public class TestEx {
+
+ public int[] task1(int[] data) {
+ for (int i = data.length - 1; i >= 0; i--) {
+ if (data[i] == 4) {
+ return Arrays.copyOfRange(data, i + 1, data.length);
+ }
+ }
+ throw new RuntimeException("Invalid array");
+ }
+
+ public boolean task2(int[] data) {
+ boolean contains1 = false;
+ boolean contains2 = false;
+
+ for (int i = 0; i < data.length; i++) {
+ switch (data[i]) {
+ case 1:
+ contains1 = true;
+ break;
+ case 4:
+ contains2 = true;
+ break;
+ default:
+ return false;
+ }
+ }
+ return contains1 && contains2;
+ }
+}
\ No newline at end of file
diff --git a/src/lesson7/classes_for_tests/TestExJU4TestCase.java b/src/lesson7/classes_for_tests/TestExJU4TestCase.java
new file mode 100644
index 0000000..a3db4f0
--- /dev/null
+++ b/src/lesson7/classes_for_tests/TestExJU4TestCase.java
@@ -0,0 +1,41 @@
+package lesson7.classes_for_tests;
+
+import lesson7.test_framework.my_annotations.AfterSuite;
+import lesson7.test_framework.my_annotations.BeforeSuite;
+import lesson7.test_framework.my_annotations.Test;
+import test_ex.TestEx;
+
+public class TestExJU4TestCase {
+ private TestEx dz;
+
+ @BeforeSuite
+ public void prepare() {
+ dz = new TestEx();
+ System.out.println("Выполняется метод @BeforeSuite prepare()");
+ }
+
+ @AfterSuite
+ public void finish() {
+ dz = null;
+ System.out.println("Выполняется метод @AfterSuite finish()");
+ }
+
+ /*@BeforeSuite // Получим RuntimeException
+ public void prepare2() {
+ dz = new TestEx();
+ }*/
+
+ @Test
+ public void test_task1_where_4_is_not_last() {
+// int[] data = {1, 2, 3, 4, 5, 6, 7};
+// Assert.assertArrayEquals(new int[]{5, 6, 7,}, dz.task1(data));
+ System.out.println("Что-то выполняется в тестовом методе test_task1_where_4_is_not_last()");
+ }
+
+ @Test
+ public void test_task1_with_some_4() {
+// int[] data = {1, 4, 3, 4, 5, 6, 4};
+// Assert.assertArrayEquals(new int[]{}, dz.task1(data));
+ System.out.println("Что-то выполняется в тестовом методе test_task1_with_some_4()");
+ }
+}
\ No newline at end of file
diff --git a/src/lesson7/test_framework/TestManager.java b/src/lesson7/test_framework/TestManager.java
new file mode 100644
index 0000000..df0440b
--- /dev/null
+++ b/src/lesson7/test_framework/TestManager.java
@@ -0,0 +1,138 @@
+package lesson7.test_framework;
+
+import lesson7.TestEx;
+import lesson7.classes_for_tests.TestExJU4TestCase;
+import lesson7.test_framework.my_annotations.AfterSuite;
+import lesson7.test_framework.my_annotations.BeforeSuite;
+import lesson7.test_framework.my_annotations.Test;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class TestManager {
+ public static void main(String[] args) {
+ Class clazz = TestExJU4TestCase.class;
+ start(clazz);
+ }
+
+ public static void start(Class clazz) {
+ doIt(clazz);
+ }
+
+ public static void start(String className) {
+ Class clazz = null;
+ try {
+ clazz = Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ doIt(clazz);
+ }
+
+ private static void doIt(Class clazz) {
+ Method[] methods = clazz.getDeclaredMethods();
+ checkAnnotations(methods);
+ Annotation[] annotations = clazz.getAnnotations();
+ for (Annotation annotation : annotations) {
+ System.out.println(annotation);
+ }
+
+ startMethodWithBeforeSuiteAnnotation(clazz, methods);
+ startMethodWithTestAnnotation(clazz, methods);
+ startMethodWithAfterSuiteAnnotation(clazz, methods);
+ }
+
+ private static void checkAnnotations(Method[] methods) {
+ int beforeCount = 0;
+ int afterCount = 0;
+ for (Method method : methods) {
+// BeforeSuite annotation = method.getAnnotation(BeforeSuite.class);
+ Annotation[] annotations = method.getAnnotations();
+ for (Annotation annotation : annotations) {
+// System.out.println("method " + method + " annotation: " + annotation);
+ if (annotation instanceof BeforeSuite) {
+ beforeCount++;
+ }
+ if (annotation instanceof AfterSuite) {
+ afterCount++;
+ }
+ }
+ if (beforeCount > 1 || afterCount > 1) {
+ throw new RuntimeException();
+ }
+ }
+ }
+
+ private static void startMethodWithAfterSuiteAnnotation(Class clazz, Method[] methods) {
+
+
+ for (Method method : methods) {
+ AfterSuite asAnnotaion = method.getAnnotation(AfterSuite.class);
+ if (asAnnotaion != null) {
+ try {
+// Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
+ Constructor defaultConstructor = clazz.getDeclaredConstructor();
+ TestExJU4TestCase testClass = defaultConstructor.newInstance();
+ method.invoke(testClass);
+// method.invoke(clazz.newInstance());
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static void startMethodWithTestAnnotation(Class clazz, Method[] methods) {
+ for (Method method : methods) {
+ Test testAnnotaion = method.getAnnotation(Test.class);
+ if (testAnnotaion != null) {
+ try {
+// Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
+ Constructor defaultConstructor = clazz.getDeclaredConstructor();
+ TestExJU4TestCase testClass = defaultConstructor.newInstance();
+ method.invoke(testClass);
+// method.invoke(clazz.newInstance());
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static void startMethodWithBeforeSuiteAnnotation(Class clazz, Method[] methods) {
+ for (Method method : methods) {
+ BeforeSuite bsAnnotaion = method.getAnnotation(BeforeSuite.class);
+ if (bsAnnotaion != null) {
+ try {
+// Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
+ Constructor defaultConstructor = clazz.getDeclaredConstructor();
+ TestExJU4TestCase testClass = defaultConstructor.newInstance();
+ method.invoke(testClass);
+// method.invoke(clazz.newInstance());
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+}
diff --git a/src/lesson7/test_framework/my_annotations/AfterSuite.java b/src/lesson7/test_framework/my_annotations/AfterSuite.java
new file mode 100644
index 0000000..738c785
--- /dev/null
+++ b/src/lesson7/test_framework/my_annotations/AfterSuite.java
@@ -0,0 +1,11 @@
+package lesson7.test_framework.my_annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface AfterSuite {
+}
diff --git a/src/lesson7/test_framework/my_annotations/BeforeSuite.java b/src/lesson7/test_framework/my_annotations/BeforeSuite.java
new file mode 100644
index 0000000..f2f27de
--- /dev/null
+++ b/src/lesson7/test_framework/my_annotations/BeforeSuite.java
@@ -0,0 +1,11 @@
+package lesson7.test_framework.my_annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface BeforeSuite {
+}
diff --git a/src/lesson7/test_framework/my_annotations/Test.java b/src/lesson7/test_framework/my_annotations/Test.java
new file mode 100644
index 0000000..f7fb63b
--- /dev/null
+++ b/src/lesson7/test_framework/my_annotations/Test.java
@@ -0,0 +1,12 @@
+package lesson7.test_framework.my_annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Test {
+
+}
diff --git a/src/logging_testing_6/ChatServer.java b/src/logging_testing_6/ChatServer.java
new file mode 100644
index 0000000..c1d203b
--- /dev/null
+++ b/src/logging_testing_6/ChatServer.java
@@ -0,0 +1,130 @@
+package logging_testing_6;
+
+
+import logging_testing_6.auth.AuthService;
+import logging_testing_6.auth.AuthServiceImpl;
+import logging_testing_6.gui.Message;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+//import org.slf4j.Logger;
+//import org.slf4j.LoggerFactory;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ChatServer {
+
+ // private static final String USER_CONNECTED_PATTERN = "/userconn";
+// private static final String USER_DISCONN_PATTERN = "/userdissconn";
+ private static final Pattern AUTH_PATTERN = Pattern.compile("^/auth (\\w+) (\\w+)$");
+
+ private AuthService authService = new AuthServiceImpl();
+
+ private Map clientHandlerMap = Collections.synchronizedMap(new HashMap<>());
+ private ExecutorService executorService;
+
+ // private static final Logger logger = LoggerFactory.getLogger(ChatServer.class);
+ private static final Logger log = LogManager.getLogger(ChatServer.class);
+
+ public static void main(String[] args) {
+ ChatServer chatServer = new ChatServer();
+ chatServer.start(7777);
+ }
+
+ public void start(int port) {
+ executorService = Executors.newCachedThreadPool();
+ try (ServerSocket serverSocket = new ServerSocket(port)) {
+ log.info("Server started!");
+ while (true) {
+ Socket socket = serverSocket.accept();
+ DataInputStream inp = new DataInputStream(socket.getInputStream());
+ DataOutputStream out = new DataOutputStream(socket.getOutputStream());
+ log.info("New client connected!");
+
+ try {
+ String authMessage = inp.readUTF();
+ Matcher matcher = AUTH_PATTERN.matcher(authMessage);
+ if (matcher.matches()) {
+ String username = matcher.group(1);
+ String password = matcher.group(2);
+ if (authService.authUser(username, password)) {
+ clientHandlerMap.put(username, new ClientHandler(username, socket, this));
+ out.writeUTF("/auth successful");
+ out.flush();
+ broadcastUserConnected();
+
+ log.info("Authorization for user {} %s successful", username);
+ } else {
+ log.info("Authorization for user {} failed", username);
+ out.writeUTF("/auth fails");
+ out.flush();
+ socket.close();
+ }
+ } else {
+ log.info("Incorrect authorization message {}", authMessage);
+ out.writeUTF("/auth fails");
+ out.flush();
+ socket.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+// authService.close();
+ executorService.shutdown();
+ }
+ }
+
+ public void sendMessage(String userTo, String userFrom, String msg) throws IOException {
+ ClientHandler userToClientHandler = clientHandlerMap.get(userTo);
+ if (userToClientHandler != null) {
+ userToClientHandler.sendMessage(userFrom, msg);
+ } else {
+ log.debug("User {} not found. Message from {} is lost.", userTo, userFrom);
+ }
+ }
+
+ public ExecutorService getExecutorService() {
+ return executorService;
+ }
+
+ public void sendMessage(Message message) throws IOException {
+ String userTo = message.getUserTo();
+ String userFrom = message.getUserFrom();
+ String msg = message.getText();
+ ClientHandler userToClientHandler = clientHandlerMap.get(userTo);
+ if (userToClientHandler != null) {
+ userToClientHandler.sendMessage(userFrom, msg);
+ } else {
+ log.debug("User {} not found. Message from {} is lost.", userTo, userFrom);
+ }
+ }
+
+ public List getUserList() {
+ return new ArrayList<>(clientHandlerMap.keySet());
+ }
+
+ public void unsubscribeClient(ClientHandler clientHandler) {
+ clientHandlerMap.remove(clientHandler.getUsername());
+ broadcastUserDisconnected();
+ }
+
+ public void broadcastUserConnected() {
+ // TODO сообщать о том, что конкретный пользователь подключился
+ }
+
+ public void broadcastUserDisconnected() {
+ // TODO сообщать о том, что конкретный пользователь отключился
+ }
+}
diff --git a/src/logging_testing_6/ClientHandler.java b/src/logging_testing_6/ClientHandler.java
new file mode 100644
index 0000000..7f466dc
--- /dev/null
+++ b/src/logging_testing_6/ClientHandler.java
@@ -0,0 +1,77 @@
+package logging_testing_6;
+
+import logging_testing_6.gui.Message;
+import logging_testing_6.history.HistoryKeeper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class ClientHandler {
+
+ private static final Pattern MESSAGE_PATTERN = Pattern.compile("^/w (\\w+) (.+)", Pattern.MULTILINE);
+ private static final String MESSAGE_SEND_PATTERN = "/w %s %s";
+ private static final Logger log = LogManager.getLogger(ClientHandler.class);
+
+
+// private final Thread handleThread;
+ private final DataInputStream inp;
+ private final DataOutputStream out;
+ private final ChatServer server;
+ private final String username;
+ private final Socket socket;
+
+ public ClientHandler(String username, Socket socket, ChatServer server) throws IOException {
+ this.username = username;
+ this.socket = socket;
+ this.server = server;
+ this.inp = new DataInputStream(socket.getInputStream());
+ this.out = new DataOutputStream(socket.getOutputStream());
+
+ server.getExecutorService().submit(() -> {
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ String msg = inp.readUTF();
+ log.info("Message from user {}: {}", username, msg);
+
+ Matcher matcher = MESSAGE_PATTERN.matcher(msg);
+ if (matcher.matches()) {
+ String userTo = matcher.group(1);
+ String messageText = matcher.group(2);
+ Message message = new Message(username, userTo, messageText);
+ server.sendMessage(message);
+
+ // Добавляем сообщения в файл истории отправителя
+ HistoryKeeper.saveMassageToHistoryFrom(message);
+ // Добавляем сообщения в файл истории получателя
+ HistoryKeeper.saveMassageToHistoryTo(message);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ log.info("Client {} disconnected", username);
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ server.unsubscribeClient(ClientHandler.this);
+ }
+ });
+ }
+
+ public void sendMessage(String userTo, String msg) throws IOException {
+ out.writeUTF(String.format(MESSAGE_SEND_PATTERN, userTo, msg));
+ }
+
+ public String getUsername() {
+ return username;
+ }
+}
diff --git a/src/logging_testing_6/auth/AuthService.java b/src/logging_testing_6/auth/AuthService.java
new file mode 100644
index 0000000..8a47ee4
--- /dev/null
+++ b/src/logging_testing_6/auth/AuthService.java
@@ -0,0 +1,6 @@
+package logging_testing_6.auth;
+
+public interface AuthService {
+
+ boolean authUser(String username, String password);
+}
diff --git a/src/logging_testing_6/auth/AuthServiceImpl.java b/src/logging_testing_6/auth/AuthServiceImpl.java
new file mode 100644
index 0000000..03794ba
--- /dev/null
+++ b/src/logging_testing_6/auth/AuthServiceImpl.java
@@ -0,0 +1,13 @@
+package logging_testing_6.auth;
+
+import logging_testing_6.dbconn.JdbcExample;
+
+public class AuthServiceImpl implements AuthService {
+
+ @Override
+ public boolean authUser(String username, String password) {
+ String pwd = JdbcExample.readFromDB(username);
+
+ return pwd != null && pwd.equals(password);
+ }
+}
diff --git a/src/logging_testing_6/dbconn/JdbcExample.java b/src/logging_testing_6/dbconn/JdbcExample.java
new file mode 100644
index 0000000..05268f9
--- /dev/null
+++ b/src/logging_testing_6/dbconn/JdbcExample.java
@@ -0,0 +1,44 @@
+package logging_testing_6.dbconn;
+
+import java.sql.*;
+
+public class JdbcExample {
+ private static final String URL = "jdbc:sqlite:database.db";
+
+ static {
+ try {
+ Class.forName("org.sqlite.JDBC");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static String readFromDB(String clientName) {
+ String password = null;
+ try (Connection connection = DriverManager.getConnection(URL)) {
+ PreparedStatement preparedStatement = connection.prepareStatement("SELECT u.name, p.password FROM users u INNER JOIN passwords p on u.id = p.id WHERE u.name = ?");
+ preparedStatement.setString(1, clientName);
+ ResultSet resultSet = preparedStatement.executeQuery();
+ while (resultSet.next()) {
+// String name = resultSet.getString("name");
+ password = resultSet.getString("password");
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ System.out.println("returned password: " + password);
+ return password;
+ }
+
+ public static void changeNick(String oldName, String newName) {
+ try (Connection connection = DriverManager.getConnection(URL)) {
+ PreparedStatement preparedStatement = connection.prepareStatement("UPDATE users SET name = ? WHERE name = ?;");
+ preparedStatement.setString(1, newName);
+ preparedStatement.setString(2, oldName);
+ preparedStatement.executeUpdate();
+ System.out.println("Name " + oldName + " changed to: " + newName);
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/logging_testing_6/gui/App.java b/src/logging_testing_6/gui/App.java
new file mode 100644
index 0000000..2027773
--- /dev/null
+++ b/src/logging_testing_6/gui/App.java
@@ -0,0 +1,17 @@
+package logging_testing_6.gui;
+
+import javax.swing.*;
+
+public class App {
+
+ private static MainWindow mainWindow;
+
+ public static void main(String[] args) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ mainWindow = new MainWindow();
+ }
+ });
+ }
+}
diff --git a/src/logging_testing_6/gui/AuthException.java b/src/logging_testing_6/gui/AuthException.java
new file mode 100644
index 0000000..974d389
--- /dev/null
+++ b/src/logging_testing_6/gui/AuthException.java
@@ -0,0 +1,4 @@
+package logging_testing_6.gui;
+
+public class AuthException extends RuntimeException {
+}
diff --git a/src/logging_testing_6/gui/LoginDialog.java b/src/logging_testing_6/gui/LoginDialog.java
new file mode 100644
index 0000000..1f107ce
--- /dev/null
+++ b/src/logging_testing_6/gui/LoginDialog.java
@@ -0,0 +1,107 @@
+package logging_testing_6.gui;
+
+import javax.swing.*;
+import javax.swing.border.LineBorder;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+
+
+public class LoginDialog extends JDialog {
+
+ private JTextField tfUsername;
+ private JPasswordField pfPassword;
+ private JLabel lbUsername;
+ private JLabel lbPassword;
+ private JButton btnLogin;
+ private JButton btnCancel;
+
+ private final Network network;
+
+ private boolean connected;
+
+ public LoginDialog(Frame parent, Network network) {
+ super(parent, "Login", true);
+
+ this.network = network;
+ this.connected = false;
+
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints cs = new GridBagConstraints();
+
+ cs.fill = GridBagConstraints.HORIZONTAL;
+
+ lbUsername = new JLabel("Username: ");
+ cs.gridx = 0;
+ cs.gridy = 0;
+ cs.gridwidth = 1;
+ panel.add(lbUsername, cs);
+
+ tfUsername = new JTextField(20);
+ cs.gridx = 1;
+ cs.gridy = 0;
+ cs.gridwidth = 2;
+ panel.add(tfUsername, cs);
+
+ lbPassword = new JLabel("Password: ");
+ cs.gridx = 0;
+ cs.gridy = 1;
+ cs.gridwidth = 1;
+ panel.add(lbPassword, cs);
+
+ pfPassword = new JPasswordField(20);
+ cs.gridx = 1;
+ cs.gridy = 1;
+ cs.gridwidth = 2;
+ panel.add(pfPassword, cs);
+ panel.setBorder(new LineBorder(Color.GRAY));
+
+ btnLogin = new JButton("Login");
+ btnCancel = new JButton("Cancel");
+
+ JPanel bp = new JPanel();
+ bp.add(btnLogin);
+ btnLogin.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ network.authorize(tfUsername.getText(), String.valueOf(pfPassword.getPassword()));
+ connected = true;
+ } catch (AuthException ex) {
+ JOptionPane.showMessageDialog(LoginDialog.this,
+ "Ошибка авторизации",
+ "Авторизация",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ } catch (IOException ex) {
+ JOptionPane.showMessageDialog(LoginDialog.this,
+ "Ошибка сети",
+ "Авторизация",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ dispose();
+ }
+ });
+
+ bp.add(btnCancel);
+ btnCancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ dispose();
+ }
+ });
+
+ getContentPane().add(panel, BorderLayout.CENTER);
+ getContentPane().add(bp, BorderLayout.PAGE_END);
+
+ pack();
+ setResizable(false);
+ setLocationRelativeTo(parent);
+ }
+
+ public boolean isConnected() {
+ return connected;
+ }
+}
diff --git a/src/logging_testing_6/gui/MainWindow.java b/src/logging_testing_6/gui/MainWindow.java
new file mode 100644
index 0000000..bd08833
--- /dev/null
+++ b/src/logging_testing_6/gui/MainWindow.java
@@ -0,0 +1,155 @@
+package logging_testing_6.gui;
+
+import logging_testing_6.gui.elements_for_changing_name.DialogWindow;
+import logging_testing_6.history.HistoryKeeper;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.*;
+import java.util.List;
+
+public class MainWindow extends JFrame implements MessageSender {
+
+ private JTextField textField;
+ private JButton button;
+ private JScrollPane scrollPane;
+ private JList messageList;
+ private DefaultListModel messageListModel;
+ private JList userList;
+ private JPanel panel;
+
+ private Network network;
+
+ public MainWindow() {
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+ setBounds(200, 200, 500, 500);
+
+ // Добавим контекстное меню
+ JPopupMenu popupMenu = createPopupMenu();
+ ((JComponent) getContentPane()).setComponentPopupMenu(popupMenu);
+
+ setLayout(new BorderLayout());
+
+ messageListModel = new DefaultListModel<>();
+ messageList = new JList<>(messageListModel);
+ messageList.setCellRenderer(new MessageCellRenderer());
+
+ panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.add(messageList, BorderLayout.SOUTH);
+ panel.setBackground(messageList.getBackground());
+ scrollPane = new JScrollPane(panel);
+ scrollPane.setInheritsPopupMenu(true); // Добавим контекстное меню
+ add(scrollPane, BorderLayout.CENTER);
+
+ userList = new JList<>();
+ // TODO добавить класс Model для userList по аналогии с messageListModel
+ userList.setListData(new String[]{"ivan", "petr", "julia"}); // Для простоты, пока фиксированный список имен пользователей
+ userList.setPreferredSize(new Dimension(100, 0));
+ add(userList, BorderLayout.WEST);
+ userList.setInheritsPopupMenu(true); // Добавим контекстное меню
+
+ textField = new JTextField();
+ button = new JButton("Отправить");
+ button.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String userTo = userList.getSelectedValue();
+ if (userTo == null) {
+ JOptionPane.showMessageDialog(MainWindow.this,
+ "Не указан получатель",
+ "Отправка сообщения",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ String text = textField.getText();
+ if (text == null || text.trim().isEmpty()) {
+ JOptionPane.showMessageDialog(MainWindow.this,
+ "Нельзя отправить пустое сообщение",
+ "Отправка сообщения",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ Message msg = new Message(network.getUsername(), userTo, text.trim());
+ submitMessage(msg);
+ textField.setText(null);
+ textField.requestFocus();
+
+ network.sendMessageToUser(msg);
+ }
+ });
+
+ this.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent evt) {
+ messageList.ensureIndexIsVisible(messageListModel.size() - 1);
+ }
+ });
+
+ panel = new JPanel();
+ panel.setLayout(new BorderLayout());
+ panel.add(button, BorderLayout.EAST);
+ panel.add(textField, BorderLayout.CENTER);
+
+ add(panel, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ if (network != null) {
+ network.close();
+ }
+ super.windowClosing(e);
+ }
+ });
+
+
+ setVisible(true);
+
+ network = new Network("localhost", 7777, this);
+
+ LoginDialog loginDialog = new LoginDialog(this, network);
+ loginDialog.setVisible(true);
+
+ if (!loginDialog.isConnected()) {
+ System.exit(0);
+ }
+
+ setTitle("Сетевой чат. Пользователь " + network.getUsername());
+
+ List listMessages = HistoryKeeper.getHistory(network.getUsername() + ".txt", 10);
+ for (Message message : listMessages) {
+ messageListModel.addElement(message);
+ }
+ }
+
+ @Override
+ public void submitMessage(Message msg) {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ messageListModel.add(messageListModel.size(), msg);
+ messageList.ensureIndexIsVisible(messageListModel.size() - 1);
+ }
+ });
+ }
+
+ private JPopupMenu createPopupMenu() {
+ JPopupMenu popupMenu = new JPopupMenu();
+ JMenuItem changeNameItem = new JMenuItem("Сменить ник");
+ changeNameItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ DialogWindow dialogWindow = new DialogWindow(getNetwork());
+ }
+ });
+ popupMenu.add(changeNameItem);
+ return popupMenu;
+ }
+
+ public Network getNetwork() {
+ return network;
+ }
+}
diff --git a/src/logging_testing_6/gui/Message.java b/src/logging_testing_6/gui/Message.java
new file mode 100644
index 0000000..aa77eb9
--- /dev/null
+++ b/src/logging_testing_6/gui/Message.java
@@ -0,0 +1,37 @@
+package logging_testing_6.gui;
+
+import java.time.LocalDate;
+
+public class Message {
+
+ private String userFrom;
+
+ private String userTo;
+
+ private String text;
+
+ private LocalDate date;
+
+ public Message(String userFrom, String userTo, String text) {
+ this.userFrom = userFrom;
+ this.userTo = userTo;
+ this.text = text;
+ this.date = LocalDate.now();
+ }
+
+ public String getUserFrom() {
+ return userFrom;
+ }
+
+ public String getUserTo() {
+ return userTo;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+}
diff --git a/src/logging_testing_6/gui/MessageCellRenderer.java b/src/logging_testing_6/gui/MessageCellRenderer.java
new file mode 100644
index 0000000..171be89
--- /dev/null
+++ b/src/logging_testing_6/gui/MessageCellRenderer.java
@@ -0,0 +1,32 @@
+package logging_testing_6.gui;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class MessageCellRenderer extends JPanel implements ListCellRenderer {
+
+ private JLabel userName;
+
+ private JLabel message;
+
+ public MessageCellRenderer() {
+ super();
+ setLayout(new BorderLayout());
+ userName = new JLabel();
+ Font f = userName.getFont();
+ userName.setFont(f.deriveFont(f.getStyle() | Font.BOLD));
+ message = new JLabel();
+ add(userName, BorderLayout.NORTH);
+ add(message, BorderLayout.SOUTH);
+ }
+
+ @Override
+ public Component getListCellRendererComponent(JList extends Message> list, Message value,
+ int index, boolean isSelected, boolean cellHasFocus) {
+ setBackground(list.getBackground());
+ userName.setOpaque(true);
+ userName.setText(value.getUserFrom());
+ message.setText(value.getText());
+ return this;
+ }
+}
diff --git a/src/logging_testing_6/gui/MessageSender.java b/src/logging_testing_6/gui/MessageSender.java
new file mode 100644
index 0000000..4c85248
--- /dev/null
+++ b/src/logging_testing_6/gui/MessageSender.java
@@ -0,0 +1,16 @@
+package logging_testing_6.gui;
+
+/**
+ * Интерфейс для взаимодействия класса сети {@link Network}
+ * с пользовательским интерфейсом на
+ */
+public interface MessageSender {
+
+ /**
+ * Метод вызывается классом сети при получении нового сообщения
+ * @param msg новое сообщение
+ */
+ void submitMessage(Message msg);
+
+ // TODO добавить метод для оповещения о новом пользователе
+}
diff --git a/src/logging_testing_6/gui/Network.java b/src/logging_testing_6/gui/Network.java
new file mode 100644
index 0000000..e1f300f
--- /dev/null
+++ b/src/logging_testing_6/gui/Network.java
@@ -0,0 +1,108 @@
+package logging_testing_6.gui;
+
+import java.io.Closeable;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class Network implements Closeable {
+
+ private static final String AUTH_PATTERN = "/auth %s %s";
+ private static final String MESSAGE_SEND_PATTERN = "/w %s %s";
+ private static final String USER_LIST_PATTERN = "/userlist";
+ private static final Pattern MESSAGE_PATTERN = Pattern.compile("^/w (\\w+) (.+)", Pattern.MULTILINE);
+
+ private Socket socket;
+ private DataOutputStream out;
+ private DataInputStream in;
+ private final MessageSender messageSender;
+ private final Thread receiver;
+
+ private String username;
+ private final String hostName;
+ private final int port;
+
+ public Network(String hostName, int port, MessageSender messageSender) {
+ this.hostName = hostName;
+ this.port = port;
+ this.messageSender = messageSender;
+
+ this.receiver = createReceiverThread();
+ }
+
+ private Thread createReceiverThread() {
+ return new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (!Thread.currentThread().isInterrupted()) {
+ try {
+ String text = in.readUTF();
+
+ System.out.println("New message " + text);
+ Matcher matcher = MESSAGE_PATTERN.matcher(text);
+ if (matcher.matches()) {
+ Message msg = new Message(matcher.group(1), username,
+ matcher.group(2));
+ messageSender.submitMessage(msg);
+ } else if (text.startsWith(USER_LIST_PATTERN)) {
+ // TODO обновить список подключенных пользователей
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ System.out.printf("Network connection is closed for user %s%n", username);
+ }
+ });
+ }
+
+ public void sendMessageToUser(Message message) {
+ sendMessage(String.format(MESSAGE_SEND_PATTERN, message.getUserTo(), message.getText()));
+ }
+
+ private void sendMessage(String msg) {
+ try {
+ out.writeUTF(msg);
+ out.flush();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void authorize(String username, String password) throws IOException {
+ socket = new Socket(hostName, port);
+ out = new DataOutputStream(socket.getOutputStream());
+ in = new DataInputStream(socket.getInputStream());
+
+ out.writeUTF(String.format(AUTH_PATTERN, username, password));
+ String response = in.readUTF();
+ if (response.equals("/auth successful")) {
+ this.username = username;
+ receiver.start();
+ } else {
+ throw new AuthException();
+ }
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ @Override
+ public void close() {
+ try {
+ socket.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ receiver.interrupt();
+ try {
+ receiver.join();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java b/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java
new file mode 100644
index 0000000..ec076b6
--- /dev/null
+++ b/src/logging_testing_6/gui/elements_for_changing_name/DialogWindow.java
@@ -0,0 +1,55 @@
+package logging_testing_6.gui.elements_for_changing_name;
+
+import logging_testing_6.dbconn.JdbcExample;
+import logging_testing_6.gui.Network;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class DialogWindow extends JFrame {
+ private final Network network;
+
+ public DialogWindow(Network network) {
+ super("Введите новое имени пользователя");
+ this.network = network;
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ JTextField tf = new JTextField("Введите новое имя пользователя");
+
+ JButton bOK = new JButton("OK");
+ bOK.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String currentUserName = network.getUsername();
+ String newUserName = tf.getText();
+ JdbcExample.changeNick(currentUserName, newUserName);
+ dispose();
+ }
+ });
+
+ JButton bCancel = new JButton("Отмена");
+ bCancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ dispose();
+ }
+ });
+
+ JPanel textPanel = new JPanel();
+ JPanel buttonPanel = new JPanel();
+ buttonPanel.add(bCancel);
+ buttonPanel.add(bOK);
+
+ textPanel.add(tf);
+
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new GridLayout(2, 1, 5, 10));
+ mainPanel.add(textPanel);
+ mainPanel.add(buttonPanel);
+ getContentPane().add(mainPanel);
+ pack();
+ setVisible(true);
+ }
+}
diff --git a/src/logging_testing_6/history/HistoryKeeper.java b/src/logging_testing_6/history/HistoryKeeper.java
new file mode 100644
index 0000000..6132712
--- /dev/null
+++ b/src/logging_testing_6/history/HistoryKeeper.java
@@ -0,0 +1,84 @@
+package logging_testing_6.history;
+
+import logging_testing_6.gui.Message;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class HistoryKeeper {
+ private static final String HISTORY_DIR = "history";
+
+ public static void saveMassageToHistoryFrom(Message message) {
+ String userName = message.getUserFrom();
+ String messageText = message.getText();
+ String fileName = userName + ".txt";
+ File file = new File(HISTORY_DIR, fileName);
+ try (BufferedWriter out = new BufferedWriter(new FileWriter(file, true))
+// BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))
+ ) {
+ String str = userName + ": " + messageText + "\r\n";
+ out.write(str);
+ out.flush();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void saveMassageToHistoryTo(Message message) {
+ String userName = message.getUserTo();
+ String messageText = message.getText();
+ String fileName = userName + ".txt";
+ File file = new File(HISTORY_DIR, fileName);
+ try (BufferedWriter out = new BufferedWriter(new FileWriter(file, true))) {
+// String str = userName + ": " + messageText + "\r\n";
+ String str = message.getUserFrom() + ": " + messageText + "\r\n";
+ out.write(str);
+ out.flush();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static List getHistory(String fileName, int numberOfRows) {
+ List textMessageList = new ArrayList<>();
+ StringBuilder sb = new StringBuilder();
+ File file = new File(HISTORY_DIR, fileName);
+ try {
+ RandomAccessFile raf = new RandomAccessFile(file, "r");
+ for (long pointer = file.length() - 1; pointer >= 0 && textMessageList.size() < numberOfRows; pointer--) {
+ raf.seek(pointer);
+ char aChar = (char) raf.read();
+ if (aChar != '\n') {
+ sb.append(aChar);
+ } else if (sb.length() > 1) {
+ textMessageList.add(sb.reverse().toString());
+ sb.delete(0, sb.length());
+ }
+ }
+ if (sb.length() > 1) {
+ textMessageList.add(sb.reverse().toString());
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ List messageList = textMessageList.stream()
+ .map(record -> {
+ String userFrom = record.substring(0, record.indexOf(" ") - 1);
+ String textMessage = record.substring(record.indexOf(" ") - 1);
+ return new Message(userFrom, null, textMessage);
+ }).collect(Collectors.toList());
+
+ Collections.reverse(messageList);
+ return messageList;
+ }
+}
diff --git a/src/test_ex/TestEx.java b/src/test_ex/TestEx.java
new file mode 100644
index 0000000..0268ca5
--- /dev/null
+++ b/src/test_ex/TestEx.java
@@ -0,0 +1,34 @@
+package test_ex;
+
+import java.util.Arrays;
+
+public class TestEx {
+
+ public int[] task1(int[] data) {
+ for (int i = data.length - 1; i >= 0; i--) {
+ if (data[i] == 4) {
+ return Arrays.copyOfRange(data, i + 1, data.length);
+ }
+ }
+ throw new RuntimeException("Invalid array");
+ }
+
+ public boolean task2(int[] data) {
+ boolean contains1 = false;
+ boolean contains2 = false;
+
+ for (int i = 0; i < data.length; i++) {
+ switch (data[i]) {
+ case 1:
+ contains1 = true;
+ break;
+ case 4:
+ contains2 = true;
+ break;
+ default:
+ return false;
+ }
+ }
+ return contains1 && contains2;
+ }
+}
\ No newline at end of file
diff --git a/src/test_ex/calculator/Calculator.java b/src/test_ex/calculator/Calculator.java
new file mode 100644
index 0000000..a5e344e
--- /dev/null
+++ b/src/test_ex/calculator/Calculator.java
@@ -0,0 +1,36 @@
+package test_ex.calculator;
+
+public class Calculator implements ICalc {
+ NumberProvader numberProvader;
+
+ public Calculator(NumberProvader numberProvader) {
+ this.numberProvader = numberProvader;
+ }
+
+ @Override
+ public int add(int a, int b) {
+ return a + b;
+ }
+
+ @Override
+ public int sub(int a, int b) {
+ return a - b;
+ }
+
+ @Override
+ public int mul(int a, int b) {
+ return a * b;
+ }
+
+ @Override
+ public int div(int a, int b) {
+ return a / b;
+ }
+
+ @Override
+ public int sumFromProvider() {
+ int a = numberProvader.getNumber();
+ int b = numberProvader.getNumber();
+ return add(a, b);
+ }
+}
diff --git a/src/test_ex/calculator/ICalc.java b/src/test_ex/calculator/ICalc.java
new file mode 100644
index 0000000..f678a1f
--- /dev/null
+++ b/src/test_ex/calculator/ICalc.java
@@ -0,0 +1,9 @@
+package test_ex.calculator;
+
+public interface ICalc {
+ int add(int a, int b);
+ int sub(int a, int b);
+ int mul(int a, int b);
+ int div(int a, int b);
+ int sumFromProvider();
+}
diff --git a/src/test_ex/calculator/NumberProvader.java b/src/test_ex/calculator/NumberProvader.java
new file mode 100644
index 0000000..b6c4103
--- /dev/null
+++ b/src/test_ex/calculator/NumberProvader.java
@@ -0,0 +1,5 @@
+package test_ex.calculator;
+
+public interface NumberProvader {
+ int getNumber();
+}
diff --git a/src/test_ex/calculator/NumberProviderImpl.java b/src/test_ex/calculator/NumberProviderImpl.java
new file mode 100644
index 0000000..9be7720
--- /dev/null
+++ b/src/test_ex/calculator/NumberProviderImpl.java
@@ -0,0 +1,13 @@
+package test_ex.calculator;
+
+import java.util.Scanner;
+
+public class NumberProviderImpl implements NumberProvader{
+
+ @Override
+ public int getNumber() {
+ try (Scanner scanner = new Scanner(System.in)){
+ return scanner.nextInt();
+ }
+ }
+}
diff --git a/tests/test_ex/calculator/CalculatorTest4.java b/tests/test_ex/calculator/CalculatorTest4.java
new file mode 100644
index 0000000..c1f92b9
--- /dev/null
+++ b/tests/test_ex/calculator/CalculatorTest4.java
@@ -0,0 +1,69 @@
+package test_ex.calculator;
+
+import org.hamcrest.core.Is;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class CalculatorTest4 {
+ private ICalc calc;
+ private NumberProvader numberProvader;
+
+ @Before
+ public void setUp() {
+ numberProvader = Mockito.mock(NumberProvader.class);
+ calc = new Calculator(numberProvader);
+ }
+
+ @After
+ public void tearDown() {
+ calc = null;
+ }
+
+ @Test
+ public void test_sum() {
+ int result = calc.add(2, 2);
+ Assert.assertEquals(4, result);
+ }
+
+ @Test
+ public void test_sum1() {
+ int result = calc.add(5, 10);
+ Assert.assertEquals(15, result);
+ }
+
+ @Test
+ public void test_sub() {
+ Assert.assertThat(calc.sub(5, 12), Is.is(-7));
+ }
+
+ @Test
+ public void test_mul() {
+ Assert.assertThat(calc.mul(2, 3), Is.is(6));
+ }
+
+ @Test(timeout = 100L)
+ public void test_div() {
+ Assert.assertThat(calc.div(6, 3), Is.is(2));
+ }
+
+ @Test
+ public void test_div1() {
+ Assert.assertThat(calc.div(0, 3), Is.is(0));
+ }
+
+ @Test(expected = ArithmeticException.class)
+ public void test_div2() {
+ Assert.assertThat(calc.div(3, 0), Is.is(0));
+ }
+
+ @Test
+ public void testMock() {
+ Mockito.when(numberProvader.getNumber())
+ .thenReturn(2, 6);
+ int result = calc.sumFromProvider();
+ Assert.assertEquals(8, result);
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/Task2TestJU4.java b/tests/tests/Task2TestJU4.java
new file mode 100644
index 0000000..a93b1a7
--- /dev/null
+++ b/tests/tests/Task2TestJU4.java
@@ -0,0 +1,47 @@
+package tests;
+
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import test_ex.TestEx;
+
+public class Task2TestJU4 {
+ private TestEx dz;
+
+ @Before
+ public void prepare() {
+ dz = new TestEx();
+ }
+
+ @Test
+ public void test_task2_empty_array() {
+ Assert.assertThat(dz.task2(new int[]{}), Is.is(false));
+ }
+
+ @Test
+ public void test_task2_only_1_and_4() {
+ Assert.assertThat(dz.task2(new int[]{1, 4, 4, 1}), Is.is(true));
+ }
+
+ @Test
+ public void test_task2_1_and_4_and_others() {
+ Assert.assertThat(dz.task2(new int[]{1, 4, 3, 1}), Is.is(false));
+ }
+
+ @Test
+ public void test_task2_without_1_and_4() {
+ Assert.assertThat(dz.task2(new int[]{2, 3}), Is.is(false));
+ }
+
+ @Test
+ public void test_task2_only_1() {
+ Assert.assertThat(dz.task2(new int[]{1, 1, 1}), Is.is(false));
+ }
+
+ @Test
+ public void test_task2_only_4() {
+// Assert.assertThat(dz.task2(new int[]{4, 4, 4}), Is.is(false));
+ Assert.assertFalse(String.valueOf(dz.task2(new int[]{4, 4, 4})), false);
+ }
+}
diff --git a/tests/tests/TestExJU4TestCase.java b/tests/tests/TestExJU4TestCase.java
new file mode 100644
index 0000000..f3ecd0b
--- /dev/null
+++ b/tests/tests/TestExJU4TestCase.java
@@ -0,0 +1,37 @@
+package tests;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import test_ex.TestEx;
+
+public class TestExJU4TestCase {
+ private TestEx dz;
+
+ @Before
+ public void prepare() {
+ dz = new TestEx();
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void test_task1_empty_array() {
+ dz.task1(new int[0]);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void test_task1_without_4() {
+ dz.task1(new int[]{1, 2, 3});
+ }
+
+ @Test
+ public void test_task1_where_4_is_not_last() {
+ int[] data = {1, 2, 3, 4, 5, 6, 7};
+ Assert.assertArrayEquals(new int[]{5, 6, 7,}, dz.task1(data));
+ }
+
+ @Test
+ public void test_task1_with_some_4() {
+ int[] data = {1, 4, 3, 4, 5, 6, 4};
+ Assert.assertArrayEquals(new int[]{}, dz.task1(data));
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/TestExJU5TestCase.java b/tests/tests/TestExJU5TestCase.java
new file mode 100644
index 0000000..4735507
--- /dev/null
+++ b/tests/tests/TestExJU5TestCase.java
@@ -0,0 +1,66 @@
+package tests;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import test_ex.TestEx;
+
+import java.util.stream.Stream;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TestExJU5TestCase {
+ private TestEx dz;
+
+ @BeforeEach
+ public void prepare() {
+ dz = new TestEx();
+ }
+
+ @Test
+ void test_task1_empty_array() {
+ Assertions.assertThrows(RuntimeException.class, () -> {
+ dz.task1(new int[0]);
+ });
+ }
+
+ @Test
+ public void test_tsak1_without_4() {
+ Assertions.assertThrows(RuntimeException.class, () -> dz.task1(new int[]{1, 2, 3}));
+ }
+
+ @Test
+ public void test_task1_where_4_is_not_last() {
+ int[] data = {1, 2, 3, 4, 5, 6, 7};
+ Assertions.assertArrayEquals(new int[]{5, 6, 7}, dz.task1(data));
+ }
+
+ @Test
+ public void test_task1_whith_some_4() {
+ int[] data = {1, 4, 3, 4, 5, 6, 4};
+ Assertions.assertArrayEquals(new int[]{}, dz.task1(data));
+ }
+
+ @ParameterizedTest
+ @MethodSource("params")
+ public void test_task1_whith_params(int[] data, int[] result) {
+ Assertions.assertArrayEquals(result, dz.task1(data));
+ }
+
+ private static Stream params() {
+ return Stream.of(
+ Arguments.of(
+ new int[]{1, 3, 4},
+ new int[]{}),
+ Arguments.of(
+ new int[]{1, 4, 3, 4},
+ new int[]{}),
+ Arguments.of(
+ new int[]{1, 4, 3, 5},
+ new int[]{3, 5})
+ );
+ }
+}
\ No newline at end of file