Ver Fonte

tests (82)

FIX: ReflectUtils#readSourceCode

FIX: StrBuilder, StrUtils - bound checks

FIX: StrBuilder#resize, #reserve, #trim - semantic
FIX: StrBuilder#append(..., begin, end) - invalid "size" calculation
FIX: StrBuilder#append(NativeArray, IntFunction) - changed to #append(size, IntFunction)
FIX: StrBuilder#equals - works for CharSequences (as side effect: for Strings too)
FIX: StrBuilder#StrBuilderState#copy - endl

refactor: StringLoader -> StringIO, remove some methods
Ranides Atterwim há 10 anos atrás
pai
commit
3b474fd426

+ 5 - 0
assira/pom.xml

@@ -161,8 +161,13 @@
                                 <exclude>net/ranides/assira/text/FormatNumber.class</exclude>
                                 <exclude>net/ranides/assira/text/MazoviaCharset$*</exclude>
                                 <exclude>net/ranides/assira/text/MazoviaCharset.class</exclude>
+                                <exclude>net/ranides/assira/text/StrBuilder.class</exclude>
+                                <exclude>net/ranides/assira/text/StrBuilder$*</exclude>
+                                <exclude>net/ranides/assira/text/StrBuilderOptions.class</exclude>
+                                <exclude>net/ranides/assira/text/StringIO.class</exclude>
                                 <exclude>net/ranides/assira/text/StringUtils.class</exclude>
                                 <exclude>net/ranides/assira/text/StringUtils$*</exclude>
+                                <exclude>net/ranides/assira/text/Wildcard.class</exclude>
                                 
 								<exclude>net/ranides/assira/trace/ExceptionInspector$*</exclude>
 								<exclude>net/ranides/assira/trace/ExceptionInspector.class</exclude>

+ 14 - 11
assira/src/main/java/net/ranides/assira/reflection/util/ReflectUtils.java

@@ -10,7 +10,8 @@ import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.AccessibleObject;
-import net.ranides.assira.text.StringLoader;
+import net.ranides.assira.text.Charsets;
+import net.ranides.assira.text.StringIO;
 
 /**
  *
@@ -64,21 +65,23 @@ public final class ReflectUtils {
     }
     
     private static String readSourceCode(ClassLoader loader, String classname) throws IOException {
-        String file = classname.replace('.', '/').replaceAll("\\$.+", "") + ".java";
-        InputStream istream = loader.getResourceAsStream(file);
+        String name = classname.replace('.', '/').replaceAll("\\$.+", "") + ".java";
+        InputStream istream = loader.getResourceAsStream(name);
         if(istream != null) {
-            return StringLoader.fromStream(istream);
+            return StringIO.read(istream, Charsets.UTF8);
         }
-        if(new File(file).exists() ) {
-            return StringLoader.fromFile(file);
+
+        File file;        
+        if((file = new File(name)).exists()) {
+            return StringIO.read(file, Charsets.UTF8);
         }
-        if(new File("src/test/java/" + file).exists() ) {
-            return StringLoader.fromFile("src/test/java/" + file);
+        if((file = new File("src/test/java/" + name)).exists()) {
+            return StringIO.read(file, Charsets.UTF8);
         }
-        if(new File("src/test/main/" + file).exists() ) {
-            return StringLoader.fromFile("src/test/main/" + file);
+        if((file = new File("src/main/java/" + name)).exists()) {
+            return StringIO.read(file, Charsets.UTF8);
         }
-        throw new IOException("unknown location of file: " + file);
+        throw new IOException("unknown location of file: " + name);
     }
     
     /**

+ 42 - 28
assira/src/main/java/net/ranides/assira/text/StrBuilder.java

@@ -47,8 +47,8 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         this(CAPACITY);
     }
 
-    public StrBuilder(int initialCapacity) {
-        buffer = new char[initialCapacity];
+    public StrBuilder(int capacity) {
+        buffer = new char[capacity];
         options.push(new BuilderState(OPTIONS));
     }
     
@@ -61,30 +61,24 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         return size;
     }
 
-    
-    
     public int capacity() {
         return buffer.length;
     }
     
     public StrBuilder resize(int length, char c) {
         if (length < 0) {
-            throw new StringIndexOutOfBoundsException(length);
+            throw new IllegalArgumentException("negative size: " + length);
         }
         if (length > size) {
             reserve(length);
             ArrayUtils.fill(buffer, size, length, c);
-            size = length;
-        } 
+        }
+        size = length;
         return this;
     }
 
     public StrBuilder reserve(int capacity) {
-        if (capacity > buffer.length) {
-            char[] old = buffer;
-            buffer = new char[capacity * 2];
-            System.arraycopy(old, 0, buffer, 0, size);
-        }
+        buffer = ArrayAllocator.grow(buffer, capacity, size);
         return this;
     }
 
@@ -99,7 +93,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
     
     public StrBuilder trim(int n) {
         if (buffer.length > n) {
-            buffer = ArrayAllocator.trim(buffer, size);
+            buffer = ArrayAllocator.trim(buffer, Math.max(n,size));
         }
         return this;
     }
@@ -114,10 +108,12 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
     
     @Override
     public char charAt(int index) {
+        StringUtils.checkIndex(size, index);
         return buffer[index];
     }
     
     public StrBuilder setCharAt(int index, char value) {
+        StringUtils.checkIndex(size, index);
         buffer[index] = value;
         return this;
     }
@@ -133,6 +129,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
     }
     
     public char[] getChars(int begin, int end) {
+        StringUtils.checkRange(size, begin, end);
         if (end == begin) {
             return EMPTY; //NOPMD
         }
@@ -144,7 +141,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
     }
     
     public char[] getChars(int begin, int end, char target[], int offset) {
-        NativeArrayAllocator.ensureFromTo(size, begin, end);
+        StringUtils.checkRange(size, begin, end);
         System.arraycopy(buffer, begin, target, offset, end - begin);
         return target;
     }
@@ -237,7 +234,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         if (n > 0) {
             reserve(size + n);
             value.getChars(begin, end, buffer, size);
-            size += end;
+            size += n;
         }
         return this;
     }
@@ -255,7 +252,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         if (n > 0) {
             reserve(size + n);
             value.getChars(begin, end, buffer, size);
-            size += end;
+            size += n;
         }
         return this;
     }
@@ -273,7 +270,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         if (n > 0) {
             reserve(size + n);
             value.getChars(begin, end, buffer, size);
-            size += end;
+            size += n;
         }
         return this;
     }
@@ -291,7 +288,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         if (n > 0) {
             reserve(size + end);
             System.arraycopy(value, begin, buffer, size, n);
-            size += end;
+            size += n;
         }
         return this;
     }
@@ -371,17 +368,16 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
 	}
     
     public <T> StrBuilder append(NativeArray values) {
-        return append(values, i -> String.valueOf(values.get(i)));
+        return append(values.size(), i -> String.valueOf(values.get(i)));
     }
     
-    public <T> StrBuilder append(NativeArray array, IntFunction<String> function) {
-        int n = array.size();
-        if ( 0==n ) {
+    public <T> StrBuilder append(int size, IntFunction<String> function) {
+        if ( 0==size ) {
             return this;
         }
         String separator = options.peek().separator();
-		append(function.apply(0));
-        for (int i=1; i<n; i++) {
+        append(function.apply(0));
+        for (int i=1; i<size; i++) {
             append(separator).append(function.apply(i));
         }
 		return this;
@@ -392,10 +388,16 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         if (this == object) {
             return true;
         }
-        if (!(object instanceof StrBuilder)) {
-            return false;
+        if (object instanceof StrBuilder) {
+            return equalsSB((StrBuilder)object);
         }
-        StrBuilder other = (StrBuilder)object;
+        if (object instanceof CharSequence) {
+            return equalsCS((CharSequence)object);
+        }
+        return false;
+    }
+
+    private boolean equalsSB(StrBuilder other) {
         if (this.size != other.size) {
             return false;
         }
@@ -407,6 +409,18 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         return true;
     }
 
+    private boolean equalsCS(CharSequence other) {
+        if (this.size != other.length()) {
+            return false;
+        }
+        for(int i=0; i<size; i++) {
+            if(this.buffer[i] != other.charAt(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     @Override
     public int hashCode() {
         return NativeArray.wrap(buffer).hashCode(0, size);
@@ -563,7 +577,7 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
             BuilderState state = new BuilderState(OPTIONS);
             
             state.blank(this.blank());
-            state.endl(this.blank());
+            state.endl(this.endl());
             state.separator(this.separator());
             state.open(this.open());
             state.close(this.close());

+ 15 - 1
assira/src/main/java/net/ranides/assira/text/StrBuilderOptions.java

@@ -16,6 +16,8 @@ public class StrBuilderOptions implements Serializable {
     
     private static final long serialVersionUID = 1L;
     
+    private static final byte[] EMPTY = new byte[0];
+    
     protected StrBuilderOptions() {
         // do nothing
     }
@@ -63,7 +65,19 @@ public class StrBuilderOptions implements Serializable {
     public StrBuilderOptions close(String close) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public String toString() {
+        String b = hex(blank());
+        String e = hex(endl());
+        String s = hex(separator());
+        String o = hex(open());
+        String c = hex(close());
+        return "{ blank='" + b + "', endl='" + e + "', separator='" + s + "', open='" + o + "', close='" + c + "' }";
+    }
     
-    
+    private static String hex(String s) {
+        return FormatHex.format(null == s ? EMPTY : s.getBytes(Charsets.UTF8));
+    }
     
 }

+ 87 - 0
assira/src/main/java/net/ranides/assira/text/StringIO.java

@@ -0,0 +1,87 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.text;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.ArrayList;
+import java.util.List;
+import net.ranides.assira.collection.arrays.ArrayAllocator;
+
+/**
+ *
+ * @author ranides
+ */
+public final class StringIO {
+    
+    private StringIO() { }
+    
+    // @todo (assira #4) adapter Reader -- (charset) --> InputStream
+    // @todo (assira #4) adapter Writer -- (charset) --> OutputStream
+    // nie robić jak apache commons, tylko używać Charset# newEncoder() # encode(...)
+    // bo konwersja byte-by-byte po prostu jest nieprawidłowa
+    // dobra, to jest jakiś crap, przecież my z "chars" do byte robimy, więc whatever ...
+    // https://bz.apache.org/bugzilla/show_bug.cgi?id=40455
+    
+    
+    // @todo (assira #3) IOStrings #write(String, writer | stream | file)
+    // @todo (assira #3) IOStrings #writeLines(List<String>, writer | stream | file)
+
+    public static String read(Reader reader) throws IOException {
+        try {
+            char[] buffer = new char[32];
+            int r, c = 0;
+            while((r = reader.read(buffer, c, buffer.length-c)) > 0) {
+                c += r;
+                buffer = ArrayAllocator.grow(buffer, c+32);
+            }
+            return new String(buffer, 0, c);
+        } finally {
+            reader.close();
+        }
+    }
+
+    public static String read(InputStream istream, Charset charset) throws IOException {
+        try {
+            return StringIO.read(new InputStreamReader(istream, charset));
+        } finally {
+            istream.close();
+        }
+    }
+
+    public static String read(File file, Charset charset) throws IOException {
+        return StringIO.read( new FileInputStream(file), charset );
+    }
+
+    public static List<String> readLines(Reader ireader) throws IOException {
+        ArrayList<String> result = new ArrayList<>();
+        try (BufferedReader reader = new BufferedReader(ireader)) {
+            String line;
+            while( null != (line=reader.readLine())) {
+                result.add(line);
+            }
+        }
+        result.trimToSize();
+        return result;
+    }
+    
+    public static List<String> readLines(InputStream istream, Charset charset) throws IOException {
+        return StringIO.readLines(new BufferedReader(new InputStreamReader(istream, charset)));
+    }
+    
+    public static List<String> readLines(File file, Charset charset) throws IOException {
+        return StringIO.readLines(new FileInputStream(file), charset);
+    }
+    
+}

+ 0 - 104
assira/src/main/java/net/ranides/assira/text/StringLoader.java

@@ -1,104 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.text;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-import net.ranides.assira.collection.arrays.ArrayAllocator;
-
-/**
- *
- * @author ranides
- */
-public final class StringLoader {
-    
-    private StringLoader() { }
-
-    public static String fromReader(Reader reader) throws IOException {
-        try {
-            char[] buffer = new char[32];
-            int r, c = 0;
-            while((r = reader.read(buffer, c, buffer.length-c)) > 0) {
-                c += r;
-                buffer = ArrayAllocator.grow(buffer, c+32);
-            }
-            return new String(buffer, 0, c);
-        } finally {
-            reader.close();
-        }
-    }
-
-    public static String fromStream(InputStream istream, Charset charset) throws IOException {
-        try {
-            return fromReader(new InputStreamReader(istream, charset));
-        } finally {
-            istream.close();
-        }
-    }
-
-    public static String fromStream(InputStream istream) throws IOException {
-        return fromStream(istream, Charsets.UTF8);
-    }
-
-
-    public static String fromFile(File file, Charset charset) throws IOException {
-        return fromStream( new FileInputStream(file), charset );
-    }
-
-    public static String fromFile(File file) throws IOException {
-        return fromFile(file, Charsets.UTF8);
-    }
-
-    public static String fromFile(String path, Charset charset) throws IOException {
-        return fromFile(new File(path), charset);
-    }
-
-    public static String fromFile(String path) throws IOException {
-        return fromFile(path, Charsets.UTF8 );
-    }
-    
-    public static List<String> linesFromReader(Reader ireader) throws IOException {
-        ArrayList<String> result = new ArrayList<>();
-        try (BufferedReader reader = new BufferedReader(ireader)) {
-            String line;
-            while( null != (line=reader.readLine())) {
-                result.add(line);
-            }
-        }
-        result.trimToSize();
-        return result;
-    }
-    
-    public static List<String> linesFromStream(InputStream istream, Charset charset) throws IOException {
-        return linesFromReader(new BufferedReader(new InputStreamReader(istream, charset)));
-    }
-    
-    public static List<String> linesFromFile(File file, Charset charset) throws IOException {
-        return linesFromStream(new FileInputStream(file), charset);
-    }
-    
-    public static List<String> linesFromFile(String file, Charset charset) throws IOException {
-        return linesFromFile(new File(file), charset);
-    }
-    
-    public static List<String> linesFromFile(File file) throws IOException {
-        return linesFromFile(file, Charsets.UTF8);
-    }
-    
-    public static List<String> linesFromFile(String file) throws IOException {
-        return linesFromFile(file, Charsets.UTF8);
-    }
-    
-}

+ 3 - 4
assira/src/main/java/net/ranides/assira/text/StringUtils.java

@@ -21,7 +21,6 @@ import java.util.Locale;
 import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import net.ranides.assira.collection.arrays.NativeArrayAllocator;
 import net.ranides.assira.lexer.CharStreamer;
 import net.ranides.assira.math.MathUtils;
 import net.ranides.assira.reflection.util.ReflectUtils;
@@ -903,13 +902,13 @@ public final class StringUtils {
 
     }
     
-    private static void checkIndex(int size, int index) {
+    static void checkIndex(int size, int index) {
         if( index<0 || index >= size ) {
             throw new StringIndexOutOfBoundsException(index);
         }
     }
     
-    private static void checkRange(int size, int begin, int end) {
+    static void checkRange(int size, int begin, int end) {
         if (begin < 0) {
             throw new StringIndexOutOfBoundsException(begin);
         }
@@ -917,7 +916,7 @@ public final class StringUtils {
             throw new StringIndexOutOfBoundsException(end);
         }
         if (end < begin) {
-            throw new StringIndexOutOfBoundsException(begin + " shoud be <= " + end);
+            throw new IllegalArgumentException("Start index (" + begin + ") is greater than end index (" + end + ")");
         }
     }
 	

+ 93 - 0
assira/src/test/java/net/ranides/assira/text/StringIOTest.java

@@ -0,0 +1,93 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.text;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class StringIOTest {
+    
+    public StringIOTest() {
+    }
+
+    @Test
+    public void testFromReader() throws IOException {
+        String inp1 = "Hello world";
+        String out1 = StringIO.read(new StringReader(inp1));
+        assertEquals(inp1, out1);
+        
+        String inp2 = random(10247) ;
+        String out2 = StringIO.read(new StringReader(inp2));
+        assertEquals(inp2, out2);
+    }
+    
+    @Test
+    public void testFromStream() throws IOException {
+        String text = "źrebię skacze po łące patrząc na słońce";
+        
+        ByteArrayInputStream istream1 = new ByteArrayInputStream(text.getBytes(Charsets.UTF8));
+        ByteArrayInputStream istream2 = new ByteArrayInputStream(text.getBytes(Charsets.PL_WINDOWS));
+        
+        assertNotEquals(text, StringIO.read(istream1, Charsets.PL_WINDOWS));
+        istream1.reset();
+        assertEquals(text, StringIO.read(istream1, Charsets.UTF8));
+        
+        assertNotEquals(text, StringIO.read(istream2, Charsets.UTF8));
+        istream2.reset();
+        assertEquals(text, StringIO.read(istream2, Charsets.PL_WINDOWS));
+    }
+    
+    @Test
+    public void testLinesFromReader() throws IOException {
+        String c1 = "1\n2\n3\n4\n5";
+        String c2 = "1\n2\n3\n4\n5\n";
+        List<String> expected = Arrays.asList("1","2", "3", "4", "5");
+        
+        assertEquals(expected, StringIO.readLines(new StringReader(c1)));
+        assertEquals(expected, StringIO.readLines(new StringReader(c2)));
+    }
+    
+    @Test
+    public void testLinesFromStream_UTF8() throws IOException {
+        ByteArrayInputStream s1 = new ByteArrayInputStream("słońce\nźrebię\nłąka\ndom".getBytes(Charsets.UTF8));
+        ByteArrayInputStream s2 = new ByteArrayInputStream("słońce\nźrebię\nłąka\ndom\n".getBytes(Charsets.UTF8));
+        List<String> expected = Arrays.asList("słońce", "źrebię", "łąka", "dom");
+        
+        assertEquals(expected, StringIO.readLines(s1, Charsets.UTF8));
+        assertEquals(expected, StringIO.readLines(s2, Charsets.UTF8));
+    }
+    
+    @Test
+    public void testLinesFromStream_CS() throws IOException {
+        ByteArrayInputStream s1 = new ByteArrayInputStream("słońce\nźrebię\nłąka\ndom".getBytes(Charsets.PL_DOS));
+        ByteArrayInputStream s2 = new ByteArrayInputStream("słońce\nźrebię\nłąka\ndom\n".getBytes(Charsets.PL_DOS));
+        List<String> expected = Arrays.asList("słońce", "źrebię", "łąka", "dom");
+        
+        assertEquals(expected, StringIO.readLines(s1, Charsets.PL_DOS));
+        assertEquals(expected, StringIO.readLines(s2, Charsets.PL_DOS));
+    }
+
+    
+    private String random(int size) {
+        Random rand = new Random(777);
+        char[] c = new char[size];
+        for(int i=0; i<size; i++) {
+            c[i] = (char)(' ' + rand.nextInt(64));
+        }
+        return new String(c);
+    }
+}

+ 0 - 43
assira/src/test/java/net/ranides/assira/text/StringLoaderTest.java

@@ -1,43 +0,0 @@
-/*
- * @author Ranides Atterwim <ranides@gmail.com>
- * @copyright Ranides Atterwim
- * @license WTFPL
- * @url http://ranides.net/projects/assira
- */
-package net.ranides.assira.text;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.Random;
-import org.junit.Test;
-import static org.junit.Assert.*;
-
-/**
- *
- * @author Ranides Atterwim <ranides@gmail.com>
- */
-public class StringLoaderTest {
-    
-    public StringLoaderTest() {
-    }
-
-    @Test
-    public void testFromReader() throws IOException {
-        String inp1 = "Hello world";
-        String out1 = StringLoader.fromReader(new StringReader(inp1));
-        assertEquals(inp1, out1);
-        
-        String inp2 = random(10247) ;
-        String out2 = StringLoader.fromReader(new StringReader(inp2));
-        assertEquals(inp2, out2);
-    }
-    
-    private String random(int size) {
-        Random rand = new Random(777);
-        char[] c = new char[size];
-        for(int i=0; i<size; i++) {
-            c[i] = (char)(' ' + rand.nextInt(64));
-        }
-        return new String(c);
-    }
-}

+ 56 - 0
assira/src/test/java/net/ranides/assira/text/StringTester.java

@@ -0,0 +1,56 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.text;
+
+import static net.ranides.assira.junit.NewAssert.*;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public final class StringTester {
+    
+    private StringTester() {
+        /* utility class */
+    }
+    
+    public static void assertString(String expected, CharSequence value) {
+        
+        assertEquals(expected, value.toString());
+        
+        assertTrue(expected.contentEquals(value));
+        
+        cmp(expected, value);
+                
+        assertThrows(IndexOutOfBoundsException.class, ()->{
+            value.charAt(-1);
+        });
+        assertThrows(IndexOutOfBoundsException.class, ()->{
+            value.charAt(value.length());
+        });
+        assertThrows(IndexOutOfBoundsException.class, ()->{
+            value.charAt(value.length()+1);
+        });
+        assertThrows(IndexOutOfBoundsException.class, ()->{
+            value.subSequence(1, value.length()+2);
+        });
+        assertThrows(IndexOutOfBoundsException.class, ()->{
+            value.subSequence(-1, 2);
+        });
+        assertThrows(IllegalArgumentException.class, ()->{
+            value.subSequence(2, 1);
+        });
+    }
+    
+    private static void cmp(CharSequence expected, CharSequence value) {
+        String message = "'" + expected + "' != '" + value + "'";
+        assertEquals(message, expected.length(), value.length());
+        for(int i=0, n=expected.length(); i<n; i++) {
+            assertEquals("At ["+i+"] " + message, expected.charAt(i), value.charAt(i));
+        }
+    }
+}

+ 19 - 36
assira/src/test/java/net/ranides/assira/text/StringUtilsTest.java

@@ -18,7 +18,11 @@ import org.junit.Test;
  *
  * @author Ranides Atterwim <ranides@gmail.com>
  */
-@SuppressWarnings("PMD.AvoidDuplicateLiterals")
+@SuppressWarnings({
+    "PMD.AvoidDuplicateLiterals",
+    "PMD.TooManyPublicMethods",
+    "PMD.TooManyDifferentMethods"
+})
 public class StringUtilsTest {
 	
 	public StringUtilsTest() {
@@ -508,50 +512,29 @@ c*/
     }
     
     @Test
-    public void testWrap() {
-        assertString("Hel", StringUtils.wrap("Hel".toCharArray()));
-        assertString("Hel", StringUtils.wrap("Hello".toCharArray(),0,3));
-        assertString("l" , StringUtils.wrap("Hello".toCharArray(),2,3));
-        assertString("llo", StringUtils.wrap("Hello".toCharArray(),2,5));
+    public void testWrap() { //NOPMD
+        StringTester.assertString("Hel", StringUtils.wrap("Hel".toCharArray()));
+        StringTester.assertString("Hel", StringUtils.wrap("Hello".toCharArray(),0,3));
+        StringTester.assertString("l" , StringUtils.wrap("Hello".toCharArray(),2,3));
+        StringTester.assertString("llo", StringUtils.wrap("Hello".toCharArray(),2,5));
         
-        assertString("ello wo", StringUtils.wrap("Hello world".toCharArray()).subSequence(1, 8) );
+        StringTester.assertString("ello wo", StringUtils.wrap("Hello world".toCharArray()).subSequence(1, 8) );
     }
     
     @Test
-    public void testRepeatChar() {
-        assertString("...", StringUtils.repeat(3,'.'));
-        assertString(".....", StringUtils.repeat(16,'.').subSequence(3, 8));
+    public void testRepeatChar() { //NOPMD
+        StringTester.assertString("...", StringUtils.repeat(3,'.'));
+        StringTester.assertString(".....", StringUtils.repeat(16,'.').subSequence(3, 8));
     }
     
     @Test
-    public void testRepeatString() {
-        assertString("rerere", StringUtils.repeat(3,"re"));
-        assertString("arvarvar", StringUtils.repeat(4,"var").subSequence(4, 12));
-        assertString("arvarvarv", StringUtils.repeat(5,"var").subSequence(4, 13));
+    public void testRepeatString() { //NOPMD
+        StringTester.assertString("rerere", StringUtils.repeat(3,"re"));
+        StringTester.assertString("arvarvar", StringUtils.repeat(4,"var").subSequence(4, 12));
+        StringTester.assertString("arvarvarv", StringUtils.repeat(5,"var").subSequence(4, 13));
     }
     
-    private void assertString(String expected, CharSequence value) {
-        assertTrue(expected.contentEquals(value));
-        assertEquals(expected, value.toString());
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.charAt(-1);
-        });
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.charAt(value.length());
-        });
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.charAt(value.length()+1);
-        });
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.subSequence(1, value.length()+2);
-        });
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.subSequence(-1, 2);
-        });
-        assertThrows(IndexOutOfBoundsException.class, ()->{
-            value.subSequence(2, 1);
-        });
-    }
+    
     
     @Test
     public void testIsEmpty() {