Selaa lähdekoodia

fix: DataAdapter#asReader#read
fix: DataAdapter#asReader#skip
fix: DataAdapter#asReader#ready

test: Reader

Ranides Atterwim 10 vuotta sitten
vanhempi
commit
0219e9b0c6

+ 76 - 12
assira/src/main/java/net/ranides/assira/io/DataAdapter.java

@@ -98,17 +98,36 @@ public final class DataAdapter {
 
         @Override
         public int read() throws IOException {
-            return idata.readByte();
+            System.err.printf(">>read x%n");
+            try {
+                return idata.readByte();
+            } catch(EOFException cause) {
+                return -1;
+            }
         }
 
         @Override
         public int read(byte[] target, int offset, int len) throws IOException {
+            System.err.printf(">>read 1%n");
+            // tutaj musimy w rękach byte-by-byte czytać, bo readFully nie potrafi kawałka pobrać
+            // ma zupełnie inną semantykę niż #read
+            int ret = 0;
             try {
-                idata.readFully(target, offset, len);
-                return len;
+                target[offset++] = idata.readByte();
+                ret++;
+            } catch(EOFException cause) {
+                return -10;
+            }
+            try {
+                while(ret < len) {
+                    target[offset++] = idata.readByte();
+                    ret++;
+                }
             } catch (EOFException cause) {
-                return -1;
+                // do nothing
             }
+            System.err.printf(">>read 2%n");
+            return ret;
         }
 
         @Override
@@ -198,9 +217,10 @@ public final class DataAdapter {
         
     }
     
-    private static class DIReader extends Reader {
+    static class DIReader extends Reader {
         
-        private final DataInput idata;
+        Character last;
+        final DataInput idata;
 
         public DIReader(DataInput idata) {
             this.idata = idata;
@@ -213,26 +233,70 @@ public final class DataAdapter {
         
         @Override
         public int read() throws IOException {
-            return idata.readChar();
+            if(last != null) {
+                int ret = last;
+                last = null;
+                return ret;
+            }
+            try {
+                return idata.readChar();
+            } catch(EOFException cause) {
+                return -1;
+            }
         }
 
         @Override
         public int read(char[] target, int offset, int len) throws IOException {
+            int ret = 0;
+            if(last != null) {
+                target[offset++] = last;
+                last = null;
+            } else {
+                try {
+                    target[offset++] = idata.readChar();
+                    ret++;
+                } catch(EOFException cause) {
+                    return -1;
+                }
+            }
             try {
-                for(int i=offset, n=offset+len; i<n; i++) {
-                    target[i] = idata.readChar();
+                while(ret < len) {
+                    target[offset++] = idata.readChar();
+                    ret++;
                 }
-                return len;
             } catch (EOFException cause) {
-                return -1;
+                // do nothing
             }
+            return ret;
         }
 
         @Override
         public long skip(long count) throws IOException {
             assert count == (int) count;
-            return idata.skipBytes(2*(int)count);
+            if(count <=0 ) {
+                return 0;
+            }
+            if(last != null) {
+                last = null;
+                count--;
+            }
+            return idata.skipBytes(2*(int)count) / 2;
+        }
+
+        @Override
+        public boolean ready() throws IOException {
+            if(last != null) {
+                return true;
+            }
+            try {
+                last = idata.readChar();
+                return true;
+            } catch(EOFException cause) {
+                return false;
+            }
         }
+        
+        
                 
     }
 }

+ 31 - 0
assira/src/main/java/net/ranides/assira/test/TReader.java

@@ -0,0 +1,31 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.test;
+
+import java.io.Reader;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public interface TReader {
+
+    void append(Reader reader, String text);
+    
+    static String decode(int[] codepoints) {
+        return new String(codepoints, 0, codepoints.length);
+    }
+    
+    static int[] encode(String value) {
+        int[] a = new int[ value.codePointCount(0, value.length())];
+        for(int i=0; i<a.length; i++) {
+            a[i] = value.codePointAt(i);
+        }
+        return a;
+    }
+    
+}

+ 8 - 0
assira/src/main/java/net/ranides/assira/text/StrBuilder.java

@@ -446,6 +446,10 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
         return new SReader();
     }
     
+    static StrBuilder reader_append(Reader reader, String text) {
+        return ((SReader)reader).parent().append(text);
+    }
+    
     private final class SReader extends Reader {
         
         private int pos;
@@ -509,6 +513,10 @@ public final class StrBuilder implements CharSequence, Appendable, Serializable
             pos = mark;
         }
         
+        StrBuilder parent() {
+            return StrBuilder.this;
+        }
+        
     }
 
     private final class SWriter extends Writer {

+ 84 - 0
assira/src/test/java/net/ranides/assira/io/DataAdapterTest.java

@@ -0,0 +1,84 @@
+/*
+ * @author Ranides Atterwim <ranides@gmail.com>
+ * @copyright Ranides Atterwim
+ * @license WTFPL
+ * @url http://ranides.net/projects/assira
+ */
+package net.ranides.assira.io;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import net.ranides.assira.ContractTesters;
+import net.ranides.assira.collection.arrays.ArrayUtils;
+import net.ranides.assira.test.TReader;
+import net.ranides.assira.text.Charsets;
+import static org.junit.Assert.*;
+import org.junit.Test;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class DataAdapterTest {
+    
+    public DataAdapterTest() {
+    }
+
+    @Test
+    public void testAsReader() throws IOException {
+        // @todo (assira #0) DataBuffer implements DataInput, DataOutput
+        // @todo (assira #2) ContractTesterRunner support for testMethod(Function<String,Interface> generator)
+        //      ponieważ to trudne, to może po prostu ReaderTester będzie konwertował String na byte ?
+        //      to chyba nie przejdzie
+        //      oczywiście, że przejdzie. przecież przekazujemy int[]
+        //      możemy String <-> codepoints konwertować jednoznacznie
+        //      przekażemy int[] a potem sobie z tego String zrobimy i wykorzystamy po prostru TReader#append(string)
+        //      żadnych modyfikacji w assira.junit
+        //
+        //      w praktyce to po prostu kolejny test-case będzie w testerze.
+        //      w teście po prostu musimy zmyślną funkcję-generator napisać i przekazywać do TesterRunner#run
+        
+        
+        TReader tr = (Reader r, String v) -> {
+            ((FDStream)((DataAdapter.DIReader)r).idata).append(v);
+        };
+        ContractTesters.runner()
+            .param("reader!", tr)
+            .ignore("ReaderTester.functionalMark")
+            .run(()->DataAdapter.asReader(new FDStream()));
+        
+        assertEquals("Hello world", TReader.decode(TReader.encode("Hello world")));
+    }
+    
+    private static final class FDStream extends DataInputStream {
+        
+        public FDStream() {
+            super(new FIStream());
+        }
+        
+        public void append(String value) {
+            FIStream fis = ((FIStream)in);
+            fis.buffer = ArrayUtils.concat(fis.buffer, value.getBytes(Charsets.UTF16BE));
+        }
+        
+    }
+    
+    private static final class FIStream extends InputStream  {
+        
+        byte[] buffer = new byte[0];
+        int position = 0;
+
+        @Override
+        public int read() throws IOException {
+            if(position >= buffer.length) {
+                return -1;
+            }
+            return buffer[position++];
+        }
+        
+    }
+    
+    
+}

+ 1 - 1
assira/src/test/java/net/ranides/assira/reflection/util/ClassUtilsTest.java

@@ -82,7 +82,7 @@ public class ClassUtilsTest {
 	@Test
 	public void testIsChild() throws Exception {
 		ClassLoader loader0 = getClass().getClassLoader();
-		ClassLoader loader1 = newLoader(loader0, "../assira.rules/target/assira.rules-1.1.jar");
+		ClassLoader loader1 = newLoader(loader0, "../assira.rules/target/assira.rules-2.0.1.jar");
 		ClassLoader loader2 = newLoader(loader1, "../assira.test/target/assira.test-2.0.0.jar");
 		
 		assertTrue(ClassUtils.isChild(loader0, loader2));

+ 90 - 0
assira/src/test/java/net/ranides/assira/text/ReaderTester.java

@@ -0,0 +1,90 @@
+/*
+ * @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.Reader;
+import javax.annotation.Resource;
+import net.ranides.assira.junit.TestContract;
+import net.ranides.assira.test.TReader;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ * @author Ranides Atterwim <ranides@gmail.com>
+ */
+public class ReaderTester {
+    
+    @Resource(name = "reader!")
+    private TReader tr;
+    
+    @TestContract
+    public void functionalRead(Reader reader) throws IOException {
+        tr.append(reader, "Hello world");
+        
+        // #close should be NOP
+        reader.close();
+        
+        int a = reader.read();
+        assertEquals('H', (char)a);
+        
+        char[] b = ".##...".toCharArray();
+        assertEquals(2, reader.read(b, 1, 2));
+        assertArrayEquals(".el...".toCharArray(), b);
+
+        assertEquals(0, reader.skip(-5));        
+        assertEquals(5, reader.skip(5));
+        
+        char[] c = ".###...".toCharArray();
+        assertEquals(3, reader.read(c, 1, 4));
+        assertArrayEquals(".rld...".toCharArray(), c);
+        
+        assertFalse(reader.ready());
+        assertEquals(0, reader.skip(3));
+        assertEquals(-1, reader.read());
+        
+        tr.append(reader, "!? ");
+        assertTrue(reader.ready());
+        assertEquals('!', (char)reader.read());
+        assertEquals(2, reader.skip(7));
+        assertFalse(reader.ready());
+        assertFalse(reader.ready());
+        
+        tr.append(reader, "text.");
+        assertTrue(reader.ready());
+        assertTrue(reader.ready());
+        
+        reader.close();
+    }
+    
+    @TestContract
+    public void functionalMark(Reader reader) throws IOException {
+        
+        tr.append(reader, "text.");
+        assertTrue(reader.ready());
+        assertTrue(reader.ready());
+        assertTrue(reader.markSupported());
+        
+        reader.mark(100);
+        char d[] = "-----".toCharArray();
+        assertEquals(5, reader.read(d, 0, 5));
+        assertArrayEquals("text.".toCharArray(), d);
+        
+        char e[] = "-----".toCharArray();
+        assertEquals(-1, reader.read(e, 0, 30));
+        assertEquals(-1, reader.read(e, 0, 30));
+        reader.reset();
+        assertEquals(5, reader.read(e, 0, 30));
+        assertArrayEquals("text.".toCharArray(), e);
+        
+        reader.close();
+    }
+    
+}

+ 8 - 55
assira/src/test/java/net/ranides/assira/text/StrBuilderTest.java

@@ -7,14 +7,14 @@
 package net.ranides.assira.text;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
-import edu.umd.cs.findbugs.annotations.SuppressWarnings;
 import java.io.IOException;
-import java.io.Reader;
 import java.io.Writer;
 import java.util.Arrays;
 import java.util.List;
+import net.ranides.assira.ContractTesters;
 import net.ranides.assira.collection.arrays.NativeArray;
 import static net.ranides.assira.junit.NewAssert.*;
+import net.ranides.assira.test.TReader;
 import org.junit.Test;
 
 /**
@@ -50,9 +50,7 @@ public class StrBuilderTest {
             .close()
             .endl();
                 
-        if(false) { // NOPMD
-            System.out.printf("%s%n", sb.toString());
-        }
+//        System.out.printf("%s%n", sb.toString());
         
         String expected = String.format(
             "{ a1,b1,c1,d1 }%n" +
@@ -79,9 +77,8 @@ public class StrBuilderTest {
                 .close()
             .close();
         
-        if(false) {
-            System.out.printf("%s%n", sb.toString());
-        }
+//        System.out.printf("%s%n", sb.toString());
+
         assertEquals("{1-2-3} <1+2+3 (1+2+3 //1+2+3 ))>", sb.toString());
         
         assertThrows(IllegalStateException.class, sb::close);
@@ -465,53 +462,9 @@ public class StrBuilderTest {
     
     @Test
     public void testReader() throws IOException {
-        StrBuilder sb = new StrBuilder();
-        Reader reader = sb.asReader();
-        sb.append("Hello world");
-        
-        // #close should be NOP
-        reader.close();
-        
-        int a = reader.read();
-        assertEquals('H', (char)a);
-        
-        char[] b = ".##...".toCharArray();
-        assertEquals(2, reader.read(b, 1, 2));
-        assertArrayEquals(".el...".toCharArray(), b);
-
-        assertEquals(0, reader.skip(-5));        
-        assertEquals(5, reader.skip(5));
-        
-        char[] c = ".###...".toCharArray();
-        assertEquals(3, reader.read(c, 1, 30));
-        assertArrayEquals(".rld...".toCharArray(), c);
-        
-        assertFalse(reader.ready());
-        assertEquals(0, reader.skip(3));
-        assertEquals(-1, reader.read());
-        
-        sb.append("!? ");
-        assertTrue(reader.ready());
-        assertEquals('!', (char)reader.read());
-        assertEquals(2, reader.skip(7));
-        assertFalse(reader.ready());
-        
-        sb.append("text.");
-        assertTrue(reader.ready());
-        assertTrue(reader.markSupported());
-        reader.mark(100);
-        char d[] = "-----".toCharArray();
-        assertEquals(5, reader.read(d, 0, 5));
-        assertArrayEquals("text.".toCharArray(), d);
-        
-        char e[] = "-----".toCharArray();
-        assertEquals(-1, reader.read(e, 0, 30));
-        assertEquals(-1, reader.read(e, 0, 30));
-        reader.reset();
-        assertEquals(5, reader.read(e, 0, 30));
-        assertArrayEquals("text.".toCharArray(), e);
-        
-        reader.close();
+        ContractTesters.runner()
+            .param("reader!", (TReader)StrBuilder::reader_append)
+            .run(()->new StrBuilder().asReader());
     }
     
     @Test