| /* |
| * @(#)$RCSfile: TestParagraphStyles.java,v $ $Revision: 1.2 $ $Date: 2000/04/24 20:52:58 $ |
| * |
| * (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.test.richtext; |
| |
| import com.ibm.test.TestFmwk; |
| |
| 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 extends TestFmwk { |
| |
| static final String COPYRIGHT = |
| "(C) Copyright IBM Corp. 1998-1999 - All Rights Reserved"; |
| |
| public static void main(String[] args) throws Exception { |
| |
| new TestParagraphStyles().run(args); |
| } |
| |
| 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 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))) { |
| errln("Paragraph styles are wrong"); |
| } |
| } |
| for (int i=0; i < src.length(); i++) { |
| if (!temp.paragraphStyleAt(i+text.length()).equals(src.paragraphStyleAt(i))) { |
| errln("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) { |
| errln("Paragraph limit is wrong"); |
| } |
| if (!temp.paragraphStyleAt(0).equals(B_STYLE)) { |
| errln("First style is wrong"); |
| } |
| if (!temp.paragraphStyleAt(4).equals(A_STYLE)) { |
| errln("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()) { |
| errln("Should only be one paragraph"); |
| } |
| if (initC.paragraphStyleAt(0) != initC.paragraphStyleAt(initC.length())) { |
| errln("Two different paragraph styles"); |
| } |
| if (!initC.paragraphStyleAt(initC.length()/2).equals(B_STYLE)) { |
| errln("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) { |
| errln("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)) { |
| errln("Style incorrect in trailingP2"); |
| } |
| if (!trailingP2.paragraphStyleAt(trailingP2.length()).equals(B_STYLE)) { |
| errln("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) { |
| logln("iteration=" + i); |
| } |
| } |
| } |
| |
| private 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) { |
| logln("limit: " + damageLimit + "; target.limit: " + |
| target.damagedRangeLimit()); |
| errln("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) { |
| logln("start: " + damageStart + "; target.start: " + |
| target.damagedRangeStart()); |
| errln("Damaged range start is incorrect"); |
| } |
| |
| verifyParagraphCount(target); |
| |
| // check endpoints |
| if (!before.equals(target.paragraphStyleAt(Math.max(start-1, 0)))) { |
| errln("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))) { |
| errln("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) { |
| errln("paragraph limits are not consistent"); |
| } |
| if (!src.paragraphStyleAt(startP-offset) |
| .equals(target.paragraphStyleAt(startP))) { |
| errln("paragraph styles are not consistent"); |
| } |
| startP = limitP; |
| } |
| } |
| else { |
| for (int i=start; i < start+(srcLimit-srcStart); i++) { |
| if (!after.equals(target.paragraphStyleAt(i))) { |
| errln("paragraph style changed unexpectedly"); |
| } |
| } |
| } |
| } |
| |
| private 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) { |
| logln("sepCount=" + sepCount + "; pCount=" + pCount); |
| errln("Paragraph count is not consistent with characters"); |
| } |
| } |
| |
| private 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) { |
| errln("Final paragraph length is incorrect"); |
| } |
| } |
| } |