1/* 2 * RopeTest.java 3 * Copyright (C) 2007 Amin Ahmad. 4 * 5 * This file is part of Java Ropes. 6 * 7 * Java Ropes is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * Java Ropes is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with Java Ropes. If not, see <http://www.gnu.org/licenses/>. 19 * 20 * Amin Ahmad can be contacted at amin.ahmad@gmail.com or on the web at 21 * www.ahmadsoft.org. 22 */ 23package org.ahmadsoft.ropes.test; 24 25import java.io.ByteArrayInputStream; 26import java.io.ByteArrayOutputStream; 27import java.io.IOException; 28import java.io.ObjectInputStream; 29import java.io.ObjectOutputStream; 30import java.io.StringWriter; 31import java.io.Writer; 32import java.util.Iterator; 33import java.util.regex.Pattern; 34 35import junit.framework.Assert; 36import junit.framework.TestCase; 37 38import org.ahmadsoft.ropes.Rope; 39import org.ahmadsoft.ropes.impl.ConcatenationRope; 40import org.ahmadsoft.ropes.impl.FlatCharSequenceRope; 41import org.ahmadsoft.ropes.impl.ReverseRope; 42import org.ahmadsoft.ropes.impl.SubstringRope; 43 44public class RopeTest extends TestCase { 45 46 private String fromRope(Rope rope, int start, int end) { 47 try { 48 Writer out = new StringWriter(end - start); 49 rope.write(out, start, end - start); 50 return out.toString(); 51 } catch (IOException ex) { 52 ex.printStackTrace(); 53 return null; 54 } 55 } 56 public void testSubstringDeleteBug() { 57 String s = "12345678902234567890"; 58 59 Rope rope = Rope.BUILDER.build(s.toCharArray()); // bugs 60 61 rope = rope.delete(0, 1); 62 assertEquals("23", fromRope(rope, 0, 2)); 63 assertEquals("", fromRope(rope, 0, 0)); 64 assertEquals("902", fromRope(rope, 7, 10)); 65 66 67 rope = Rope.BUILDER.build(s); // no bugs 68 rope = rope.delete(0, 1); 69 assertEquals("23", fromRope(rope, 0, 2)); 70 assertEquals("", fromRope(rope, 0, 0)); 71 assertEquals("902", fromRope(rope, 7, 10)); 72 } 73 74 /** 75 * Bug reported by ugg.ugg@gmail.com. 76 */ 77 public void testRopeWriteBug() { 78 Rope r = Rope.BUILDER.build(""); 79 r = r.append("round "); 80 r = r.append(Integer.toString(0)); 81 r = r.append(" 1234567890"); 82 83 assertEquals("round ", fromRope(r,0,6)); 84 assertEquals("round 0", fromRope(r,0,7)); 85 assertEquals("round 0 ", fromRope(r,0,8)); 86 assertEquals("round 0 1", fromRope(r,0,9)); 87 assertEquals("round 0 12", fromRope(r,0,10)); 88 assertEquals("round 0 1234567890", fromRope(r,0,18)); 89 assertEquals("round 0 1234567890", fromRope(r,0,r.length())); 90 } 91 92 93 public void testTemp() { 94 // insert temporary code here. 95 } 96 97 public void testLengthOverflow() { 98 Rope x1 = Rope.BUILDER.build("01"); 99 for (int j=2;j<31;++j) 100 x1 = x1.append(x1); 101 assertEquals(1073741824, x1.length()); 102 try { 103 x1 = x1.append(x1); 104 fail("Expected overflow."); 105 } catch (IllegalArgumentException e) { 106 // this is what we expect 107 } 108 } 109 110 public void testMatches() { 111 Rope x1 = new FlatCharSequenceRope("0123456789"); 112 Rope x2 = new ConcatenationRope(x1, x1); 113 114 assertTrue(x2.matches("0.*9")); 115 assertTrue(x2.matches(Pattern.compile("0.*9"))); 116 117 assertTrue(x2.matches("0.*90.*9")); 118 assertTrue(x2.matches(Pattern.compile("0.*90.*9"))); 119 } 120 121 public void testConcatenationFlatFlat() { 122 Rope r1 = Rope.BUILDER.build("alpha"); 123 final Rope r2 = Rope.BUILDER.build("beta"); 124 Rope r3 = r1.append(r2); 125 Assert.assertEquals("alphabeta", r3.toString()); 126 127 r1 = Rope.BUILDER.build("The quick brown fox jumped over"); 128 r3 = r1.append(r1); 129 Assert.assertEquals("The quick brown fox jumped overThe quick brown fox jumped over", r3.toString()); 130 } 131 132 public void testIterator() { 133 Rope x1 = new FlatCharSequenceRope("0123456789"); 134 Rope x2 = new FlatCharSequenceRope("0123456789"); 135 Rope x3 = new FlatCharSequenceRope("0123456789"); 136 ConcatenationRope c1 = new ConcatenationRope(x1, x2); 137 ConcatenationRope c2 = new ConcatenationRope(c1, x3); 138 139 Iterator<Character> i = c2.iterator(); 140 for (int j = 0; j < c2.length(); ++j) { 141 assertTrue("Has next (" + j + "/" + c2.length() + ")", i.hasNext()); 142 i.next(); 143 } 144 assertTrue(!i.hasNext()); 145 146 FlatCharSequenceRope z1 = new FlatCharSequenceRope("0123456789"); 147 Rope z2 = new SubstringRope(z1, 2, 0); 148 Rope z3 = new SubstringRope(z1, 2, 2); 149 Rope z4 = new ConcatenationRope(z3, new SubstringRope(z1, 6, 2)); // 2367 150 151 i = z2.iterator(); 152 assertTrue(!i.hasNext()); 153 i = z3.iterator(); 154 assertTrue(i.hasNext()); 155 assertEquals((char) '2',(char) i.next()); 156 assertTrue(i.hasNext()); 157 assertEquals((char) '3', (char) i.next()); 158 assertTrue(!i.hasNext()); 159 for (int j=0; j<=z3.length(); ++j) { 160 try { 161 z3.iterator(j); 162 } catch (Exception e) { 163 fail(j + " " + e.toString()); 164 } 165 } 166 assertTrue(4 == z4.length()); 167 for (int j=0; j<=z4.length(); ++j) { 168 try { 169 z4.iterator(j); 170 } catch (Exception e) { 171 fail(j + " " + e.toString()); 172 } 173 } 174 i=z4.iterator(4); 175 assertTrue(!i.hasNext()); 176 i=z4.iterator(2); 177 assertTrue(i.hasNext()); 178 assertEquals((char) '6',(char) i.next()); 179 assertTrue(i.hasNext()); 180 assertEquals((char) '7',(char) i.next()); 181 assertTrue(!i.hasNext()); 182 183 184 } 185 186 public void testReverse() { 187 Rope x1 = new FlatCharSequenceRope("012345"); 188 Rope x2 = new FlatCharSequenceRope("67"); 189 Rope x3 = new ConcatenationRope(x1, x2); 190 191 assertEquals("543210", x1.reverse().toString()); 192 assertEquals("76543210", x3.reverse().toString()); 193 assertEquals(x3.reverse(), x3.reverse().reverse().reverse()); 194 assertEquals("654321", x3.reverse().subSequence(1, 7).toString()); 195 } 196 197 198 public void testTrim() { 199 Rope x1 = new FlatCharSequenceRope("\u0012 012345"); 200 Rope x2 = new FlatCharSequenceRope("\u0002 67 \u0007"); 201 Rope x3 = new ConcatenationRope(x1, x2); 202 203 assertEquals("012345", x1.trimStart().toString()); 204 assertEquals("67 \u0007", x2.trimStart().toString()); 205 assertEquals("012345\u0002 67 \u0007", x3.trimStart().toString()); 206 207 assertEquals("\u0012 012345", x1.trimEnd().toString()); 208 assertEquals("\u0002 67", x2.trimEnd().toString()); 209 assertEquals("\u0012 012345\u0002 67", x3.trimEnd().toString()); 210 assertEquals("012345\u0002 67", x3.trimEnd().reverse().trimEnd().reverse().toString()); 211 212 assertEquals(x3.trimStart().trimEnd(), x3.trimEnd().trimStart()); 213 assertEquals(x3.trimStart().trimEnd(), x3.trimStart().reverse().trimStart().reverse()); 214 assertEquals(x3.trimStart().trimEnd(), x3.trim()); 215 } 216 217 public void testCreation() { 218 try { 219 Rope.BUILDER.build("The quick brown fox jumped over"); 220 } catch (final Exception e) { 221 Assert.fail("Nonempty string: " + e.getMessage()); 222 } 223 try { 224 Rope.BUILDER.build(""); 225 } catch (final Exception e) { 226 Assert.fail("Empty string: " + e.getMessage()); 227 } 228 } 229 230 public void testEquals() { 231 final Rope r1 = Rope.BUILDER.build("alpha"); 232 final Rope r2 = Rope.BUILDER.build("beta"); 233 final Rope r3 = Rope.BUILDER.build("alpha"); 234 235 Assert.assertEquals(r1, r3); 236 Assert.assertFalse(r1.equals(r2)); 237 } 238 239 public void testHashCode() { 240 final Rope r1 = Rope.BUILDER.build("alpha"); 241 final Rope r2 = Rope.BUILDER.build("beta"); 242 final Rope r3 = Rope.BUILDER.build("alpha"); 243 244 Assert.assertEquals(r1.hashCode(), r3.hashCode()); 245 Assert.assertFalse(r1.hashCode() == r2.hashCode()); 246 } 247 248 public void testHashCode2() { 249 Rope r1 = new FlatCharSequenceRope(new StringBuffer("The quick brown fox.")); 250 Rope r2 = new ConcatenationRope(new FlatCharSequenceRope(""), new FlatCharSequenceRope("The quick brown fox.")); 251 252 assertTrue(r1.equals(r2)); 253 assertTrue(r1.equals(r2)); 254 } 255 256 public void testIndexOf() { 257 final Rope r1 = Rope.BUILDER.build("alpha"); 258 final Rope r2 = Rope.BUILDER.build("beta"); 259 final Rope r3 = r1.append(r2); 260 Assert.assertEquals(1, r3.indexOf('l')); 261 Assert.assertEquals(6, r3.indexOf('e')); 262 263 264 Rope r = Rope.BUILDER.build("abcdef"); 265 assertEquals(-1, r.indexOf('z')); 266 assertEquals(0, r.indexOf('a')); 267 assertEquals(1, r.indexOf('b')); 268 assertEquals(5, r.indexOf('f')); 269 270 271 assertEquals(1, r.indexOf('b', 0)); 272 assertEquals(0, r.indexOf('a', 0)); 273 assertEquals(-1, r.indexOf('z', 0)); 274 assertEquals(-1, r.indexOf('b',2)); 275 assertEquals(5, r.indexOf('f',5)); 276 277 assertEquals(2, r.indexOf("cd", 1)); 278 279 r = Rope.BUILDER.build("The quick brown fox jumped over the jumpy brown dog."); 280 assertEquals(0, r.indexOf("The")); 281 assertEquals(10, r.indexOf("brown")); 282 assertEquals(10, r.indexOf("brown", 10)); 283 assertEquals(42, r.indexOf("brown",11)); 284 assertEquals(-1, r.indexOf("brown",43)); 285 assertEquals(-1, r.indexOf("hhe")); 286 287 r = Rope.BUILDER.build("zbbzzz"); 288 assertEquals(-1, r.indexOf("ab",1)); 289 } 290 291 public void testInsert() { 292 final Rope r1 = Rope.BUILDER.build("alpha"); 293 Assert.assertEquals("betaalpha", r1.insert(0, "beta").toString()); 294 Assert.assertEquals("alphabeta", r1.insert(r1.length(), "beta").toString()); 295 Assert.assertEquals("abetalpha", r1.insert(1, "beta").toString()); 296 } 297 298 public void testPrepend() { 299 Rope r1 = Rope.BUILDER.build("alphabeta"); 300 for (int j=0;j<2;++j) 301 r1 = r1.subSequence(0, 5).append(r1); 302 Assert.assertEquals("alphaalphaalphabeta", r1.toString()); 303 r1 = r1.append(r1.subSequence(5, 15)); 304 Assert.assertEquals("alphaalphaalphabetaalphaalpha", r1.toString()); 305 } 306 307 public void testCompareTo() { 308 final Rope r1 = Rope.BUILDER.build("alpha"); 309 final Rope r2 = Rope.BUILDER.build("beta"); 310 final Rope r3 = Rope.BUILDER.build("alpha"); 311 final Rope r4 = Rope.BUILDER.build("alpha1"); 312 final String s2 = "beta"; 313 314 assertTrue(r1.compareTo(r3) == 0); 315 assertTrue(r1.compareTo(r2) < 0); 316 assertTrue(r2.compareTo(r1) > 0); 317 assertTrue(r1.compareTo(r4) < 0); 318 assertTrue(r4.compareTo(r1) > 0); 319 assertTrue(r1.compareTo(s2) < 0); 320 assertTrue(r2.compareTo(s2) == 0); 321 } 322 323 public void testToString() { 324 String phrase = "The quick brown fox jumped over the lazy brown dog. Boy am I glad the dog was asleep."; 325 final Rope r1 = Rope.BUILDER.build(phrase); 326 assertTrue(phrase.equals(r1.toString())); 327 assertTrue(phrase.subSequence(7, 27).equals(r1.subSequence(7, 27).toString())); 328 } 329 330 public void testReverseIterator() { 331 FlatCharSequenceRope r1 = new FlatCharSequenceRope("01234"); 332 ReverseRope r2 = new ReverseRope(r1); 333 SubstringRope r3 = new SubstringRope(r1, 0, 3); 334 ConcatenationRope r4 = new ConcatenationRope(new ConcatenationRope(r1,r2),r3); //0123443210012 335 336 Iterator<Character> x = r1.reverseIterator(); 337 assertTrue(x.hasNext()); 338 assertEquals((char) '4',(char) x.next()); 339 assertTrue(x.hasNext()); 340 assertEquals((char) '3',(char) x.next()); 341 assertTrue(x.hasNext()); 342 assertEquals((char) '2',(char) x.next()); 343 assertTrue(x.hasNext()); 344 assertEquals((char) '1',(char) x.next()); 345 assertTrue(x.hasNext()); 346 assertEquals((char) '0',(char) x.next()); 347 assertFalse(x.hasNext()); 348 349 x = r1.reverseIterator(4); 350 assertTrue(x.hasNext()); 351 assertEquals((char) '0',(char) x.next()); 352 assertFalse(x.hasNext()); 353 354 x = r2.reverseIterator(); 355 assertTrue(x.hasNext()); 356 assertEquals((char) '0',(char) x.next()); 357 assertTrue(x.hasNext()); 358 assertEquals((char) '1',(char) x.next()); 359 assertTrue(x.hasNext()); 360 assertEquals((char) '2',(char) x.next()); 361 assertTrue(x.hasNext()); 362 assertEquals((char) '3',(char) x.next()); 363 assertTrue(x.hasNext()); 364 assertEquals((char) '4',(char) x.next()); 365 assertFalse(x.hasNext()); 366 367 x = r2.reverseIterator(4); 368 assertTrue(x.hasNext()); 369 assertEquals((char) '4',(char) x.next()); 370 assertFalse(x.hasNext()); 371 372 x = r3.reverseIterator(); 373 assertTrue(x.hasNext()); 374 assertEquals((char) '2',(char) x.next()); 375 assertTrue(x.hasNext()); 376 assertEquals((char) '1',(char) x.next()); 377 assertTrue(x.hasNext()); 378 assertEquals((char) '0',(char) x.next()); 379 assertFalse(x.hasNext()); 380 381 x = r3.reverseIterator(1); 382 assertTrue(x.hasNext()); 383 assertEquals((char) '1',(char) x.next()); 384 assertTrue(x.hasNext()); 385 assertEquals((char) '0',(char) x.next()); 386 assertFalse(x.hasNext()); 387 388 x = r4.reverseIterator(); //0123443210012 389 assertTrue(x.hasNext()); 390 assertEquals((char) '2',(char) x.next()); 391 assertTrue(x.hasNext()); 392 assertEquals((char) '1',(char) x.next()); 393 assertTrue(x.hasNext()); 394 assertEquals((char) '0',(char) x.next()); 395 assertTrue(x.hasNext()); 396 assertEquals((char) '0',(char) x.next()); 397 assertTrue(x.hasNext()); 398 assertEquals((char) '1',(char) x.next()); 399 assertTrue(x.hasNext()); 400 assertEquals((char) '2',(char) x.next()); 401 assertTrue(x.hasNext()); 402 assertEquals((char) '3',(char) x.next()); 403 assertTrue(x.hasNext()); 404 assertEquals((char) '4',(char) x.next()); 405 assertTrue(x.hasNext()); 406 assertEquals((char) '4',(char) x.next()); 407 assertTrue(x.hasNext()); 408 assertEquals((char) '3',(char) x.next()); 409 assertTrue(x.hasNext()); 410 assertEquals((char) '2',(char) x.next()); 411 assertTrue(x.hasNext()); 412 assertEquals((char) '1',(char) x.next()); 413 assertTrue(x.hasNext()); 414 assertEquals((char) '0',(char) x.next()); 415 assertFalse(x.hasNext()); 416 417 x = r4.reverseIterator(7); 418 assertEquals((char) '4',(char) x.next()); 419 assertTrue(x.hasNext()); 420 assertEquals((char) '4',(char) x.next()); 421 assertTrue(x.hasNext()); 422 assertEquals((char) '3',(char) x.next()); 423 assertTrue(x.hasNext()); 424 assertEquals((char) '2',(char) x.next()); 425 assertTrue(x.hasNext()); 426 assertEquals((char) '1',(char) x.next()); 427 assertTrue(x.hasNext()); 428 assertEquals((char) '0',(char) x.next()); 429 assertFalse(x.hasNext()); 430 431 x = r4.reverseIterator(12); 432 assertTrue(x.hasNext()); 433 assertEquals((char) '0',(char) x.next()); 434 assertFalse(x.hasNext()); 435 436 x = r4.reverseIterator(13); 437 assertFalse(x.hasNext()); 438 439 } 440 441 public void testSerialize() { 442 FlatCharSequenceRope r1 = new FlatCharSequenceRope("01234"); 443 ReverseRope r2 = new ReverseRope(r1); 444 SubstringRope r3 = new SubstringRope(r1, 0, 1); 445 ConcatenationRope r4 = new ConcatenationRope(new ConcatenationRope(r1,r2),r3); //01234432100 446 447 ByteArrayOutputStream out = new ByteArrayOutputStream(); 448 try { 449 ObjectOutputStream oos = new ObjectOutputStream(out); 450 oos.writeObject(r4); 451 oos.close(); 452 ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); 453 ObjectInputStream ois = new ObjectInputStream(in); 454 Rope r = (Rope) ois.readObject(); 455 assertTrue(r instanceof FlatCharSequenceRope); 456 } catch (Exception e) { 457 fail(e.toString()); 458 } 459 460 461 } 462 463 public void testPadStart() { 464 Rope r = Rope.BUILDER.build("hello"); 465 assertEquals("hello", r.padStart(5).toString()); 466 assertEquals("hello", r.padStart(0).toString()); 467 assertEquals("hello", r.padStart(-1).toString()); 468 assertEquals(" hello", r.padStart(6).toString()); 469 assertEquals(" hello", r.padStart(7).toString()); 470 assertEquals("~hello", r.padStart(6, '~').toString()); 471 assertEquals("~~hello", r.padStart(7, '~').toString()); 472 assertEquals("~~~~~~~~~~~~~~~~~~~~~~~~~hello", r.padStart(30, '~').toString()); 473 } 474 475 public void testPadEnd() { 476 Rope r = Rope.BUILDER.build("hello"); 477 assertEquals("hello", r.padEnd(5).toString()); 478 assertEquals("hello", r.padEnd(0).toString()); 479 assertEquals("hello", r.padEnd(-1).toString()); 480 assertEquals("hello ", r.padEnd(6).toString()); 481 assertEquals("hello ", r.padEnd(7).toString()); 482 assertEquals("hello~", r.padEnd(6, '~').toString()); 483 assertEquals("hello~~", r.padEnd(7, '~').toString()); 484 assertEquals("hello~~~~~~~~~~~~~~~~~~~~~~~~~", r.padEnd(30, '~').toString()); 485 } 486 487 public void testSubstringBounds() { 488 Rope r = Rope.BUILDER.build("01234567890123456789012345678901234567890123456789012345678901234567890123456789".toCharArray()); 489 Rope r2 = r.subSequence(0, 30); 490 try{ 491 r2.charAt(31); 492 fail("Expected IndexOutOfBoundsException"); 493 } catch (IndexOutOfBoundsException e) { 494 // success 495 } 496 } 497 498 public void testAppend() { 499 Rope r = Rope.BUILDER.build(""); 500 r=r.append('a'); 501 assertEquals("a", r.toString()); 502 r=r.append("boy"); 503 assertEquals("aboy", r.toString()); 504 r=r.append("test", 0, 4); 505 assertEquals("aboytest", r.toString()); 506 } 507 508 public void testEmpty() { 509 Rope r1 = Rope.BUILDER.build(""); 510 Rope r2 = Rope.BUILDER.build("012345"); 511 512 assertTrue(r1.isEmpty()); 513 assertFalse(r2.isEmpty()); 514 assertTrue(r2.subSequence(2, 2).isEmpty()); 515 } 516 public void testCharAt() { 517 FlatCharSequenceRope r1 = new FlatCharSequenceRope("0123456789"); 518 SubstringRope r2 = new SubstringRope(r1,0,1); 519 SubstringRope r3 = new SubstringRope(r1,9,1); 520 ConcatenationRope r4 = new ConcatenationRope(r1, r3); 521 522 assertEquals('0', r1.charAt(0)); 523 assertEquals('9', r1.charAt(9)); 524 assertEquals('0', r2.charAt(0)); 525 assertEquals('9', r3.charAt(0)); 526 assertEquals('0', r4.charAt(0)); 527 assertEquals('9', r4.charAt(9)); 528 assertEquals('9', r4.charAt(10)); 529 } 530 531 public void testRegexp() { 532 ConcatenationRope r = new ConcatenationRope(new FlatCharSequenceRope("012345"), new FlatCharSequenceRope("6789")); 533 CharSequence c = r.getForSequentialAccess(); 534 for (int j=0; j<10; ++j) { 535 assertEquals(r.charAt(j), c.charAt(j)); 536 } 537 c = r.getForSequentialAccess(); 538 539 int[] indices={1,2,1,3,5,0,6,7,8,1,7,7,7}; 540 for (int i: indices) { 541 assertEquals("Index: " + i, r.charAt(i), c.charAt(i)); 542 } 543 } 544 545 public void testStartsEndsWith() { 546 final Rope r = Rope.BUILDER.build("Hello sir, how do you do?"); 547 assertTrue(r.startsWith("")); 548 assertTrue(r.startsWith("H")); 549 assertTrue(r.startsWith("He")); 550 assertTrue(r.startsWith("Hello ")); 551 assertTrue(r.startsWith("", 0)); 552 assertTrue(r.startsWith("H", 0)); 553 assertTrue(r.startsWith("He", 0)); 554 assertTrue(r.startsWith("Hello ", 0)); 555 assertTrue(r.startsWith("", 1)); 556 assertTrue(r.startsWith("e", 1)); 557 assertTrue(r.endsWith("?")); 558 assertTrue(r.endsWith("do?")); 559 assertTrue(r.endsWith("o", 1)); 560 assertTrue(r.endsWith("you do", 1)); 561 } 562} 563