Skip to content

Fix serial monitor timestamp print regression #8131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 36 additions & 42 deletions app/src/processing/app/AbstractTextMonitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,21 +43,18 @@ public abstract class AbstractTextMonitor extends AbstractMonitor {
protected JComboBox lineEndings;
protected JComboBox serialRates;

private SimpleDateFormat logDateFormat;

public AbstractTextMonitor(BoardPort boardPort) {
super(boardPort);
logDateFormat = new SimpleDateFormat("HH:mm:ss.SSS -> ");
}

protected void onCreateWindow(Container mainPane) {
Font consoleFont = Theme.getFont("console.font");
Font editorFont = PreferencesData.getFont("editor.font");
Font font = Theme.scale(new Font(consoleFont.getName(), consoleFont.getStyle(), editorFont.getSize()));

mainPane.setLayout(new BorderLayout());

textArea = new TextAreaFIFO(8000000);
textArea = new TextAreaFIFO(8_000_000);
textArea.setRows(16);
textArea.setColumns(40);
textArea.setEditable(false);
Expand All @@ -70,7 +67,7 @@ protected void onCreateWindow(Container mainPane) {
scrollPane = new JScrollPane(textArea);

mainPane.add(scrollPane, BorderLayout.CENTER);

JPanel upperPane = new JPanel();
upperPane.setLayout(new BoxLayout(upperPane, BoxLayout.X_AXIS));
upperPane.setBorder(new EmptyBorder(4, 4, 4, 4));
Expand Down Expand Up @@ -165,49 +162,46 @@ public void onSendCommand(ActionListener listener) {
textField.addActionListener(listener);
sendButton.addActionListener(listener);
}

public void onClearCommand(ActionListener listener) {
clearButton.addActionListener(listener);
}

public void onSerialRateChange(ActionListener listener) {
serialRates.addActionListener(listener);
}

public void message(final String s) {
SwingUtilities.invokeLater(new Runnable() {
// Pre-allocate all objects used for streaming data
Date t = new Date();
String now;
StringBuilder out = new StringBuilder(16384);
boolean isStartingLine = false;

public void run() {
if (addTimeStampBox.isSelected()) {
t.setTime(System.currentTimeMillis());
now = logDateFormat.format(t);
out.setLength(0);

StringTokenizer tokenizer = new StringTokenizer(s, "\n", true);
while (tokenizer.hasMoreTokens()) {
if (isStartingLine) {
out.append(now);
}
String token = tokenizer.nextToken();
out.append(token);
// tokenizer returns "\n" as a single token
isStartingLine = token.charAt(0) == '\n';
}

textArea.append(out.toString());
} else {
textArea.append(s);
}

if (autoscrollBox.isSelected()) {
textArea.setCaretPosition(textArea.getDocument().getLength());
}

public void message(String msg) {
SwingUtilities.invokeLater(() -> updateTextArea(msg));
}

private static final String LINE_SEPARATOR = "\n";
private boolean isStartingLine = true;

protected void updateTextArea(String msg) {
if (addTimeStampBox.isSelected()) {
textArea.append(addTimestamps(msg));
} else {
textArea.append(msg);
}
if (autoscrollBox.isSelected()) {
textArea.setCaretPosition(textArea.getDocument().getLength());
}
}

private String addTimestamps(String text) {
String now = new SimpleDateFormat("HH:mm:ss.SSS -> ").format(new Date());
final StringBuilder sb = new StringBuilder(text.length() + now.length());
StringTokenizer tokenizer = new StringTokenizer(text, LINE_SEPARATOR, true);
while (tokenizer.hasMoreTokens()) {
if (isStartingLine) {
sb.append(now);
}
});
String token = tokenizer.nextToken();
sb.append(token);
// tokenizer returns "\n" as a single token
isStartingLine = token.equals(LINE_SEPARATOR);
}
return sb.toString();
}
}
91 changes: 91 additions & 0 deletions app/test/processing/app/UpdateTextAreaActionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package processing.app;

import static org.fest.assertions.Assertions.assertThat;

import org.junit.Before;
import org.junit.Test;

import cc.arduino.packages.BoardPort;
import processing.app.helpers.PreferencesMap;

public class UpdateTextAreaActionTest {

private static final String TIMESTAMP_REGEX = "\\d\\d:\\d\\d:\\d\\d.\\d\\d\\d";

class DummyTextMonitor extends AbstractTextMonitor {
public DummyTextMonitor(BoardPort boardPort) {
super(boardPort);
}
}

@Before
public void setup() {
PreferencesData.defaults = new PreferencesMap();
PreferencesData.set("editor.font", "Monospaced,plain,12");
PreferencesData.set("gui.scale", "100");
Theme.defaults = new PreferencesMap();
Theme.table.put("console.font", "Monospaced,plain,12");
}

@Test
public void noTimestampAdded() {
DummyTextMonitor textMon = new DummyTextMonitor(new BoardPort());
textMon.addTimeStampBox.setSelected(false);

textMon.updateTextArea("line1\nline2\r\nline3");
assertThat(textMon.textArea.getText()).matches("line1\nline2\r\nline3");
}

@Test
public void all3LinesHaveTimestampAdded() {
DummyTextMonitor textMon = new DummyTextMonitor(new BoardPort());
textMon.addTimeStampBox.setSelected(true);

textMon.updateTextArea("line1\nline2\r\nline3");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> line1\\n" + //
TIMESTAMP_REGEX + " -> line2\\r\\n" + //
TIMESTAMP_REGEX + " -> line3");
}

@Test
public void emptyLinesHaveTimestampToo() {
DummyTextMonitor textMon = new DummyTextMonitor(new BoardPort());
textMon.addTimeStampBox.setSelected(true);

textMon.updateTextArea("line_1\n\nline_2");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> line_1\\n" + //
TIMESTAMP_REGEX + " -> \\n" + //
TIMESTAMP_REGEX + " -> line_2");
}

@Test
public void newLinesAreRememberedWhenNewBufferIsUsed() {
DummyTextMonitor textMon = new DummyTextMonitor(new BoardPort());
textMon.addTimeStampBox.setSelected(true);

textMon.updateTextArea("no newline");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> no newline");

textMon.updateTextArea(" more text");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> no newline more text");

textMon.updateTextArea("\n");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> no newline more text\n");

textMon.updateTextArea("\n");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> no newline more text\n" + //
TIMESTAMP_REGEX + " -> \n");

textMon.updateTextArea("third line");
assertThat(textMon.textArea.getText())
.matches(TIMESTAMP_REGEX + " -> no newline more text\n" + //
TIMESTAMP_REGEX + " -> \n" + //
TIMESTAMP_REGEX + " -> third line");
}
}