RichEdit control classes - tests.

X-SVN-Rev: 1188
This commit is contained in:
Alan Liu 2000-04-20 17:46:57 +00:00
parent 3e71bec515
commit 836a55c735
15 changed files with 4620 additions and 0 deletions

View File

@ -0,0 +1,44 @@
/*
* @(#)$RCSfile: Declaration.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.textlayout.attributes.AttributeMap;
/**
* This class contains the first four paragraphs of the Declaration
* of Independence, as both styled and unstyled text. The views
* expressed therein are not necessarily those of the programmer or of
* his/her employer. No criticism of any monarchy, oligarchy, dictatorship,
* autocracy, plutocracy, theocracy, anarchist territory, colonial power,
* or any other nondemocratic form of government is intended. This document
* is provided "as-is" without any warranty expressed or implied.
*/
public final class Declaration {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
public static final String fgDeclarationStr = "In Congress, July 4, 1776, THE UNANIMOUS DECLARATION OF THE THIRTEEN UNITED STATES OF AMERICA\n" +
"\n" +
"When in the Course of human Events, it becomes necessary for one People to dissolve the Political Bands which have connected them with another, and to assume among the Powers of the Earth, the separate and equal Station to which the Laws of Nature and of Nature's God entitle them, a decent Respect to the Opinions of Mankind requires that they should declare the causes which impel them to the Separation.\n" +
"\n" +
"We hold these Truths to be self-evident, that all Men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty, and the Pursuit of Happiness.\n" +
"\n" +
"That to secure these Rights, Governments are instituted among Men, deriving their just Powers from the Consent of the Governed, that whenever any Form of Government becomes destructive of these Ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its Foundation on such Principles, and organizing its Powers in such Form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient Causes; and accordingly all Experience hath shewn, that Mankind are more disposed to suffer, while Evils are sufferable, than to right themselves by abolishing the Forms to which they are accustomed. But when a long Train of Abuses and Usurpations, pursuing invariably the same Object, evinces a Design to reduce them under absolute Despotism, it is their Right, it is their Duty, to throw off such Government, and to provide new Guards for their future Security.\n" +
"\n";
public static final MConstText fgDeclaration = new StyledText(fgDeclarationStr, AttributeMap.EMPTY_ATTRIBUTE_MAP);
}

View File

@ -0,0 +1,214 @@
/*
* @(#)$RCSfile: ITestTextPanel.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.datatransfer.Clipboard;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.util.Date;
import java.text.DateFormat;
import com.ibm.richtext.textpanel.MTextPanel;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.awtui.TextFrame;
public class ITestTextPanel extends Frame implements ActionListener {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static long fgOpCount = 0;
private TestTextPanel fTest;
private MTextPanel fTextPanel;
private Frame fTextFrame;
private Clipboard fClipboard;
private Button fExersize, fStressTest, fResize;
public static void main(String[] args) {
Date startDate = new Date();
try {
Clipboard clipboard = new Clipboard("ITextTestPanel");
TextFrame frame = new TextFrame(null, "Interactive Test", clipboard);
MTextPanel panel = frame.getTextPanel();
new ITestTextPanel(panel, frame, clipboard).show();
}
finally {
DateFormat df = DateFormat.getDateTimeInstance();
System.out.println("Start time: " + df.format(startDate));
System.out.println("End Time: " + df.format(new Date()));
System.out.println("Op count: " + fgOpCount);
}
}
public ITestTextPanel(MTextPanel panel,
Frame frame,
Clipboard clipboard) {
fTextPanel = panel;
fTest = new TestTextPanel(fTextPanel);
fClipboard = clipboard;
setLayout(new GridLayout(0, 1));
fTextFrame = frame;
fTextFrame.setSize(350, 500);
fTextFrame.show();
// initialize UI:
fExersize = new Button("Exercise");
fExersize.addActionListener(this);
add(fExersize);
fStressTest = new Button("Stress Test");
fStressTest.addActionListener(this);
add(fStressTest);
pack();
addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
//activateTextFrame();
}
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(280, 150);
}
private void activateTextFrame() {
fTextFrame.toFront();
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
activateTextFrame();
Date startDate = new Date();
boolean exitedNormally = false;
try {
if (source == fExersize) {
fTest.incRandSeed();
for (int i=0; i < 100; i++) {
selectOperation(fTextFrame, fClipboard);
}
}
else if (source == fStressTest) {
fTest.incRandSeed();
while (true) {
selectOperation(fTextFrame, fClipboard);
}
}
exitedNormally = true;
}
finally {
if (!exitedNormally) {
DateFormat df = DateFormat.getDateTimeInstance();
System.out.println("Start time: " + df.format(startDate));
System.out.println("End Time: " + df.format(new Date()));
System.out.println("Rand seed: " + fTest.getRandSeed());
System.out.println("Op count: " + fgOpCount);
}
}
}
/**
* Perform a random operation on the MTextPanel. Frame can
* be null.
*/
private static final int OP_COUNT = 15;
public void selectOperation(Frame frame,
Clipboard fClipboard) {
int op = fTest.randInt(OP_COUNT);
switch (op) {
case 0:
fTest.testSetSelection();
break;
case 1:
fTest.testModifications(fTest.MOD_TEXT,
true);
break;
case 2:
fTest.testEditMenuOperations(fClipboard);
break;
case 3:
fTest.testModFlag(fTextPanel.getCommandLogSize());
break;
case 4:
fTest.applyCharacterStyle();
break;
case 5:
fTest.applyParagraphStyle();
break;
case 6:
case 7:
case 8:
case 9:
fTest.typeKeys();
break;
case 10:
fTest.selectText();
break;
case 11:
fTest.undoRedo();
break;
case 12:
//if (frame != null) {
// fTest.resizeFrame(frame);
// break;
//}
case 13:
fTest.applyKeyRemap();
break;
case 14:
fTest.testCommandLogControl();
break;
default:
throw new Error("OP_COUNT is incorrect");
}
fgOpCount++;
}
}

View File

@ -0,0 +1,823 @@
/*
* @(#)$RCSfile: TestTextPanel.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.util.Random;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import com.ibm.richtext.textpanel.KeyRemap;
import com.ibm.richtext.textpanel.KeyEventForwarder;
import com.ibm.richtext.textpanel.MTextPanel;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.textpanel.TextPanelEvent;
import com.ibm.richtext.textpanel.TextPanelListener;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.richtext.styledtext.StyleModifier;
import com.ibm.textlayout.attributes.AttributeSet;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.AttributeMap;
public final class TestTextPanel {
private final class TestListener implements TextPanelListener {
private int NO_WAY = 0;
private int DEFINITELY = 1;
private int MAYBE = 2;
private final int[] status;
TestListener(MTextPanel textPanel) {
int length = TextPanelEvent.TEXT_PANEL_LAST -
TextPanelEvent.TEXT_PANEL_FIRST + 1;
status = new int[length];
textPanel.addListener(this);
allowAll();
}
void refuseAll() {
for (int i=0; i < status.length; i++) {
status[i] = NO_WAY;
}
}
void allowAll() {
for (int i=0; i < status.length; i++) {
status[i] = MAYBE;
}
}
void expectEvent(int type) {
int index = type - TextPanelEvent.TEXT_PANEL_FIRST;
status[index] = DEFINITELY;
}
void allowEvent(int type) {
int index = type - TextPanelEvent.TEXT_PANEL_FIRST;
status[index] = MAYBE;
}
void assertNotExpectingEvents() {
boolean e = false;
for (int i=0; i < status.length; i++) {
if (status[i] == DEFINITELY) {
System.out.println("Expecting event " +
(i+TextPanelEvent.TEXT_PANEL_FIRST));
e = true;
}
}
if (e) {
throw new Error("Some events pending");
}
}
public void textEventOccurred(TextPanelEvent event) {
int index = event.getID() - TextPanelEvent.TEXT_PANEL_FIRST;
if (status[index] == NO_WAY) {
throw new Error("Unexpected event: " + event);
}
else if (status[index] == DEFINITELY) {
status[index] = NO_WAY;
}
}
public boolean respondsToEventType(int type) {
return true;
}
}
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static final String STRING_CONTENT = "Some content";
private static final int TEST_ITERS = 2;
public static final MConstText MOD_TEXT =
new StyledText("Styled", AttributeMap.EMPTY_ATTRIBUTE_MAP);
private Clipboard fClipboard;
private MTextPanel fTextPanel = null;
private TestListener fListener = null;
private int fRandSeed = 0;
private Random rand;
private static final int BIG_COMMAND_LOG_SIZE = 40;
private static final int SMALL_COMMAND_LOG_SIZE = 8;
private static final StyleModifier[] paraMods = {
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_LEADING)),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_CENTER),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_TRAILING),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FULLY_JUSTIFIED),
StyleModifier.createAddModifier(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL),
StyleModifier.createAddModifier(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_LTR),
StyleModifier.createRemoveModifier(
new AttributeSet(TextAttribute.LINE_FLUSH)),
StyleModifier.createRemoveModifier(
new AttributeSet(TextAttribute.RUN_DIRECTION))
};
private static final int SELECT = 0;
private static final int SET_CARET_POS = 1;
private static final int SET_START = 2;
private static final int SET_END = 3;
// using both styles of add modifier: AttributeMap and
// key-value, just for variety...
private static final StyleModifier[] charMods = {
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD)),
StyleModifier.createAddModifier(TextAttribute.FOREGROUND,
Color.green),
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.UNDERLINE,
TextAttribute.UNDERLINE_ON).addAttributes(
new AttributeMap(TextAttribute.SIZE, new Float(6)))),
StyleModifier.createReplaceModifier(
new AttributeMap(TextAttribute.FAMILY, "Dialog")),
StyleModifier.createRemoveModifier(
new AttributeSet(
new Object[] { TextAttribute.WEIGHT,
TextAttribute.POSTURE,
TextAttribute.UNDERLINE,
TextAttribute.STRIKETHROUGH,
TextAttribute.SUPERSCRIPT })),
StyleModifier.IDENTITY
};
private static final char[] TYPED_CHARS = new char[128 - ' ' + 3];
static {
TYPED_CHARS[0] = 8; // backspace
TYPED_CHARS[1] = '\t';
TYPED_CHARS[2] = '\n';
for (int i=3; i < TYPED_CHARS.length; i++) {
TYPED_CHARS[i] = (char) (' ' + i - 3);
}
}
public static void main(String[] args) {
new TestTextPanel().test();
System.out.println("TextPanelTest PASSED");
}
public TestTextPanel() {
fClipboard = new Clipboard("TestTextPanel");
incRandSeed();
}
public TestTextPanel(MTextPanel panel) {
this();
setTextPanel(panel);
}
void incRandSeed() {
rand = new Random(++fRandSeed);
}
int getRandSeed() {
return fRandSeed;
}
int randInt(int limit) {
return randInt(0, limit);
}
int randInt(int start, int limit) {
if (start > limit) {
throw new IllegalArgumentException("Range is 0-length.");
}
else if (start == limit) {
return start;
}
return start + (Math.abs(rand.nextInt())%(limit-start)) ;
}
public void test() {
AttributeMap bold = new AttributeMap(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD);
MConstText text1 = new StyledText("Test contents. 1234\nHow about it?",
AttributeMap.EMPTY_ATTRIBUTE_MAP);
MConstText text2 = new StyledText("Another test string.", bold);
testWithText(text1);
testWithText(text2);
testWithText(new StyledText());
StyledText big1 = new StyledText();
for (int i=0; i < 50; i++) {
big1.append(text1);
}
testWithText(big1);
StyledText big2 = new StyledText(text1);
for (int i=0; i < 80; i++) {
big2.append(text2);
}
testWithText(big2);
}
private void setTextPanel(MTextPanel panel) {
fTextPanel = panel;
fListener = new TestListener(panel);
}
private void testWithText(MConstText text) {
setTextPanel(new TextPanel(text, fClipboard));
for (int i=0; i < TEST_ITERS; i++) {
testSetSelection();
testModifications(MOD_TEXT, true);
testEditMenuOperations(fClipboard);
testModFlag(fTextPanel.getCommandLogSize());
testCommandLogControl();
}
}
private void testSelection(int function,
final int aStart,
final int aLimit) {
int oldStart = fTextPanel.getSelectionStart();
int oldLimit = fTextPanel.getSelectionEnd();
final int length = fTextPanel.getTextLength();
int start = aStart;
int limit = aLimit;
if (start < 0) {
start = 0;
}
else if (start > length) {
start = length;
}
if (limit < start) {
limit = start;
}
else if (limit > length) {
limit = length;
}
fListener.refuseAll();
if (oldStart != start || oldLimit != limit) {
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
}
if ((oldStart==oldLimit) != (start==limit)) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
if (oldStart==oldLimit) {
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
}
switch(function) {
case SELECT:
fTextPanel.select(aStart, aLimit);
break;
case SET_CARET_POS:
fTextPanel.setCaretPosition(aStart);
break;
case SET_START:
fTextPanel.setSelectionStart(aStart);
break;
case SET_END:
fTextPanel.setSelectionEnd(aLimit);
break;
default:
throw new IllegalArgumentException("Invalid function");
}
if (fTextPanel.getSelectionStart() != start) {
throw new Error("getSelectionStart is incorrect after set");
}
if (fTextPanel.getSelectionEnd() != limit) {
throw new Error("getSelectionEnd is incorrect after set");
}
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
private void setAndTestSelection(int start, int limit) {
testSelection(SELECT, start, limit);
}
private void setAndTestCaret(int caretPos) {
testSelection(SET_CARET_POS, caretPos, caretPos);
}
private void setAndTestSelectionStart(int selStart) {
int limit = fTextPanel.getSelectionEnd();
testSelection(SET_START, selStart, limit);
}
private void setAndTestSelectionEnd(int selEnd) {
int start = fTextPanel.getSelectionStart();
testSelection(SET_END, start, selEnd);
}
public void testSetSelection() {
int textLength = fTextPanel.getTextLength();
if (textLength != fTextPanel.getText().length()) {
throw new Error("Text panel length is not correct");
}
setAndTestSelection(0, textLength / 2);
setAndTestSelection(textLength / 2, textLength);
setAndTestSelection(0, textLength);
setAndTestSelection(-1, textLength+1);
if (textLength > 0) {
setAndTestSelection(0, textLength - 1);
setAndTestSelection(0, 1);
}
final int incAmount = Math.max(1, textLength/5);
for (int index = 0; index <= textLength; index += incAmount) {
setAndTestCaret(index);
setAndTestSelectionStart(textLength-index);
setAndTestSelectionEnd(textLength);
setAndTestSelectionStart(0);
setAndTestSelectionEnd(textLength-index);
}
}
/**
* Text must be editable to pass this test.
*/
public void testModifications(MConstText insertionText,
boolean restoreOldText) {
MConstText oldText = new StyledText(fTextPanel.getText());
final int insLength = insertionText.length();
fListener.allowAll();
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fTextPanel.append(insertionText);
fListener.assertNotExpectingEvents();
if (fTextPanel.getSelectionStart() != oldText.length() + insLength) {
throw new Error("Append didn't result in correct selection");
}
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fTextPanel.insert(insertionText, 0);
fListener.assertNotExpectingEvents();
fListener.allowAll();
if (fTextPanel.getSelectionStart() != insLength) {
throw new Error("Insert didn't result in correct selection");
}
fTextPanel.replaceRange(insertionText, insLength, insLength+oldText.length());
if (fTextPanel.getSelectionStart() != insLength*2) {
throw new Error("Replace didn't result in correct selection");
}
if (fTextPanel.getSelectionEnd() != insLength*2) {
throw new Error("Replace didn't result in correct selection");
}
if (fTextPanel.getTextLength() != insLength*3) {
throw new Error("textLength is incorrect");
}
if (restoreOldText) {
fTextPanel.setText(oldText);
if (fTextPanel.getSelectionStart() != oldText.length()) {
throw new Error("setText didn't result in correct selection");
}
if (fTextPanel.getTextLength() != oldText.length()) {
throw new Error("length incorrect after setText");
}
}
fListener.allowAll();
}
private static int iterationCount = 0;
public void testCommandLogControl() {
fListener.refuseAll();
iterationCount++;
boolean exp = false;
if (fTextPanel.canRedo() || BIG_COMMAND_LOG_SIZE==0) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
exp = true;
}
try {
fTextPanel.setCommandLogSize(BIG_COMMAND_LOG_SIZE);
if (fTextPanel.canRedo()) {
throw new Error("canRedo after setCommandLogSize");
}
fListener.assertNotExpectingEvents();
}
catch(Error e) {
System.out.println("iterationCount="+iterationCount+"; expexting="+exp);
throw e;
}
MConstText insText = new StyledText("7",
AttributeMap.EMPTY_ATTRIBUTE_MAP);
final int origLength = fTextPanel.getTextLength();
int start = origLength / 3;
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
for (int i=start; i < BIG_COMMAND_LOG_SIZE+start; i++) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
fTextPanel.insert(insText, i);
fListener.assertNotExpectingEvents();
}
fListener.allowEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
for (int i=0; i < BIG_COMMAND_LOG_SIZE-1; i++) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fTextPanel.undo();
fListener.assertNotExpectingEvents();
}
if (!fTextPanel.canUndo()) {
throw new Error("Command log is too small");
}
fListener.allowAll();
fTextPanel.undo();
if (fTextPanel.canUndo()) {
throw new Error("Command log is too large");
}
if (fTextPanel.getTextLength() != origLength * insText.length()) {
throw new Error("Text length was not restored");
}
for (int i=0; i < BIG_COMMAND_LOG_SIZE; i++) {
fTextPanel.redo();
}
if (fTextPanel.getTextLength() != origLength+BIG_COMMAND_LOG_SIZE) {
throw new Error("Text length was not restored after redo");
}
if (fTextPanel.canRedo()) {
throw new Error("Should not be able to redo");
}
fTextPanel.undo();
fTextPanel.setCommandLogSize(SMALL_COMMAND_LOG_SIZE);
if (fTextPanel.canRedo()) {
throw new Error("canRedo after setCommandLogSize(small)");
}
for (int i=0; i < SMALL_COMMAND_LOG_SIZE; i++) {
if (!fTextPanel.canUndo()) {
throw new Error("should be able to undo");
}
fTextPanel.undo();
}
if (fTextPanel.canUndo()) {
throw new Error("should not be able to undo after setCommandLogSize(small)");
}
if (!fTextPanel.canRedo()) {
throw new Error("why can't this redo???");
}
fTextPanel.redo();
fTextPanel.clearCommandLog();
if (fTextPanel.canUndo() || fTextPanel.canRedo()) {
throw new Error("Command log wasn't cleared");
}
}
/**
* Test cut, copy, paste, undo, redo, clear, canUndo, canRedo.
* Text must be editable to pass this test.
*/
public void testEditMenuOperations(Clipboard clipboard) {
if (clipboard != null) {
// test paste and undo / redo
Transferable tr = new StringSelection(STRING_CONTENT);
clipboard.setContents(tr, new ClipboardOwner() {
public void lostOwnership(Clipboard c, Transferable t) {
}
});
if (!fTextPanel.clipboardNotEmpty()) {
throw new Error("MTextPanel doesn't recognize string content.");
}
fTextPanel.setCaretPosition(fTextPanel.getSelectionStart());
int oldLength = fTextPanel.getTextLength();
fTextPanel.paste();
if (fTextPanel.getTextLength() != oldLength + STRING_CONTENT.length()) {
throw new Error("Text length is wrong after paste.");
}
if (!fTextPanel.canUndo()) {
throw new Error("canUndo should be true");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != oldLength) {
throw new Error("Length is wrong after undo");
}
if (!fTextPanel.canRedo()) {
throw new Error("canRedo should be true");
}
fTextPanel.redo();
if (fTextPanel.getTextLength() != oldLength + STRING_CONTENT.length()) {
throw new Error("Text length is wrong after redo.");
}
}
int origLength = fTextPanel.getTextLength();
fTextPanel.selectAll();
fTextPanel.clear();
if (fTextPanel.getTextLength() != 0) {
throw new Error("Length is nonzero after clear");
}
if (!fTextPanel.canUndo()) {
throw new Error("canUndo should be true");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Old text not restored");
}
if (origLength > 0) {
fTextPanel.select(0, 1);
fTextPanel.cut();
if (fTextPanel.getTextLength() != origLength-1) {
throw new Error("Length wrong after cut");
}
fTextPanel.paste();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Length wrong after paste");
}
fTextPanel.select(0, origLength);
fTextPanel.copy();
fTextPanel.setCaretPosition(0);
fTextPanel.paste();
if (fTextPanel.getTextLength() != 2*origLength) {
throw new Error("Length wrong after paste");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Length wrong after undo");
}
}
}
private void setAndTestModFlag(final int depth,
boolean modified) {
fTextPanel.setModified(modified);
for (int i=0; i < depth; i++) {
if (!fTextPanel.canUndo()) {
throw new Error("Panel cannot undo at valid depth. Depth=" + i);
}
fTextPanel.undo();
fTextPanel.setModified(modified);
}
// check that all mod flags are false:
if (fTextPanel.isModified() != modified) {
throw new Error("isModified is not correct");
}
for (int i=0; i < depth; i++) {
fTextPanel.redo();
if (fTextPanel.isModified() != modified) {
throw new Error("isModified is not correct");
}
}
}
/**
* Make <code>depth</code> modifications to the text in textfTextPanel.
* Set the modified flag on each operation, and then retrieve its
* value. Finally, undo the modifications.
*/
public void testModFlag(final int depth) {
final int oldLength = fTextPanel.getTextLength();
for (int i=0; i < depth; i++) {
fTextPanel.insert(MOD_TEXT, 0);
}
setAndTestModFlag(depth, false);
setAndTestModFlag(depth, true);
for (int i=0; i < depth; i++) {
fTextPanel.undo();
}
if (fTextPanel.getTextLength() != oldLength) {
throw new Error("Undo did not restore old text.");
}
}
void applyCharacterStyle() {
StyleModifier stMod = charMods[randInt(charMods.length)];
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fTextPanel.modifyCharacterStyleOnSelection(stMod);
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void applyParagraphStyle() {
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
StyleModifier stMod = paraMods[randInt(paraMods.length)];
fTextPanel.modifyParagraphStyleOnSelection(stMod);
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void applyKeyRemap() {
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.KEYREMAP_CHANGED);
int op = randInt(5);
switch (op) {
case 0:
fTextPanel.setKeyRemap(KeyRemap.getIdentityRemap());
break;
case 1:
fTextPanel.setKeyRemap(KeyRemap.getArabicTransliteration());
break;
case 2:
fTextPanel.setKeyRemap(KeyRemap.getHebrewTransliteration());
break;
case 3:
fTextPanel.setKeyRemap(KeyRemap.getIsraelNikud());
break;
case 4:
//fTextPanel.setKeyRemap(KeyRemap.getThaiKetmanee());
fTextPanel.setKeyRemap(KeyRemap.getIsraelNikud());
break;
default:
throw new Error("Invalid operation!");
}
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void resizeFrame(Frame frame) {
fListener.refuseAll();
fListener.allowEvent(TextPanelEvent.FORMAT_WIDTH_CHANGED);
int wd = randInt(50, 1000);
int ht = randInt(20, 800);
frame.setSize(wd, ht);
fListener.allowAll();
}
void selectText() {
int selStart = randInt(-10, fTextPanel.getTextLength());
int selLimit = randInt(0, fTextPanel.getTextLength() + 10);
testSelection(SELECT, selStart, selLimit);
}
void undoRedo() {
final int opCount = randInt(-10, 15);
for (int i=opCount; i <= 0; i++) {
fTextPanel.redo();
}
for (int i=0; i < opCount; i++) {
fTextPanel.undo();
}
}
void typeKeys() {
final int keyCount = randInt(1, 100);
TextPanel textPanel = (TextPanel) fTextPanel;
KeyEventForwarder forwarder = new KeyEventForwarder(textPanel);
fListener.refuseAll();
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
for (int i=0; i < keyCount; i++) {
char typedChar = TYPED_CHARS[randInt(TYPED_CHARS.length)];
KeyEvent event = new KeyEvent(textPanel,
KeyEvent.KEY_TYPED,
0,
0,
KeyEvent.VK_UNDEFINED,
typedChar);
if (typedChar == 8 || typedChar == 0x7f) {
fListener.allowEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
else {
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
forwarder.handleKeyEvent(event);
try {
fListener.assertNotExpectingEvents();
}
catch(Error e) {
System.out.println("i="+i+"; typedChar="+Integer.toHexString(typedChar));
throw e;
}
}
fListener.allowAll();
}
}

View File

@ -0,0 +1,227 @@
/*
* @(#)$RCSfile: TypingPerfTest.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.awt.Button;
import java.awt.GridLayout;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import com.ibm.richtext.textpanel.KeyEventForwarder;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.awtui.TextFrame;
public class TypingPerfTest implements ActionListener {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private TextFrame fTextFrame;
private KeyEventForwarder fKeyEventForwarder;
private PrintWriter fOut;
private static final String fgAtStartCommand = "Insert at start";
private static final String fgAtEndCommand = "Insert at end";
private static final String fgFwdDelete = "Forward delete";
private static final String fgBackspace = "Backspace";
private static final String fgAtCurrentPosCommand = "Insert at current position";
private static final String fgLotsOfTextCommand = "Insert a lot of text";
private static final char[] fgInsText =
"The quick brown fox jumps over the lazy dog. The end.".toCharArray();
public static void main(String[] args) {
OutputStream outStream = null;
PrintWriter writer;
try {
if (args.length == 1) {
outStream = new FileOutputStream(args[0], true);
writer = new PrintWriter(outStream);
}
else {
writer = new PrintWriter(System.out);
}
new TypingPerfTest(writer);
}
catch(IOException e) {
System.out.println("Caught exception: " + e);
}
}
public TypingPerfTest(PrintWriter out) throws IOException {
fTextFrame = new TextFrame(Declaration.fgDeclaration, "", null);
TextPanel textPanel = (TextPanel) fTextFrame.getTextPanel();
fKeyEventForwarder = new KeyEventForwarder(textPanel);
fOut = out;
DateFormat df = DateFormat.getDateTimeInstance();
out.println("Test date: " + df.format(new Date()));
fTextFrame.setSize(500, 700);
fTextFrame.show();
Frame f = new Frame("Typing Perf Test");
f.setLayout(new GridLayout(0, 1));
Button b;
/*
b = new Button(fgAtStartCmd);
b.addActionListener(this);
f.add(b);
b = new Button(fgAtEndCmd);
b.addActionListener(this);
f.add(b);
*/
b = new Button(fgAtCurrentPosCommand);
b.addActionListener(this);
f.add(b);
b = new Button(fgLotsOfTextCommand);
b.addActionListener(this);
f.add(b);
b = new Button(fgFwdDelete);
b.addActionListener(this);
f.add(b);
b = new Button(fgBackspace);
b.addActionListener(this);
f.add(b);
f.doLayout();
WindowAdapter closer = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
fOut.close();
System.exit(0);
}
};
f.addWindowListener(closer);
fTextFrame.addWindowListener(closer);
f.setSize(200, 80);
f.show();
}
public void actionPerformed(ActionEvent evt) {
try {
if (evt.getActionCommand().equals(fgAtCurrentPosCommand)) {
insertAtCurrentPos(1);
}
else if (evt.getActionCommand().equals(fgLotsOfTextCommand)) {
insertAtCurrentPos(8);
}
else if (evt.getActionCommand().equals(fgFwdDelete)) {
forwardDelete(1);
}
else if (evt.getActionCommand().equals(fgBackspace)) {
backspace(1);
}
}
catch(IOException e) {
System.out.println("Caught exception: " + e);
}
}
private void insertAtCurrentPos(final int times) throws IOException {
//EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
fTextFrame.toFront();
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, KeyEvent.KEY_TYPED, 0, 0, 0, fgInsText[i]);
fKeyEventForwarder.handleKeyEvent(event);
//eventQueue.postEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
private void forwardDelete(final int times) throws IOException {
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, 0, 0, 0, KeyEvent.VK_DELETE, '\u00FF');
fKeyEventForwarder.handleKeyEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
private void backspace(final int times) throws IOException {
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, 0, 0, 0, KeyEvent.VK_BACK_SPACE, '\u0010');
fKeyEventForwarder.handleKeyEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
}

View File

@ -0,0 +1,44 @@
/*
* @(#)$RCSfile: Declaration.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.textlayout.attributes.AttributeMap;
/**
* This class contains the first four paragraphs of the Declaration
* of Independence, as both styled and unstyled text. The views
* expressed therein are not necessarily those of the programmer or of
* his/her employer. No criticism of any monarchy, oligarchy, dictatorship,
* autocracy, plutocracy, theocracy, anarchist territory, colonial power,
* or any other nondemocratic form of government is intended. This document
* is provided "as-is" without any warranty expressed or implied.
*/
public final class Declaration {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
public static final String fgDeclarationStr = "In Congress, July 4, 1776, THE UNANIMOUS DECLARATION OF THE THIRTEEN UNITED STATES OF AMERICA\n" +
"\n" +
"When in the Course of human Events, it becomes necessary for one People to dissolve the Political Bands which have connected them with another, and to assume among the Powers of the Earth, the separate and equal Station to which the Laws of Nature and of Nature's God entitle them, a decent Respect to the Opinions of Mankind requires that they should declare the causes which impel them to the Separation.\n" +
"\n" +
"We hold these Truths to be self-evident, that all Men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty, and the Pursuit of Happiness.\n" +
"\n" +
"That to secure these Rights, Governments are instituted among Men, deriving their just Powers from the Consent of the Governed, that whenever any Form of Government becomes destructive of these Ends, it is the Right of the People to alter or to abolish it, and to institute new Government, laying its Foundation on such Principles, and organizing its Powers in such Form, as to them shall seem most likely to effect their Safety and Happiness. Prudence, indeed, will dictate that Governments long established should not be changed for light and transient Causes; and accordingly all Experience hath shewn, that Mankind are more disposed to suffer, while Evils are sufferable, than to right themselves by abolishing the Forms to which they are accustomed. But when a long Train of Abuses and Usurpations, pursuing invariably the same Object, evinces a Design to reduce them under absolute Despotism, it is their Right, it is their Duty, to throw off such Government, and to provide new Guards for their future Security.\n" +
"\n";
public static final MConstText fgDeclaration = new StyledText(fgDeclarationStr, AttributeMap.EMPTY_ATTRIBUTE_MAP);
}

View File

@ -0,0 +1,214 @@
/*
* @(#)$RCSfile: ITestTextPanel.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.awt.Button;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.datatransfer.Clipboard;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;
import java.util.Date;
import java.text.DateFormat;
import com.ibm.richtext.textpanel.MTextPanel;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.awtui.TextFrame;
public class ITestTextPanel extends Frame implements ActionListener {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static long fgOpCount = 0;
private TestTextPanel fTest;
private MTextPanel fTextPanel;
private Frame fTextFrame;
private Clipboard fClipboard;
private Button fExersize, fStressTest, fResize;
public static void main(String[] args) {
Date startDate = new Date();
try {
Clipboard clipboard = new Clipboard("ITextTestPanel");
TextFrame frame = new TextFrame(null, "Interactive Test", clipboard);
MTextPanel panel = frame.getTextPanel();
new ITestTextPanel(panel, frame, clipboard).show();
}
finally {
DateFormat df = DateFormat.getDateTimeInstance();
System.out.println("Start time: " + df.format(startDate));
System.out.println("End Time: " + df.format(new Date()));
System.out.println("Op count: " + fgOpCount);
}
}
public ITestTextPanel(MTextPanel panel,
Frame frame,
Clipboard clipboard) {
fTextPanel = panel;
fTest = new TestTextPanel(fTextPanel);
fClipboard = clipboard;
setLayout(new GridLayout(0, 1));
fTextFrame = frame;
fTextFrame.setSize(350, 500);
fTextFrame.show();
// initialize UI:
fExersize = new Button("Exercise");
fExersize.addActionListener(this);
add(fExersize);
fStressTest = new Button("Stress Test");
fStressTest.addActionListener(this);
add(fStressTest);
pack();
addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) {
//activateTextFrame();
}
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
setSize(280, 150);
}
private void activateTextFrame() {
fTextFrame.toFront();
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
activateTextFrame();
Date startDate = new Date();
boolean exitedNormally = false;
try {
if (source == fExersize) {
fTest.incRandSeed();
for (int i=0; i < 100; i++) {
selectOperation(fTextFrame, fClipboard);
}
}
else if (source == fStressTest) {
fTest.incRandSeed();
while (true) {
selectOperation(fTextFrame, fClipboard);
}
}
exitedNormally = true;
}
finally {
if (!exitedNormally) {
DateFormat df = DateFormat.getDateTimeInstance();
System.out.println("Start time: " + df.format(startDate));
System.out.println("End Time: " + df.format(new Date()));
System.out.println("Rand seed: " + fTest.getRandSeed());
System.out.println("Op count: " + fgOpCount);
}
}
}
/**
* Perform a random operation on the MTextPanel. Frame can
* be null.
*/
private static final int OP_COUNT = 15;
public void selectOperation(Frame frame,
Clipboard fClipboard) {
int op = fTest.randInt(OP_COUNT);
switch (op) {
case 0:
fTest.testSetSelection();
break;
case 1:
fTest.testModifications(fTest.MOD_TEXT,
true);
break;
case 2:
fTest.testEditMenuOperations(fClipboard);
break;
case 3:
fTest.testModFlag(fTextPanel.getCommandLogSize());
break;
case 4:
fTest.applyCharacterStyle();
break;
case 5:
fTest.applyParagraphStyle();
break;
case 6:
case 7:
case 8:
case 9:
fTest.typeKeys();
break;
case 10:
fTest.selectText();
break;
case 11:
fTest.undoRedo();
break;
case 12:
//if (frame != null) {
// fTest.resizeFrame(frame);
// break;
//}
case 13:
fTest.applyKeyRemap();
break;
case 14:
fTest.testCommandLogControl();
break;
default:
throw new Error("OP_COUNT is incorrect");
}
fgOpCount++;
}
}

View File

@ -0,0 +1,33 @@
/*
* @(#)$RCSfile: TestAll.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
public class TestAll {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
public static void main(String[] args) {
TestAttributeSet.main(args);
TestAttributeMap.main(args);
TestFormatter.main(args);
TestMText.main(args);
TestMTextStreaming.main(args);
TestParagraphStyles.main(args);
TestTextPanel.main(args);
System.out.println("TestAll: DONE");
}
}

View File

@ -0,0 +1,412 @@
/*
* @(#)$RCSfile: TestAttributeMap.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
//import java.util.Hashtable;
import com.ibm.textlayout.attributes.AttributeSet;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.Map;
import com.ibm.textlayout.attributes.AttributeMap;
import java.util.Enumeration;
public class TestAttributeMap {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private AttributeSet maps; // A Set of AttributeMaps
private AttributeSet sets; // A Set of Sets
private static final class TestAttribute extends TextAttribute {
TestAttribute(String name) {
super(name);
}
}
private static final TestAttribute[] attributes = {
new TestAttribute("0"), new TestAttribute("1"), new TestAttribute("2")
};
private static final Object[] values = {
"Hello world", new Float(-42), new Object(), new AttributeMap(new TestAttribute("3"), "HH")
};
/**
* If the test fails an exception will propogate out of main.
*/
public static void main(String[] args) {
new TestAttributeMap().test();
System.out.println("PASSED");
}
/**
* Returns lhs.equals(rhs) - but also checks for symmetry, and
* consistency with hashCode().
*/
private static boolean equalMaps(AttributeMap lhs, Object rhs) {
boolean equal = lhs.equals(rhs);
if (equal != (rhs.equals(lhs))) {
throw new Error("AttributeMap.equals is not symetric");
}
if (equal) {
if (lhs.hashCode() != rhs.hashCode()) {
throw new Error("AttributeMaps are equal but hashCodes differ");
}
}
return equal;
}
public TestAttributeMap() {
maps = AttributeSet.EMPTY_SET;
maps = maps.addElement(AttributeMap.EMPTY_ATTRIBUTE_MAP);
maps.addElement(new AttributeMap(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB));
maps.addElement(new AttributeMap(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER));
for (int i=0; i < attributes.length; i++) {
for (int j=0; j < values.length; j++) {
maps = maps.addElement(new AttributeMap(attributes[i], values[j]));
}
}
AttributeMap bigMap = new AttributeMap(new TestAttribute("4"), "value");
for (int i=0; i < Math.min(attributes.length, values.length); i++) {
bigMap = bigMap.addAttribute(attributes[i], values[values.length-i-1]);
}
maps = maps.addElement(bigMap);
sets = AttributeSet.EMPTY_SET;
sets = new AttributeSet(AttributeSet.EMPTY_SET);
for (int i=0; i < attributes.length; i++) {
AttributeSet newSet = new AttributeSet(attributes[i]);
sets = sets.addElement(newSet);
}
AttributeSet allAttrs = AttributeSet.EMPTY_SET;
for (int i=0; i < attributes.length; i++) {
allAttrs = allAttrs.addElement(attributes[i]);
}
sets = sets.addElement(allAttrs);
}
/**
* Run tests on AttributeMap. If a test fails an exception will propogate out
* of this method.
*/
public void test() {
easyTests();
//onlyAttributeKeyTests();
Enumeration mapIter = maps.elements();
while (mapIter.hasMoreElements()) {
AttributeMap testMap = (AttributeMap) mapIter.nextElement();
testModifiers(testMap);
testViews(testMap);
Enumeration unionIter = maps.elements();
while (unionIter.hasMoreElements()) {
testUnionWith(testMap, (AttributeMap) unionIter.nextElement());
}
Enumeration setIter = sets.elements();
while (setIter.hasMoreElements()) {
AttributeSet testSet = (AttributeSet) setIter.nextElement();
testIntersectWith(testMap, testSet);
testRemoveAttributes(testMap, testSet);
}
}
}
/**
* Invoke modifiers on map. All should throw
* UnsupportedOperationException, and leave map unmodified.
*/
public static void testModifiers(AttributeMap map) {
/*
AttributeMap originalMap = new AttributeMap(map);
try {
map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
throw new Error("Put should throw UnsupportedOperationException.");
}
catch(UnsupportedOperationException e) {
}
try {
Object key = TextAttribute.WEIGHT;
Iterator iter = map.keySet().iterator();
if (iter.hasNext()) {
key = iter.next();
}
map.remove(key);
throw new Error("Set should throw UnsupportedOperationException.");
}
catch(UnsupportedOperationException e) {
}
try {
map.putAll(map);
throw new Error("putAll should throw UnsupportedOperationException.");
}
catch(UnsupportedOperationException e) {
}
try {
map.clear();
throw new Error("clear should throw UnsupportedOperationException.");
}
catch(UnsupportedOperationException e) {
}
if (!originalMap.equals(map)) {
throw new Error("Modifiers changed map.");
}
*/
}
/**
* Ensure that map.addAttributes(addMap) is equivalent to calling
* map.add on all of addMap's entries.
*/
public static void testUnionWith(AttributeMap map, AttributeMap addMap) {
AttributeMap lhs = map.addAttributes(addMap);
AttributeMap rhs = map;
Enumeration iter = addMap.getKeySet().elements();
while (iter.hasMoreElements()) {
Object attr = iter.nextElement();
Object value = addMap.get(attr);
rhs = rhs.addAttribute(attr, value);
}
if (!equalMaps(lhs, rhs)) {
throw new Error("Maps are not equal.");
}
}
/**
* Ensure that map.removeAttributes(remove) is equivalent to calling
* map.removeAttribute on remove's elements.
*/
public static void testRemoveAttributes(AttributeMap map, AttributeSet remove) {
AttributeMap lhs = map.removeAttributes(remove);
AttributeMap rhs = map;
Enumeration iter = remove.elements();
while (iter.hasMoreElements()) {
Object attr = iter.nextElement();
rhs = rhs.removeAttribute(attr);
}
if (!equalMaps(lhs, rhs)) {
throw new Error("Maps are not equal.");
}
}
/**
* Ensure that map.intersectWith(intersect) is equivalent to
* map.removeAttributes(map.keySet() - intersect);
*/
public static void testIntersectWith(AttributeMap map, AttributeSet intersect) {
AttributeMap lhs = map.intersectWith(intersect);
AttributeSet keySet = map.getKeySet();
AttributeSet removeSet = keySet.subtract(intersect);
AttributeMap rhs = map.removeAttributes(removeSet);
if (!equalMaps(lhs, rhs)) {
map.intersectWith(intersect);
System.out.println("intersect: " + intersect);
System.out.println("keySet: " + keySet);
System.out.println("removeSet: " + removeSet);
System.out.println("map: " + map);
System.out.println("lhs: " + lhs);
System.out.println("rhs: " + rhs);
throw new Error("Maps are not equal.");
}
}
/**
* Ensure that:
* map, map.keySet(), and map.entrySet() are the same size;
* map.containsKey() is true for every key in keySet();
* map.containsValue() is true for every value in values;
* every entry key is in keySet, every entry value is in map.values();
* map.get() is consistent with entry's key, value;
* sum of hashcodes of entries equals map.hashCode().
*/
public static void testViews(AttributeMap map) {
AttributeSet keySet = map.getKeySet();
//Collection values = map.values();
//Set entrySet = map.entrySet();
if (keySet.size() != map.size() /*|| entrySet.size() != map.size()*/) {
throw new Error("Set sizes are inconsistent with map size.");
}
int hashCode = 0;
Enumeration keyIter = keySet.elements();
while (keyIter.hasMoreElements()) {
if (!map.containsKey(keyIter.nextElement())) {
throw new Error("keySet contains key not in map");
}
}
/*
Iterator valueIter = values.iterator();
while (valueIter.hasNext()) {
if (!map.containsValue(valueIter.next())) {
throw new Error("value set contains value not in map");
}
}
Iterator entryIter = entrySet.iterator();
while (entryIter.hasNext()) {
Entry entry = (Entry) entryIter.next();
Object key = entry.getKey();
if (!keySet.contains(key)) {
throw new Error("Entry key is not in key set.");
}
Object value = map.get(entry.getKey());
if (!values.contains(value)) {
throw new Error("Entry value is not in value set.");
}
if (map.get(key) != value) {
throw new Error("map.get did not return entry value.");
}
hashCode += entry.hashCode();
}
if (hashCode != map.hashCode()) {
throw new Error("map hashcode is not sum of entry hashcodes.");
}
*/
}
/**
* Look for correct behavior in obvious cases.
*/
private void easyTests() {
AttributeMap map = new AttributeMap();
if (!map.equals(AttributeMap.EMPTY_ATTRIBUTE_MAP)) {
throw new Error("Default-constructed map is not equal to empty map.");
}
map = map.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
Object otherMap = new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
if (!map.equals(otherMap)) {
throw new Error("Maps are inconsistent after map.add");
}
otherMap = map.addAttributes(map);
if (!equalMaps(map,otherMap)) {
throw new Error("Maps are inconsistent after addAttributes");
}
map = map.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON);
if (map.size() != 2) {
throw new Error("Map size is wrong. map="+map);
}
if (equalMaps(map,otherMap)) {
throw new Error("Maps should not be equal");
}
Object posture = new Float(0);
map = map.addAttribute(TextAttribute.POSTURE, posture);
if (map.size() != 2) {
throw new Error("Map size is wrong");
}
if (!map.get(TextAttribute.POSTURE).equals(posture)) {
throw new Error("Map element is wrong");
}
map = map.removeAttribute(TextAttribute.UNDERLINE);
if (map.size() != 1) {
throw new Error("Map size is wrong");
}
if (map.get(TextAttribute.UNDERLINE) != null) {
throw new Error("Map should not have element");
}
// map has POSTURE_REGULAR. If we addAttributes a map with
// POSTURE_ITALIC the new map should have POSTURE_ITALIC
map = map.addAttributes(new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE));
if (map.get(TextAttribute.POSTURE) != TextAttribute.POSTURE_OBLIQUE) {
throw new Error("Map element is wrong");
}
testModifiers(map);
testViews(map);
Enumeration mapIter = maps.elements();
while (mapIter.hasMoreElements()) {
AttributeMap testMap = (AttributeMap) mapIter.nextElement();
Object newValue = new Object();
AttributeMap newMap = testMap.addAttribute(attributes[0], newValue);
if (newMap.get(attributes[0]) != newValue) {
throw new Error("Did not get expected value back. map=" + map);
}
}
}
/* private void onlyAttributeKeyTests() {
Hashtable ht = new Hashtable();
ht.put("Not an attribute!", "Shouldn't work!");
try {
new AttributeMap(ht);
throw new Error("No exception from non-Attribute key in constructor");
}
catch(ClassCastException e) {
}
try {
AttributeMap.EMPTY_ATTRIBUTE_MAP.addAttributes(ht);
throw new Error("No exception from non-Attribute key in addAttributes");
}
catch(ClassCastException e) {
}
}
*/
}

View File

@ -0,0 +1,90 @@
/*
* @(#)$RCSfile: TestAttributeSet.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.textlayout.attributes.AttributeSet;
import java.util.Enumeration;
public class TestAttributeSet {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
public static void main(String[] args) {
new TestAttributeSet().test();
System.out.println("PASSED");
}
public void test() {
final Object elem1 = new Object();
final Object elem2 = new Float(4);
final Object elem3 = "String";
final Object elem4 = Boolean.FALSE;
AttributeSet set1 = new AttributeSet(new Object[] {elem1, elem2, elem3});
if (set1.size() != 3) {
throw new Error("Size is wrong.");
}
if (set1.contains(elem4)){
throw new Error("Set contents are wrong.");
}
if (!set1.contains(elem1)) {
throw new Error("Set contents are wrong.");
}
AttributeSet set2 = new AttributeSet(elem4);
if (set2.size() != 1) {
throw new Error("Size is wrong.");
}
if (!set2.contains(elem4)){
throw new Error("Set contents are wrong.");
}
if (set2.contains(elem1)) {
throw new Error("Set contents are wrong.");
}
Enumeration iter = set2.elements();
if (!iter.nextElement().equals(elem4)) {
throw new Error("Invalid object in iterator.");
}
AttributeSet union = set2.unionWith(set1);
if (!set1.unionWith(set2).equals(union)) {
throw new Error("unionWith is not commutative.");
}
if (!union.contains(elem1) || !union.contains(elem4)) {
throw new Error("Set contents are wrong.");
}
if (!set1.addElement(elem4).equals(union)) {
throw new Error("addElement is wrong.");
}
if (!union.intersectWith(set1).equals(set1)) {
throw new Error("intersectWith is wrong.");
}
if (!union.subtract(set1).equals(set2)) {
throw new Error("subtract is wrong.");
}
}
}

View File

@ -0,0 +1,250 @@
/*
* @(#)$RCSfile: TestFormatter.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.richtext.styledtext.MText;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.StandardTabRuler;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.richtext.textformat.TextOffset;
import com.ibm.richtext.textformat.MFormatter;
import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.image.MemoryImageSource;
import java.util.Hashtable;
public final class TestFormatter {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static final Point ORIGIN = new Point(0, 0);
private static final AttributeMap DEFAULTS;
static {
final Float floatZero = new Float(0.0f);
Hashtable defaults = new Hashtable();
defaults.put(TextAttribute.FAMILY, "Serif");
defaults.put(TextAttribute.WEIGHT, new Float(1.0f));
defaults.put(TextAttribute.POSTURE, floatZero);
defaults.put(TextAttribute.SIZE, new Float(18.0f));
defaults.put(TextAttribute.SUPERSCRIPT, new Integer(0));
defaults.put(TextAttribute.FOREGROUND, Color.black);
defaults.put(TextAttribute.UNDERLINE, new Integer(-1));
defaults.put(TextAttribute.STRIKETHROUGH, Boolean.FALSE);
defaults.put(TextAttribute.EXTRA_LINE_SPACING, floatZero);
defaults.put(TextAttribute.FIRST_LINE_INDENT, floatZero);
defaults.put(TextAttribute.MIN_LINE_SPACING, floatZero);
defaults.put(TextAttribute.LINE_FLUSH, TextAttribute.FLUSH_LEADING);
defaults.put(TextAttribute.LEADING_MARGIN, floatZero);
defaults.put(TextAttribute.TRAILING_MARGIN, floatZero);
defaults.put(TextAttribute.TAB_RULER, new StandardTabRuler());
DEFAULTS = new AttributeMap(defaults);
}
// arg to testLineExceptions
private static final int UNKNOWN = -1;
private Graphics fGraphics;
public static void main(String[] args) {
new TestFormatter().test();
System.out.println("Formatter test PASSED");
}
public TestFormatter() {
//MemoryImageSource mis = new MemoryImageSource(10, 10, new int[100], 0, 10);
//Image img = Toolkit.getDefaultToolkit().createImage(mis);
//img = img.getScaledInstance(10, 10, 0);
Frame f = new Frame();
f.show();
fGraphics = f.getGraphics();
}
private String fiveLines = "a\nb\nc\nd\ne";
private String twelveLines = fiveLines + "\n" + fiveLines + "\nf\n";
AttributeMap PLAIN = AttributeMap.EMPTY_ATTRIBUTE_MAP;
public void test() {
//MConstText text = new StyledText(fiveLines, PLAIN);
//testLineExceptions(makeFormatter(text, 100, true), 5);
//testLineAccess(makeFormatter(text, 100, true), 5);
//text = new StyledText(twelveLines, PLAIN);
//testLineExceptions(makeFormatter(text, 3, false), 12);
//testLineAccess(makeFormatter(text, 100, true), 12);
testWithModification();
}
private void testWithModification() {
MText text = new StyledText(fiveLines, PLAIN);
MFormatter formatter = makeFormatter(text, 100, true);
Rectangle viewRect = new Rectangle(0, 0, 100, Integer.MAX_VALUE);
formatter.stopBackgroundFormatting();
text.append(new StyledText("\n", PLAIN));
formatter.updateFormat(text.length()-1, 1, viewRect, ORIGIN);
testLineAccess(formatter, 6);
formatter.stopBackgroundFormatting();
text.append(new StyledText("ad", PLAIN));
formatter.updateFormat(text.length()-2, 2, viewRect, ORIGIN);
testLineAccess(formatter, 6);
testLineExceptions(formatter, 6);
formatter.stopBackgroundFormatting();
text.remove(0, 1);
formatter.updateFormat(0, 0, viewRect, ORIGIN);
testLineAccess(formatter, 6);
testLineExceptions(formatter, 6);
}
private MFormatter makeFormatter(MConstText text,
int lineBound,
boolean wrap) {
return MFormatter.createFormatter(text,
DEFAULTS,
lineBound,
wrap,
fGraphics);
}
private void testLineExceptions(MFormatter formatter,
int numLines) {
if (numLines == UNKNOWN) {
numLines = formatter.getLineCount();
}
boolean caught = false;
try {
formatter.lineRangeLow(numLines);
}
catch(IllegalArgumentException e) {
caught = true;
}
if (!caught) {
throw new Error("Didn't get exception");
}
caught = false;
try {
formatter.lineRangeLimit(numLines);
}
catch(IllegalArgumentException e) {
caught = true;
}
if (!caught) {
throw new Error("Didn't get exception");
}
caught = false;
try {
formatter.lineGraphicStart(numLines+1);
}
catch(IllegalArgumentException e) {
caught = true;
}
if (!caught) {
throw new Error("Didn't get exception");
}
caught = false;
}
private void testLineAccess(MFormatter formatter,
int numLines) {
if (numLines == UNKNOWN) {
numLines = formatter.getLineCount();
}
if (formatter.lineGraphicStart(0) != 0) {
throw new Error("Line 0 doesn't start at height 0");
}
if (formatter.lineRangeLow(0) != 0) {
throw new Error("Line 0 doesn't start at character 0");
}
int lastLimit = formatter.lineRangeLimit(0);
final int lineBound = formatter.lineBound();
int[] hitX = new int[] { -1, 1, lineBound + 2 };
TextOffset offset = new TextOffset();
for (int i=1; i < numLines; i++) {
int height = formatter.lineGraphicStart(i);
if (lastLimit != formatter.lineRangeLow(i)) {
throw new Error("lastLine limit is not current line start");
}
int limit = formatter.lineRangeLimit(i);
if (limit < lastLimit || (limit == lastLimit && i != numLines-1)) {
throw new Error("line has negative or 0 length");
}
int nextHeight = formatter.lineGraphicStart(i+1);
if (nextHeight <= height) {
throw new Error("0-height line");
}
int incAmount = Math.max((nextHeight-height)/4, 1);
for (int hitY = height; hitY < nextHeight; hitY += incAmount) {
if (formatter.lineAtHeight(hitY) != i) {
throw new Error("lineAtHeight is wrong");
}
for (int j=0; j < hitX.length; j++) {
offset = formatter.pointToTextOffset(offset,
hitX[j], hitY, ORIGIN, null, false);
if (offset.fOffset < lastLimit || offset.fOffset > limit) {
throw new Error("Inconsistent offset from pointToTextOffset");
}
//if (formatter.lineContaining(offset) != i) {
// int debug = formatter.lineContaining(offset);
// throw new Error("lineContaining is incorrect");
//}
}
}
lastLimit = limit;
}
}
}

View File

@ -0,0 +1,721 @@
/*
* @(#)$RCSfile: TestMText.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.MText;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.richtext.styledtext.StyleModifier;
import java.text.CharacterIterator;
import java.util.Random;
import java.io.*;
public class TestMText {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static final int TEST_ITERATIONS = 5000;
private static final int STYLE_TEST_ITERATIONS = 5000;
private static final long RAND_SEED = 598436;
private static StyleModifier createMinusModifier(final Object attr) {
return new StyleModifier() {
public AttributeMap modifyStyle(AttributeMap style) {
return style.removeAttribute(attr);
}
};
}
private static final String NO_STREAMING_ARG = "-nostreaming";
public static void main(String[] args) {
TestMText t = new TestMText();
boolean streaming = true;
if (args.length > 0) {
if (args.length == 1 && args[0].equals(NO_STREAMING_ARG)) {
streaming = false;
}
else {
throw new Error("USAGE: java TestMText [" + NO_STREAMING_ARG + "]");
}
}
t.simpleTest();
t.styleTest();
t.monkeyTest(streaming);
System.out.println("MText test PASSED");
}
public void simpleTest() {
AttributeMap boldStyle = new AttributeMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
AttributeMap italicStyle = new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
MConstText allBold = new StyledText("bbbbb", boldStyle);
MConstText allItalic = new StyledText("iii", italicStyle);
MConstText plain = new StyledText("pppppp", AttributeMap.EMPTY_ATTRIBUTE_MAP);
{
MText buf = new StyledText();
int ts = buf.getTimeStamp();
buf.append(allBold);
buf.append(allItalic);
if (ts == buf.getTimeStamp()) {
throw new Error("Time stamp not incremented");
}
// should be bbbbbiii now
if (buf.length() != allBold.length() + allItalic.length()) {
throw new Error("Length is wrong.");
}
for (int i=0; i < buf.length(); i++) {
char rightChar;
AttributeMap rightStyle;
if (i < allBold.length()) {
rightChar = allBold.at(0);
rightStyle = boldStyle;
}
else {
rightChar = allItalic.at(0);
rightStyle = italicStyle;
}
if (buf.at(i) != rightChar) {
throw new Error("Character is wrong.");
}
if (!buf.characterStyleAt(i).equals(rightStyle)) {
throw new Error("Style is wrong.");
}
}
int pos = 0;
if (!buf.characterStyleAt(pos).equals(boldStyle)) {
throw new Error("First style is wrong.");
}
if (buf.characterStyleLimit(pos) != allBold.length()) {
throw new Error("Run length is wrong.");
}
pos = allBold.length();
if (!buf.characterStyleAt(pos).equals(italicStyle)) {
throw new Error("Second style is wrong.");
}
if (buf.characterStyleLimit(pos) != buf.length()) {
throw new Error("Run length is wrong.");
}
{
buf.resetDamagedRange();
int oldLength = buf.length();
buf.replace(buf.length(), buf.length(), allBold, 0, allBold.length());
// bbbbbiiibbbbb
if (buf.damagedRangeStart() != oldLength) {
throw new Error("Damaged range start is incorrect");
}
if (buf.damagedRangeLimit() != buf.length()) {
throw new Error("Damaged range limit is incorrect");
}
}
int start = allBold.length();
int limit = start + allItalic.length();
buf.remove(start, limit);
// bbbbbbbbbb
if (buf.length() != 2 * allBold.length()) {
throw new Error("Text should be twice the length of bold text.");
}
pos = buf.length() / 2;
if (buf.characterStyleStart(pos) != 0 ||
buf.characterStyleLimit(pos) != buf.length()) {
throw new Error("Run range is wrong.");
}
if (!buf.characterStyleAt(pos).equals(boldStyle)) {
throw new Error("Run style is wrong.");
}
ts = buf.getTimeStamp();
CharacterIterator cIter = buf.createCharacterIterator();
for (char ch = cIter.first(); ch != cIter.DONE; ch = cIter.next()) {
if (ch != allBold.at(0)) {
throw new Error("Character is wrong.");
}
}
if (ts != buf.getTimeStamp()) {
throw new Error("Time stamp should not have changed");
}
buf.replace(0, 1, plain, 0, plain.length());
if (ts == buf.getTimeStamp()) {
throw new Error("Time stamp not incremented");
}
// ppppppbbbbbbbbb
buf.replace(plain.length(), buf.length(), allItalic, 0, allItalic.length());
// ppppppiii
if (buf.length() != allItalic.length()+plain.length()) {
throw new Error("Length is wrong.");
}
pos = 0;
if (buf.characterStyleLimit(pos) != plain.length()) {
throw new Error("Run limit is wrong.");
}
pos = plain.length();
if (buf.characterStyleLimit(pos) != buf.length()) {
throw new Error("Run limit is wrong.");
}
buf.replace(plain.length(), plain.length(), allBold, 0, allBold.length());
// ppppppbbbbbiii
AttributeMap st = buf.characterStyleAt(1);
if (!st.equals(AttributeMap.EMPTY_ATTRIBUTE_MAP)) {
throw new Error("Style is wrong.");
}
if (buf.characterStyleStart(1) != 0 || buf.characterStyleLimit(1) != plain.length()) {
throw new Error("Style start is wrong.");
}
st = buf.characterStyleAt(buf.length() - 1);
if (!st.equals(italicStyle)) {
throw new Error("Style is wrong.");
}
if (buf.characterStyleStart(buf.length() - 1) != plain.length()+allBold.length()) {
throw new Error("Style start is wrong.");
}
if (buf.characterStyleLimit(buf.length() - 1) != buf.length()) {
throw new Error("Style limit is wrong.");
}
}
}
private static int randInt(Random rand, int limit) {
return randInt(rand, 0, limit);
}
private static int randInt(Random rand, int start, int limit) {
if (start > limit) {
throw new IllegalArgumentException("Range length is negative.");
}
else if (start == limit) {
return start;
}
return start + (Math.abs(rand.nextInt())%(limit-start)) ;
}
public void styleTest() {
MText text = new StyledText("0123456789", AttributeMap.EMPTY_ATTRIBUTE_MAP);
AttributeMap[] styles = new AttributeMap[text.length()];
for (int i=0; i < styles.length; i++) {
styles[i] = AttributeMap.EMPTY_ATTRIBUTE_MAP;
}
AttributeMap[] oldStyles = new AttributeMap[styles.length];
System.arraycopy(styles, 0, oldStyles, 0, styles.length);
AttributeMap bigStyle = new AttributeMap(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON).
addAttribute(TextAttribute.SIZE, new Float(23.0f));
StyleModifier[] modifiers = {
StyleModifier.createReplaceModifier(new AttributeMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD)),
StyleModifier.createAddModifier(new AttributeMap(TextAttribute.WEIGHT, new Float(1.0f))),
createMinusModifier(TextAttribute.WEIGHT),
StyleModifier.createAddModifier(new AttributeMap(TextAttribute.POSTURE, new Float(0.0f))),
StyleModifier.createReplaceModifier(new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE)),
createMinusModifier(TextAttribute.POSTURE),
StyleModifier.createAddModifier(bigStyle),
StyleModifier.createReplaceModifier(bigStyle),
createMinusModifier(bigStyle.getKeySet())
};
Random rand = new Random(RAND_SEED);
final int stopAt = 4;
for (int testIteration=0; testIteration < STYLE_TEST_ITERATIONS + 1; testIteration++) {
System.arraycopy(styles, 0, oldStyles, 0, styles.length);
int startingAt = Integer.MAX_VALUE;
int endingAt = Integer.MIN_VALUE;
int oldTs = text.getTimeStamp();
// hack way to do an invariant check before starting...
if (testIteration != 0) {
// modify styles
text.resetDamagedRange();
startingAt = randInt(rand, styles.length+1);
endingAt = randInt(rand, startingAt, styles.length+1);
StyleModifier modifier = modifiers[randInt(rand, modifiers.length)];
if (testIteration == stopAt) {
testIteration = stopAt;
}
text.modifyCharacterStyles(startingAt, endingAt, modifier);
for (int j=startingAt; j < endingAt; j++) {
styles[j] = modifier.modifyStyle(styles[j]);
}
}
// check invariants
AttributeMap oldStyle = null;
int textLength = text.length();
for (int runStart = 0; runStart < textLength;) {
AttributeMap currentStyle = text.characterStyleAt(runStart);
int runLimit = text.characterStyleLimit(runStart);
if (runStart >= runLimit) {
throw new Error("Run length is not positive");
}
if (currentStyle.equals(oldStyle)) {
throw new Error("Styles didn't merge");
}
for (int pos=runStart; pos < runLimit; pos++) {
AttributeMap charStyleAtPos = text.characterStyleAt(pos);
if (currentStyle != charStyleAtPos) {
throw new Error("Iterator style is not equal to text style at " + pos + ".");
}
AttributeMap expected = styles[pos];
if (!currentStyle.equals(expected)) {
throw new Error("Iterator style doesn't match expected style at " + pos + ".");
}
if (!(text.characterStyleStart(pos) == runStart) ||
!(text.characterStyleLimit(pos) == runLimit)) {
throw new Error("style run start / limit is not consistent");
}
}
runStart = runLimit;
}
if (textLength > 0) {
if (text.characterStyleAt(textLength) !=
text.characterStyleAt(textLength-1)) {
throw new Error("Character styles at end aren't the same");
}
}
// check damaged range:
int damageStart = Integer.MAX_VALUE;
int damageLimit = Integer.MIN_VALUE;
for (int i=0; i < textLength; i++) {
if (!styles[i].equals(oldStyles[i])) {
damageStart = Math.min(i, damageStart);
damageLimit = Math.max(i+1, damageLimit);
}
}
if (damageStart != text.damagedRangeStart() ||
damageLimit != text.damagedRangeLimit()) {
System.out.println("Test iteration: " + testIteration);
System.out.println("startingAt: " + startingAt + "; endingAt: " + endingAt);
System.out.println("damageStart: " + damageStart + "; damageLimit: " + damageLimit);
System.out.println("text.rangeStart: " + text.damagedRangeStart() +
"text.rangeLimit: " + text.damagedRangeLimit());
throw new Error("Damage range start or limit is not expected value");
}
if ((damageLimit == Integer.MIN_VALUE) != (oldTs == text.getTimeStamp())) {
throw new Error("timeStamp is incorrect");
}
}
}
/**
* Perform a random series of operations on an MText and
* check the result of each operation against a set of invariants.
*/
public void monkeyTest(boolean streaming) {
/*
You can add any operation to the switch statement provided it
preserves the following invariants:
- The String plainText contains the same text as the StyledStringBuffer.
Obviously, for the test to be meaningful plainText must be computed
independently of the buffer (ie don't write: plainText = buf.getStyledString().toString()).
- Every 'b' is bold, every 'i' is italic, every 'p' is plain, and
no other characters appear in the text.
*/
AttributeMap boldAttrs = new AttributeMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD);
AttributeMap italicAttrs = new AttributeMap(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
AttributeMap emptyAttrs = AttributeMap.EMPTY_ATTRIBUTE_MAP;
final String bold1Str_getString = "b";
MConstText bold1Str = new StyledText(bold1Str_getString, boldAttrs);
final String italic1Str_getString = "i";
MConstText italic1Str = new StyledText(italic1Str_getString, italicAttrs);
final String plain1Str_getString = "p";
MConstText plain1Str = new StyledText(plain1Str_getString, emptyAttrs);
StyledText temp = new StyledText();
temp.append(bold1Str);
temp.append(italic1Str);
final String boldItalicStr_getString = bold1Str_getString.concat(italic1Str_getString);
MConstText boldItalicStr = temp;
temp = new StyledText();
temp.append(bold1Str);
temp.append(bold1Str);
temp.append(bold1Str);
final String bold3Str_getString = "bbb";
MConstText bold3Str = temp;
MText buf = new StyledText();
String plainText = new String();
int testIteration=0;
int theCase=0;
final int NUM_CASES = 14;
boolean[] casesExecuted = new boolean[NUM_CASES];
final int stopAt = -1;
Random rand = new Random(RAND_SEED);
final String ALWAYS_DIFFERENT = "\uFEFF";
try {
for (testIteration=0; testIteration < TEST_ITERATIONS; testIteration++) {
theCase = randInt(rand, NUM_CASES);
casesExecuted[theCase] = true;
if (testIteration == stopAt) {
System.out.println("Stop here!");
}
int timeStamp = buf.getTimeStamp();
String oldPlainText = plainText;
if (oldPlainText == null) {
throw new Error("oldPlainText is null!");
}
switch (theCase) {
case 0:
// create new string; replace chars at start with different style
buf = new StyledText();
buf.append(bold3Str);
buf.replace(0, 1, italic1Str, 0, italic1Str.length());
buf.replace(0, 0, italic1Str, 0, italic1Str.length());
plainText = bold3Str_getString.substring(1, bold3Str.length());
plainText = italic1Str_getString.concat(plainText);
plainText = italic1Str_getString.concat(plainText);
oldPlainText = null;
break;
case 1:
// delete the last character from the string
if (buf.length() == 0) {
buf.replace(0, 0, italic1Str, 0, italic1Str.length());
plainText = italic1Str_getString;
oldPlainText = ALWAYS_DIFFERENT;
}
buf.remove(buf.length()-1, buf.length());
plainText = plainText.substring(0, plainText.length()-1);
break;
case 2:
// replace some of the buffer with boldItalicStr
int rStart = randInt(rand, buf.length()+1);
int rStop = randInt(rand, rStart, buf.length()+1);
buf.replace(rStart, rStop, boldItalicStr);
{
String newString = (rStart>0)? plainText.substring(0, rStart) : new String();
newString = newString.concat(boldItalicStr_getString);
if (rStop < plainText.length())
newString = newString.concat(plainText.substring(rStop, plainText.length()));
oldPlainText = ALWAYS_DIFFERENT;
plainText = newString;
}
break;
case 3:
// repeatedly insert strings into the center of the buffer
{
int insPos = buf.length() / 2;
String prefix = plainText.substring(0, insPos);
String suffix = plainText.substring(insPos, plainText.length());
String middle = new String();
for (int ii=0; ii<4; ii++) {
MConstText which = (ii%2==0)? boldItalicStr : bold3Str;
String whichString = (ii%2==0)? boldItalicStr_getString : bold3Str_getString;
int tempPos = insPos+middle.length();
buf.insert(tempPos, which);
middle = middle.concat(whichString);
}
plainText = prefix.concat(middle).concat(suffix);
oldPlainText = ALWAYS_DIFFERENT;
}
break;
case 4:
// insert bold1Str at end
buf.append(bold1Str);
plainText = plainText.concat(bold1Str_getString);
break;
case 5:
// delete a character from the string
if (buf.length() > 0) {
int delPos = randInt(rand, buf.length()-1);
buf.remove(delPos, delPos+1);
plainText = plainText.substring(0, delPos).concat(plainText.substring(delPos+1));
}
else {
buf.replace(0, 0, plain1Str, 0, plain1Str.length());
plainText = plain1Str_getString;
}
break;
case 6:
// replace the contents of the buffer (except the first character) with itself
{
int start = buf.length() > 1? 1 : 0;
buf.replace(start, buf.length(), buf);
plainText = plainText.substring(0, start).concat(plainText);
if (buf.length() > 0) {
oldPlainText = ALWAYS_DIFFERENT;
}
}
break;
case 7:
// append the contents of the buffer to itself
{
MConstText content = buf;
buf.insert(buf.length(), content);
plainText = plainText.concat(plainText);
}
break;
case 8:
// replace the buffer with boldItalicStr+bold3Str
{
MText replacement = new StyledText();
replacement.append(boldItalicStr);
replacement.append(bold3Str);
buf.replace(0, buf.length(), replacement, 0, replacement.length());
plainText = boldItalicStr_getString.concat(bold3Str_getString);
oldPlainText = ALWAYS_DIFFERENT;
}
break;
case 9:
// insert bold1Str at end - same as 4 but uses different API
buf.replace(buf.length(),
buf.length(),
bold1Str_getString.toCharArray(),
0,
bold1Str_getString.length(),
boldAttrs);
plainText = plainText.concat(bold1Str_getString);
break;
case 10:
// remove all
buf.remove();
plainText = "";
oldPlainText = ALWAYS_DIFFERENT;
break;
case 11:
// remove all - different way
buf.remove(0, buf.length());
plainText = "";
break;
case 12:
// insert 'i' at 3rd character (or last, if fewer than 3 chars)
{
int insPos = Math.min(buf.length(), 3);
buf.replace(insPos, insPos, 'i', italicAttrs);
plainText = (plainText.substring(0, insPos)).
concat(italic1Str_getString).
concat(plainText.substring(insPos));
}
break;
case 13:
if (streaming) {
Throwable error = null;
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bytesOut);
objOut.writeObject(buf);
ByteArrayInputStream bytesIn =
new ByteArrayInputStream(bytesOut.toByteArray());
ObjectInputStream objIn = new ObjectInputStream(bytesIn);
buf = (MText) objIn.readObject();
oldPlainText = null;
}
catch(IOException e) {
error = e;
}
catch(ClassNotFoundException e) {
error = e;
}
if (error != null) {
error.printStackTrace();
throw new Error("Streaming problem: " + error);
}
}
break;
default:
throw new Error("Invalid case.");
}
// Check time stamp if oldPlainText != null.
// Time stamp should be different iff
// oldPlainText == plainText
if (oldPlainText != null) {
if ((timeStamp==buf.getTimeStamp()) !=
oldPlainText.equals(plainText)) {
System.out.println("plainText hashCode: " + plainText.hashCode());
System.out.println("oldPlainText hashCode: " + oldPlainText.hashCode());
throw new Error("Time stamp is incorrect");
}
}
// now check invariants:
if (plainText.length() != buf.length()) {
throw new Error("Lengths don't match");
}
for (int j=0; j < buf.length(); j++) {
if (buf.at(j) != plainText.charAt(j)) {
throw new Error("Characters don't match.");
}
}
int start;
for (start = 0; start < buf.length();) {
if (start != buf.characterStyleStart(start)) {
throw new Error("style start is wrong");
}
int limit = buf.characterStyleLimit(start);
if (start >= limit) {
throw new Error("start >= limit");
}
char current = plainText.charAt(start);
AttributeMap comp;
if (current == 'p') {
comp = emptyAttrs;
}
else if (current == 'b') {
comp = boldAttrs;
}
else if (current == 'i') {
comp = italicAttrs;
}
else {
throw new Error("An invalid character snuck in!");
}
AttributeMap startStyle = buf.characterStyleAt(start);
if (!startStyle.equals(comp)) {
throw new Error("Style is not expected style.");
}
for (int j = start; j < limit; j++) {
if (plainText.charAt(j) != current) {
throw new Error("Character doesn't match style.");
}
if (buf.characterStyleAt(j) != startStyle) {
throw new Error("Incorrect style in run");
}
}
if (limit < buf.length()) {
if (plainText.charAt(limit) == current) {
throw new Error("Style run ends too soon.");
}
}
start = limit;
}
if (start != buf.length()) {
throw new Error("Last limit is not buffer length.");
}
// won't try to compute and check damaged range; however,
// if nonempty it should always be within text
int damageStart = buf.damagedRangeStart();
int damageLimit = buf.damagedRangeLimit();
if (damageStart == Integer.MAX_VALUE) {
if (damageLimit != Integer.MIN_VALUE) {
throw new Error("Invalid empty interval");
}
}
else {
if (damageStart > damageLimit) {
throw new Error("Damage range inverted");
}
if (damageStart < 0 || damageLimit > buf.length()) {
throw new Error("Damage range endpoint out of bounds");
}
}
}
}
catch(Error e) {
System.out.println("Iteration=" + testIteration + "; case=" + theCase);
throw e;
}
boolean allCasesExecuted = true;
for (int index=0; index < NUM_CASES; index++) {
allCasesExecuted &= casesExecuted[index];
if (casesExecuted[index] == false) {
System.out.println("Case " + index + " not executed.");
}
}
//if (allCasesExecuted) {
// System.out.println("All cases executed.");
//}
}
}

View File

@ -0,0 +1,161 @@
/*
* @(#)$RCSfile: TestMTextStreaming.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.io.*;
import java.awt.Color;
import com.ibm.richtext.styledtext.MText;
import com.ibm.richtext.styledtext.StandardTabRuler;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.richtext.styledtext.StyleModifier;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.textlayout.attributes.TextAttribute;
public class TestMTextStreaming {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
public static void main(String[] args) {
TestMTextStreaming t = new TestMTextStreaming();
t.test();
System.out.println("PASSED");
}
public TestMTextStreaming() {
}
public void test() {
simpleTest();
allAttributesTest();
}
private void simpleTest() {
AttributeMap style = AttributeMap.EMPTY_ATTRIBUTE_MAP;
MText text = new StyledText("Hello world!", style);
streamAndCompare(text);
}
private static class TestModifier extends StyleModifier {
private Object fKey;
private Object fValue;
public AttributeMap modifyStyle(AttributeMap style) {
return style.addAttribute(fKey, fValue);
}
TestModifier(Object key, Object value) {
fKey = key;
fValue = value;
}
}
private void allAttributesTest() {
AttributeMap style = AttributeMap.EMPTY_ATTRIBUTE_MAP;
MText text = new StyledText("Hello world!", style);
int length = text.length();
final boolean CHARACTER = true;
final boolean PARAGRAPH = false;
addStyle(text, 0, length/2, TextAttribute.FAMILY, "Times", CHARACTER);
addStyle(text, length/2, length, TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, CHARACTER);
addStyle(text, 0, length/2, TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, CHARACTER);
addStyle(text, 0, length/2, TextAttribute.SIZE, new Float(13.7f), CHARACTER);
addStyle(text, length/2, length, TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUB, CHARACTER);
addStyle(text, 0, length/2, TextAttribute.FOREGROUND, Color.blue, CHARACTER);
addStyle(text, 0, length/2, TextAttribute.BACKGROUND, Color.red, CHARACTER);
addStyle(text, 0, length-1, TextAttribute.STRIKETHROUGH, Boolean.TRUE, CHARACTER);
addStyle(text, 0, length, TextAttribute.EXTRA_LINE_SPACING, new Float(4), PARAGRAPH);
addStyle(text, 0, length, TextAttribute.FIRST_LINE_INDENT, new Float(6), PARAGRAPH);
addStyle(text, 0, length, TextAttribute.MIN_LINE_SPACING, new Float(7), PARAGRAPH);
addStyle(text, 0, length, TextAttribute.LINE_FLUSH, TextAttribute.FLUSH_TRAILING, PARAGRAPH);
addStyle(text, 0, length, TextAttribute.LEADING_MARGIN, new Float(9), PARAGRAPH);
addStyle(text, 0, length, TextAttribute.TRAILING_MARGIN, new Float(9), PARAGRAPH);
addStyle(text, 0, length, TextAttribute.TAB_RULER, new StandardTabRuler(), PARAGRAPH);
streamAndCompare(text);
}
private static void addStyle(MText text,
int start,
int limit,
Object key,
Object value,
boolean character) {
StyleModifier modifier = new TestModifier(key, value);
if (character) {
text.modifyCharacterStyles(start, limit, modifier);
}
else {
text.modifyParagraphStyles(start, limit, modifier);
}
}
public static void streamAndCompare(MText text) {
Throwable error = null;
try {
ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
ObjectOutputStream objOut = new ObjectOutputStream(bytesOut);
objOut.writeObject(text);
ByteArrayInputStream bytesIn =
new ByteArrayInputStream(bytesOut.toByteArray());
ObjectInputStream objIn = new ObjectInputStream(bytesIn);
MText streamedText = (MText) objIn.readObject();
if (!isEqual(text, streamedText)) {
isEqual(text, streamedText);
throw new Error("Streamed text is not equal");
}
}
/* catch(OptionalDataException e) {
error = e;
}
catch(StreamCorruptedException e) {
error = e;
}*/
catch(IOException e) {
error = e;
}
catch(ClassNotFoundException e) {
error = e;
}
if (error != null) {
error.printStackTrace();
throw new Error("Serialization failed.");
}
}
public static boolean isEqual(MText lhs, MText rhs) {
return lhs.equals(rhs);
}
}

View File

@ -0,0 +1,337 @@
/*
* @(#)$RCSfile: TestParagraphStyles.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.MText;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.richtext.styledtext.StyleModifier;
import java.util.Random;
public final class TestParagraphStyles {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static final int RAND_SEED = 1234;
private static final int NUM_TESTS = 2500;
private static final boolean isParagraphBreak(char c) {
return c =='\u2029' || c == '\n';
}
private static final Object KEY = "KEY";
private static final AttributeMap PLAIN = AttributeMap.EMPTY_ATTRIBUTE_MAP;
private static final AttributeMap A_STYLE = new AttributeMap(KEY, new Character('a'));
private static final StyleModifier A_MOD =
StyleModifier.createReplaceModifier(A_STYLE);
private static final AttributeMap B_STYLE = new AttributeMap(KEY, new Character('b'));
private static final StyleModifier B_MOD =
StyleModifier.createReplaceModifier(B_STYLE);
private static final AttributeMap C_STYLE = new AttributeMap(KEY, new Character('c'));
private static final StyleModifier C_MOD =
StyleModifier.createReplaceModifier(C_STYLE);
private static final AttributeMap D_STYLE = new AttributeMap(KEY, new Character('d'));
private static final StyleModifier D_MOD =
StyleModifier.createReplaceModifier(D_STYLE);
private static final AttributeMap E_STYLE = new AttributeMap(KEY, new Character('e'));
private static final StyleModifier E_MOD =
StyleModifier.createReplaceModifier(E_STYLE);
public static void main(String[] args) {
new TestParagraphStyles().test();
System.out.println("Paragraph Styles test PASSED");
}
public void test() {
easyTests();
randomTest();
}
private void easyTests() {
MText text = new StyledText("a\nb\nc\nd\n", PLAIN);
text.modifyParagraphStyles(0, text.length(), A_MOD);
verifyParagraphCount(text);
MText src = new StyledText("XXX\nYYY", PLAIN);
src.modifyParagraphStyles(0, src.length(), B_MOD);
verifyParagraphCount(src);
MText temp = text.extractWritable(0, text.length());
temp.append(src);
verifyParagraphCount(temp);
for (int i=0; i < text.length(); i++) {
if (!temp.paragraphStyleAt(i).equals(text.paragraphStyleAt(i))) {
throw new Error("Paragraph styles are wrong");
}
}
for (int i=0; i < src.length(); i++) {
if (!temp.paragraphStyleAt(i+text.length()).equals(src.paragraphStyleAt(i))) {
throw new Error("Paragraph styles are wrong");
}
}
temp = text.extractWritable(0, text.length());
temp.replace(0, 1, src, 0, src.length());
verifyParagraphCount(temp);
if (temp.paragraphLimit(0) != 4) {
throw new Error("Paragraph limit is wrong");
}
if (!temp.paragraphStyleAt(0).equals(B_STYLE)) {
throw new Error("First style is wrong");
}
if (!temp.paragraphStyleAt(4).equals(A_STYLE)) {
throw new Error("Style after insert is wrong");
}
// test append
MConstText newSrc = src.extract(4, 7);
MText initC = new StyledText("cccccc", PLAIN);
initC.modifyParagraphStyles(0, initC.length(), C_MOD);
initC.append(newSrc);
// now initC should be one paragraph with style B
if (initC.paragraphLimit(0) != initC.length()) {
throw new Error("Should only be one paragraph");
}
if (initC.paragraphStyleAt(0) != initC.paragraphStyleAt(initC.length())) {
throw new Error("Two different paragraph styles");
}
if (!initC.paragraphStyleAt(initC.length()/2).equals(B_STYLE)) {
throw new Error("Incorrect paragraph style");
}
text = new StyledText("aaa\n", PLAIN);
text.modifyParagraphStyles(0, text.length(), A_MOD);
text.modifyParagraphStyles(text.length(), text.length(), B_MOD);
if (text.paragraphStyleAt(text.length()) != B_STYLE) {
throw new Error("0-length paragraph at end has incorrect style");
}
}
private static int randInt(Random rand, int limit) {
return randInt(rand, 0, limit);
}
private static int randInt(Random rand, int start, int limit) {
if (start > limit) {
throw new IllegalArgumentException("Range is 0-length.");
}
else if (start == limit) {
return start;
}
return start + (Math.abs(rand.nextInt())%(limit-start)) ;
}
private void randomTest() {
MText noParagraph = new StyledText("zzzz", PLAIN);
noParagraph.modifyParagraphStyles(0, noParagraph.length(), A_MOD);
MText twoParagraphs = new StyledText("aaa\nbbb", PLAIN);
twoParagraphs.modifyParagraphStyles(0, twoParagraphs.paragraphLimit(0), B_MOD);
MText threeParagraphs = new StyledText("cc\ndd\nee", PLAIN);
threeParagraphs.modifyParagraphStyles(0, 3, C_MOD);
threeParagraphs.modifyParagraphStyles(3, 6, D_MOD);
threeParagraphs.modifyParagraphStyles(6, 8, E_MOD);
MText trailingP1 = new StyledText("hhhh\n", PLAIN);
trailingP1.modifyParagraphStyles(0, trailingP1.paragraphLimit(0), C_MOD);
MText trailingP2 = new StyledText("iii\n", PLAIN);
trailingP2.modifyParagraphStyles(0, 0, D_MOD);
trailingP2.modifyParagraphStyles(trailingP2.length(), trailingP2.length(), B_MOD);
if (!trailingP2.paragraphStyleAt(trailingP2.length()-1).equals(D_STYLE)) {
throw new Error("Style incorrect in trailingP2");
}
if (!trailingP2.paragraphStyleAt(trailingP2.length()).equals(B_STYLE)) {
throw new Error("Ending style incorrect in trailingP2");
}
MConstText[] tests = { noParagraph, twoParagraphs,
threeParagraphs, trailingP1, trailingP2 };
Random random = new Random(RAND_SEED);
int stopAt = 465;
int i = 0;
try {
for (i=0; i < NUM_TESTS; i++) {
int srcIndex = randInt(random, tests.length);
int targetIndex = randInt(random, tests.length);
MText target = new StyledText(tests[targetIndex]);
MConstText src = tests[srcIndex];
int srcStart = randInt(random, src.length());
int srcLimit = randInt(random, srcStart, src.length());
int start = randInt(random, target.length());
int limit = randInt(random, start, target.length());
if (i == stopAt) {
stopAt = i;
}
insertAndCheck(src, srcStart, srcLimit, target, start, limit);
}
}
finally {
if (i < NUM_TESTS) {
System.out.println("i=" + i);
}
}
}
private static void insertAndCheck(MConstText src, int srcStart, int srcLimit,
MText target, int start, int limit) {
// p-style after insertion
AttributeMap after;
if (limit == target.length() && srcLimit > srcStart) {
after = src.paragraphStyleAt(srcLimit);
}
else {
after = target.paragraphStyleAt(limit);
}
AttributeMap before;
boolean srcHasPBreak = false;
for (int i=srcStart; i < srcLimit; i++) {
if (isParagraphBreak(src.at(i))) {
srcHasPBreak = true;
break;
}
}
if (start > 0 && isParagraphBreak(target.at(start-1))) {
before = target.paragraphStyleAt(start-1);
}
else {
before = srcHasPBreak? src.paragraphStyleAt(srcStart) : after;
}
boolean stylePropogated = !before.equals(target.paragraphStyleAt(Math.max(0, start-1)));
target.resetDamagedRange();
target.replace(start, limit, src, srcStart, srcLimit);
final int damageLimit = (start==limit && srcStart==srcLimit)?
Integer.MIN_VALUE : start + (srcLimit-srcStart);
if (target.damagedRangeLimit() != damageLimit) {
System.out.println("limit: " + damageLimit + "; target.limit: " +
target.damagedRangeLimit());
throw new Error("Damaged range limit is incorrect");
}
final int damageStart = (damageLimit==Integer.MIN_VALUE)? Integer.MAX_VALUE :
(stylePropogated? target.paragraphStart(Math.max(0, start-1)) : start);
if (target.damagedRangeStart() > damageStart) {
System.out.println("start: " + damageStart + "; target.start: " +
target.damagedRangeStart());
throw new Error("Damaged range start is incorrect");
}
verifyParagraphCount(target);
// check endpoints
if (!before.equals(target.paragraphStyleAt(Math.max(start-1, 0)))) {
throw new Error("Incorrect paragraph style before modified range");
}
int lengthDelta = (srcLimit-srcStart) - (limit-start);
int indexAfterInsert = Math.min(target.length(), limit + lengthDelta);
if (!after.equals(target.paragraphStyleAt(indexAfterInsert))) {
throw new Error("Incorrect paragraph style after modified range");
}
if (srcHasPBreak) {
int startP = target.paragraphLimit(start);
int limitOfTest = target.paragraphStart(indexAfterInsert);
int offset = start - srcStart;
while (startP < limitOfTest) {
int limitP = target.paragraphLimit(startP);
if (src.paragraphLimit(startP-offset) + offset != limitP) {
throw new Error("paragraph limits are not consistent");
}
if (!src.paragraphStyleAt(startP-offset)
.equals(target.paragraphStyleAt(startP))) {
throw new Error("paragraph styles are not consistent");
}
startP = limitP;
}
}
else {
for (int i=start; i < start+(srcLimit-srcStart); i++) {
if (!after.equals(target.paragraphStyleAt(i))) {
throw new Error("paragraph style changed unexpectedly");
}
}
}
}
private static void verifyParagraphCount(MConstText text) {
int pCount = 0;
int textLength = text.length();
if (textLength == 0) {
pCount = 1;
}
else {
for (int s=0; s < textLength; s = text.paragraphLimit(s)) {
pCount++;
}
if (isParagraphBreak(text.at(textLength-1))) {
pCount++;
}
}
int sepCount = 0;
for (int i=0; i < textLength; i++) {
if (isParagraphBreak(text.at(i))) {
sepCount++;
}
}
if (sepCount + 1 != pCount) {
System.out.println("sepCount=" + sepCount + "; pCount=" + pCount);
throw new Error("Paragraph count is not consistent with characters");
}
}
private static void checkEndpoint(MConstText text) {
boolean emptyFinalParagraph;
int length = text.length();
if (length != 0) {
char ch = text.at(length-1);
emptyFinalParagraph = isParagraphBreak(ch);
}
else {
emptyFinalParagraph = true;
}
if ((text.paragraphStart(length) == length) != emptyFinalParagraph) {
throw new Error("Final paragraph length is incorrect");
}
}
}

View File

@ -0,0 +1,823 @@
/*
* @(#)$RCSfile: TestTextPanel.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.util.Random;
import java.awt.Color;
import java.awt.Frame;
import java.awt.event.KeyEvent;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import com.ibm.richtext.textpanel.KeyRemap;
import com.ibm.richtext.textpanel.KeyEventForwarder;
import com.ibm.richtext.textpanel.MTextPanel;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.textpanel.TextPanelEvent;
import com.ibm.richtext.textpanel.TextPanelListener;
import com.ibm.richtext.styledtext.MConstText;
import com.ibm.richtext.styledtext.StyledText;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.AttributeMap;
import com.ibm.richtext.styledtext.StyleModifier;
import com.ibm.textlayout.attributes.AttributeSet;
import com.ibm.textlayout.attributes.TextAttribute;
import com.ibm.textlayout.attributes.AttributeMap;
public final class TestTextPanel {
private final class TestListener implements TextPanelListener {
private int NO_WAY = 0;
private int DEFINITELY = 1;
private int MAYBE = 2;
private final int[] status;
TestListener(MTextPanel textPanel) {
int length = TextPanelEvent.TEXT_PANEL_LAST -
TextPanelEvent.TEXT_PANEL_FIRST + 1;
status = new int[length];
textPanel.addListener(this);
allowAll();
}
void refuseAll() {
for (int i=0; i < status.length; i++) {
status[i] = NO_WAY;
}
}
void allowAll() {
for (int i=0; i < status.length; i++) {
status[i] = MAYBE;
}
}
void expectEvent(int type) {
int index = type - TextPanelEvent.TEXT_PANEL_FIRST;
status[index] = DEFINITELY;
}
void allowEvent(int type) {
int index = type - TextPanelEvent.TEXT_PANEL_FIRST;
status[index] = MAYBE;
}
void assertNotExpectingEvents() {
boolean e = false;
for (int i=0; i < status.length; i++) {
if (status[i] == DEFINITELY) {
System.out.println("Expecting event " +
(i+TextPanelEvent.TEXT_PANEL_FIRST));
e = true;
}
}
if (e) {
throw new Error("Some events pending");
}
}
public void textEventOccurred(TextPanelEvent event) {
int index = event.getID() - TextPanelEvent.TEXT_PANEL_FIRST;
if (status[index] == NO_WAY) {
throw new Error("Unexpected event: " + event);
}
else if (status[index] == DEFINITELY) {
status[index] = NO_WAY;
}
}
public boolean respondsToEventType(int type) {
return true;
}
}
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private static final String STRING_CONTENT = "Some content";
private static final int TEST_ITERS = 2;
public static final MConstText MOD_TEXT =
new StyledText("Styled", AttributeMap.EMPTY_ATTRIBUTE_MAP);
private Clipboard fClipboard;
private MTextPanel fTextPanel = null;
private TestListener fListener = null;
private int fRandSeed = 0;
private Random rand;
private static final int BIG_COMMAND_LOG_SIZE = 40;
private static final int SMALL_COMMAND_LOG_SIZE = 8;
private static final StyleModifier[] paraMods = {
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_LEADING)),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_CENTER),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FLUSH_TRAILING),
StyleModifier.createAddModifier(TextAttribute.LINE_FLUSH,
TextAttribute.FULLY_JUSTIFIED),
StyleModifier.createAddModifier(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL),
StyleModifier.createAddModifier(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_LTR),
StyleModifier.createRemoveModifier(
new AttributeSet(TextAttribute.LINE_FLUSH)),
StyleModifier.createRemoveModifier(
new AttributeSet(TextAttribute.RUN_DIRECTION))
};
private static final int SELECT = 0;
private static final int SET_CARET_POS = 1;
private static final int SET_START = 2;
private static final int SET_END = 3;
// using both styles of add modifier: AttributeMap and
// key-value, just for variety...
private static final StyleModifier[] charMods = {
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD)),
StyleModifier.createAddModifier(TextAttribute.FOREGROUND,
Color.green),
StyleModifier.createAddModifier(
new AttributeMap(TextAttribute.UNDERLINE,
TextAttribute.UNDERLINE_ON).addAttributes(
new AttributeMap(TextAttribute.SIZE, new Float(6)))),
StyleModifier.createReplaceModifier(
new AttributeMap(TextAttribute.FAMILY, "Dialog")),
StyleModifier.createRemoveModifier(
new AttributeSet(
new Object[] { TextAttribute.WEIGHT,
TextAttribute.POSTURE,
TextAttribute.UNDERLINE,
TextAttribute.STRIKETHROUGH,
TextAttribute.SUPERSCRIPT })),
StyleModifier.IDENTITY
};
private static final char[] TYPED_CHARS = new char[128 - ' ' + 3];
static {
TYPED_CHARS[0] = 8; // backspace
TYPED_CHARS[1] = '\t';
TYPED_CHARS[2] = '\n';
for (int i=3; i < TYPED_CHARS.length; i++) {
TYPED_CHARS[i] = (char) (' ' + i - 3);
}
}
public static void main(String[] args) {
new TestTextPanel().test();
System.out.println("TextPanelTest PASSED");
}
public TestTextPanel() {
fClipboard = new Clipboard("TestTextPanel");
incRandSeed();
}
public TestTextPanel(MTextPanel panel) {
this();
setTextPanel(panel);
}
void incRandSeed() {
rand = new Random(++fRandSeed);
}
int getRandSeed() {
return fRandSeed;
}
int randInt(int limit) {
return randInt(0, limit);
}
int randInt(int start, int limit) {
if (start > limit) {
throw new IllegalArgumentException("Range is 0-length.");
}
else if (start == limit) {
return start;
}
return start + (Math.abs(rand.nextInt())%(limit-start)) ;
}
public void test() {
AttributeMap bold = new AttributeMap(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD);
MConstText text1 = new StyledText("Test contents. 1234\nHow about it?",
AttributeMap.EMPTY_ATTRIBUTE_MAP);
MConstText text2 = new StyledText("Another test string.", bold);
testWithText(text1);
testWithText(text2);
testWithText(new StyledText());
StyledText big1 = new StyledText();
for (int i=0; i < 50; i++) {
big1.append(text1);
}
testWithText(big1);
StyledText big2 = new StyledText(text1);
for (int i=0; i < 80; i++) {
big2.append(text2);
}
testWithText(big2);
}
private void setTextPanel(MTextPanel panel) {
fTextPanel = panel;
fListener = new TestListener(panel);
}
private void testWithText(MConstText text) {
setTextPanel(new TextPanel(text, fClipboard));
for (int i=0; i < TEST_ITERS; i++) {
testSetSelection();
testModifications(MOD_TEXT, true);
testEditMenuOperations(fClipboard);
testModFlag(fTextPanel.getCommandLogSize());
testCommandLogControl();
}
}
private void testSelection(int function,
final int aStart,
final int aLimit) {
int oldStart = fTextPanel.getSelectionStart();
int oldLimit = fTextPanel.getSelectionEnd();
final int length = fTextPanel.getTextLength();
int start = aStart;
int limit = aLimit;
if (start < 0) {
start = 0;
}
else if (start > length) {
start = length;
}
if (limit < start) {
limit = start;
}
else if (limit > length) {
limit = length;
}
fListener.refuseAll();
if (oldStart != start || oldLimit != limit) {
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
}
if ((oldStart==oldLimit) != (start==limit)) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
if (oldStart==oldLimit) {
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
}
switch(function) {
case SELECT:
fTextPanel.select(aStart, aLimit);
break;
case SET_CARET_POS:
fTextPanel.setCaretPosition(aStart);
break;
case SET_START:
fTextPanel.setSelectionStart(aStart);
break;
case SET_END:
fTextPanel.setSelectionEnd(aLimit);
break;
default:
throw new IllegalArgumentException("Invalid function");
}
if (fTextPanel.getSelectionStart() != start) {
throw new Error("getSelectionStart is incorrect after set");
}
if (fTextPanel.getSelectionEnd() != limit) {
throw new Error("getSelectionEnd is incorrect after set");
}
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
private void setAndTestSelection(int start, int limit) {
testSelection(SELECT, start, limit);
}
private void setAndTestCaret(int caretPos) {
testSelection(SET_CARET_POS, caretPos, caretPos);
}
private void setAndTestSelectionStart(int selStart) {
int limit = fTextPanel.getSelectionEnd();
testSelection(SET_START, selStart, limit);
}
private void setAndTestSelectionEnd(int selEnd) {
int start = fTextPanel.getSelectionStart();
testSelection(SET_END, start, selEnd);
}
public void testSetSelection() {
int textLength = fTextPanel.getTextLength();
if (textLength != fTextPanel.getText().length()) {
throw new Error("Text panel length is not correct");
}
setAndTestSelection(0, textLength / 2);
setAndTestSelection(textLength / 2, textLength);
setAndTestSelection(0, textLength);
setAndTestSelection(-1, textLength+1);
if (textLength > 0) {
setAndTestSelection(0, textLength - 1);
setAndTestSelection(0, 1);
}
final int incAmount = Math.max(1, textLength/5);
for (int index = 0; index <= textLength; index += incAmount) {
setAndTestCaret(index);
setAndTestSelectionStart(textLength-index);
setAndTestSelectionEnd(textLength);
setAndTestSelectionStart(0);
setAndTestSelectionEnd(textLength-index);
}
}
/**
* Text must be editable to pass this test.
*/
public void testModifications(MConstText insertionText,
boolean restoreOldText) {
MConstText oldText = new StyledText(fTextPanel.getText());
final int insLength = insertionText.length();
fListener.allowAll();
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fTextPanel.append(insertionText);
fListener.assertNotExpectingEvents();
if (fTextPanel.getSelectionStart() != oldText.length() + insLength) {
throw new Error("Append didn't result in correct selection");
}
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fTextPanel.insert(insertionText, 0);
fListener.assertNotExpectingEvents();
fListener.allowAll();
if (fTextPanel.getSelectionStart() != insLength) {
throw new Error("Insert didn't result in correct selection");
}
fTextPanel.replaceRange(insertionText, insLength, insLength+oldText.length());
if (fTextPanel.getSelectionStart() != insLength*2) {
throw new Error("Replace didn't result in correct selection");
}
if (fTextPanel.getSelectionEnd() != insLength*2) {
throw new Error("Replace didn't result in correct selection");
}
if (fTextPanel.getTextLength() != insLength*3) {
throw new Error("textLength is incorrect");
}
if (restoreOldText) {
fTextPanel.setText(oldText);
if (fTextPanel.getSelectionStart() != oldText.length()) {
throw new Error("setText didn't result in correct selection");
}
if (fTextPanel.getTextLength() != oldText.length()) {
throw new Error("length incorrect after setText");
}
}
fListener.allowAll();
}
private static int iterationCount = 0;
public void testCommandLogControl() {
fListener.refuseAll();
iterationCount++;
boolean exp = false;
if (fTextPanel.canRedo() || BIG_COMMAND_LOG_SIZE==0) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
exp = true;
}
try {
fTextPanel.setCommandLogSize(BIG_COMMAND_LOG_SIZE);
if (fTextPanel.canRedo()) {
throw new Error("canRedo after setCommandLogSize");
}
fListener.assertNotExpectingEvents();
}
catch(Error e) {
System.out.println("iterationCount="+iterationCount+"; expexting="+exp);
throw e;
}
MConstText insText = new StyledText("7",
AttributeMap.EMPTY_ATTRIBUTE_MAP);
final int origLength = fTextPanel.getTextLength();
int start = origLength / 3;
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
for (int i=start; i < BIG_COMMAND_LOG_SIZE+start; i++) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
fTextPanel.insert(insText, i);
fListener.assertNotExpectingEvents();
}
fListener.allowEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
for (int i=0; i < BIG_COMMAND_LOG_SIZE-1; i++) {
fListener.expectEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fTextPanel.undo();
fListener.assertNotExpectingEvents();
}
if (!fTextPanel.canUndo()) {
throw new Error("Command log is too small");
}
fListener.allowAll();
fTextPanel.undo();
if (fTextPanel.canUndo()) {
throw new Error("Command log is too large");
}
if (fTextPanel.getTextLength() != origLength * insText.length()) {
throw new Error("Text length was not restored");
}
for (int i=0; i < BIG_COMMAND_LOG_SIZE; i++) {
fTextPanel.redo();
}
if (fTextPanel.getTextLength() != origLength+BIG_COMMAND_LOG_SIZE) {
throw new Error("Text length was not restored after redo");
}
if (fTextPanel.canRedo()) {
throw new Error("Should not be able to redo");
}
fTextPanel.undo();
fTextPanel.setCommandLogSize(SMALL_COMMAND_LOG_SIZE);
if (fTextPanel.canRedo()) {
throw new Error("canRedo after setCommandLogSize(small)");
}
for (int i=0; i < SMALL_COMMAND_LOG_SIZE; i++) {
if (!fTextPanel.canUndo()) {
throw new Error("should be able to undo");
}
fTextPanel.undo();
}
if (fTextPanel.canUndo()) {
throw new Error("should not be able to undo after setCommandLogSize(small)");
}
if (!fTextPanel.canRedo()) {
throw new Error("why can't this redo???");
}
fTextPanel.redo();
fTextPanel.clearCommandLog();
if (fTextPanel.canUndo() || fTextPanel.canRedo()) {
throw new Error("Command log wasn't cleared");
}
}
/**
* Test cut, copy, paste, undo, redo, clear, canUndo, canRedo.
* Text must be editable to pass this test.
*/
public void testEditMenuOperations(Clipboard clipboard) {
if (clipboard != null) {
// test paste and undo / redo
Transferable tr = new StringSelection(STRING_CONTENT);
clipboard.setContents(tr, new ClipboardOwner() {
public void lostOwnership(Clipboard c, Transferable t) {
}
});
if (!fTextPanel.clipboardNotEmpty()) {
throw new Error("MTextPanel doesn't recognize string content.");
}
fTextPanel.setCaretPosition(fTextPanel.getSelectionStart());
int oldLength = fTextPanel.getTextLength();
fTextPanel.paste();
if (fTextPanel.getTextLength() != oldLength + STRING_CONTENT.length()) {
throw new Error("Text length is wrong after paste.");
}
if (!fTextPanel.canUndo()) {
throw new Error("canUndo should be true");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != oldLength) {
throw new Error("Length is wrong after undo");
}
if (!fTextPanel.canRedo()) {
throw new Error("canRedo should be true");
}
fTextPanel.redo();
if (fTextPanel.getTextLength() != oldLength + STRING_CONTENT.length()) {
throw new Error("Text length is wrong after redo.");
}
}
int origLength = fTextPanel.getTextLength();
fTextPanel.selectAll();
fTextPanel.clear();
if (fTextPanel.getTextLength() != 0) {
throw new Error("Length is nonzero after clear");
}
if (!fTextPanel.canUndo()) {
throw new Error("canUndo should be true");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Old text not restored");
}
if (origLength > 0) {
fTextPanel.select(0, 1);
fTextPanel.cut();
if (fTextPanel.getTextLength() != origLength-1) {
throw new Error("Length wrong after cut");
}
fTextPanel.paste();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Length wrong after paste");
}
fTextPanel.select(0, origLength);
fTextPanel.copy();
fTextPanel.setCaretPosition(0);
fTextPanel.paste();
if (fTextPanel.getTextLength() != 2*origLength) {
throw new Error("Length wrong after paste");
}
fTextPanel.undo();
if (fTextPanel.getTextLength() != origLength) {
throw new Error("Length wrong after undo");
}
}
}
private void setAndTestModFlag(final int depth,
boolean modified) {
fTextPanel.setModified(modified);
for (int i=0; i < depth; i++) {
if (!fTextPanel.canUndo()) {
throw new Error("Panel cannot undo at valid depth. Depth=" + i);
}
fTextPanel.undo();
fTextPanel.setModified(modified);
}
// check that all mod flags are false:
if (fTextPanel.isModified() != modified) {
throw new Error("isModified is not correct");
}
for (int i=0; i < depth; i++) {
fTextPanel.redo();
if (fTextPanel.isModified() != modified) {
throw new Error("isModified is not correct");
}
}
}
/**
* Make <code>depth</code> modifications to the text in textfTextPanel.
* Set the modified flag on each operation, and then retrieve its
* value. Finally, undo the modifications.
*/
public void testModFlag(final int depth) {
final int oldLength = fTextPanel.getTextLength();
for (int i=0; i < depth; i++) {
fTextPanel.insert(MOD_TEXT, 0);
}
setAndTestModFlag(depth, false);
setAndTestModFlag(depth, true);
for (int i=0; i < depth; i++) {
fTextPanel.undo();
}
if (fTextPanel.getTextLength() != oldLength) {
throw new Error("Undo did not restore old text.");
}
}
void applyCharacterStyle() {
StyleModifier stMod = charMods[randInt(charMods.length)];
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fTextPanel.modifyCharacterStyleOnSelection(stMod);
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void applyParagraphStyle() {
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.SELECTION_STYLES_CHANGED);
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
StyleModifier stMod = paraMods[randInt(paraMods.length)];
fTextPanel.modifyParagraphStyleOnSelection(stMod);
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void applyKeyRemap() {
fListener.refuseAll();
fListener.expectEvent(TextPanelEvent.KEYREMAP_CHANGED);
int op = randInt(5);
switch (op) {
case 0:
fTextPanel.setKeyRemap(KeyRemap.getIdentityRemap());
break;
case 1:
fTextPanel.setKeyRemap(KeyRemap.getArabicTransliteration());
break;
case 2:
fTextPanel.setKeyRemap(KeyRemap.getHebrewTransliteration());
break;
case 3:
fTextPanel.setKeyRemap(KeyRemap.getIsraelNikud());
break;
case 4:
//fTextPanel.setKeyRemap(KeyRemap.getThaiKetmanee());
fTextPanel.setKeyRemap(KeyRemap.getIsraelNikud());
break;
default:
throw new Error("Invalid operation!");
}
fListener.assertNotExpectingEvents();
fListener.allowAll();
}
void resizeFrame(Frame frame) {
fListener.refuseAll();
fListener.allowEvent(TextPanelEvent.FORMAT_WIDTH_CHANGED);
int wd = randInt(50, 1000);
int ht = randInt(20, 800);
frame.setSize(wd, ht);
fListener.allowAll();
}
void selectText() {
int selStart = randInt(-10, fTextPanel.getTextLength());
int selLimit = randInt(0, fTextPanel.getTextLength() + 10);
testSelection(SELECT, selStart, selLimit);
}
void undoRedo() {
final int opCount = randInt(-10, 15);
for (int i=opCount; i <= 0; i++) {
fTextPanel.redo();
}
for (int i=0; i < opCount; i++) {
fTextPanel.undo();
}
}
void typeKeys() {
final int keyCount = randInt(1, 100);
TextPanel textPanel = (TextPanel) fTextPanel;
KeyEventForwarder forwarder = new KeyEventForwarder(textPanel);
fListener.refuseAll();
fListener.allowEvent(TextPanelEvent.UNDO_STATE_CHANGED);
if (fTextPanel.getSelectionStart() != fTextPanel.getSelectionEnd()) {
fListener.expectEvent(TextPanelEvent.SELECTION_EMPTY_CHANGED);
}
for (int i=0; i < keyCount; i++) {
char typedChar = TYPED_CHARS[randInt(TYPED_CHARS.length)];
KeyEvent event = new KeyEvent(textPanel,
KeyEvent.KEY_TYPED,
0,
0,
KeyEvent.VK_UNDEFINED,
typedChar);
if (typedChar == 8 || typedChar == 0x7f) {
fListener.allowEvent(TextPanelEvent.TEXT_CHANGED);
fListener.allowEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
else {
fListener.expectEvent(TextPanelEvent.TEXT_CHANGED);
fListener.expectEvent(TextPanelEvent.SELECTION_RANGE_CHANGED);
}
forwarder.handleKeyEvent(event);
try {
fListener.assertNotExpectingEvents();
}
catch(Error e) {
System.out.println("i="+i+"; typedChar="+Integer.toHexString(typedChar));
throw e;
}
}
fListener.allowAll();
}
}

View File

@ -0,0 +1,227 @@
/*
* @(#)$RCSfile: TypingPerfTest.java,v $ $Revision: 1.1 $ $Date: 2000/04/20 17:46:57 $
*
* (C) Copyright IBM Corp. 1998-1999. All Rights Reserved.
*
* The program is provided "as is" without any warranty express or
* implied, including the warranty of non-infringement and the implied
* warranties of merchantibility and fitness for a particular purpose.
* IBM will not be liable for any damages suffered by you as a result
* of using the Program. In no event will IBM be liable for any
* special, indirect or consequential damages or lost profits even if
* IBM has been advised of the possibility of their occurrence. IBM
* will not be liable for any third party claims against you.
*/
package com.ibm.richtext.tests;
import java.awt.Button;
import java.awt.GridLayout;
import java.awt.Frame;
import java.awt.Toolkit;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.util.Date;
import com.ibm.richtext.textpanel.KeyEventForwarder;
import com.ibm.richtext.textpanel.TextPanel;
import com.ibm.richtext.awtui.TextFrame;
public class TypingPerfTest implements ActionListener {
static final String COPYRIGHT =
"(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved";
private TextFrame fTextFrame;
private KeyEventForwarder fKeyEventForwarder;
private PrintWriter fOut;
private static final String fgAtStartCommand = "Insert at start";
private static final String fgAtEndCommand = "Insert at end";
private static final String fgFwdDelete = "Forward delete";
private static final String fgBackspace = "Backspace";
private static final String fgAtCurrentPosCommand = "Insert at current position";
private static final String fgLotsOfTextCommand = "Insert a lot of text";
private static final char[] fgInsText =
"The quick brown fox jumps over the lazy dog. The end.".toCharArray();
public static void main(String[] args) {
OutputStream outStream = null;
PrintWriter writer;
try {
if (args.length == 1) {
outStream = new FileOutputStream(args[0], true);
writer = new PrintWriter(outStream);
}
else {
writer = new PrintWriter(System.out);
}
new TypingPerfTest(writer);
}
catch(IOException e) {
System.out.println("Caught exception: " + e);
}
}
public TypingPerfTest(PrintWriter out) throws IOException {
fTextFrame = new TextFrame(Declaration.fgDeclaration, "", null);
TextPanel textPanel = (TextPanel) fTextFrame.getTextPanel();
fKeyEventForwarder = new KeyEventForwarder(textPanel);
fOut = out;
DateFormat df = DateFormat.getDateTimeInstance();
out.println("Test date: " + df.format(new Date()));
fTextFrame.setSize(500, 700);
fTextFrame.show();
Frame f = new Frame("Typing Perf Test");
f.setLayout(new GridLayout(0, 1));
Button b;
/*
b = new Button(fgAtStartCmd);
b.addActionListener(this);
f.add(b);
b = new Button(fgAtEndCmd);
b.addActionListener(this);
f.add(b);
*/
b = new Button(fgAtCurrentPosCommand);
b.addActionListener(this);
f.add(b);
b = new Button(fgLotsOfTextCommand);
b.addActionListener(this);
f.add(b);
b = new Button(fgFwdDelete);
b.addActionListener(this);
f.add(b);
b = new Button(fgBackspace);
b.addActionListener(this);
f.add(b);
f.doLayout();
WindowAdapter closer = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
fOut.close();
System.exit(0);
}
};
f.addWindowListener(closer);
fTextFrame.addWindowListener(closer);
f.setSize(200, 80);
f.show();
}
public void actionPerformed(ActionEvent evt) {
try {
if (evt.getActionCommand().equals(fgAtCurrentPosCommand)) {
insertAtCurrentPos(1);
}
else if (evt.getActionCommand().equals(fgLotsOfTextCommand)) {
insertAtCurrentPos(8);
}
else if (evt.getActionCommand().equals(fgFwdDelete)) {
forwardDelete(1);
}
else if (evt.getActionCommand().equals(fgBackspace)) {
backspace(1);
}
}
catch(IOException e) {
System.out.println("Caught exception: " + e);
}
}
private void insertAtCurrentPos(final int times) throws IOException {
//EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
fTextFrame.toFront();
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, KeyEvent.KEY_TYPED, 0, 0, 0, fgInsText[i]);
fKeyEventForwarder.handleKeyEvent(event);
//eventQueue.postEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
private void forwardDelete(final int times) throws IOException {
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, 0, 0, 0, KeyEvent.VK_DELETE, '\u00FF');
fKeyEventForwarder.handleKeyEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
private void backspace(final int times) throws IOException {
System.gc();
long startTime = System.currentTimeMillis();
for (int t=0; t < times; t++) {
for (int i=0; i < fgInsText.length; i++) {
KeyEvent event = new KeyEvent(fTextFrame, 0, 0, 0, KeyEvent.VK_BACK_SPACE, '\u0010');
fKeyEventForwarder.handleKeyEvent(event);
}
}
long time = System.currentTimeMillis() - startTime;
fOut.println("Total time: " + time);
fOut.println("Millis per character: " + (time / (fgInsText.length*times)));
fOut.flush();
}
}