| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.lucene.analysis.tokenattributes; |
| |
| |
| import org.apache.lucene.util.AttributeImpl; |
| import org.apache.lucene.util.LuceneTestCase; |
| import org.apache.lucene.util.BytesRef; |
| import org.apache.lucene.util.TestUtil; |
| |
| import java.nio.CharBuffer; |
| import java.util.HashMap; |
| import java.util.Formatter; |
| import java.util.Locale; |
| import java.util.regex.Pattern; |
| |
| public class TestCharTermAttributeImpl extends LuceneTestCase { |
| |
| public void testResize() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| char[] content = "hello".toCharArray(); |
| t.copyBuffer(content, 0, content.length); |
| for (int i = 0; i < 2000; i++) |
| { |
| t.resizeBuffer(i); |
| assertTrue(i <= t.buffer().length); |
| assertEquals("hello", t.toString()); |
| } |
| } |
| |
| public void testSetLength() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| char[] content = "hello".toCharArray(); |
| t.copyBuffer(content, 0, content.length); |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.setLength(-1); |
| }); |
| } |
| |
| @Slow |
| public void testGrow() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| StringBuilder buf = new StringBuilder("ab"); |
| for (int i = 0; i < 20; i++) |
| { |
| char[] content = buf.toString().toCharArray(); |
| t.copyBuffer(content, 0, content.length); |
| assertEquals(buf.length(), t.length()); |
| assertEquals(buf.toString(), t.toString()); |
| buf.append(buf.toString()); |
| } |
| assertEquals(1048576, t.length()); |
| |
| // now as a StringBuilder, first variant |
| t = new CharTermAttributeImpl(); |
| buf = new StringBuilder("ab"); |
| for (int i = 0; i < 20; i++) |
| { |
| t.setEmpty().append(buf); |
| assertEquals(buf.length(), t.length()); |
| assertEquals(buf.toString(), t.toString()); |
| buf.append(t); |
| } |
| assertEquals(1048576, t.length()); |
| |
| // Test for slow growth to a long term |
| t = new CharTermAttributeImpl(); |
| buf = new StringBuilder("a"); |
| for (int i = 0; i < 20000; i++) |
| { |
| t.setEmpty().append(buf); |
| assertEquals(buf.length(), t.length()); |
| assertEquals(buf.toString(), t.toString()); |
| buf.append("a"); |
| } |
| assertEquals(20000, t.length()); |
| } |
| |
| public void testToString() throws Exception { |
| char[] b = {'a', 'l', 'o', 'h', 'a'}; |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.copyBuffer(b, 0, 5); |
| assertEquals("aloha", t.toString()); |
| |
| t.setEmpty().append("hi there"); |
| assertEquals("hi there", t.toString()); |
| } |
| |
| public void testClone() throws Exception { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| char[] content = "hello".toCharArray(); |
| t.copyBuffer(content, 0, 5); |
| char[] buf = t.buffer(); |
| CharTermAttributeImpl copy = assertCloneIsEqual(t); |
| assertEquals(t.toString(), copy.toString()); |
| assertNotSame(buf, copy.buffer()); |
| } |
| |
| public void testEquals() throws Exception { |
| CharTermAttributeImpl t1a = new CharTermAttributeImpl(); |
| char[] content1a = "hello".toCharArray(); |
| t1a.copyBuffer(content1a, 0, 5); |
| CharTermAttributeImpl t1b = new CharTermAttributeImpl(); |
| char[] content1b = "hello".toCharArray(); |
| t1b.copyBuffer(content1b, 0, 5); |
| CharTermAttributeImpl t2 = new CharTermAttributeImpl(); |
| char[] content2 = "hello2".toCharArray(); |
| t2.copyBuffer(content2, 0, 6); |
| assertTrue(t1a.equals(t1b)); |
| assertFalse(t1a.equals(t2)); |
| assertFalse(t2.equals(t1b)); |
| } |
| |
| public void testCopyTo() throws Exception { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| CharTermAttributeImpl copy = assertCopyIsEqual(t); |
| assertEquals("", t.toString()); |
| assertEquals("", copy.toString()); |
| |
| t = new CharTermAttributeImpl(); |
| char[] content = "hello".toCharArray(); |
| t.copyBuffer(content, 0, 5); |
| char[] buf = t.buffer(); |
| copy = assertCopyIsEqual(t); |
| assertEquals(t.toString(), copy.toString()); |
| assertNotSame(buf, copy.buffer()); |
| } |
| |
| public void testAttributeReflection() throws Exception { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.append("foobar"); |
| TestUtil.assertAttributeReflection(t, new HashMap<String, Object>() {{ |
| put(CharTermAttribute.class.getName() + "#term", "foobar"); |
| put(TermToBytesRefAttribute.class.getName() + "#bytes", new BytesRef("foobar")); |
| }}); |
| } |
| |
| public void testCharSequenceInterface() { |
| final String s = "0123456789"; |
| final CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.append(s); |
| |
| assertEquals(s.length(), t.length()); |
| assertEquals("12", t.subSequence(1,3).toString()); |
| assertEquals(s, t.subSequence(0,s.length()).toString()); |
| |
| assertTrue(Pattern.matches("01\\d+", t)); |
| assertTrue(Pattern.matches("34", t.subSequence(3,5))); |
| |
| assertEquals(s.subSequence(3,7).toString(), t.subSequence(3,7).toString()); |
| |
| for (int i = 0; i < s.length(); i++) { |
| assertTrue(t.charAt(i) == s.charAt(i)); |
| } |
| } |
| |
| public void testAppendableInterface() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| Formatter formatter = new Formatter(t, Locale.ROOT); |
| formatter.format("%d", 1234); |
| assertEquals("1234", t.toString()); |
| formatter.format("%d", 5678); |
| assertEquals("12345678", t.toString()); |
| t.append('9'); |
| assertEquals("123456789", t.toString()); |
| t.append((CharSequence) "0"); |
| assertEquals("1234567890", t.toString()); |
| t.append((CharSequence) "0123456789", 1, 3); |
| assertEquals("123456789012", t.toString()); |
| t.append((CharSequence) CharBuffer.wrap("0123456789".toCharArray()), 3, 5); |
| assertEquals("12345678901234", t.toString()); |
| t.append((CharSequence) t); |
| assertEquals("1234567890123412345678901234", t.toString()); |
| t.append((CharSequence) new StringBuilder("0123456789"), 5, 7); |
| assertEquals("123456789012341234567890123456", t.toString()); |
| t.append((CharSequence) new StringBuffer(t)); |
| assertEquals("123456789012341234567890123456123456789012341234567890123456", t.toString()); |
| // very wierd, to test if a subSlice is wrapped correct :) |
| CharBuffer buf = CharBuffer.wrap("0123456789".toCharArray(), 3, 5); |
| assertEquals("34567", buf.toString()); |
| t.setEmpty().append((CharSequence) buf, 1, 2); |
| assertEquals("4", t.toString()); |
| CharTermAttribute t2 = new CharTermAttributeImpl(); |
| t2.append("test"); |
| t.append((CharSequence) t2); |
| assertEquals("4test", t.toString()); |
| t.append((CharSequence) t2, 1, 2); |
| assertEquals("4teste", t.toString()); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.append((CharSequence) t2, 1, 5); |
| }); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.append((CharSequence) t2, 1, 0); |
| }); |
| |
| t.append((CharSequence) null); |
| assertEquals("4testenull", t.toString()); |
| } |
| |
| public void testAppendableInterfaceWithLongSequences() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.append((CharSequence) "01234567890123456789012345678901234567890123456789"); |
| t.append((CharSequence) CharBuffer.wrap("01234567890123456789012345678901234567890123456789".toCharArray()), 3, 50); |
| assertEquals("0123456789012345678901234567890123456789012345678934567890123456789012345678901234567890123456789", t.toString()); |
| t.setEmpty().append((CharSequence) new StringBuilder("01234567890123456789"), 5, 17); |
| assertEquals((CharSequence) "567890123456", t.toString()); |
| t.append(new StringBuffer(t)); |
| assertEquals((CharSequence) "567890123456567890123456", t.toString()); |
| // very wierd, to test if a subSlice is wrapped correct :) |
| CharBuffer buf = CharBuffer.wrap("012345678901234567890123456789".toCharArray(), 3, 15); |
| assertEquals("345678901234567", buf.toString()); |
| t.setEmpty().append(buf, 1, 14); |
| assertEquals("4567890123456", t.toString()); |
| |
| // finally use a completely custom CharSequence that is not catched by instanceof checks |
| final String longTestString = "012345678901234567890123456789"; |
| t.append(new CharSequence() { |
| @Override |
| public char charAt(int i) { return longTestString.charAt(i); } |
| @Override |
| public int length() { return longTestString.length(); } |
| @Override |
| public CharSequence subSequence(int start, int end) { return longTestString.subSequence(start, end); } |
| @Override |
| public String toString() { return longTestString; } |
| }); |
| assertEquals("4567890123456"+longTestString, t.toString()); |
| } |
| |
| public void testNonCharSequenceAppend() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.append("0123456789"); |
| t.append("0123456789"); |
| assertEquals("01234567890123456789", t.toString()); |
| t.append(new StringBuilder("0123456789")); |
| assertEquals("012345678901234567890123456789", t.toString()); |
| CharTermAttribute t2 = new CharTermAttributeImpl(); |
| t2.append("test"); |
| t.append(t2); |
| assertEquals("012345678901234567890123456789test", t.toString()); |
| t.append((String) null); |
| t.append((StringBuilder) null); |
| t.append((CharTermAttribute) null); |
| assertEquals("012345678901234567890123456789testnullnullnull", t.toString()); |
| } |
| |
| public void testExceptions() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| t.append("test"); |
| assertEquals("test", t.toString()); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.charAt(-1); |
| }); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.charAt(4); |
| }); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.subSequence(0, 5); |
| }); |
| |
| expectThrows(IndexOutOfBoundsException.class, () -> { |
| t.subSequence(5, 0); |
| }); |
| } |
| |
| public static <T extends AttributeImpl> T assertCloneIsEqual(T att) { |
| @SuppressWarnings("unchecked") |
| T clone = (T) att.clone(); |
| assertEquals("Clone must be equal", att, clone); |
| assertEquals("Clone's hashcode must be equal", att.hashCode(), clone.hashCode()); |
| return clone; |
| } |
| |
| public static <T extends AttributeImpl> T assertCopyIsEqual(T att) throws Exception { |
| @SuppressWarnings("unchecked") |
| T copy = (T) att.getClass().newInstance(); |
| att.copyTo(copy); |
| assertEquals("Copied instance must be equal", att, copy); |
| assertEquals("Copied instance's hashcode must be equal", att.hashCode(), copy.hashCode()); |
| return copy; |
| } |
| |
| /* |
| |
| // test speed of the dynamic instanceof checks in append(CharSequence), |
| // to find the best max length for the generic while (start<end) loop: |
| public void testAppendPerf() { |
| CharTermAttributeImpl t = new CharTermAttributeImpl(); |
| final int count = 32; |
| CharSequence[] csq = new CharSequence[count * 6]; |
| final StringBuilder sb = new StringBuilder(); |
| for (int i=0,j=0; i<count; i++) { |
| sb.append(i%10); |
| final String testString = sb.toString(); |
| CharTermAttribute cta = new CharTermAttributeImpl(); |
| cta.append(testString); |
| csq[j++] = cta; |
| csq[j++] = testString; |
| csq[j++] = new StringBuilder(sb); |
| csq[j++] = new StringBuffer(sb); |
| csq[j++] = CharBuffer.wrap(testString.toCharArray()); |
| csq[j++] = new CharSequence() { |
| public char charAt(int i) { return testString.charAt(i); } |
| public int length() { return testString.length(); } |
| public CharSequence subSequence(int start, int end) { return testString.subSequence(start, end); } |
| public String toString() { return testString; } |
| }; |
| } |
| |
| Random rnd = newRandom(); |
| long startTime = System.currentTimeMillis(); |
| for (int i=0; i<100000000; i++) { |
| t.setEmpty().append(csq[rnd.nextInt(csq.length)]); |
| } |
| long endTime = System.currentTimeMillis(); |
| System.out.println("Time: " + (endTime-startTime)/1000.0 + " s"); |
| } |
| |
| */ |
| |
| } |