From 85e1410647f5886125ac1fedcc2e61bbfdde9c23 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 15 Feb 2024 05:40:57 +1000 Subject: [PATCH 01/11] Test creating a parser for created logs, to load the history back into the channel --- src/urChatBasic/backend/logging/URLogger.java | 25 +++ src/urChatBasic/base/IRCChannelBase.java | 15 ++ tests/utils/LogPatternParser.java | 165 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 tests/utils/LogPatternParser.java diff --git a/src/urChatBasic/backend/logging/URLogger.java b/src/urChatBasic/backend/logging/URLogger.java index 758155d..7029bf7 100644 --- a/src/urChatBasic/backend/logging/URLogger.java +++ b/src/urChatBasic/backend/logging/URLogger.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.lang.reflect.Field; import java.net.URISyntaxException; +import java.util.Map; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Logger; import org.apache.logging.log4j.core.LoggerContext; @@ -89,6 +90,30 @@ public static Marker getMarker (String markerName) // } // } + /** + * Get the path for the logfile associated with the given markerName. + * + * @param markerName The markerName associated with the logfile. + * @return The path for the associated logfile, or null if not found. + */ + public static FileAppender getLogFilePath(String markerName) { + // Get the root LoggerConfig + Configuration rootLoggerConfig = currentConfig; + if (rootLoggerConfig != null) { + // Find the appender associated with the given markerName + Map appenders = rootLoggerConfig.getAppenders(); + String appenderName = markerName + "Appender"; + Appender appender = appenders.get(appenderName); + if (appender instanceof FileAppender) { + // If the appender is a FileAppender, return its file name + FileAppender fileAppender = (FileAppender) appender; + return fileAppender; + } + } + // Return null if the logfile for the given markerName is not found + return null; + } + public static void logChannelComms (IRCChannelBase ircChannel, String message) { diff --git a/src/urChatBasic/base/IRCChannelBase.java b/src/urChatBasic/base/IRCChannelBase.java index 891eb9e..b652634 100644 --- a/src/urChatBasic/base/IRCChannelBase.java +++ b/src/urChatBasic/base/IRCChannelBase.java @@ -13,6 +13,7 @@ import urChatBasic.frontend.LineFormatter.ClickableText; import urChatBasic.frontend.components.FontPanel; import urChatBasic.frontend.dialogs.FontDialog; +import urChatBasic.frontend.dialogs.MessageDialog; import urChatBasic.frontend.panels.InterfacePanel; import urChatBasic.frontend.utils.URColour; import urChatBasic.frontend.UserGUI; @@ -841,6 +842,7 @@ public class ChannelPopUp extends JPopupMenu private static final long serialVersionUID = 640768684923757684L; JMenuItem nameItem; JMenuItem quitItem; + JMenuItem loadChannelHistory; JMenuItem hideUsersItem; JMenuItem hideTickerItem; public JMenuItem addAsFavouriteItem; @@ -856,6 +858,10 @@ public ChannelPopUp() add(quitItem); quitItem.addActionListener(new QuitItem()); // + loadChannelHistory = new JMenuItem("Show Log Path"); + add(loadChannelHistory); + loadChannelHistory.addActionListener(new LoadChannelHistory()); + // hideUsersItem = new JMenuItem("Toggle Users List"); add(hideUsersItem); hideUsersItem.addActionListener(new ToggleHideUsersListItem()); @@ -909,6 +915,15 @@ public void actionPerformed(ActionEvent arg0) } } + private class LoadChannelHistory implements ActionListener + { + @Override + public void actionPerformed(ActionEvent arg0) + { + + } + } + private class QuitItem implements ActionListener { @Override diff --git a/tests/utils/LogPatternParser.java b/tests/utils/LogPatternParser.java new file mode 100644 index 0000000..9e2f7e4 --- /dev/null +++ b/tests/utils/LogPatternParser.java @@ -0,0 +1,165 @@ +package utils; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.testng.annotations.Test; + +public class LogPatternParser +{ + + // Define enum for log patterns + public enum LogPattern + { + DATE("%d", "(?.*UTC)", Date.class), + SERVER("%marker", "(?^[A-Za-z0-9.-]+)-", String.class), + CHANNEL("%marker", "(?^#.*?)\\s", String.class), // Named group for channel, excluding the trailing whitespace + USER("%msg|%message", "(?^.*?):", String.class), + MESSAGE("%msg|%message", "(?.*)", String.class); + + private final String pattern; + private final String regex; + private final Class patternClass; + + LogPattern (String pattern, String regex, Class patternClass) + { + this.pattern = pattern; + this.regex = regex; + this.patternClass = patternClass; + } + + public String getPattern () + { + return pattern; + } + + public Class getPatternClass () + { + return patternClass; + } + + public String getRegex () + { + return regex; + } + + public String getMatchGroup () + { + return this.toString(); + } + + public String getPatternLayout () + { + return "%d{yyy-MM-dd HH:mm:ss.SSS}{UTC}UTC %marker %msg%n"; + } + } + + public static Date parseDate (String dateString) { + + // Step 1: Define the DateTimeFormatter with the pattern + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + // Step 2: Parse the string into a TemporalAccessor object using the formatter + TemporalAccessor temporalAccessor = formatter.parse(dateString.replace("UTC", "")); + + // Step 3: Convert the TemporalAccessor to a LocalDateTime object + LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor); + + // Step 4: Convert the LocalDateTime to the local timezone + LocalDateTime localDateTimeInLocalTimeZone = localDateTime + .atZone(ZoneId.of("UTC")) + .withZoneSameInstant(ZoneId.systemDefault()) + .toLocalDateTime(); + + // Step 5: Convert the LocalDateTime to a Date object + Date date = Date.from(localDateTimeInLocalTimeZone.atZone(ZoneId.systemDefault()).toInstant()); + + + return date; + } + + // Parse log line using specified pattern + public static void parseLogLine (String logLine) + { + Map parsedValues = new HashMap(); + + for (LogPattern pattern : LogPattern.values()) + { + Pattern regexPattern = Pattern.compile(pattern.getRegex()); + Matcher matcher = regexPattern.matcher(logLine); + if (matcher.find()) + { + String fullMatch = matcher.group(0); + String match = matcher.group(pattern.getMatchGroup()); + System.out.println(pattern.name() + " group: " + match); + // parsedValues.put(pattern.toString(), match); + switch (pattern.getPatternClass().getSimpleName()) { + case "Date": + parsedValues.put(pattern.toString(), parseDate(match)); + logLine = logLine.replaceFirst(fullMatch, "").trim(); + break; + default: + parsedValues.put(pattern.toString(), match); + if(logLine.length() == fullMatch.length()) + break; + + logLine = logLine.replaceFirst(fullMatch, "").trim(); + break; + } + } + } + + System.out.println("Done"); + } + + public static void parseLogLineFull (String logLine) { + Map parsedValues = new HashMap<>(); + + StringBuilder combinedRegexBuilder = new StringBuilder(); + for (LogPattern pattern : LogPattern.values()) { + if (combinedRegexBuilder.length() > 0) { + combinedRegexBuilder.append("|"); + } + combinedRegexBuilder.append("(").append(pattern.getRegex()).append(")"); + } + String combinedRegex = combinedRegexBuilder.toString(); + + Pattern regexPattern = Pattern.compile(combinedRegex); + Matcher matcher = regexPattern.matcher(logLine); + while (matcher.find()) { + for (LogPattern pattern : LogPattern.values()) { + if (matcher.group(pattern.getPattern()) != null) { + String fullMatch = matcher.group(0); + String match = matcher.group(pattern.getMatchGroup()); + System.out.println(pattern.name() + " group: " + match); + switch (pattern.getPatternClass().getSimpleName()) { + case "Date": + parsedValues.put(pattern.toString(), parseDate(match)); + break; + default: + parsedValues.put(pattern.toString(), match); + break; + } + logLine = logLine.replaceFirst(fullMatch, "").trim(); + break; // Break to the outer loop to handle the next log line part + } + } + } + + System.out.println("Done"); + } + + @Test + public void testParsing () + { + String logLine = "2024-02-13 19:27:31.414UTC irc.libera.chat-#java matty_r: morning:asdjnwk 123AD?asd,123uADAjkalas[];'das[]"; + // parseLogLine(logLine); + parseLogLineFull(logLine); + } +} From 44c18e89eb54a7cf1d4036ac2fd29a91ab79fde4 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 15 Feb 2024 07:18:56 +1000 Subject: [PATCH 02/11] Log Pattern Parser --- .../backend}/utils/LogPatternParser.java | 81 +++++++++++-------- tests/backend/LogParsingTests.java | 67 +++++++++++++++ 2 files changed, 113 insertions(+), 35 deletions(-) rename {tests => src/urChatBasic/backend}/utils/LogPatternParser.java (64%) create mode 100644 tests/backend/LogParsingTests.java diff --git a/tests/utils/LogPatternParser.java b/src/urChatBasic/backend/utils/LogPatternParser.java similarity index 64% rename from tests/utils/LogPatternParser.java rename to src/urChatBasic/backend/utils/LogPatternParser.java index 9e2f7e4..1fad618 100644 --- a/tests/utils/LogPatternParser.java +++ b/src/urChatBasic/backend/utils/LogPatternParser.java @@ -1,4 +1,4 @@ -package utils; +package urChatBasic.backend.utils; import java.time.LocalDateTime; import java.time.ZoneId; @@ -9,7 +9,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.testng.annotations.Test; public class LogPatternParser { @@ -17,21 +16,25 @@ public class LogPatternParser // Define enum for log patterns public enum LogPattern { - DATE("%d", "(?.*UTC)", Date.class), - SERVER("%marker", "(?^[A-Za-z0-9.-]+)-", String.class), - CHANNEL("%marker", "(?^#.*?)\\s", String.class), // Named group for channel, excluding the trailing whitespace - USER("%msg|%message", "(?^.*?):", String.class), - MESSAGE("%msg|%message", "(?.*)", String.class); + DATE("%d", "(?.*UTC?)", Date.class, "UTC "), + SERVER("%marker", "\\s(?[A-Za-z0-9.-]+)-", String.class, "-"), + CHANNEL("%marker", "(?#.*?)\\s", String.class, " "), // Named group for channel, excluding the trailing whitespace + USER("%msg", "(?.*?):", String.class, ": "), + MESSAGE("%msg", "\\s(?.*)$", String.class, ""); private final String pattern; private final String regex; + private final String appendString; private final Class patternClass; + public final static String PATTERN_LAYOUT = "%d{yyy-MM-dd HH:mm:ss.SSS}{UTC}UTC %marker %msg%n"; + public final static String DATE_LAYOUT = "yyyy-MM-dd HH:mm:ss.SSS"; - LogPattern (String pattern, String regex, Class patternClass) + LogPattern (String pattern, String regex, Class patternClass, String appendString) { this.pattern = pattern; this.regex = regex; this.patternClass = patternClass; + this.appendString = appendString; } public String getPattern () @@ -54,19 +57,25 @@ public String getMatchGroup () return this.toString(); } - public String getPatternLayout () + public String getAppendString () { - return "%d{yyy-MM-dd HH:mm:ss.SSS}{UTC}UTC %marker %msg%n"; + return appendString; } } - public static Date parseDate (String dateString) { - + public static Date parseDate (String dateString) + { + dateString = dateString.trim(); // Step 1: Define the DateTimeFormatter with the pattern DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); - + TemporalAccessor temporalAccessor = null; + try{ // Step 2: Parse the string into a TemporalAccessor object using the formatter - TemporalAccessor temporalAccessor = formatter.parse(dateString.replace("UTC", "")); + temporalAccessor = formatter.parse(dateString.replace("UTC", "")); + } catch (Exception exc) + { + System.out.println(exc); + } // Step 3: Convert the TemporalAccessor to a LocalDateTime object LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor); @@ -84,6 +93,21 @@ public static Date parseDate (String dateString) { return date; } + // Method to format Date object to string in UTC + public static String formatDateToString(Date date) { + // Define the DateTimeFormatter with the pattern + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + // Convert the Date object to LocalDateTime + LocalDateTime localDateTime = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + + // Convert the LocalDateTime to UTC time zone + LocalDateTime localDateTimeInUtc = localDateTime.atZone(ZoneId.systemDefault()).withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime(); + + // Format the LocalDateTime to string + return formatter.format(localDateTimeInUtc); + } + // Parse log line using specified pattern public static void parseLogLine (String logLine) { @@ -118,26 +142,23 @@ public static void parseLogLine (String logLine) System.out.println("Done"); } - public static void parseLogLineFull (String logLine) { + public static Map parseLogLineFull (String logLine) { Map parsedValues = new HashMap<>(); StringBuilder combinedRegexBuilder = new StringBuilder(); - for (LogPattern pattern : LogPattern.values()) { - if (combinedRegexBuilder.length() > 0) { - combinedRegexBuilder.append("|"); - } - combinedRegexBuilder.append("(").append(pattern.getRegex()).append(")"); - } + combinedRegexBuilder.append(LogPattern.DATE.getRegex()); + combinedRegexBuilder.append(LogPattern.SERVER.getRegex()); + combinedRegexBuilder.append(LogPattern.CHANNEL.getRegex()); + combinedRegexBuilder.append(LogPattern.USER.getRegex()); + combinedRegexBuilder.append(LogPattern.MESSAGE.getRegex()); String combinedRegex = combinedRegexBuilder.toString(); Pattern regexPattern = Pattern.compile(combinedRegex); Matcher matcher = regexPattern.matcher(logLine); while (matcher.find()) { for (LogPattern pattern : LogPattern.values()) { - if (matcher.group(pattern.getPattern()) != null) { - String fullMatch = matcher.group(0); + if (matcher.group(pattern.toString()) != null) { String match = matcher.group(pattern.getMatchGroup()); - System.out.println(pattern.name() + " group: " + match); switch (pattern.getPatternClass().getSimpleName()) { case "Date": parsedValues.put(pattern.toString(), parseDate(match)); @@ -146,20 +167,10 @@ public static void parseLogLineFull (String logLine) { parsedValues.put(pattern.toString(), match); break; } - logLine = logLine.replaceFirst(fullMatch, "").trim(); - break; // Break to the outer loop to handle the next log line part } } } - System.out.println("Done"); - } - - @Test - public void testParsing () - { - String logLine = "2024-02-13 19:27:31.414UTC irc.libera.chat-#java matty_r: morning:asdjnwk 123AD?asd,123uADAjkalas[];'das[]"; - // parseLogLine(logLine); - parseLogLineFull(logLine); + return parsedValues; } } diff --git a/tests/backend/LogParsingTests.java b/tests/backend/LogParsingTests.java new file mode 100644 index 0000000..cf24c8e --- /dev/null +++ b/tests/backend/LogParsingTests.java @@ -0,0 +1,67 @@ +package backend; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import org.testng.annotations.Test; +import urChatBasic.backend.utils.LogPatternParser; +import static org.testng.AssertJUnit.assertEquals; +import static urChatBasic.backend.utils.LogPatternParser.LogPattern; + +public class LogParsingTests { + + + @Test + public void testLogLinesManual () + { + testParsing("2024-02-13 19:27:31.414UTC irc.libera.chat-#java matty_r: morning:asdjnwk 123AD?asd,123uADAjkalas[];'das[]"); + testParsing("2024-01-31 20:49:43.003UTC irc.libera.chat-#linux ****: You have joined #linux"); + testParsing("2024-02-11 02:17:40.207UTC irc.libera.chat-#linux ****: Welcome to #linux! Help & support for any Linux distribution or related topic -- Rules/Info: https://linux.chat -- Forum: https://linux.forum -- Pastebin: https://paste.linux.chat/ -- @linux.social on Mastodon: https://linux.social -- Need an op? !ops or join #linux-ops"); + testParsing("2024-01-31 20:58:55.016UTC irc.libera.chat-#linux user: 😢😢😢😢😢😢😢😢😢😢😢"); + } + + @Test + public void testLogLines() { + String logFilePath = "/home/matt/urChat/Logs/irc.libera.chat-#linux.log"; + String line = ""; + + try (BufferedReader br = new BufferedReader(new FileReader(logFilePath))) { + while ((line = br.readLine()) != null) { + testParsing(line); + } + } catch (Exception e) { + System.out.println(line); + e.printStackTrace(); + } + } + + public void testParsing (String logLine) + { + Map parsedValues = new HashMap<>(); + + // parseLogLine(logLine); + // parsedValues = parseLogLineFull(logLine); + parsedValues = LogPatternParser.parseLogLineFull(logLine); + + String assertString = ""; + + for (LogPattern logPattern : LogPattern.values()) { + Object parsedValue = parsedValues.get(logPattern.toString()); + + switch (logPattern.getPatternClass().getSimpleName()) { + case "Date": + assertString += LogPatternParser.formatDateToString((Date) parsedValue); + break; + default: + assertString += parsedValue.toString(); + break; + } + + assertString += logPattern.getAppendString(); + } + + assertEquals(logLine.trim(), assertString.trim()); + } +} From cd01b810ebc195ad15e5cd2a901cd09f58157c6a Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 19 Feb 2024 05:49:35 +1000 Subject: [PATCH 03/11] Adds a maximum message queue size constant, increased to 100 from 20. Adds a menu item to load the channel history (up to the channel line limit). Adjusted how the messages are appended, can either be anywhere, or at the end of the document (default). --- src/urChatBasic/backend/logging/URLogger.java | 4 +- .../backend/utils/LogPatternParser.java | 1 + .../backend/utils/ReverseLineInputStream.java | 101 ++++++++++++ src/urChatBasic/base/Constants.java | 2 + src/urChatBasic/base/IRCChannelBase.java | 150 ++++++++++++------ src/urChatBasic/frontend/LineFormatter.java | 57 +++++-- src/urChatBasic/frontend/UserGUI.java | 12 +- tests/backend/LogParsingTests.java | 9 +- 8 files changed, 261 insertions(+), 75 deletions(-) create mode 100644 src/urChatBasic/backend/utils/ReverseLineInputStream.java diff --git a/src/urChatBasic/backend/logging/URLogger.java b/src/urChatBasic/backend/logging/URLogger.java index 7029bf7..c4291e1 100644 --- a/src/urChatBasic/backend/logging/URLogger.java +++ b/src/urChatBasic/backend/logging/URLogger.java @@ -96,7 +96,7 @@ public static Marker getMarker (String markerName) * @param markerName The markerName associated with the logfile. * @return The path for the associated logfile, or null if not found. */ - public static FileAppender getLogFilePath(String markerName) { + public static String getLogFilePath(String markerName) { // Get the root LoggerConfig Configuration rootLoggerConfig = currentConfig; if (rootLoggerConfig != null) { @@ -107,7 +107,7 @@ public static FileAppender getLogFilePath(String markerName) { if (appender instanceof FileAppender) { // If the appender is a FileAppender, return its file name FileAppender fileAppender = (FileAppender) appender; - return fileAppender; + return fileAppender.getFileName(); } } // Return null if the logfile for the given markerName is not found diff --git a/src/urChatBasic/backend/utils/LogPatternParser.java b/src/urChatBasic/backend/utils/LogPatternParser.java index 1fad618..7cfcfe9 100644 --- a/src/urChatBasic/backend/utils/LogPatternParser.java +++ b/src/urChatBasic/backend/utils/LogPatternParser.java @@ -143,6 +143,7 @@ public static void parseLogLine (String logLine) } public static Map parseLogLineFull (String logLine) { + logLine = logLine.trim(); Map parsedValues = new HashMap<>(); StringBuilder combinedRegexBuilder = new StringBuilder(); diff --git a/src/urChatBasic/backend/utils/ReverseLineInputStream.java b/src/urChatBasic/backend/utils/ReverseLineInputStream.java new file mode 100644 index 0000000..f69c150 --- /dev/null +++ b/src/urChatBasic/backend/utils/ReverseLineInputStream.java @@ -0,0 +1,101 @@ +package urChatBasic.backend.utils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; + +/** + * @see https://web.archive.org/web/20220701011119/https://stackoverflow.com/questions/8664705/how-to-read-file-from-end-to-start-in-reverse-order-in-javaa + */ +public class ReverseLineInputStream extends InputStream { + + RandomAccessFile in; + + long currentLineStart = -1; + long currentLineEnd = -1; + long currentPos = -1; + long lastPosInFile = -1; + int lastChar = -1; + + + public ReverseLineInputStream(File file) throws FileNotFoundException { + in = new RandomAccessFile(file, "r"); + currentLineStart = file.length(); + currentLineEnd = file.length(); + lastPosInFile = file.length() -1; + currentPos = currentLineEnd; + + } + + private void findPrevLine() throws IOException { + if (lastChar == -1) { + in.seek(lastPosInFile); + lastChar = in.readByte(); + } + + currentLineEnd = currentLineStart; + + // There are no more lines, since we are at the beginning of the file and no lines. + if (currentLineEnd == 0) { + currentLineEnd = -1; + currentLineStart = -1; + currentPos = -1; + return; + } + + long filePointer = currentLineStart -1; + + while ( true) { + filePointer--; + + // we are at start of file so this is the first line in the file. + if (filePointer < 0) { + break; + } + + in.seek(filePointer); + int readByte = in.readByte(); + + // We ignore last LF in file. search back to find the previous LF. + if (readByte == 0xA && filePointer != lastPosInFile ) { + break; + } + } + // we want to start at pointer +1 so we are after the LF we found or at 0 the start of the file. + currentLineStart = filePointer + 1; + currentPos = currentLineStart; + } + + public int read() throws IOException { + + if (currentPos < currentLineEnd ) { + in.seek(currentPos++); + int readByte = in.readByte(); + return readByte; + } else if (currentPos > lastPosInFile && currentLineStart < currentLineEnd) { + // last line in file (first returned) + findPrevLine(); + if (lastChar != '\n' && lastChar != '\r') { + // last line is not terminated + return '\n'; + } else { + return read(); + } + } else if (currentPos < 0) { + return -1; + } else { + findPrevLine(); + return read(); + } + } + + @Override + public void close() throws IOException { + if (in != null) { + in.close(); + in = null; + } + } +} diff --git a/src/urChatBasic/base/Constants.java b/src/urChatBasic/base/Constants.java index 2308ebb..1e17f20 100644 --- a/src/urChatBasic/base/Constants.java +++ b/src/urChatBasic/base/Constants.java @@ -152,6 +152,8 @@ public class Constants public static final char SPACES_AHEAD_DELIMITER = ':'; public static final int MESSAGE_LIMIT = 510; public static final String END_MESSAGE = "\r\n"; + public static final int MAXIMUM_QUEUE_SIZE = 100; + // We 'must' match against http(s) in order to define the correct protocol to be used public static final String URL_REGEX = "((http:\\/\\/|https:\\/\\/)(www.)?(([a-zA-Z0-9-]){2,}\\.){1,4}([a-zA-Z]){2,6}(\\/([a-zA-Z-_\\/\\.0-9#:?=&;,]*)?)?)"; public static final String CHANNEL_REGEX = "(?:^|\s)(#([^\s,]+)(?!,))(?:$|\s)"; diff --git a/src/urChatBasic/base/IRCChannelBase.java b/src/urChatBasic/base/IRCChannelBase.java index b652634..d1e7ba9 100644 --- a/src/urChatBasic/base/IRCChannelBase.java +++ b/src/urChatBasic/base/IRCChannelBase.java @@ -1,6 +1,7 @@ package urChatBasic.base; import urChatBasic.backend.logging.URLogger; +import urChatBasic.backend.utils.ReverseLineInputStream; import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.base.IRCChannelBase; import urChatBasic.base.Constants.EventType; @@ -13,12 +14,12 @@ import urChatBasic.frontend.LineFormatter.ClickableText; import urChatBasic.frontend.components.FontPanel; import urChatBasic.frontend.dialogs.FontDialog; -import urChatBasic.frontend.dialogs.MessageDialog; import urChatBasic.frontend.panels.InterfacePanel; import urChatBasic.frontend.utils.URColour; import urChatBasic.frontend.UserGUI; import urChatBasic.frontend.UsersListModel; import java.awt.event.*; +import static urChatBasic.backend.utils.LogPatternParser.parseLogLineFull; import java.awt.*; import java.io.*; import java.util.*; @@ -89,7 +90,7 @@ public class IRCChannelBase extends JPanel // Text Area private JTextPane channelTextArea = new JTextPane(); protected JScrollPane channelScroll = new JScrollPane(channelTextArea); - private BlockingQueue messageQueue = new ArrayBlockingQueue<>(20); + private BlockingQueue messageQueue = new ArrayBlockingQueue<>(Constants.MAXIMUM_QUEUE_SIZE); public boolean messageQueueInProgress = false; private LineFormatter lineFormatter; @@ -459,28 +460,55 @@ public String getMarker () return markerName; } - class MessagePair { + class Message { + private Optional date = Optional.empty(); private String line; private String fromUser; - public MessagePair(String line, String fromUser) { + public Message(String line, String fromUser) { this.line = line; this.fromUser = fromUser; } - public String getLine() { + public Message(Date date, String line, String fromUser) { + this.date = Optional.of(date); + this.line = line; + this.fromUser = fromUser; + } + + public String getLine () { return line; } - public String getUser() { + public String getUser () { return fromUser; } + + public Optional getDate () + { + return date; + } } // TODO: Change this to accept IRCUser instead - public void printText(String line, String fromUser) { + // TODO: Overload method with date object + public void printText(String line, String fromUser) + { + try { + messageQueue.put(new Message(line, fromUser)); + + if(!messageQueueInProgress) + handleMessageQueue(); + + } catch (InterruptedException e) { + Constants.LOGGER.warn(e.getLocalizedMessage(), e); + } + } + + public void printText(Date messageDate, String message, String fromUser) + { try { - messageQueue.put(new MessagePair(line, fromUser)); + messageQueue.put(new Message(messageDate, message, fromUser)); if(!messageQueueInProgress) handleMessageQueue(); @@ -495,37 +523,38 @@ public boolean messageQueueWorking() return (!messageQueue.isEmpty() || messageQueueInProgress); } - public void handleMessageQueue() + public void handleMessageQueue () { SwingUtilities.invokeLater(new Runnable() { - public void run() + public void run () { while (!messageQueue.isEmpty()) { try { messageQueueInProgress = true; - MessagePair messagePair = messageQueue.take(); + Message message = messageQueue.take(); - if(null == messagePair) + if (null == message) { messageQueueInProgress = false; continue; } - String line = messagePair.getLine(); - String fromUser = messagePair.getUser(); + Optional messageDate = message.getDate(); + String line = message.getLine(); + String fromUser = message.getUser(); Document document = lineFormatter.getDocument(); Element root = lineFormatter.getDocument().getDefaultRootElement(); int lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); - if(IRCChannelBase.this instanceof IRCServer) + if (IRCChannelBase.this instanceof IRCServer) lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitServerLinesCount(); - if(null != messagePair && root.getElementCount() > lineLimit) + if (null != message && root.getElementCount() > lineLimit) { Element firstLine = root.getElement(0); int endIndex = firstLine.getEndOffset(); @@ -533,8 +562,7 @@ public void run() try { document.remove(0, endIndex); - } - catch(BadLocationException ble) + } catch (BadLocationException ble) { Constants.LOGGER.error(ble.getLocalizedMessage()); } @@ -546,12 +574,13 @@ public void run() return; } + // StyledDocument doc = channelTextArea.getStyledDocument(); IRCUser fromIRCUser = getCreatedUser(fromUser); // If we received a message from a user that isn't in the channel // then add them to the users list. - // But don't add them if it's from the Event Ticker + // But don't add them if it's from the Event Ticker or we're loading historical if (fromIRCUser == null) { if (!fromUser.equals(Constants.EVENT_USER)) @@ -561,51 +590,57 @@ public void run() // fromIRCUser = getCreatedUsers(fromUser); // Constants.LOGGER.error("Message from a user that isn't in the user list!"); fromIRCUser = server.getIRCUser(fromUser); - addToUsersList(fromIRCUser); + + // Only add users if we haven't specified a date, which means we aren't loading historical messages + if (messageDate.isEmpty()) + addToUsersList(fromIRCUser); } } - if (fromUser.equals(Constants.EVENT_USER) || !fromIRCUser.isMuted()) { - lineFormatter.formattedDocument(new Date(), fromIRCUser, fromUser, line); + lineFormatter.appendMessage(messageDate, fromIRCUser, fromUser, line); - if(IRCChannelBase.this instanceof IRCServerBase) + // Only save history and call events if we aren't loading historical messages + if (messageDate.isEmpty()) { - if (((InterfacePanel) gui.interfacePanel).saveServerHistory()) - URLogger.logChannelComms(IRCChannelBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); - } else if(!(IRCChannelBase.this instanceof IRCServerBase)) - { - if (((InterfacePanel) gui.interfacePanel).saveChannelHistory()) - URLogger.logChannelComms(IRCChannelBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); + if (IRCChannelBase.this instanceof IRCServerBase) + { + if (((InterfacePanel) gui.interfacePanel).saveServerHistory()) + URLogger.logChannelComms(IRCChannelBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); + } else if (!(IRCChannelBase.this instanceof IRCServerBase)) + { + if (((InterfacePanel) gui.interfacePanel).saveChannelHistory()) + URLogger.logChannelComms(IRCChannelBase.this, (fromIRCUser != null ? fromIRCUser.getName() : fromUser) + ": " + line); + } + + if (server.getNick() != null && line.indexOf(server.getNick()) > -1) + { + callForAttention(); + } + + // Always alert on IRCPrivate messages + if (IRCChannelBase.this instanceof IRCPrivate) + { + callForAttention(); + } + + // TODO: Scrolls to the bottom of the channelTextArea on message received, this should be + // disabled + // when the user has scrolled up + // channelTextArea.setCaretPosition(channelTextArea.getDocument().getLength()); } - - if (server.getNick() != null && line.indexOf(server.getNick()) > -1) - { - callForAttention(); - } - - // Always alert on IRCPrivate messages - if (IRCChannelBase.this instanceof IRCPrivate) - { - callForAttention(); - } - - // TODO: Scrolls to the bottom of the channelTextArea on message received, this should be - // disabled - // when the user has scrolled up - channelTextArea.setCaretPosition(channelTextArea.getDocument().getLength()); - messageQueueInProgress = false; } + } catch (InterruptedException e) { Constants.LOGGER.error(e.getLocalizedMessage()); } } + messageQueueInProgress = false; } }); - } /** @@ -858,7 +893,7 @@ public ChannelPopUp() add(quitItem); quitItem.addActionListener(new QuitItem()); // - loadChannelHistory = new JMenuItem("Show Log Path"); + loadChannelHistory = new JMenuItem("Load Channel History"); add(loadChannelHistory); loadChannelHistory.addActionListener(new LoadChannelHistory()); // @@ -920,7 +955,24 @@ private class LoadChannelHistory implements ActionListener @Override public void actionPerformed(ActionEvent arg0) { - + Thread fileReadingThread = new Thread(() -> { + String logFilePath = URLogger.getLogFilePath(getMarker()); + String line = ""; + try (BufferedReader br = new BufferedReader (new InputStreamReader (new ReverseLineInputStream(new File(logFilePath))))) { + int maxCount = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); + while ((line = br.readLine()) != null && lineFormatter.getLineCount() < maxCount) { + if(messageQueueInProgress && messageQueue.remainingCapacity() == 0) + Thread.sleep(10); + + Map parsedLine = parseLogLineFull(line); + if(parsedLine.size() != 0) + printText((Date) parsedLine.get("DATE"), parsedLine.get("MESSAGE").toString(), parsedLine.get("USER").toString()); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + fileReadingThread.start(); } } diff --git a/src/urChatBasic/frontend/LineFormatter.java b/src/urChatBasic/frontend/LineFormatter.java index 50d337b..bda00fe 100644 --- a/src/urChatBasic/frontend/LineFormatter.java +++ b/src/urChatBasic/frontend/LineFormatter.java @@ -461,14 +461,26 @@ private synchronized void insertString(String insertedString, URStyle style, int setDocAttributes(position, insertedString.length(), style); } - // Adds the string (with all needed attributes) to the end of the document - private void appendString(String insertedString, URStyle style) + /** + * Adds the string (with all needed attributes) to the document either at the end, or the docPosition. + * @param insertedString + * @param style + * @param docPosition + * @return doc position after inserted string + * @throws BadLocationException + */ + private int addString(String insertedString, URStyle style, Optional docPosition) throws BadLocationException { int position = doc.getLength(); + if(docPosition.isPresent()) + position = docPosition.get(); + if((myServer == null || !myServer.hasConnection()) || myServer.isConnected()) insertString(insertedString, style, position); + + return position + insertedString.length(); } public URStyle getStyleDefault(String styleName) @@ -754,6 +766,12 @@ public String getLineAtPosition(int position) throws BadLocationException { return lineText; } + public int getLineCount () + { + Element root = doc.getDefaultRootElement(); + return root.getElementCount(); + } + private int getLinePosition(String targetLine) throws BadLocationException { Element root = doc.getDefaultRootElement(); @@ -794,7 +812,7 @@ public URStyle getStyleAtPosition(int position, String relativeLine) return new URStyle(new SimpleAttributeSet(textStyle)); } - private void parseClickableText(IRCUser fromUser, String line, URStyle defaultStyle) + private int parseClickableText(IRCUser fromUser, String line, URStyle defaultStyle, int position) throws BadLocationException { HashMap regexStrings = new HashMap<>(); @@ -849,14 +867,16 @@ private void parseClickableText(IRCUser fromUser, String line, URStyle defaultSt int nextLineLength = Integer.parseInt(nextLine.getAttribute("styleLength").toString()); // Append the string that comes before the next clickable text - appendString(remainingLine.substring(0, nextLineStart - offset), defaultStyle); + position = addString(remainingLine.substring(0, nextLineStart - offset), defaultStyle, Optional.of(position)); - appendString(nextLine.getAttribute("clickableText").toString(), nextLine); + position = addString(nextLine.getAttribute("clickableText").toString(), nextLine, Optional.of(position)); remainingLine = remainingLine.substring((nextLineStart + nextLineLength) - offset); } - appendString(remainingLine, defaultStyle); + position = addString(remainingLine, defaultStyle, Optional.of(position)); + + return position; } /** @@ -866,10 +886,17 @@ private void parseClickableText(IRCUser fromUser, String line, URStyle defaultSt * @param fromString * @param line */ - public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString, String line) + public void appendMessage(Optional lineDate, IRCUser fromUser, String fromString, String line) { + int insertPosition = doc.getLength(); + + if(lineDate.isEmpty()) + lineDate = Optional.of(new Date()); + else + insertPosition = 0; + // build the timeLine string - timeLine = Optional.of(lineDate); + timeLine = lineDate; String[] nickParts; final URStyle nickPositionStyle; @@ -914,12 +941,12 @@ public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString { // add the date to the end of the string to preserve the timestamp of the line // when updating styles - appendString(DriverGUI.gui.getTimeStampString(timeLine.get()) + " ", dateStyle(timePositionStyle, lineDate, false)); + insertPosition = addString(DriverGUI.gui.getTimeStampString(timeLine.get()) + " ", dateStyle(timePositionStyle, lineDate.get(), false), Optional.of(insertPosition)); } linePositionStyle.addAttribute("type", "nickPart0"); linePositionStyle.addAttribute("nickParts", nickParts); - appendString(nickParts[0], linePositionStyle); + insertPosition = addString(nickParts[0], linePositionStyle, Optional.of(insertPosition)); if (fromUser != null) { @@ -929,16 +956,16 @@ public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString new ClickableText(fromUser.toString(), nickPositionStyle, fromUser)); clickableNameStyle.addAttribute("nickParts", nickParts); - appendString(nickParts[1], clickableNameStyle); + insertPosition = addString(nickParts[1], clickableNameStyle, Optional.of(insertPosition)); } else { nickPositionStyle.addAttribute("type", "nick"); nickPositionStyle.addAttribute("nickParts", nickParts); - appendString(nickParts[1], nickPositionStyle); + insertPosition = addString(nickParts[1], nickPositionStyle, Optional.of(insertPosition)); } linePositionStyle.addAttribute("type", "nickPart2"); - appendString(nickParts[2], linePositionStyle); + insertPosition = addString(nickParts[2], linePositionStyle, Optional.of(insertPosition)); linePositionStyle.removeAttribute("type"); linePositionStyle.removeAttribute("nickParts"); @@ -947,8 +974,8 @@ public void formattedDocument(Date lineDate, IRCUser fromUser, String fromString // appendString(doc, " "+line, lineStyle); // parse the outputted line for clickable text - parseClickableText(fromUser, " " + line, linePositionStyle); - appendString(System.getProperty("line.separator"), linePositionStyle); + insertPosition = parseClickableText(fromUser, " " + line, linePositionStyle, insertPosition); + insertPosition = addString(System.getProperty("line.separator"), linePositionStyle, Optional.of(insertPosition)); } catch (BadLocationException e) { Constants.LOGGER.error( e.getLocalizedMessage()); diff --git a/src/urChatBasic/frontend/UserGUI.java b/src/urChatBasic/frontend/UserGUI.java index 5fc6561..eff3218 100644 --- a/src/urChatBasic/frontend/UserGUI.java +++ b/src/urChatBasic/frontend/UserGUI.java @@ -352,14 +352,14 @@ public void updatePreviewTextArea () IRCUser tempUser = new IRCUser(null, "matty_r"); IRCUser tempUser2 = new IRCUser(null, System.getProperty("user.name")); previewLineFormatter.setNick(System.getProperty("user.name")); - previewLineFormatter.formattedDocument(new Date(), null, Constants.EVENT_USER, + previewLineFormatter.appendMessage(Optional.empty(), null, Constants.EVENT_USER, "urChat has loaded - this is an Event"); - previewLineFormatter.formattedDocument(new Date(), tempUser, "matty_r", "Normal line. Hello, world!"); - previewLineFormatter.formattedDocument(new Date(), tempUser, "matty_r", + previewLineFormatter.appendMessage(Optional.empty(), tempUser, "matty_r", "Normal line. Hello, world!"); + previewLineFormatter.appendMessage(Optional.empty(), tempUser, "matty_r", "This is what it looks like when your nick is mentioned, " + System.getProperty("user.name") + "!"); - previewLineFormatter.formattedDocument(new Date(), tempUser2, System.getProperty("user.name"), + previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), "Go to https://github.com/matty-r/urChat"); - previewLineFormatter.formattedDocument(new Date(), tempUser2, System.getProperty("user.name"), + previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), "Join #urchat on irc.libera.chat"); } else { @@ -694,7 +694,7 @@ public void stateChanged (ChangeEvent e) } } - protected class SaveFontListener implements ActionListener + public class SaveFontListener implements ActionListener { @Override public void actionPerformed (ActionEvent arg0) diff --git a/tests/backend/LogParsingTests.java b/tests/backend/LogParsingTests.java index cf24c8e..dfc2738 100644 --- a/tests/backend/LogParsingTests.java +++ b/tests/backend/LogParsingTests.java @@ -7,7 +7,9 @@ import java.util.Map; import org.testng.annotations.Test; import urChatBasic.backend.utils.LogPatternParser; +import urChatBasic.backend.utils.LogPatternParser.LogPattern; import static org.testng.AssertJUnit.assertEquals; +import static org.testng.AssertJUnit.fail; import static urChatBasic.backend.utils.LogPatternParser.LogPattern; public class LogParsingTests { @@ -20,11 +22,13 @@ public void testLogLinesManual () testParsing("2024-01-31 20:49:43.003UTC irc.libera.chat-#linux ****: You have joined #linux"); testParsing("2024-02-11 02:17:40.207UTC irc.libera.chat-#linux ****: Welcome to #linux! Help & support for any Linux distribution or related topic -- Rules/Info: https://linux.chat -- Forum: https://linux.forum -- Pastebin: https://paste.linux.chat/ -- @linux.social on Mastodon: https://linux.social -- Need an op? !ops or join #linux-ops"); testParsing("2024-01-31 20:58:55.016UTC irc.libera.chat-#linux user: 😢😢😢😢😢😢😢😢😢😢😢"); + testParsing("2024-01-01 03:58:55.016UTC irc.libera.chat-#linux another user: HAPPY NEW YEAR, for me"); + testParsing("2024-01-28 10:19:43.380UTC irc.libera.chat-#urchat ****: You have joined #urchat"); } @Test public void testLogLines() { - String logFilePath = "/home/matt/urChat/Logs/irc.libera.chat-#linux.log"; + String logFilePath = "Logs/irc.libera.chat-#urchat.log"; String line = ""; try (BufferedReader br = new BufferedReader(new FileReader(logFilePath))) { @@ -32,8 +36,7 @@ public void testLogLines() { testParsing(line); } } catch (Exception e) { - System.out.println(line); - e.printStackTrace(); + fail("Error parsing line ["+ line +"] " + e.getLocalizedMessage()); } } From c7ed7042de9d536318e8684363b97e8b5d2615f0 Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 24 Feb 2024 05:47:39 +1000 Subject: [PATCH 04/11] Fix formatting. Improves messageQueue performance --- src/urChatBasic/base/IRCChannelBase.java | 19 +-- src/urChatBasic/frontend/LineFormatter.java | 13 ++ src/urChatBasic/frontend/UserGUI.java | 138 +++++++-------- tests/backend/LogParsingTests.java | 3 +- .../frontend/UpdateStylesBenchmarkTests.java | 157 ++++++++++++++++++ tests/utils/TestDriverGUI.java | 55 +++++- 6 files changed, 291 insertions(+), 94 deletions(-) create mode 100644 tests/frontend/UpdateStylesBenchmarkTests.java diff --git a/src/urChatBasic/base/IRCChannelBase.java b/src/urChatBasic/base/IRCChannelBase.java index d1e7ba9..d3b6a40 100644 --- a/src/urChatBasic/base/IRCChannelBase.java +++ b/src/urChatBasic/base/IRCChannelBase.java @@ -520,7 +520,8 @@ public void printText(Date messageDate, String message, String fromUser) public boolean messageQueueWorking() { - return (!messageQueue.isEmpty() || messageQueueInProgress); + + return (messageQueue.remainingCapacity() == 0); } public void handleMessageQueue () @@ -546,26 +547,14 @@ public void run () String line = message.getLine(); String fromUser = message.getUser(); - Document document = lineFormatter.getDocument(); - Element root = lineFormatter.getDocument().getDefaultRootElement(); - int lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); if (IRCChannelBase.this instanceof IRCServer) lineLimit = ((InterfacePanel) gui.interfacePanel).getLimitServerLinesCount(); - if (null != message && root.getElementCount() > lineLimit) + if (null != message && getLineFormatter().getLineCount() > lineLimit) { - Element firstLine = root.getElement(0); - int endIndex = firstLine.getEndOffset(); - - try - { - document.remove(0, endIndex); - } catch (BadLocationException ble) - { - Constants.LOGGER.error(ble.getLocalizedMessage()); - } + getLineFormatter().removeFirstLine(); } if (null == channelTextArea) diff --git a/src/urChatBasic/frontend/LineFormatter.java b/src/urChatBasic/frontend/LineFormatter.java index bda00fe..faf32a1 100644 --- a/src/urChatBasic/frontend/LineFormatter.java +++ b/src/urChatBasic/frontend/LineFormatter.java @@ -720,6 +720,19 @@ public String getFirstLine() throws BadLocationException return finalLine; } + public void removeFirstLine () + { + Element firstLine = doc.getDefaultRootElement().getElement(0); + int endIndex = firstLine.getEndOffset(); + try { + doc.remove(0, endIndex); + } catch (BadLocationException ble) + { + // TODO: + ble.printStackTrace(); + } + } + public String getLatestLine() throws BadLocationException { Element root = doc.getDefaultRootElement(); diff --git a/src/urChatBasic/frontend/UserGUI.java b/src/urChatBasic/frontend/UserGUI.java index eff3218..c00e869 100644 --- a/src/urChatBasic/frontend/UserGUI.java +++ b/src/urChatBasic/frontend/UserGUI.java @@ -67,8 +67,7 @@ public class UserGUI extends JPanel implements Runnable, UserGUIBase private final UROptionsPanel profilePanel = new ProfilePanel((MainOptionsPanel) optionsMainPanel); - private final JComboBox lafOptions = - new JComboBox(UIManager.getInstalledLookAndFeels()); + private final JComboBox lafOptions = new JComboBox(UIManager.getInstalledLookAndFeels()); // Appearance Panel private FontPanel clientFontPanel; @@ -191,46 +190,46 @@ public UROptionsPanel getAppearancePanel () } // /** - // * Sets the current active profile - if the newProfileName doesn't exist it will be created. - // * @param newProfileName - // */ + // * Sets the current active profile - if the newProfileName doesn't exist it will be created. + // * @param newProfileName + // */ // public void setActiveProfile (String newProfileName) // { - // // save the current profile settings, if it exists - // if (URProfilesUtil.profileExists(URProfilesUtil.getActiveProfileName())) - // { - // setClientSettings(); - // } - - // if(!URProfilesUtil.profileExists(newProfileName)) - // { - // URProfilesUtil.createProfile(newProfileName); - // } - - // // change the profile name - // URProfilesUtil.setActiveProfileName(newProfileName); - - // // now load the new profile settings - // getClientSettings(false); + // // save the current profile settings, if it exists + // if (URProfilesUtil.profileExists(URProfilesUtil.getActiveProfileName())) + // { + // setClientSettings(); + // } + + // if(!URProfilesUtil.profileExists(newProfileName)) + // { + // URProfilesUtil.createProfile(newProfileName); + // } + + // // change the profile name + // URProfilesUtil.setActiveProfileName(newProfileName); + + // // now load the new profile settings + // getClientSettings(false); // } // TODO: Is this needed any more or should we be adding IRCServer only? // @Override // public void addToCreatedServers (String serverName) // { - // if (getCreatedServer(serverName) == null) - // { - // createdServers.add(new IRCServer(serverName.trim(), userNameTextField.getText().trim(), - // realNameTextField.getText().trim(), new String(passwordTextField.getPassword()), - // serverPortTextField.getText().trim(), serverTLSCheckBox.isSelected(), - // proxyHostNameTextField.getText(), proxyPortTextField.getText(), serverProxyCheckBox.isSelected())); - // } + // if (getCreatedServer(serverName) == null) + // { + // createdServers.add(new IRCServer(serverName.trim(), userNameTextField.getText().trim(), + // realNameTextField.getText().trim(), new String(passwordTextField.getPassword()), + // serverPortTextField.getText().trim(), serverTLSCheckBox.isSelected(), + // proxyHostNameTextField.getText(), proxyPortTextField.getText(), serverProxyCheckBox.isSelected())); + // } // } @Override public void addToCreatedServers (IRCServerBase newServer) { - if(getCreatedServer(newServer.getName()) != null) + if (getCreatedServer(newServer.getName()) != null) createdServers.remove(newServer); createdServers.add(newServer); @@ -255,8 +254,7 @@ private void setupAppearancePanel () lafOptions.setRenderer(new DefaultListCellRenderer() { @Override - public Component getListCellRendererComponent (JList list, Object value, int index, boolean isSelected, - boolean cellHasFocus) + public Component getListCellRendererComponent (JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { LookAndFeelInfo info = (LookAndFeelInfo) value; return super.getListCellRendererComponent(list, info.getName(), index, isSelected, cellHasFocus); @@ -352,15 +350,12 @@ public void updatePreviewTextArea () IRCUser tempUser = new IRCUser(null, "matty_r"); IRCUser tempUser2 = new IRCUser(null, System.getProperty("user.name")); previewLineFormatter.setNick(System.getProperty("user.name")); - previewLineFormatter.appendMessage(Optional.empty(), null, Constants.EVENT_USER, - "urChat has loaded - this is an Event"); + previewLineFormatter.appendMessage(Optional.empty(), null, Constants.EVENT_USER, "urChat has loaded - this is an Event"); previewLineFormatter.appendMessage(Optional.empty(), tempUser, "matty_r", "Normal line. Hello, world!"); previewLineFormatter.appendMessage(Optional.empty(), tempUser, "matty_r", "This is what it looks like when your nick is mentioned, " + System.getProperty("user.name") + "!"); - previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), - "Go to https://github.com/matty-r/urChat"); - previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), - "Join #urchat on irc.libera.chat"); + previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), "Go to https://github.com/matty-r/urChat"); + previewLineFormatter.appendMessage(Optional.empty(), tempUser2, System.getProperty("user.name"), "Join #urchat on irc.libera.chat"); } else { previewLineFormatter.updateStyles(getStyle()); @@ -379,8 +374,7 @@ public void mouseClicked (MouseEvent mouseEvent) if (SwingUtilities.isRightMouseButton(mouseEvent) && wordAttributeSet.getAttribute("name") != null) { String styleName = styleLabel.getText(); - FontDialog styleFontDialog = - new FontDialog(styleName, previewLineFormatter.getStyleDefault(styleName), URProfilesUtil.getActiveProfilePath()); + FontDialog styleFontDialog = new FontDialog(styleName, previewLineFormatter.getStyleDefault(styleName), URProfilesUtil.getActiveProfilePath()); styleFontDialog.addFontSaveListener(new SaveFontListener()); styleFontDialog.setVisible(true); @@ -433,7 +427,7 @@ public String[] getNickFormatString (String nick) nickParts[1] = nick; String nickString = nickFormatField.getText(); - if(nickString.indexOf("nick") >= 0) + if (nickString.indexOf("nick") >= 0) { int nickIndex = nickString.indexOf("nick"); String leftPart = nickString.substring(0, nickIndex); @@ -441,7 +435,7 @@ public String[] getNickFormatString (String nick) nickParts[0] = leftPart; nickParts[2] = rightPart; - } else if(nickString.length() == 1) + } else if (nickString.length() == 1) { // both parts are the same nickParts[0] = nickString; @@ -470,7 +464,8 @@ public void setNickFormatString (String newFormat) */ public void setupServerTab (IRCServerBase server) { - SwingUtilities.invokeLater(new Runnable() { + SwingUtilities.invokeLater(new Runnable() + { @Override public void run () @@ -479,7 +474,7 @@ public void run () { boolean iconsShown = (boolean) URPanels.getKeyComponentValue(Constants.KEY_SHOW_TAB_ICON); int currentServerIndex = DriverGUI.gui.getTabIndex((IRCChannelBase) server); - if(currentServerIndex < 0) + if (currentServerIndex < 0) { tabbedPane.addTab(server.getName(), iconsShown ? ((IRCChannelBase) server).icon : null, ((IRCServer) server)); setCurrentTab(server.getName()); @@ -524,7 +519,7 @@ public void quitServers () } // if(createdServers.size() == 0) - // profilePicker.setEnabled(true); + // profilePicker.setEnabled(true); } /* @@ -540,7 +535,7 @@ public void quitServer (IRCServerBase server) createdServers.remove(server); // if(createdServers.size() == 0) - // profilePicker.setEnabled(true); + // profilePicker.setEnabled(true); } /** @@ -549,7 +544,8 @@ public void quitServer (IRCServerBase server) public void setClientSettings () { URPreferencesUtil.putPref(Constants.KEY_TIME_STAMP_FORMAT, timeStampField.getText(), URProfilesUtil.getActiveProfilePath()); - URPreferencesUtil.putPref(Constants.KEY_LAF_NAME, ((LookAndFeelInfo) lafOptions.getSelectedItem()).getClassName(), URProfilesUtil.getActiveProfilePath()); + URPreferencesUtil.putPref(Constants.KEY_LAF_NAME, ((LookAndFeelInfo) lafOptions.getSelectedItem()).getClassName(), + URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.saveStyle(defaultStyle, clientFontPanel.getStyle(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_WINDOW_X, (int) DriverGUI.frame.getBounds().getX(), URProfilesUtil.getActiveProfilePath()); URPreferencesUtil.putPref(Constants.KEY_WINDOW_Y, (int) DriverGUI.frame.getBounds().getY(), URProfilesUtil.getActiveProfilePath()); @@ -570,11 +566,9 @@ public void getClientSettings (boolean loadWindowSettings) clientFontPanel.loadStyle(); - timeStampField - .setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_TIME_STAMP_FORMAT, Constants.DEFAULT_TIME_STAMP_FORMAT)); + timeStampField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_TIME_STAMP_FORMAT, Constants.DEFAULT_TIME_STAMP_FORMAT)); - nickFormatField - .setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_NICK_FORMAT, Constants.DEFAULT_NICK_FORMAT)); + nickFormatField.setText(URProfilesUtil.getActiveProfilePath().get(Constants.KEY_NICK_FORMAT, Constants.DEFAULT_NICK_FORMAT)); updatePreviewTextArea(); @@ -586,9 +580,8 @@ public void getClientSettings (boolean loadWindowSettings) URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_WIDTH, Constants.DEFAULT_WINDOW_WIDTH), URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_HEIGHT, Constants.DEFAULT_WINDOW_HEIGHT)); - this.setPreferredSize( - new Dimension(URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_WIDTH, Constants.DEFAULT_WINDOW_WIDTH), - URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_HEIGHT, Constants.DEFAULT_WINDOW_HEIGHT))); + this.setPreferredSize(new Dimension(URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_WIDTH, Constants.DEFAULT_WINDOW_WIDTH), + URProfilesUtil.getActiveProfilePath().getInt(Constants.KEY_WINDOW_HEIGHT, Constants.DEFAULT_WINDOW_HEIGHT))); } } @@ -622,8 +615,7 @@ private void setupTabbedPane () } /** - * Used to listen to the right click on the tabs to determine what type we clicked on and pop up a - * menu or exit. I will add menus to all types eventually. + * Used to listen to the right click on the tabs to determine what type we clicked on and pop up a menu or exit. I will add menus to all types eventually. * * @author Matt * @@ -715,12 +707,12 @@ public void actionPerformed (ActionEvent arg0) // TODO: Favourites handling to be done elsewhere // for (int index = 0; index < favouritesList.getModel().getSize(); index++) // { - // FavouritesItem favouriteItem = favouritesList.getModel().getElementAt(index); - // if(favouriteItem.favFontDialog != null) - // { - // favouriteItem.favFontDialog.getFontPanel().setDefaultStyle(getStyle()); - // favouriteItem.favFontDialog.getFontPanel().loadStyle(); - // } + // FavouritesItem favouriteItem = favouritesList.getModel().getElementAt(index); + // if(favouriteItem.favFontDialog != null) + // { + // favouriteItem.favFontDialog.getFontPanel().setDefaultStyle(getStyle()); + // favouriteItem.favFontDialog.getFontPanel().loadStyle(); + // } // } // defaultStyle = clientFontPanel.getStyle(); @@ -730,7 +722,7 @@ public void actionPerformed (ActionEvent arg0) public UserGUI (Optional initialProfile) { - if(initialProfile.isPresent()) + if (initialProfile.isPresent()) URProfilesUtil.setActiveProfileName(initialProfile.get()); else URProfilesUtil.setActiveProfileName(URProfilesUtil.getDefaultProfile()); @@ -748,7 +740,7 @@ public void setupUserGUI () // this.setBackground(Color.gray); getClientSettings(true); - URProfilesUtil.addListener(EventType.CHANGE, e-> { + URProfilesUtil.addListener(EventType.CHANGE, e -> { getClientSettings(false); }); lafOptions.addActionListener(new ChangeLAFListener()); @@ -814,7 +806,7 @@ private LookAndFeelInfo getLAF (String lafClassName) } } - Constants.LOGGER.error( "Unable to set LAF to " + lafClassName); + Constants.LOGGER.error("Unable to set LAF to " + lafClassName); // Set to the System LAF if we've chosen an invalid/unavailable LAF theme return getLAF(UIManager.getSystemLookAndFeelClassName()); @@ -826,7 +818,7 @@ public void setNewLAF (String newLAFname) // String previousDefaultBackground = URColour.hexEncode(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING)); // Font previousDefaultFont = getFont(); - Constants.LOGGER.info( "Setting to LookAndFeel to " + newLAFname); + Constants.LOGGER.info("Setting to LookAndFeel to " + newLAFname); boolean flatLafAvailable = false; try { @@ -869,29 +861,25 @@ public void setNewLAF (String newLAFname) defaultStyle.setFont(UIManager.getFont(Constants.DEFAULT_FONT_STRING)); - // reset the defaults on the guiStyle if they were already at the default - // if (previousDefaultForeground.equals(URColour.hexEncode(guiStyle.getForeground()))) - defaultStyle.setForeground(UIManager.getColor(Constants.DEFAULT_FOREGROUND_STRING)); - - // if (previousDefaultBackground.equals(URColour.hexEncode(guiStyle.getBackground()))) - defaultStyle.setBackground(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING)); + defaultStyle.setForeground(UIManager.getColor(Constants.DEFAULT_FOREGROUND_STRING)); + defaultStyle.setBackground(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING)); clientFontPanel.setDefaultStyle(defaultStyle); - if(DriverGUI.frame.isVisible()) + if (DriverGUI.frame.isVisible()) SwingUtilities.updateComponentTreeUI(DriverGUI.frame); updateExtras(); - // DriverGUI.frame.dispose(); - if(DriverGUI.frame.isVisible()) + if (DriverGUI.frame.isVisible()) DriverGUI.frame.validate(); } // Update the fonts and popup menus - these aren't under the component tree private void updateExtras () { - SwingUtilities.invokeLater(new Runnable() { + SwingUtilities.invokeLater(new Runnable() + { @Override public void run () diff --git a/tests/backend/LogParsingTests.java b/tests/backend/LogParsingTests.java index dfc2738..8f171db 100644 --- a/tests/backend/LogParsingTests.java +++ b/tests/backend/LogParsingTests.java @@ -5,9 +5,9 @@ import java.util.Date; import java.util.HashMap; import java.util.Map; +import org.testng.annotations.Ignore; import org.testng.annotations.Test; import urChatBasic.backend.utils.LogPatternParser; -import urChatBasic.backend.utils.LogPatternParser.LogPattern; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.fail; import static urChatBasic.backend.utils.LogPatternParser.LogPattern; @@ -27,6 +27,7 @@ public void testLogLinesManual () } @Test + @Ignore public void testLogLines() { String logFilePath = "Logs/irc.libera.chat-#urchat.log"; String line = ""; diff --git a/tests/frontend/UpdateStylesBenchmarkTests.java b/tests/frontend/UpdateStylesBenchmarkTests.java new file mode 100644 index 0000000..709b9d1 --- /dev/null +++ b/tests/frontend/UpdateStylesBenchmarkTests.java @@ -0,0 +1,157 @@ +package frontend; + +import static org.testng.Reporter.log; +import java.awt.Font; +import java.awt.GraphicsEnvironment; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import urChatBasic.backend.Connection; +import urChatBasic.backend.MessageHandler; +import urChatBasic.backend.MessageHandler.Message; +import urChatBasic.backend.utils.URProfilesUtil; +import urChatBasic.backend.utils.URStyle; +import urChatBasic.base.IRCChannelBase; +import urChatBasic.base.capabilities.CapabilityTypes; +import urChatBasic.base.proxy.ProxyTypes; +import urChatBasic.frontend.DriverGUI; +import urChatBasic.frontend.IRCServer; +import urChatBasic.frontend.IRCUser; +import urChatBasic.frontend.UserGUI; +import urChatBasic.frontend.utils.URColour; +import utils.TestDriverGUI; +import utils.TestUtils; + +public class UpdateStylesBenchmarkTests { + MessageHandler testHandler; + IRCServer testServer; + TestDriverGUI testDriver; + UserGUI testGUI; + final static int MAX_CHANNEL_NAMES = 10; + final static String CHANNEL_PREFIX = "#someChannel"; + final List PUB_CHANNEL_NAMES = new ArrayList<>(); + IRCUser testUser; + Connection testConnection; + + LinkedList importantInfo = new LinkedList<>(); + + @BeforeClass(alwaysRun = true) + public void setUp () throws Exception + { + testDriver = new TestDriverGUI(); + TestDriverGUI.startTestGUI(DriverGUI.gui); + testGUI = DriverGUI.gui; + testServer = new IRCServer("testServer", "testUser", "testUser", "testPassword", "1337", true, "testProxy", "1234", ProxyTypes.NONE.getType(), + CapabilityTypes.NONE.getType()); + testUser = new IRCUser(testServer, "testUser"); + + for (int i = 0; i < MAX_CHANNEL_NAMES; i++) + { + PUB_CHANNEL_NAMES.add(CHANNEL_PREFIX + i); + } + + for (String channelName : PUB_CHANNEL_NAMES) + { + testServer.addToCreatedChannels(channelName, false); + } + + testConnection = new Connection(testServer); + testHandler = testConnection.getMessageHandler(); + + Instant startBenchmark = Instant.now(); + for (IRCChannelBase channel : testServer.createdChannels) + { + String rawMessage = ":someuser!~someuser@urchatclient PRIVMSG " + channel.getName() + " :Welcome to " + channel.getName(); + + Message testMessage = testHandler.new Message(rawMessage); + testHandler.parseMessage(testMessage); + + testDriver.loadTestLogs(channel); + } + + TestDriverGUI.waitForEverything(testGUI); + logImportantInfo("Took " + Duration.between(startBenchmark, Instant.now()).toMillis() + "ms to load test logs."); + } + + private void logImportantInfo (String message) + { + importantInfo.add(message); + log(message, true); + } + + @AfterClass(alwaysRun = true) + public void tearDown () throws Exception + { + for (String message : importantInfo) { + System.out.println(message); + } + // Reporter.log("Deleting testing profile.", true); + testServer.quitChannels(); + // URProfilesUtil.getActiveProfilePath().sync(); + // URProfilesUtil.getActiveProfilePath().sync(); + URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); + TestDriverGUI.closeWindow(); + } + + @Test + public void changeFontBenchmark () throws InterruptedException + { + Instant startBenchmark = Instant.now(); + // Get Current Font in Appearance panel + URStyle guiStyle = testGUI.getStyle(); + URStyle newStyle = guiStyle.clone(); + + String[] FONT_LIST = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); + newStyle.setFont(new Font(FONT_LIST[new Random().nextInt(FONT_LIST.length)], Font.PLAIN, 8)); + testGUI.getFontPanel().setDefaultStyle(newStyle); + TestDriverGUI.waitForEverything(testGUI); + guiStyle = testGUI.getStyle(); + logImportantInfo( "Took " + Duration.between(startBenchmark, Instant.now()).toMillis() + "ms to update font."); + + } + + @Test + public void changeColoursBenchmark () throws InterruptedException + { + Instant startBenchmark = Instant.now(); + // Get Current Font in Appearance panel + URStyle guiStyle = testGUI.getStyle(); + URStyle newStyle = guiStyle.clone(); + + newStyle.setForeground(TestUtils.getRandomColour()); + log("Set foreground to " +URColour.hexEncode(newStyle.getForeground().get()), true); + + testGUI.getFontPanel().setDefaultStyle(newStyle); + TestDriverGUI.waitForEverything(testGUI); + guiStyle = testGUI.getStyle(); + logImportantInfo( "Took " + Duration.between(startBenchmark, Instant.now()).toMillis() + "ms to update colours."); + } + + @Test + public void changeStylesBenchmark () throws InterruptedException + { + Instant startBenchmark = Instant.now(); + // Get Current Font in Appearance panel + URStyle guiStyle = testGUI.getStyle(); + URStyle newStyle = guiStyle.clone(); + + newStyle.setForeground(TestUtils.getRandomColour()); + log("Set foreground to " +URColour.hexEncode(newStyle.getForeground().get()), true); + + testGUI.getFontPanel().setDefaultStyle(newStyle); + + // String styleName = styleLabel.getText(); + // FontDialog styleFontDialog = new FontDialog(styleName, previewLineFormatter.getStyleDefault(styleName), URProfilesUtil.getActiveProfilePath()); + + + TestDriverGUI.waitForEverything(testGUI); + guiStyle = testGUI.getStyle(); + logImportantInfo( "Took " + Duration.between(startBenchmark, Instant.now()).toMillis() + "ms to update colours."); + } +} diff --git a/tests/utils/TestDriverGUI.java b/tests/utils/TestDriverGUI.java index 451b78f..c854f6f 100644 --- a/tests/utils/TestDriverGUI.java +++ b/tests/utils/TestDriverGUI.java @@ -2,18 +2,24 @@ import java.awt.Toolkit; import java.awt.event.WindowEvent; +import java.io.BufferedReader; +import java.io.File; import java.io.IOException; +import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; import javax.swing.JFrame; import javax.swing.SwingUtilities; import org.testng.Reporter; import static org.testng.Reporter.log; +import static urChatBasic.backend.utils.LogPatternParser.parseLogLineFull; +import urChatBasic.backend.utils.ReverseLineInputStream; import urChatBasic.backend.utils.URProfilesUtil; import urChatBasic.base.Constants; import urChatBasic.base.IRCChannelBase; @@ -21,11 +27,13 @@ import urChatBasic.frontend.DriverGUI; import urChatBasic.frontend.IRCServer; import urChatBasic.frontend.UserGUI; +import urChatBasic.frontend.panels.InterfacePanel; public class TestDriverGUI extends DriverGUI { final String testProfileName = "testingprofile" + (new SimpleDateFormat("yyMMddss")).format(new Date()); static List testProfiles = new ArrayList<>(); + static boolean loadingLogsInProgress = false; public String getTestProfileName () { @@ -49,11 +57,10 @@ public void run() { gui = createGUI(Optional.of(testProfileName)); gui.setTimeLineString(Constants.DEFAULT_TIME_STAMP_FORMAT); gui.setNickFormatString(Constants.DEFAULT_NICK_FORMAT); - gui.setupUserGUI(); // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(gui); frame.pack(); - frame.setVisible(false); + frame.setVisible(true); } }); } @@ -74,6 +81,13 @@ public static void waitForEverything (UserGUI gui) throws InterruptedException continue; } + if(loadingLogsInProgress) + { + log("Loading logs in Progress.. waiting", true); + wait = true; + continue; + } + for (IRCServerBase server : gui.getCreatedServers()) { for (IRCChannelBase channel : ((IRCServer) server).createdChannels) @@ -106,7 +120,7 @@ public static void cleanupTestProfiles () public static void startTestGUI (UserGUI gui) throws InterruptedException { - waitForEverything(gui); + // waitForEverything(gui); SwingUtilities.invokeLater(gui); log("Started", true); } @@ -117,4 +131,39 @@ public static void closeWindow () Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closingEvent); // frame.dispose(); } + + public void loadTestLogs (IRCChannelBase channel) throws InterruptedException + { + Thread fileReadingThread = new Thread(() -> { + loadingLogsInProgress = true; + File logFile = new File("tests/Logs/testlogs-#somechannel.log"); + String line = ""; + try (BufferedReader br = new BufferedReader (new InputStreamReader (new ReverseLineInputStream(logFile)))) { + int maxCount = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount() * 2; + log("Load max count: [" + maxCount +"] Loading logs into " + channel.getName(), true); + int loadCount = 0; + while ((line = br.readLine()) != null && loadCount < maxCount) { + loadingLogsInProgress = true; + while(channel.messageQueueWorking()) + { + System.out.println("Sleeping log loading thread."); + Thread.sleep(10); + } + + Map parsedLine = parseLogLineFull(line); + if(parsedLine.size() != 0) + { + channel.printText((Date) parsedLine.get("DATE"), parsedLine.get("MESSAGE").toString(), parsedLine.get("USER").toString()); + loadCount ++; + } + } + log("Done loading logs " + channel.getName(), true); + } catch (Exception e) { + e.printStackTrace(); + } finally { + loadingLogsInProgress = false; + } + }); + fileReadingThread.start(); + } } From 34ef27bf2f910e11957332479deef8529cf8c46c Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 27 Feb 2024 06:00:52 +1000 Subject: [PATCH 05/11] Fix loading of the log4j2.xml. Adds the option to load channel logs/history on join. Start moving styles in LineFormatter to use a hashmap instead. --- src/urChatBasic/backend/logging/URLogger.java | 6 +- src/urChatBasic/base/Constants.java | 3 + src/urChatBasic/base/IRCChannelBase.java | 58 +++++++--- src/urChatBasic/frontend/LineFormatter.java | 105 ++++++++++-------- .../frontend/panels/InterfacePanel.java | 7 ++ tests/backend/MessageHandlerTests.java | 24 ++-- tests/frontend/LineFormatterTests.java | 2 +- tests/utils/TestDriverGUI.java | 7 +- 8 files changed, 129 insertions(+), 83 deletions(-) diff --git a/src/urChatBasic/backend/logging/URLogger.java b/src/urChatBasic/backend/logging/URLogger.java index c4291e1..4d954ba 100644 --- a/src/urChatBasic/backend/logging/URLogger.java +++ b/src/urChatBasic/backend/logging/URLogger.java @@ -29,19 +29,17 @@ public class URLogger public static void init () throws IOException, URISyntaxException { + // System.out.println("LOG CONFIG: "+ LOG4J_CONFIG_FILE); File logDir = new File(Constants.DIRECTORY_LOGS); if (!logDir.exists()) { logDir.mkdir(); } - File logConfigFile = new File(DriverGUI.class.getResource(LOG4J_CONFIG_FILE).toURI()); - if(!logConfigFile.exists()) - throw new IOException("LOG FILE NOT FOUND"); // System.setProperty("log4j2.debug", "true"); - System.setProperty("log4j2.configurationFile", logConfigFile.toString()); + System.setProperty("log4j2.configurationFile", DriverGUI.class.getResource(LOG4J_CONFIG_FILE).toURI().toString()); LOGGER = LoggerFactory.getLogger("urchat"); diff --git a/src/urChatBasic/base/Constants.java b/src/urChatBasic/base/Constants.java index 1e17f20..a3b1131 100644 --- a/src/urChatBasic/base/Constants.java +++ b/src/urChatBasic/base/Constants.java @@ -83,6 +83,7 @@ public class Constants public static final String KEY_CLICKABLE_LINKS_ENABLED = "clickable links"; public static final String KEY_EVENT_TICKER_JOINS_QUITS = "show events in ticker"; public static final String KEY_MAIN_WINDOW_JOINS_QUITS = "show events in main window"; + public static final String KEY_LOAD_CHANNEL_LOGS_ON_JOIN = "load channel logs on join"; public static final String KEY_LOG_CHANNEL_ACTIVITY = "log channel history"; public static final String KEY_LOG_SERVER_ACTIVITY = "log server activity"; public static final String KEY_LIMIT_CHANNEL_LINES = "limit number of channel lines"; @@ -129,6 +130,7 @@ public class Constants public static final Boolean DEFAULT_USERS_LIST_ACTIVE = true; public static final Boolean DEFAULT_EVENT_TICKER_JOINS_QUITS = true; public static final Boolean DEFAULT_MAIN_WINDOW_JOINS_QUITS = true; + public static final Boolean DEFAULT_LOAD_CHANNEL_LOGS_ON_JOIN = true; public static final Boolean DEFAULT_LOG_CHANNEL_ACTIVITY = true; public static final Boolean DEFAULT_LOG_SERVER_ACTIVITY = true; public static final Boolean DEFAULT_AUTO_CONNECT_FAVOURITES = false; @@ -265,6 +267,7 @@ public enum ConfigKeys { KEY_CLICKABLE_LINKS_ENABLED(Constants.KEY_CLICKABLE_LINKS_ENABLED, DEFAULT_CLICKABLE_LINKS_ENABLED), KEY_EVENT_TICKER_JOINS_QUITS(Constants.KEY_EVENT_TICKER_JOINS_QUITS, DEFAULT_EVENT_TICKER_JOINS_QUITS), KEY_MAIN_WINDOW_JOINS_QUITS(Constants.KEY_MAIN_WINDOW_JOINS_QUITS, DEFAULT_MAIN_WINDOW_JOINS_QUITS), + KEY_LOAD_CHANNEL_LOGS_ON_JOIN(Constants.KEY_LOAD_CHANNEL_LOGS_ON_JOIN, DEFAULT_LOAD_CHANNEL_LOGS_ON_JOIN), KEY_LOG_CHANNEL_ACTIVITY(Constants.KEY_LOG_CHANNEL_ACTIVITY, DEFAULT_LOG_CHANNEL_ACTIVITY), KEY_LOG_SERVER_ACTIVITY(Constants.KEY_LOG_SERVER_ACTIVITY, DEFAULT_LOG_SERVER_ACTIVITY), KEY_LIMIT_CHANNEL_LINES(Constants.KEY_LIMIT_CHANNEL_LINES, DEFAULT_LIMIT_CHANNEL_LINES), diff --git a/src/urChatBasic/base/IRCChannelBase.java b/src/urChatBasic/base/IRCChannelBase.java index d3b6a40..969d3d7 100644 --- a/src/urChatBasic/base/IRCChannelBase.java +++ b/src/urChatBasic/base/IRCChannelBase.java @@ -220,6 +220,10 @@ private void initChannel() fontDialog.addFontSaveListener(new SaveFontListener()); myActions = new IRCActions(this); + + if(((InterfacePanel) gui.interfacePanel).isLoadChannelLogsEnabled()) + loadChannelHistory(); + } private class ProfileChangeListener implements ActionListener @@ -518,12 +522,17 @@ public void printText(Date messageDate, String message, String fromUser) } } - public boolean messageQueueWorking() + public boolean messageQueueFull() { return (messageQueue.remainingCapacity() == 0); } + public boolean messageQueueWorking() + { + return (!messageQueue.isEmpty() || messageQueueInProgress); + } + public void handleMessageQueue () { SwingUtilities.invokeLater(new Runnable() @@ -944,25 +953,38 @@ private class LoadChannelHistory implements ActionListener @Override public void actionPerformed(ActionEvent arg0) { - Thread fileReadingThread = new Thread(() -> { - String logFilePath = URLogger.getLogFilePath(getMarker()); - String line = ""; - try (BufferedReader br = new BufferedReader (new InputStreamReader (new ReverseLineInputStream(new File(logFilePath))))) { - int maxCount = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); - while ((line = br.readLine()) != null && lineFormatter.getLineCount() < maxCount) { - if(messageQueueInProgress && messageQueue.remainingCapacity() == 0) - Thread.sleep(10); - - Map parsedLine = parseLogLineFull(line); - if(parsedLine.size() != 0) - printText((Date) parsedLine.get("DATE"), parsedLine.get("MESSAGE").toString(), parsedLine.get("USER").toString()); + loadChannelHistory(); + } + } + + private void loadChannelHistory () + { + Thread fileReadingThread = new Thread(() -> { + String logFilePath = URLogger.getLogFilePath(getMarker()); + String line = ""; + try (BufferedReader br = new BufferedReader (new InputStreamReader (new ReverseLineInputStream(new File(logFilePath))))) { + int maxCount = ((InterfacePanel) gui.interfacePanel).getLimitChannelLinesCount(); + Constants.LOGGER.info("Loading channel history, max line count [" + maxCount + "]"); + int loadCount = 0; + while ((line = br.readLine()) != null && loadCount < maxCount) { + if(messageQueueFull()) + Thread.sleep(10); + + Map parsedLine = parseLogLineFull(line); + if(parsedLine.size() != 0) + { + printText((Date) parsedLine.get("DATE"), parsedLine.get("MESSAGE").toString(), parsedLine.get("USER").toString()); + loadCount++; } - } catch (Exception e) { - e.printStackTrace(); } - }); - fileReadingThread.start(); - } + } catch (NullPointerException npe) + { + Constants.LOGGER.info("Log File doesn't yet exist."); + } catch (Exception e) { + e.printStackTrace(); + } + }); + fileReadingThread.start(); } private class QuitItem implements ActionListener diff --git a/src/urChatBasic/frontend/LineFormatter.java b/src/urChatBasic/frontend/LineFormatter.java index faf32a1..4577f69 100644 --- a/src/urChatBasic/frontend/LineFormatter.java +++ b/src/urChatBasic/frontend/LineFormatter.java @@ -11,11 +11,11 @@ import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Level; import java.util.prefs.Preferences; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -41,23 +41,25 @@ public class LineFormatter { private String myNick; - private URStyle targetStyle; private Color myForeground; private Color myBackground; private IRCServerBase myServer; private Preferences settingsPath; - private URStyle urlStyle; - private URStyle channelStyle; - private URStyle timeStyle; - private URStyle lineStyle; - private URStyle nickStyle; - private URStyle highStyle; - private URStyle mediumStyle; - private URStyle lowStyle; + // TODO: This should be an enum with all the styles + private URStyle targetStyle; + // private URStyle urlStyle; + // private URStyle channelStyle; + // private URStyle timeStyle; + // private URStyle lineStyle; + // private URStyle nickStyle; + // private URStyle highStyle; + // private URStyle mediumStyle; + // private URStyle lowStyle; private JTextPane docOwner; public StyledDocument doc; - public URStyle myStyle; + // public URStyle myStyle; private Map formatterStyles = new HashMap<>(); + private Map updatedStyles = new HashMap<>(); private Optional timeLine = Optional.empty(); private AtomicLong updateStylesTime = new AtomicLong(0); public AtomicBoolean updateStylesInProgress = new AtomicBoolean(false); @@ -108,27 +110,38 @@ public void initStyles (URStyle baseStyle) targetStyle.getForeground().ifPresent(fg -> myForeground = fg); targetStyle.getBackground().ifPresent(bg -> myBackground = bg); - timeStyle = defaultStyle(null, true); - lineStyle = defaultStyle(null, true); - nickStyle = nickStyle(true); - myStyle = myStyle(true); - channelStyle = channelStyle(true); - urlStyle = urlStyle(true); - highStyle = highStyle(true); - mediumStyle = mediumStyle(true); - lowStyle = lowStyle(true); - - formatterStyles.put(timeStyle.getName(), timeStyle); - formatterStyles.put(lineStyle.getName(), lineStyle); - formatterStyles.put(nickStyle.getName(), nickStyle); - formatterStyles.put(myStyle.getName(), myStyle); - formatterStyles.put(channelStyle.getName(), channelStyle); - formatterStyles.put(urlStyle.getName(), urlStyle); - formatterStyles.put(highStyle.getName(), highStyle); - formatterStyles.put(mediumStyle.getName(), mediumStyle); - formatterStyles.put(lowStyle.getName(), lowStyle); - - + // URStyle timeStyle = defaultStyle(null, true); + // URStyle lineStyle = defaultStyle(null, true); + URStyle defaultStyle = defaultStyle(null, true); + URStyle nickStyle = nickStyle(true); + URStyle myStyle = myStyle(true); + URStyle channelStyle = channelStyle(true); + URStyle urlStyle = urlStyle(true); + URStyle highStyle = highStyle(true); + URStyle mediumStyle = mediumStyle(true); + URStyle lowStyle = lowStyle(true); + + // updatedStyles.put(timeStyle.getName(), timeStyle); + // updatedStyles.put(lineStyle.getName(), lineStyle); + updatedStyles.put(defaultStyle.getName(), defaultStyle); + updatedStyles.put(nickStyle.getName(), nickStyle); + updatedStyles.put(myStyle.getName(), myStyle); + updatedStyles.put(channelStyle.getName(), channelStyle); + updatedStyles.put(urlStyle.getName(), urlStyle); + updatedStyles.put(highStyle.getName(), highStyle); + updatedStyles.put(mediumStyle.getName(), mediumStyle); + updatedStyles.put(lowStyle.getName(), lowStyle); + + // TODO: Styles should be an enum + + List changedStyles = new ArrayList<>(updatedStyles.values()); + + for (URStyle updatedStyle : updatedStyles.values()) { + if(formatterStyles.containsKey(updatedStyle.getName()) && formatterStyles.get(updatedStyle.getName()).equals(updatedStyle)) + changedStyles.remove(updatedStyle); + else + formatterStyles.put(updatedStyle.getName(), updatedStyle); + } } public URStyle dateStyle(URStyle baseStyle, Date date, boolean load) @@ -829,8 +842,8 @@ private int parseClickableText(IRCUser fromUser, String line, URStyle defaultSty throws BadLocationException { HashMap regexStrings = new HashMap<>(); - regexStrings.put(Constants.URL_REGEX, urlStyle); - regexStrings.put(Constants.CHANNEL_REGEX, channelStyle); + regexStrings.put(Constants.URL_REGEX, getStyle("urlStyle", false)); + regexStrings.put(Constants.CHANNEL_REGEX, getStyle("channelStyle", false)); // final String line = getLatestLine(doc); final int relativePosition = getLinePosition(getLatestLine()); @@ -919,16 +932,16 @@ public void appendMessage(Optional lineDate, IRCUser fromUser, String from if (fromUser != null && null != myNick && myNick.equals(fromUser.toString())) { // This message is from me - nickPositionStyle = myStyle.clone(); - linePositionStyle = lineStyle.clone(); - timePositionStyle = timeStyle.clone(); + nickPositionStyle = getStyle("myStyle", false); + linePositionStyle = getStyle("defaultStyle", false); + timePositionStyle = getStyle("defaultStyle", false); nickParts = DriverGUI.gui.getNickFormatString(fromUser.getName()); } else if (fromUser == null && fromString.equals(Constants.EVENT_USER)) { // This is an event message - nickPositionStyle = lowStyle.clone(); - linePositionStyle = lowStyle.clone(); - timePositionStyle = lowStyle.clone(); + nickPositionStyle = getStyle("lowStyle", false); + linePositionStyle = getStyle("lowStyle", false); + timePositionStyle = getStyle("lowStyle", false); nickParts = DriverGUI.gui.getNickFormatString(fromString); } else { @@ -937,18 +950,18 @@ public void appendMessage(Optional lineDate, IRCUser fromUser, String from // This message is from someone else // Does this message have my nick in it? if (myNick != null && line.indexOf(myNick) > -1) - nickPositionStyle = highStyle.clone(); + nickPositionStyle = getStyle("highStyle", false); else - nickPositionStyle = nickStyle.clone(); + nickPositionStyle = getStyle("nickStyle", false); - linePositionStyle = lineStyle.clone(); - timePositionStyle = timeStyle.clone(); + linePositionStyle = getStyle("defaultStyle", false); + timePositionStyle = getStyle("defaultStyle", false); } try { - // doc.insertString(doc.getLength(), timeLine, timeStyle); + // doc.insertString(doc.getLength(), timeLine, defaultStyle); // if(null != timeLine && !timeLine.isBlank()) if (((InterfacePanel) DriverGUI.gui.interfacePanel).isTimeStampsEnabled()) { @@ -963,7 +976,7 @@ public void appendMessage(Optional lineDate, IRCUser fromUser, String from if (fromUser != null) { - URStyle clickableNameStyle = nickPositionStyle.clone(); + URStyle clickableNameStyle = nickPositionStyle; clickableNameStyle.addAttribute("type", "IRCUser"); clickableNameStyle.addAttribute("clickableText", new ClickableText(fromUser.toString(), nickPositionStyle, fromUser)); diff --git a/src/urChatBasic/frontend/panels/InterfacePanel.java b/src/urChatBasic/frontend/panels/InterfacePanel.java index f70564f..4eeddc7 100644 --- a/src/urChatBasic/frontend/panels/InterfacePanel.java +++ b/src/urChatBasic/frontend/panels/InterfacePanel.java @@ -21,6 +21,7 @@ public class InterfacePanel extends UROptionsPanel private final JCheckBox enableClickableLinks = new JCheckBox("Make links clickable"); private final JCheckBox showJoinsQuitsEventTicker = new JCheckBox("Show Joins/Quits in the Event Ticker"); private final JCheckBox showJoinsQuitsMainWindow = new JCheckBox("Show Joins/Quits in the Chat Window"); + private final JCheckBox loadChannelLogsOnJoin = new JCheckBox("Load channel logs on join"); private final JCheckBox logChannelText = new JCheckBox("Save and log all channel text"); private final JCheckBox logServerActivity = new JCheckBox("Save and log all Server activity"); private final JCheckBox logClientText = new JCheckBox("Log client text (Allows up or down history)"); @@ -60,6 +61,7 @@ private void setupInterfacePanel () URPanels.addToPanel(this, enableClickableLinks, null, Placement.DEFAULT, null, Constants.KEY_CLICKABLE_LINKS_ENABLED); URPanels.addToPanel(this, showJoinsQuitsEventTicker, null, Placement.DEFAULT, null, Constants.KEY_EVENT_TICKER_JOINS_QUITS); URPanels.addToPanel(this, showJoinsQuitsMainWindow, null, Placement.DEFAULT, null, Constants.KEY_MAIN_WINDOW_JOINS_QUITS); + URPanels.addToPanel(this, loadChannelLogsOnJoin, null, Placement.DEFAULT, null, Constants.KEY_LOAD_CHANNEL_LOGS_ON_JOIN); URPanels.addToPanel(this, logChannelText, null, Placement.DEFAULT, null, Constants.KEY_LOG_CHANNEL_ACTIVITY); URPanels.addToPanel(this, logServerActivity, null, Placement.DEFAULT, null, Constants.KEY_LOG_SERVER_ACTIVITY); URPanels.addToPanel(this, logClientText, null, Placement.DEFAULT, null, Constants.KEY_LOG_CLIENT_TEXT); @@ -192,6 +194,11 @@ public Boolean isClickableLinksEnabled () return enableClickableLinks.isSelected(); } + public Boolean isLoadChannelLogsEnabled () + { + return loadChannelLogsOnJoin.isSelected(); + } + /* * (non-Javadoc) * diff --git a/tests/backend/MessageHandlerTests.java b/tests/backend/MessageHandlerTests.java index 07487fb..2325001 100644 --- a/tests/backend/MessageHandlerTests.java +++ b/tests/backend/MessageHandlerTests.java @@ -1,6 +1,7 @@ package backend; import static org.testng.AssertJUnit.*; +import static org.testng.Reporter.log; import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; @@ -77,13 +78,15 @@ public void nickIsHighStyleTest() throws BadLocationException, InterruptedExcept Message testMessage = testHandler.new Message(rawMessage); testHandler.parseMessage(testMessage); IRCPrivate someUserChannel = testServer.getCreatedPrivateChannel("someuser"); - String testLine = someUserChannel.getLineFormatter().getLatestLine(); // "[0629] hello testUser!" + while (someUserChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } + String testLine = someUserChannel.getLineFormatter().getLatestLine(); // "[0629] hello testUser!" + // Should be highStyle because someuser mentioned my nick, testUser assertEquals("highStyle", someUserChannel.getLineFormatter().getStyleAtPosition(11, testLine).getAttribute("name")); @@ -120,13 +123,14 @@ public void nickIsNickStyleTest() throws BadLocationException, InterruptedExcept String rawMessage = ":someuser!~someuser@urchatclient PRIVMSG "+PUB_CHANNEL_NAME+" :Welcome to somechannel!"; Message testMessage = testHandler.new Message(rawMessage); testHandler.parseMessage(testMessage); - String testLine = testPubChannel.getLineFormatter().getLatestLine(); // "[0629] hello world!" while (testPubChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } + String testLine = "Welcome to somechannel!"; // "[0629] Welcome to somechannel!" + // Should be nickStyle because the user didn't mention testUser and is just a normal message assertEquals("nickStyle", testPubChannel.getLineFormatter().getStyleAtPosition(11, testLine).getAttribute("name")); @@ -238,7 +242,7 @@ public void testChannelLineLimit() throws BadLocationException, InterruptedExcep while (testPubChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } // for (int i = 0; i < serverLinesLimit+10; i++) { @@ -251,8 +255,6 @@ public void testChannelLineLimit() throws BadLocationException, InterruptedExcep int channelLinesCount = testPubChannel.getLineFormatter().getDocument().getDefaultRootElement().getElementCount(); - - String firstLine = testPubChannel.getLineFormatter().getFirstLine(); String lastLine = testPubChannel.getLineFormatter().getLatestLine(); // " line # 509" @@ -280,9 +282,9 @@ public void testServerLineLimit() throws BadLocationException, InterruptedExcept testHandler.parseMessage(testMessage); } - while (testServer.messageQueueWorking()) + while (testServer.messageQueueInProgress) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } int serverLinesCount = @@ -321,7 +323,7 @@ public void urlInMessage() throws BadLocationException, InterruptedException while (testPrivChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } String testLine = testPrivChannel.getLineFormatter().getLatestLine(); // "[0629] @@ -369,7 +371,7 @@ public void channelInMessage() throws BadLocationException, InterruptedException while (testPrivChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } String testLine = testPrivChannel.getLineFormatter().getLatestLine(); diff --git a/tests/frontend/LineFormatterTests.java b/tests/frontend/LineFormatterTests.java index a28066b..4c418dd 100644 --- a/tests/frontend/LineFormatterTests.java +++ b/tests/frontend/LineFormatterTests.java @@ -74,7 +74,7 @@ public void rightClickOnNickTest () throws BadLocationException, InterruptedExce while (testPubChannel.messageQueueWorking()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } testGUI.tabbedPane.setSelectedIndex(1); diff --git a/tests/utils/TestDriverGUI.java b/tests/utils/TestDriverGUI.java index c854f6f..28dcab1 100644 --- a/tests/utils/TestDriverGUI.java +++ b/tests/utils/TestDriverGUI.java @@ -60,7 +60,7 @@ public void run() { // frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setContentPane(gui); frame.pack(); - frame.setVisible(true); + frame.setVisible(false); } }); } @@ -74,7 +74,7 @@ public static void waitForEverything (UserGUI gui) throws InterruptedException wait = false; TimeUnit.SECONDS.sleep(1); - if (gui.previewLineFormatter.updateStylesInProgress.get()) + if (gui.previewLineFormatter != null && gui.previewLineFormatter.updateStylesInProgress.get()) { log("Update styles in Progress.. waiting", true); wait = true; @@ -144,7 +144,8 @@ public void loadTestLogs (IRCChannelBase channel) throws InterruptedException int loadCount = 0; while ((line = br.readLine()) != null && loadCount < maxCount) { loadingLogsInProgress = true; - while(channel.messageQueueWorking()) + // Only wait if the queue is full + while(channel.messageQueueFull()) { System.out.println("Sleeping log loading thread."); Thread.sleep(10); From 90ce5ff80949c5f10531a70301d1d15da7291ce0 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 27 Feb 2024 06:41:58 +1000 Subject: [PATCH 06/11] Improve deletion of testing profiles during the test execution. Tightened up sleep timers. --- src/urChatBasic/backend/utils/URProfilesUtil.java | 5 ++++- tests/backend/ProfileTests.java | 6 +++--- tests/frontend/AppearanceTests.java | 6 +++++- tests/frontend/LAFTests.java | 3 +++ tests/utils/TestDriverGUI.java | 6 +++--- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/urChatBasic/backend/utils/URProfilesUtil.java b/src/urChatBasic/backend/utils/URProfilesUtil.java index 942147f..f73fa54 100644 --- a/src/urChatBasic/backend/utils/URProfilesUtil.java +++ b/src/urChatBasic/backend/utils/URProfilesUtil.java @@ -82,6 +82,7 @@ public static void deleteProfile (String profileName, boolean fireListeners) if(allProfiles.length > 1) { + Constants.BASE_PREFS.node(profileName).clear(); Constants.LOGGER.info( "Deleting profile [" + profileName + "]."); Constants.BASE_PREFS.node(profileName).removeNode(); if(fireListeners) @@ -271,7 +272,7 @@ public static void setDefaultProfile (String profileName) BASE.put(Constants.KEY_DEFAULT_PROFILE_NAME, profileName); } - public static void createProfile (String profileName) + public static String createProfile (String profileName) { int newProfileNumber = 0; String newProfileName = profileName; @@ -292,6 +293,8 @@ public static void createProfile (String profileName) Constants.LOGGER.info( "Creating new profile [" + newProfileName + "]"); setDefaultSettings(newProfileName); fireListeners(EventType.CREATE); + + return newProfileName; } private static void setDefaultSettings (String profileName) diff --git a/tests/backend/ProfileTests.java b/tests/backend/ProfileTests.java index f54a10c..f308fd9 100644 --- a/tests/backend/ProfileTests.java +++ b/tests/backend/ProfileTests.java @@ -70,7 +70,7 @@ public void createProfileAndDeleteTest () throws InterruptedException { String anotherTestProfileName = "createProfileAndDeleteTest" + (new SimpleDateFormat("yyMMdd")).format(new Date()); log("Create Profile ["+anotherTestProfileName+"]", true); - URProfilesUtil.createProfile(anotherTestProfileName); + anotherTestProfileName = URProfilesUtil.createProfile(anotherTestProfileName); log("Wait for stuff", true); TestDriverGUI.waitForEverything(TestDriverGUI.gui); @@ -133,7 +133,7 @@ public void cloneProfileTest () throws BackingStoreException, InterruptedExcepti } // Delete the cloned profile - clonedProfileRoot.removeNode(); + URProfilesUtil.deleteProfile(clonedProfileRoot.name(), false); } @Test @@ -148,6 +148,6 @@ public void switchToClonedProfileTest () throws BackingStoreException, Interrupt TestDriverGUI.waitForEverything(TestDriverGUI.gui); // Delete the cloned profile - clonedProfileRoot.removeNode(); + URProfilesUtil.deleteProfile(clonedProfileRoot.name(), false); } } diff --git a/tests/frontend/AppearanceTests.java b/tests/frontend/AppearanceTests.java index e5283f3..1f8fe63 100644 --- a/tests/frontend/AppearanceTests.java +++ b/tests/frontend/AppearanceTests.java @@ -104,6 +104,7 @@ public void changeDefaultFontAndSizeTest () throws BadLocationException, Interru assertEquals(" Welcome to " + pubChannelName, welcomeMessage); log("Check current style in the channel is correct.", true); + TestDriverGUI.waitForEverything(testGUI); URStyle channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); assertTrue(guiStyle.equals(channelStyle)); @@ -122,6 +123,8 @@ public void changeDefaultFontAndSizeTest () throws BadLocationException, Interru for (String pubChannelName : PUB_CHANNEL_NAMES) { + TestDriverGUI.waitForEverything(testGUI); + IRCChannel pubChannel = testServer.getCreatedChannel(pubChannelName); String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(13).split("] ")[1].trim(); log("Check current style has updated.", true); @@ -133,7 +136,6 @@ public void changeDefaultFontAndSizeTest () throws BadLocationException, Interru String testStyleFont = guiStyle.getFamily().get(); String channelStyleFont = channelStyle.getFamily().get(); - TestDriverGUI.waitForEverything(testGUI); log("Checking "+pubChannelName+" formatting...", true); assertEquals(pubChannelName + " font family doesn't match GUI font family.", testStyleFont, channelStyleFont); @@ -189,6 +191,8 @@ public void changeDefaultForegroundAndBackgroundTest () throws BadLocationExcept for (String pubChannelName : PUB_CHANNEL_NAMES) { + TestDriverGUI.waitForEverything(testGUI); + IRCChannel pubChannel = testServer.getCreatedChannel(pubChannelName); String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(13).split("] ")[1].trim(); log("Check current style has updated.", true); diff --git a/tests/frontend/LAFTests.java b/tests/frontend/LAFTests.java index 42c6965..e9cfda1 100644 --- a/tests/frontend/LAFTests.java +++ b/tests/frontend/LAFTests.java @@ -2,6 +2,7 @@ import static org.testng.AssertJUnit.*; import java.awt.Color; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.text.StyleConstants; import org.testng.Reporter; @@ -27,6 +28,8 @@ public void setUp() throws Exception { testDriver = new TestDriverGUI(); gui = DriverGUI.gui; + // start the gui and wait for it + SwingUtilities.invokeAndWait(gui); } @AfterClass(alwaysRun = true) diff --git a/tests/utils/TestDriverGUI.java b/tests/utils/TestDriverGUI.java index 28dcab1..534951f 100644 --- a/tests/utils/TestDriverGUI.java +++ b/tests/utils/TestDriverGUI.java @@ -31,7 +31,7 @@ public class TestDriverGUI extends DriverGUI { - final String testProfileName = "testingprofile" + (new SimpleDateFormat("yyMMddss")).format(new Date()); + String testProfileName = "testingprofile" + (new SimpleDateFormat("yyMMddss")).format(new Date()); static List testProfiles = new ArrayList<>(); static boolean loadingLogsInProgress = false; @@ -50,7 +50,7 @@ public TestDriverGUI () throws IOException, InvocationTargetException, Interrupt public void run() { frame = new JFrame("urChat"); log("Creating test profile [" + testProfileName + "]", true); - URProfilesUtil.createProfile(testProfileName); + testProfileName = URProfilesUtil.createProfile(testProfileName); testProfiles.add(testProfileName); // This will load the default profile log("Initialize test gui using test profile", true); @@ -72,7 +72,7 @@ public static void waitForEverything (UserGUI gui) throws InterruptedException while (wait) { wait = false; - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); if (gui.previewLineFormatter != null && gui.previewLineFormatter.updateStylesInProgress.get()) { From 5b051f316789cdc487c0a7ef5c6d6cad618fc21e Mon Sep 17 00:00:00 2001 From: matty-r Date: Sat, 2 Mar 2024 06:19:22 +1000 Subject: [PATCH 07/11] Update README.md --- README.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/README.md b/README.md index 50fb358..fc60026 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,38 @@ Using the testng.xml - must be in the same directory as urchat.jar Without testng.xml * java -jar urTestRunner.jar +Update History +====== + +### Update - v0.6.1 (03 FEB 24) +* Rename room to channel, everywhere + +### Update - v0.6.0 (02 FEB 24) +* Improved updateStyles performance +* Moved the Interface options panel to it's own InterfacePanel class. Rename Panels to URPanels. Move ProfilePanel and MainOptionsPanel from components to Panels. Created ConfigKeys which pairs the Preference Key to the default value in Constants. When AddToPanel is used, the appropriate preference key can be added which will then be associated with that component - this makes it easier to save the preferences instead of needing to add it for each individual component. +* Added component-label associations and fixed setting the sizes of components +* Adds a listener to Options Panels to grab the preferences as needed +* Moved the Connection stuff into its own component +* Added support for HTTP proxy, SOCKS and HTTP are now available +* Better handling of connecting to favourites +* Added an option to show tab icons +* Improved disconnection handling when connection times out, can now reconnect to the server and all open channels. +* Implemented log4j2. This raises the file size of the jar quite a bit - it may become optional at a later stage. +* Shows an error dialog if an error is received when trying to connect. + +### Update - v0.5.1 (05 JAN 24) +* Improvements made for updating styles which should lead to better performance on large chat histor + +### Update - v0.5.0 (03 JAN 24) +* Fixed a bug where saving the font didn't automatically update the Font preview +* Added an option to customise the nick format (Similar to the date format). The word nick in the Nick format text box will be replaced with the user nick, or it'll be split in half. For example: would result in the same format as <>, or <*>. But if you want a specific prefix and suffix, it's recommended to use the word nick. +* Fixed a bug with updating styles in tabs (Servers/Channels) +* Added a profiles page to better manage available profiles, such as cloning existing profiles, rename, and deleting +* A default profile can now also be set +* Saving changes to the font now only saves the difference +* Fixed a bug where changing the LAF wasn't updating the dialogs +* Add initial GitHub Actions build for Maven by @chabala in #77 + ### Update - v0.4.0 (12 DEC 23) * Added custom styling support for the different styles used in messages * Added custom Timestamp format From a6755c28b36b3ca269baee19d72b7819df4c0b0f Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 3 Mar 2024 06:54:19 +1000 Subject: [PATCH 08/11] Introduces a stylesHash in order to not waste time updating lines that already match the required styles. --- src/urChatBasic/base/IRCChannelBase.java | 4 +- src/urChatBasic/frontend/LineFormatter.java | 118 +++++++++++++++--- src/urChatBasic/frontend/UserGUI.java | 2 +- .../frontend/panels/ConnectionPanel.java | 1 + tests/frontend/AppearanceTests.java | 30 +++-- tests/frontend/LAFTests.java | 10 +- tests/frontend/LineFormatterTests.java | 2 +- .../frontend/UpdateStylesBenchmarkTests.java | 55 +++++++- 8 files changed, 190 insertions(+), 32 deletions(-) diff --git a/src/urChatBasic/base/IRCChannelBase.java b/src/urChatBasic/base/IRCChannelBase.java index 969d3d7..de0dc9c 100644 --- a/src/urChatBasic/base/IRCChannelBase.java +++ b/src/urChatBasic/base/IRCChannelBase.java @@ -188,14 +188,14 @@ private void initChannel() fontDialog = new FontDialog(channelName, gui.getStyle(), channelPrefs); - lineFormatter = new LineFormatter(getFontPanel().getStyle(), channelTextArea , getServer(), channelPrefs); + lineFormatter = new LineFormatter(getFontPanel().getStyle(), channelTextArea , channelScroll, getServer(), channelPrefs); } else { markerName = channelName; setSettingsPath(URProfilesUtil.getActiveFavouritesPath().node(channelName)); fontDialog = new FontDialog(channelName, gui.getStyle(), channelPrefs); - lineFormatter = new LineFormatter(getFontPanel().getStyle() , channelTextArea, null, channelPrefs); + lineFormatter = new LineFormatter(getFontPanel().getStyle() , channelTextArea, channelScroll, null, channelPrefs); } // Add Logging Marker diff --git a/src/urChatBasic/frontend/LineFormatter.java b/src/urChatBasic/frontend/LineFormatter.java index 4577f69..d3503f3 100644 --- a/src/urChatBasic/frontend/LineFormatter.java +++ b/src/urChatBasic/frontend/LineFormatter.java @@ -2,7 +2,9 @@ import java.awt.Color; import java.awt.Desktop; +import java.awt.Dimension; import java.awt.Font; +import java.awt.Point; import java.awt.event.ActionEvent; import java.net.URL; import java.time.Duration; @@ -22,7 +24,9 @@ import javax.swing.AbstractAction; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; import javax.swing.JTextPane; +import javax.swing.JViewport; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.text.AttributeSet; @@ -56,6 +60,7 @@ public class LineFormatter // private URStyle mediumStyle; // private URStyle lowStyle; private JTextPane docOwner; + private JScrollPane docScroller; public StyledDocument doc; // public URStyle myStyle; private Map formatterStyles = new HashMap<>(); @@ -64,12 +69,13 @@ public class LineFormatter private AtomicLong updateStylesTime = new AtomicLong(0); public AtomicBoolean updateStylesInProgress = new AtomicBoolean(false); - public LineFormatter(URStyle baseStyle, JTextPane docOwner ,final IRCServerBase server, Preferences settingsPath) + public LineFormatter(URStyle baseStyle, JTextPane docOwner ,JScrollPane docScroller, final IRCServerBase server, Preferences settingsPath) { // TODO: Need to load attributes from formatterPrefs this.settingsPath = settingsPath; this.docOwner = docOwner; + this.docScroller = docScroller; // this.docOwner.setBackground(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING)); doc = this.docOwner.getStyledDocument(); @@ -144,6 +150,42 @@ public void initStyles (URStyle baseStyle) } } + public int getStylesHash () + { + int formatterStylesHash = formatterStyles.hashCode(); + int nickFormatHash = String.join("", DriverGUI.gui.getNickFormatString("nick")).hashCode(); + int timeStampHash = DriverGUI.gui.getTimeStampString(new Date(0L)).hashCode(); + + + return formatterStylesHash + nickFormatHash + timeStampHash; + } + + class ViewPortRange { + private int start; + private int end; + + public ViewPortRange () + { + JViewport viewport = docScroller.getViewport(); + Point startPoint = viewport.getViewPosition(); + Dimension size = viewport.getExtentSize(); + Point endPoint = new Point(startPoint.x + size.width, startPoint.y + size.height); + + start = docOwner.viewToModel2D(startPoint); + end = docOwner.viewToModel2D(endPoint); + } + + public int getStart () + { + return start; + } + + public int getEnd () + { + return end; + } + } + public URStyle dateStyle(URStyle baseStyle, Date date, boolean load) { // TODO: date style can only be lowStyle or defaultStyle @@ -539,8 +581,14 @@ public URStyle getStyle(String styleName, boolean load) */ public void updateStyles (URStyle newBaseStyle) { + int lastStylesHash = getStylesHash(); + + updateStylesInProgress.set(true); + initStyles(newBaseStyle); + int currentStylesHash = getStylesHash(); + if (doc.getLength() > 0) { SwingUtilities.invokeLater(new Runnable() @@ -549,13 +597,12 @@ public void run () { try { - if(!updateStylesInProgress.get()) + if (currentStylesHash != lastStylesHash) { Constants.LOGGER.info( "Updating styles for " + settingsPath.name()); - updateStylesTime.set(Instant.now().getEpochSecond()); - updateDocStyles(0); + updateDocStyles(0, getStylesHash()); } else { - Constants.LOGGER.info( "Update already in progress."); + Constants.LOGGER.debug("NOT updating styles for " + settingsPath.name()+". Styles hash matches."); } } catch (BadLocationException e) { @@ -568,9 +615,9 @@ public void run () } } - private void updateDocStyles (int currentPosition) throws BadLocationException + private void updateDocStyles (int currentPosition, int updateHash) throws BadLocationException { - updateStylesInProgress.set(true); + updateStylesTime.set(Instant.now().getEpochSecond()); Element root = doc.getDefaultRootElement(); int lineCount = root.getElementCount(); int lineIndex = 0; @@ -593,6 +640,10 @@ private void updateDocStyles (int currentPosition) throws BadLocationException // Has style to update if (currentStyle != null && currentStyle.getAttributeCount() > 0) { + // this line has already been updated + if(currentStyle.getAttribute("stylesHash") != null && currentStyle.getAttribute("stylesHash").equals(updateHash)) + break; + int styleLength = Integer.parseInt(currentStyle.getAttribute("styleLength").toString()); String styleString = doc.getText(currentPosition, styleLength); @@ -610,8 +661,10 @@ private void updateDocStyles (int currentPosition) throws BadLocationException doc.remove(currentPosition, styleLength); currentStyle = dateStyle(currentStyle, lineDate, false); // Inserts the new timestamp, and updates the formatting + currentStyle.addAttribute("stylesHash", getStylesHash()); insertString(newTimeStamp, currentStyle, currentPosition); } else { + currentStyle.addAttribute("stylesHash", getStylesHash()); setDocAttributes(currentPosition, styleLength, currentStyle); } } else @@ -626,6 +679,7 @@ private void updateDocStyles (int currentPosition) throws BadLocationException currentStyle = dateStyle(currentStyle, lineDate, false); // Inserts the new string, and updates the formatting + currentStyle.addAttribute("stylesHash", getStylesHash()); insertString(newTimeStamp, currentStyle, currentPosition); } } @@ -773,6 +827,33 @@ public String getLatestLine() throws BadLocationException return finalLine; } + public String getLine(int lineNumber) throws BadLocationException + { + Element root = doc.getDefaultRootElement(); + int lines = root.getElementCount(); + + String finalLine = ""; + + while (finalLine.isEmpty()) + { + + if (lines < 0) + break; + + Element line = root.getElement(lineNumber); + + if (null == line) + continue; + + int start = line.getStartOffset(); + int end = line.getEndOffset(); + String text = doc.getText(start, end - start); + finalLine = text.trim(); + } + + return finalLine; + } + // New method to get line at position public String getLineAtPosition(int position) throws BadLocationException { Element root = doc.getDefaultRootElement(); @@ -798,29 +879,32 @@ public int getLineCount () return root.getElementCount(); } - private int getLinePosition(String targetLine) throws BadLocationException - { + private int getLinePosition(String targetLine) throws BadLocationException { Element root = doc.getDefaultRootElement(); int lines = root.getElementCount(); - for (int i = 0; i < lines; i++) - { + // Create a regex pattern to match the target line + Pattern pattern = Pattern.compile(".*"+Pattern.quote(targetLine.trim())+"$"); + + for (int i = 0; i < lines; i++) { Element line = root.getElement(i); - if (null == line) + if (line == null) continue; int start = line.getStartOffset(); int end = line.getEndOffset(); String text = doc.getText(start, end - start); - if (text.trim().equals(targetLine.trim())) - { + Matcher matcher = pattern.matcher(text.trim()); + + // If the pattern matches, return the start offset of the line + if (matcher.find()) { return start; } } - return 0; + return -1; // Return -1 if the target line is not found } public URStyle getStyleAtPosition(int position, String relativeLine) @@ -967,7 +1051,9 @@ public void appendMessage(Optional lineDate, IRCUser fromUser, String from { // add the date to the end of the string to preserve the timestamp of the line // when updating styles - insertPosition = addString(DriverGUI.gui.getTimeStampString(timeLine.get()) + " ", dateStyle(timePositionStyle, lineDate.get(), false), Optional.of(insertPosition)); + URStyle lineDateStyle = dateStyle(timePositionStyle, lineDate.get(), false); + lineDateStyle.addAttribute("stylesHash", getStylesHash()); + insertPosition = addString(DriverGUI.gui.getTimeStampString(timeLine.get()) + " ", lineDateStyle, Optional.of(insertPosition)); } linePositionStyle.addAttribute("type", "nickPart0"); diff --git a/src/urChatBasic/frontend/UserGUI.java b/src/urChatBasic/frontend/UserGUI.java index c00e869..d71dd5c 100644 --- a/src/urChatBasic/frontend/UserGUI.java +++ b/src/urChatBasic/frontend/UserGUI.java @@ -334,7 +334,7 @@ public void updatePreviewTextArea () // previewTextArea.setFont(clientFontPanel.getFont()); if (previewLineFormatter == null) { - previewLineFormatter = new LineFormatter(clientFontPanel.getStyle(), previewTextArea, null, URProfilesUtil.getActiveProfilePath()); + previewLineFormatter = new LineFormatter(clientFontPanel.getStyle(), previewTextArea, previewTextScroll, null, URProfilesUtil.getActiveProfilePath()); URProfilesUtil.addListener(EventType.CHANGE, e -> { previewLineFormatter.setSettingsPath(URProfilesUtil.getActiveProfilePath()); diff --git a/src/urChatBasic/frontend/panels/ConnectionPanel.java b/src/urChatBasic/frontend/panels/ConnectionPanel.java index a61c807..02c6139 100644 --- a/src/urChatBasic/frontend/panels/ConnectionPanel.java +++ b/src/urChatBasic/frontend/panels/ConnectionPanel.java @@ -243,6 +243,7 @@ public String getChannelName () public void createPopUp () { myMenu = new FavouritesPopUp(); + myMenu.setUI(new JPopupMenu().getUI()); } private class FavouritesPopUp extends JPopupMenu diff --git a/tests/frontend/AppearanceTests.java b/tests/frontend/AppearanceTests.java index 1f8fe63..feaf75b 100644 --- a/tests/frontend/AppearanceTests.java +++ b/tests/frontend/AppearanceTests.java @@ -8,6 +8,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.concurrent.TimeUnit; import javax.swing.text.BadLocationException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -34,7 +35,7 @@ public class AppearanceTests IRCServer testServer; TestDriverGUI testDriver; UserGUI testGUI; - final static int MAX_CHANNEL_NAMES = 10; + final static int MAX_CHANNEL_NAMES = 1; final static String CHANNEL_PREFIX = "#someChannel"; final List PUB_CHANNEL_NAMES = new ArrayList<>(); IRCUser testUser; @@ -100,13 +101,21 @@ public void changeDefaultFontAndSizeTest () throws BadLocationException, Interru { IRCChannel pubChannel = testServer.getCreatedChannel(pubChannelName); log("Have joined " + pubChannelName + " successfully?", true); - String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(13).split("] ")[1].trim(); + String welcomeMessage = String.join("",testGUI.getNickFormatString("someuser")) + " Welcome to " + pubChannelName; assertEquals(" Welcome to " + pubChannelName, welcomeMessage); - log("Check current style in the channel is correct.", true); + log("Wait for styles to update correctly..", true); TestDriverGUI.waitForEverything(testGUI); - URStyle channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); + URStyle channelStyle = null; + + while (channelStyle == null || !channelStyle.equals(guiStyle)) + { + TimeUnit.MILLISECONDS.sleep(10); + channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); + } + + log("Check current style in the channel is correct.", true); assertTrue(guiStyle.equals(channelStyle)); } @@ -126,10 +135,17 @@ public void changeDefaultFontAndSizeTest () throws BadLocationException, Interru TestDriverGUI.waitForEverything(testGUI); IRCChannel pubChannel = testServer.getCreatedChannel(pubChannelName); - String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(13).split("] ")[1].trim(); - log("Check current style has updated.", true); + String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(22).split("] ")[1].trim(); + log("Wait for current style has updated.", true); - URStyle channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); + URStyle channelStyle = null; + + while (channelStyle == null || !channelStyle.equals(newStyle)) + { + TimeUnit.MILLISECONDS.sleep(10); + channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); + channelStyle.removeAttribute("name"); + } log("Test Style: " + guiStyle, true); log("Channel Style: " + channelStyle, true); diff --git a/tests/frontend/LAFTests.java b/tests/frontend/LAFTests.java index e9cfda1..aca1623 100644 --- a/tests/frontend/LAFTests.java +++ b/tests/frontend/LAFTests.java @@ -2,6 +2,7 @@ import static org.testng.AssertJUnit.*; import java.awt.Color; +import java.util.concurrent.TimeUnit; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.text.StyleConstants; @@ -69,7 +70,14 @@ public void changingLAFUpdatesPreviewStyle() throws Exception TestDriverGUI.waitForEverything(gui); - Color newBackgroundColor = (Color) gui.previewLineFormatter.getStyleAtPosition(0, "urChat has loaded - this is an Event").getAttribute(StyleConstants.Background); + Color newBackgroundColor = null; + + while (newBackgroundColor == null || !newBackgroundColor.equals(UIManager.getColor(Constants.DEFAULT_BACKGROUND_STRING))) + { + TimeUnit.MILLISECONDS.sleep(10); + newBackgroundColor = (Color) gui.previewLineFormatter.getStyleAtPosition(0, "urChat has loaded - this is an Event").getAttribute(StyleConstants.Background); + } + Color lineFormatterBackground = gui.previewTextArea.getBackground(); diff --git a/tests/frontend/LineFormatterTests.java b/tests/frontend/LineFormatterTests.java index 4c418dd..ed4a08f 100644 --- a/tests/frontend/LineFormatterTests.java +++ b/tests/frontend/LineFormatterTests.java @@ -103,7 +103,7 @@ public void run() while(!canContinue.get()) { - TimeUnit.SECONDS.sleep(1); + TimeUnit.MILLISECONDS.sleep(10); } // Right-Click mouse event at the x-y coords of the caret in the text pane diff --git a/tests/frontend/UpdateStylesBenchmarkTests.java b/tests/frontend/UpdateStylesBenchmarkTests.java index 709b9d1..34b6c6c 100644 --- a/tests/frontend/UpdateStylesBenchmarkTests.java +++ b/tests/frontend/UpdateStylesBenchmarkTests.java @@ -1,14 +1,19 @@ package frontend; +import static org.junit.Assert.assertEquals; import static org.testng.Reporter.log; import java.awt.Font; import java.awt.GraphicsEnvironment; import java.time.Duration; import java.time.Instant; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Random; +import java.util.concurrent.TimeUnit; +import javax.swing.text.BadLocationException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -21,6 +26,7 @@ import urChatBasic.base.capabilities.CapabilityTypes; import urChatBasic.base.proxy.ProxyTypes; import urChatBasic.frontend.DriverGUI; +import urChatBasic.frontend.IRCChannel; import urChatBasic.frontend.IRCServer; import urChatBasic.frontend.IRCUser; import urChatBasic.frontend.UserGUI; @@ -33,7 +39,7 @@ public class UpdateStylesBenchmarkTests { IRCServer testServer; TestDriverGUI testDriver; UserGUI testGUI; - final static int MAX_CHANNEL_NAMES = 10; + final static int MAX_CHANNEL_NAMES = 1; final static String CHANNEL_PREFIX = "#someChannel"; final List PUB_CHANNEL_NAMES = new ArrayList<>(); IRCUser testUser; @@ -82,7 +88,6 @@ public void setUp () throws Exception private void logImportantInfo (String message) { importantInfo.add(message); - log(message, true); } @AfterClass(alwaysRun = true) @@ -117,7 +122,7 @@ public void changeFontBenchmark () throws InterruptedException } @Test - public void changeColoursBenchmark () throws InterruptedException + public void changeColoursBenchmark () throws InterruptedException, BadLocationException { Instant startBenchmark = Instant.now(); // Get Current Font in Appearance panel @@ -128,9 +133,51 @@ public void changeColoursBenchmark () throws InterruptedException log("Set foreground to " +URColour.hexEncode(newStyle.getForeground().get()), true); testGUI.getFontPanel().setDefaultStyle(newStyle); - TestDriverGUI.waitForEverything(testGUI); + guiStyle = testGUI.getStyle(); logImportantInfo( "Took " + Duration.between(startBenchmark, Instant.now()).toMillis() + "ms to update colours."); + + assertEquals(newStyle, guiStyle); + + for (String pubChannelName : PUB_CHANNEL_NAMES) + { + TestDriverGUI.waitForEverything(testGUI); + + IRCChannel pubChannel = testServer.getCreatedChannel(pubChannelName); + // String welcomeMessage = pubChannel.getLineFormatter().getLineAtPosition(13).split("] ")[1].trim(; + String welcomeMessage = String.join("",testGUI.getNickFormatString("someuser")) + " Welcome to " + pubChannelName; + log("Check current style has updated.", true); + + URStyle channelStyle = null; + + while (channelStyle == null || !channelStyle.equals(newStyle)) + { + TimeUnit.MILLISECONDS.sleep(10); + channelStyle = pubChannel.getLineFormatter().getStyleAtPosition(22, welcomeMessage); + } + + log("Test Style: " + guiStyle, true); + log("Channel Style: " + channelStyle, true); + + String testStyleFont = guiStyle.getFamily().get(); + String channelStyleFont = channelStyle.getFamily().get(); + log("Checking "+pubChannelName+" formatting...", true); + + assertEquals(pubChannelName + " font family doesn't match GUI font family.", testStyleFont, channelStyleFont); + + int testStyleSize = guiStyle.getSize().get(); + int channelStyleSize = channelStyle.getSize().get(); + assertEquals(pubChannelName + " font size doesn't match GUI font size.", testStyleSize, channelStyleSize); + + String testStyleForeground = URColour.hexEncode(guiStyle.getForeground().get()); + String channelStyleForeground = URColour.hexEncode(channelStyle.getForeground().get()); + assertEquals(pubChannelName + " foreground doesn't match GUI font foreground.", testStyleForeground, channelStyleForeground); + + String testStyleBackground = URColour.hexEncode(guiStyle.getBackground().get()); + String channelStyleBackground = URColour.hexEncode(channelStyle.getBackground().get()); + assertEquals(pubChannelName + " background doesn't match GUI font background.", testStyleBackground, channelStyleBackground); + + } } @Test From d3d444288b3a7bc9bfaffaadc49680a12bc3cda0 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 3 Mar 2024 07:00:51 +1000 Subject: [PATCH 09/11] Some test tweaks --- tests/backend/MessageHandlerTests.java | 2 +- tests/frontend/UpdateStylesBenchmarkTests.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/backend/MessageHandlerTests.java b/tests/backend/MessageHandlerTests.java index 2325001..38f636b 100644 --- a/tests/backend/MessageHandlerTests.java +++ b/tests/backend/MessageHandlerTests.java @@ -63,7 +63,7 @@ public void setUp() throws Exception public void tearDown () throws Exception { // Reporter.log("Deleting testing profile.", true); - testServer.quitChannels(); + // testServer.quitChannels(); // URProfilesUtil.getActiveProfilePath().sync(); // URProfilesUtil.getActiveProfilePath().sync(); URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); diff --git a/tests/frontend/UpdateStylesBenchmarkTests.java b/tests/frontend/UpdateStylesBenchmarkTests.java index 34b6c6c..5870edf 100644 --- a/tests/frontend/UpdateStylesBenchmarkTests.java +++ b/tests/frontend/UpdateStylesBenchmarkTests.java @@ -121,7 +121,7 @@ public void changeFontBenchmark () throws InterruptedException } - @Test + @Test(timeOut = 5000) public void changeColoursBenchmark () throws InterruptedException, BadLocationException { Instant startBenchmark = Instant.now(); @@ -149,7 +149,7 @@ public void changeColoursBenchmark () throws InterruptedException, BadLocationEx log("Check current style has updated.", true); URStyle channelStyle = null; - + while (channelStyle == null || !channelStyle.equals(newStyle)) { TimeUnit.MILLISECONDS.sleep(10); From 288508f3e50f3c5357c9ad040cbabfe3f75eebb7 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 4 Mar 2024 05:21:49 +1000 Subject: [PATCH 10/11] test tweaks --- tests/backend/MessageHandlerTests.java | 4 ++-- tests/frontend/AppearanceTests.java | 2 +- tests/frontend/LineFormatterTests.java | 2 +- tests/frontend/UpdateStylesBenchmarkTests.java | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/backend/MessageHandlerTests.java b/tests/backend/MessageHandlerTests.java index 38f636b..70302fa 100644 --- a/tests/backend/MessageHandlerTests.java +++ b/tests/backend/MessageHandlerTests.java @@ -63,10 +63,10 @@ public void setUp() throws Exception public void tearDown () throws Exception { // Reporter.log("Deleting testing profile.", true); - // testServer.quitChannels(); + testServer.quitChannels(); // URProfilesUtil.getActiveProfilePath().sync(); // URProfilesUtil.getActiveProfilePath().sync(); - URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); + TestDriverGUI.cleanupTestProfiles(); TestDriverGUI.closeWindow(); } diff --git a/tests/frontend/AppearanceTests.java b/tests/frontend/AppearanceTests.java index feaf75b..2d71da3 100644 --- a/tests/frontend/AppearanceTests.java +++ b/tests/frontend/AppearanceTests.java @@ -82,7 +82,7 @@ public void tearDown () throws Exception testServer.quitChannels(); // URProfilesUtil.getActiveProfilePath().sync(); // URProfilesUtil.getActiveProfilePath().sync(); - URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); + TestDriverGUI.cleanupTestProfiles(); TestDriverGUI.closeWindow(); } diff --git a/tests/frontend/LineFormatterTests.java b/tests/frontend/LineFormatterTests.java index ed4a08f..ec6d548 100644 --- a/tests/frontend/LineFormatterTests.java +++ b/tests/frontend/LineFormatterTests.java @@ -58,7 +58,7 @@ public void tearDown () throws Exception log("Quit channels", true); testServer.quitChannels(); log("Delete test profile", true); - URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); + TestDriverGUI.cleanupTestProfiles(); log("Close test window", true); TestDriverGUI.closeWindow(); } diff --git a/tests/frontend/UpdateStylesBenchmarkTests.java b/tests/frontend/UpdateStylesBenchmarkTests.java index 5870edf..6667d20 100644 --- a/tests/frontend/UpdateStylesBenchmarkTests.java +++ b/tests/frontend/UpdateStylesBenchmarkTests.java @@ -100,7 +100,7 @@ public void tearDown () throws Exception testServer.quitChannels(); // URProfilesUtil.getActiveProfilePath().sync(); // URProfilesUtil.getActiveProfilePath().sync(); - URProfilesUtil.deleteProfile(testDriver.getTestProfileName(), false); + TestDriverGUI.cleanupTestProfiles(); TestDriverGUI.closeWindow(); } From e234d37bc2c16f62aa06fe9a9e47fa039faf75e2 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 4 Mar 2024 05:27:19 +1000 Subject: [PATCH 11/11] test tweaks --- src/urChatBasic/frontend/IRCServer.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/urChatBasic/frontend/IRCServer.java b/src/urChatBasic/frontend/IRCServer.java index 7f87d3b..7663772 100644 --- a/src/urChatBasic/frontend/IRCServer.java +++ b/src/urChatBasic/frontend/IRCServer.java @@ -513,10 +513,16 @@ public void quitChannel (IRCChannelBase ircChannel) boolean tabExists = Arrays.stream(gui.tabbedPane.getComponents()).anyMatch(channel -> channel.equals(ircChannel)); + try { if (tabExists && gui.tabbedPane.getSelectedComponent().equals(ircChannel)) gui.tabbedPane.setSelectedComponent(gui.previousSelectedTab); + } catch (IllegalArgumentException iae) + { + Constants.LOGGER.debug("Previous Selected tab doesn't exist, unable to revert selection"); + } - gui.tabbedPane.remove(ircChannel); + if (tabExists) + gui.tabbedPane.remove(ircChannel); } @Override