/******************************************************************************* * Copyright (c) 2016, 2017 Pantheon Technologies, s.r.o. and others. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * SPDX-License-Identifier: EPL-2.0 *******************************************************************************/ package org.eclipse.xtext.xbase.tests.lib; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import org.eclipse.xtend2.lib.StringConcatenation; import org.eclipse.xtend2.lib.StringConcatenationClient; import org.junit.Test; public class StringConcatenationTest { // Utility class wrapping a String private static final class StringObject extends Object { final String string; StringObject(final String string) { this.string = string; } @Override public String toString() { return string; } } @Test public void testEmpty() { assertEquals("", new StringConcatenation().toString()); } @Test(expected=IllegalArgumentException.class) public void testNullDelimiter() { new StringConcatenation(null); } @Test(expected=IllegalArgumentException.class) public void testEmptyDelimiter() { new StringConcatenation(""); } @Test public void testAppendObjectNull() { final StringConcatenation c = new StringConcatenation(); c.append((Object)null); c.append((Object)null, ""); c.append((Object)null, " "); assertEquals("", c.toString()); } @Test public void testAppendStringNull() { final StringConcatenation c = new StringConcatenation(); c.append((String)null); c.append((String)null, ""); c.append((String)null, " "); assertEquals("", c.toString()); } @Test public void testAppendStringConcatNull() { final StringConcatenation c = new StringConcatenation(); c.append((StringConcatenation)null); c.append((StringConcatenation)null, ""); c.append((StringConcatenation)null, " "); assertEquals("", c.toString()); } @Test public void testAppendStringConcatClientNull() { final StringConcatenation c = new StringConcatenation(); c.append((StringConcatenationClient)null); c.append((StringConcatenationClient)null, ""); c.append((StringConcatenationClient)null, " "); assertEquals("", c.toString()); } @Test public void testAppendNullToString() { final Object o = new StringObject(null); final StringConcatenation c = new StringConcatenation(); c.append(o); c.append(o, ""); assertEquals("", new StringConcatenation().toString()); } @Test(expected=NullPointerException.class) public void testAppendWithNullIndent() { final StringConcatenation c = new StringConcatenation(); c.append("a", null); } @Test(expected=NullPointerException.class) public void testAppendNullWithNullIndent() { final StringConcatenation c = new StringConcatenation(); c.append((Object)null, null); } @Test public void testStringConcat() { final StringConcatenation c = new StringConcatenation(); c.append("a"); c.append("b"); c.append("c"); assertEquals("abc", c.toString()); } @Test public void testMaskedStringConcat() { final StringConcatenation c = new StringConcatenation(); c.append((Object)"a"); c.append((Object)"b"); c.append((Object)"c"); assertEquals("abc", c.toString()); } @Test public void testMixedConcat() { final StringConcatenation c = new StringConcatenation(); c.append("a"); c.append(Character.valueOf('b')); c.append(new StringObject("c")); assertEquals("abc", c.toString()); } @Test public void testCharSequenceMethods() { final StringConcatenation c = new StringConcatenation(); c.append("a"); c.append("b"); c.append("c"); assertEquals(3, c.length()); assertEquals('a', c.charAt(0)); assertEquals('b', c.charAt(1)); assertEquals("ab", c.subSequence(0, 2)); assertEquals("bc", c.subSequence(1, 3)); } @Test public void testNoindentConcat() { final StringConcatenation c = new StringConcatenation("\n"); c.append("a\n"); c.append("b\r"); c.append("c\n"); assertEquals("a\nb\nc\n", c.toString()); } @Test public void testIndentConcat() { final StringConcatenation c = new StringConcatenation("\n"); c.append("a\n", " "); c.append("b\r", " "); c.append("c\nd", " "); assertEquals("a\n b\n c\n d", c.toString()); } @Test public void testMaskedIndentConcat() { final StringConcatenation c = new StringConcatenation("\n"); c.append((Object)"a\n", " "); c.append((Object)"b\r", " "); c.append((Object)"c\nd", " "); assertEquals("a\n b\n c\n d", c.toString()); } @Test public void testObjectIndentConcat() { final StringConcatenation c = new StringConcatenation("\n"); c.append(new StringObject("a\n"), " "); c.append(new StringObject("b\r"), " "); c.append(new StringObject("c\nd"), " "); assertEquals("a\n b\n c\n d", c.toString()); } @Test public void testNewLine() { final StringConcatenation c = new StringConcatenation("\n"); c.newLine(); c.append("a"); c.newLine(); assertEquals("\na\n", c.toString()); } @Test public void testNewLineIfNotEmpty() { final StringConcatenation c = new StringConcatenation("\n"); c.newLineIfNotEmpty(); c.append("a"); c.newLineIfNotEmpty(); c.append("b\n"); c.newLineIfNotEmpty(); c.append(" "); c.newLineIfNotEmpty(); assertEquals("a\nb\n", c.toString()); } @Test public void testCachedToString() { final StringConcatenation c = new StringConcatenation(); c.append("a"); c.append("b\n"); final String str = c.toString(); assertSame(str, c.toString()); } @Test public void testAppendEmptyConcat() { final StringConcatenation c = new StringConcatenation(); c.append(new StringConcatenation()); assertEquals("", c.toString()); c.append(new StringConcatenation(), " "); assertEquals("", c.toString()); } @Test public void testAppendConcat() { final StringConcatenation toAppend = new StringConcatenation("\n"); toAppend.append("a\n"); toAppend.append("b"); final StringConcatenation c = new StringConcatenation("\n"); c.append(toAppend); assertEquals("a\nb", c.toString()); } @Test public void testAppendConcatSeparator() { final StringConcatenation toAppend = new StringConcatenation("\t"); toAppend.append("a\t"); toAppend.append("b"); final StringConcatenation c = new StringConcatenation(); c.append(toAppend); assertEquals("a\tb", c.toString()); } @Test public void testAppendEmptyConcatSeparator() { final StringConcatenation c = new StringConcatenation(); c.append(new StringConcatenation("\t")); assertEquals("", c.toString()); } @Test public void testAppendMaskedConcat() { final StringConcatenation toAppend = new StringConcatenation("\n"); toAppend.append("a\n"); toAppend.append("b"); final StringConcatenation c = new StringConcatenation("\n"); c.append((Object)toAppend); assertEquals("a\nb", c.toString()); } @Test public void testAppendMaskedIndentConcat() { final StringConcatenation toAppend = new StringConcatenation("\n"); toAppend.append("a\n"); toAppend.append("b"); final StringConcatenation c = new StringConcatenation("\n"); c.append((Object)toAppend, " "); assertEquals("a\n b", c.toString()); } @Test public void testAppendImmediateSimple() { final StringConcatenation c = new StringConcatenation(); c.appendImmediate("a", " "); assertEquals("a", c.toString()); } @Test public void testAppendImmediateComplex() { final StringConcatenation c = new StringConcatenation("\n"); c.append("a\n"); c.append(" b "); c.newLineIfNotEmpty(); c.append(" "); c.appendImmediate("c\nd", " "); assertEquals("a\n b c\n d\n", c.toString()); } @Test public void testGrowInChunks() throws Exception { // This is rather ugly, but gets the job done. It would be much cleaner if this test were in the same // package as the class being tested... final Field lss = StringConcatenation.class.getDeclaredField("lastSegmentsSize"); lss.setAccessible(true); final StringConcatenation c = new StringConcatenation(); final int initialSize = lss.getInt(c); assertTrue(initialSize >= 0); for (int i = 0; i < initialSize; ++i) { c.append("a"); } // No reallocation should happen assertEquals(initialSize, lss.getInt(c)); // This should trigger pre-allocation c.append("b"); final int firstGrown = lss.getInt(c); assertTrue(firstGrown > initialSize); // The delta needs to be a power-of-two final int deltaSize = firstGrown - initialSize; assertEquals(1, Integer.bitCount(deltaSize)); // Now just to make sure, append another set final StringConcatenation batch = new StringConcatenation(); for (int i = 1; i < deltaSize * 2; ++i) { batch.newLine(); } c.append(batch); final int secondGrown = lss.getInt(c); assertTrue(firstGrown < secondGrown); assertEquals(deltaSize, secondGrown - firstGrown); } }