diff --git a/src/test/java/io/usethesource/vallang/basic/BasicValueSmokeTest.java b/src/test/java/io/usethesource/vallang/basic/BasicValueSmokeTest.java index 572cea69..57763119 100644 --- a/src/test/java/io/usethesource/vallang/basic/BasicValueSmokeTest.java +++ b/src/test/java/io/usethesource/vallang/basic/BasicValueSmokeTest.java @@ -174,6 +174,27 @@ public void testStringWrite(IValueFactory vf) { } } + @ParameterizedTest @ArgumentsSource(ValueProvider.class) + public void testStringRead(IValueFactory vf) { + Random rnd = new Random(); + + for (int i = 0; i < 1000; i++) { + IString testString = vf.string(RandomUtil.string(rnd, rnd.nextInt(200))); + var result = new StringBuilder(); + try (var r = testString.asReader()) { + char[] buffer = new char[1024]; + int read = 0; + while ((read = r.read(buffer)) > 0) { + result.append(buffer, 0, read); + } + } catch (IOException e) { + fail(e.getMessage()); + } + + assertEqual(testString, vf.string(result.toString())); + } + } + @ParameterizedTest @ArgumentsSource(ValueProvider.class) public void testStringEmptyWrite(IValueFactory vf) { IString testString = vf.string(""); @@ -284,6 +305,7 @@ private void checkIndent(IValueFactory vf, String indent, String newline, boolea assertSimilarIteration(indentedDirect, indentedConcatTree); assertEqualLength(indentedDirect, indentedConcatTree); assertEqual(indentedDirect, indentedConcatTree); + assertEqualWriteAndRead(indentedDirect, indentedConcatTree); assertEquals(indentedDirect.hashCode(), indentedConcatTree.hashCode()); // these modify internal structure as a side-effect, so after this we test the above again! @@ -298,6 +320,7 @@ private void checkIndent(IValueFactory vf, String indent, String newline, boolea assertSimilarIteration(vf.string(expected), indentedConcatTree); assertSimilarIteration(indentedDirect, indentedConcatTree); assertEqual(indentedDirect, indentedConcatTree); + assertEqualWriteAndRead(indentedDirect, indentedConcatTree); assertEquals(indentedDirect.hashCode(), indentedConcatTree.hashCode()); // basic tests showing lazy versus eager indentation should have the same semantics: @@ -306,6 +329,7 @@ private void checkIndent(IValueFactory vf, String indent, String newline, boolea assertSimilarIteration(vf.string(expectedTwice), indentedDirectTwice); assertSimilarIteration(vf.string(expectedTwice), indentedConcatTreeTwice); assertEqual(indentedDirectTwice, indentedConcatTreeTwice); + assertEqualWriteAndRead(indentedDirectTwice, indentedConcatTreeTwice); assertSimilarIteration(indentedDirectTwice, indentedConcatTreeTwice); assertEquals(indentedDirectTwice.hashCode(), indentedConcatTreeTwice.hashCode()); @@ -326,10 +350,40 @@ private void checkIndent(IValueFactory vf, String indent, String newline, boolea assertSimilarIteration(vf.string(expectedTwice), indentedDirectTwice); assertSimilarIteration(vf.string(expectedTwice), indentedConcatTreeTwice); assertEqual(indentedDirectTwice, indentedConcatTreeTwice); + assertEqualWriteAndRead(indentedDirectTwice, indentedConcatTreeTwice); assertSimilarIteration(indentedDirectTwice, indentedConcatTreeTwice); assertEquals(indentedDirectTwice.hashCode(), indentedConcatTreeTwice.hashCode()); } + + private String writerToString(IString a) { + try { + var result = new StringWriter(); + a.write(result); + return result.toString(); + } catch (IOException e) { + fail("IString::write failed", e); + return ""; + } + } + + private String readerToString(IString a) { + try (var r = a.asReader()) { + var result = new StringWriter(); + a.asReader().transferTo(result); + return result.toString(); + } catch (IOException e) { + fail("IString::asReader failed", e); + return ""; + } + } + + + private void assertEqualWriteAndRead(IString one, IString two) { + assertEquals(writerToString(one), writerToString(two), "IString::write had different results"); + assertEquals(readerToString(one), readerToString(two), "IString::asReader had different results"); + } + private void assertEqualCharAt(IString one, IString two) { assertEquals(one, two); diff --git a/src/test/java/io/usethesource/vallang/basic/LazyStringOperationsTest.java b/src/test/java/io/usethesource/vallang/basic/LazyStringOperationsTest.java index 02fb70ee..17dc85ef 100644 --- a/src/test/java/io/usethesource/vallang/basic/LazyStringOperationsTest.java +++ b/src/test/java/io/usethesource/vallang/basic/LazyStringOperationsTest.java @@ -4,6 +4,7 @@ import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; +import java.io.Reader; import java.io.StringWriter; import java.util.Random; @@ -192,8 +193,22 @@ public void testStringReplace(IValueFactory vf) { vf.string("abcdefxygh").concat(str.substring(8))); } + private String fromReader(Reader r) throws IOException { + try { + var result = new StringBuilder(); + char[] buffer = new char[8 * 1024]; + int read = 0; + while ((read = r.read(buffer)) > 0) { + result.append(buffer, 0, read); + } + return result.toString(); + } finally { + r.close(); + } + } + @ParameterizedTest @ArgumentsSource(ValueProvider.class) - public void neverRunOutOfStack(IValueFactory vf) { + public void neverRunOutOfStack(IValueFactory vf) throws IOException { int outofStack = 100000; // first we have to know for sure that we would run out of stack with @see @@ -216,6 +231,16 @@ public void neverRunOutOfStack(IValueFactory vf) { // TODO Auto-generated catch block fail("unexpected IO:" + e); } + try { + fromReader(v.asReader()); + fail("this should run out of stack"); + } catch (StackOverflowError e) { + // yes, that is what is expected + } catch (IOException e) { + // TODO Auto-generated catch block + fail("unexpected IO:" + e); + } + } finally { StringValue.resetMaxFlatString(); StringValue.resetMaxUnbalance(); @@ -231,6 +256,8 @@ public void neverRunOutOfStack(IValueFactory vf) { try { new StringWriter().write(v.toString()); // do not remove this, this is the test assertTrue(true); + fromReader(v.asReader()); + assertTrue(true); } catch (StackOverflowError e) { fail("the tree balancer should have avoided a stack overflow"); }