comparison tests/OnClientTester.java @ 616:65641a7cea31

Implement line ending conversion for downloads MonetConnection.Download#getStream returns an InputStream which converts line endings when in text mode. The default line ending is the platform line ending but that can be changed. Setting it to \n can be a useful optimization if you don't need the \r's anyway.
author Joeri van Ruth <joeri.van.ruth@monetdbsolutions.com>
date Wed, 19 Jan 2022 14:58:01 +0100 (2022-01-19)
parents 34a15cd8cfc2
children 21d0f4a43697
comparison
equal deleted inserted replaced
615:34a15cd8cfc2 616:65641a7cea31
26 import java.sql.ResultSetMetaData; 26 import java.sql.ResultSetMetaData;
27 import java.sql.Statement; 27 import java.sql.Statement;
28 import java.sql.SQLException; 28 import java.sql.SQLException;
29 import java.util.ArrayList; 29 import java.util.ArrayList;
30 import java.util.List; 30 import java.util.List;
31 import java.util.Random;
31 import java.util.zip.GZIPOutputStream; 32 import java.util.zip.GZIPOutputStream;
32 33
33 import static java.nio.file.StandardOpenOption.CREATE_NEW; 34 import static java.nio.file.StandardOpenOption.CREATE_NEW;
34 35
35 36
145 test_ClientRefusesDownload(); 146 test_ClientRefusesDownload();
146 if (isSelected("LargeUpload")) 147 if (isSelected("LargeUpload"))
147 test_LargeUpload(); 148 test_LargeUpload();
148 if (isSelected("LargeDownload")) 149 if (isSelected("LargeDownload"))
149 test_LargeDownload(); 150 test_LargeDownload();
151 if (isSelected("DownloadCrLf"))
152 test_DownloadCrLf();
150 if (isSelected("UploadFromStream")) 153 if (isSelected("UploadFromStream"))
151 test_UploadFromStream(); 154 test_UploadFromStream();
152 if (isSelected("UploadFromReader")) 155 if (isSelected("UploadFromReader"))
153 test_UploadFromReader(); 156 test_UploadFromReader();
154 if (isSelected("UploadFromReaderOffset")) 157 if (isSelected("UploadFromReaderOffset"))
600 initTest("test_LargeDownload"); 603 initTest("test_LargeDownload");
601 test_Download(4_000_000); 604 test_Download(4_000_000);
602 exitTest(); 605 exitTest();
603 } 606 }
604 607
608 private void test_DownloadCrLf() throws SQLException, Failure, IOException {
609
610 // This tests forces line ending conversion and reads in small batches, hoping to trigger corner cases
611
612 initTest("test_DownloadCrLf");
613 prepare();
614 update("ALTER TABLE foo DROP COLUMN t");
615 update("ALTER TABLE foo ADD COLUMN j INT");
616 update("INSERT INTO foo SELECT rand() % CASE WHEN value % 10 = 0 THEN 1000 ELSE 10 END AS i, 0 AS j FROM generate_series(0, 500000)");
617 ByteArrayOutputStream target = new ByteArrayOutputStream();
618 Random rng = new Random(42);
619 DownloadHandler handler = (handle, name, textMode) -> {
620 handle.setLineSeparator("\r\n");
621 InputStream s = handle.getStream();
622 byte[] buf = new byte[10];
623 boolean expectEof = false;
624 for (;;) {
625 int n = rng.nextInt(buf.length - 1) + 1;
626 int nread = s.read(buf, 0, n);
627 if (nread < 0) {
628 break;
629 }
630 target.write(buf, 0, nread);
631 }
632
633 };
634 conn.setDownloadHandler(handler);
635 update("COPY SELECT * FROM foo INTO 'banana' ON CLIENT");
636 // go to String instead of byte[] because Strings have handy replace methods.
637 String result = new String(target.toByteArray(), StandardCharsets.UTF_8);
638
639 // It should contain only \r\n's, no lonely \r's or \n's.
640 String replaced = result.replaceAll("\r\n", "XX");
641
642 assertEq("Index of first lonely \\r", -1, replaced.indexOf('\r'));
643 assertEq("Index of first lonely \\n", -1, replaced.indexOf('\n'));
644
645 String withoutData = result.replaceAll("[0-9]", "");
646 Files.writeString(Path.of("/tmp/x.csv"), withoutData, StandardCharsets.UTF_8);
647 assertEq("Length after dropping data, modulo 3", 0, withoutData.length() % 3);
648 for (int i = 0; i < withoutData.length(); i += 3) {
649 String sub = withoutData.substring(i, i+3);
650 if (!sub.equals("|\r\n")) {
651 fail(String.format(
652 "At index %d out of %d in the skeleton (=digits removed) we find <%02x %02x %02x> instead of <7c 0d 0a>",
653 i, withoutData.length(),
654 (int)sub.charAt(0), (int)sub.charAt(1), (int)sub.charAt(2)));
655 }
656 }
657 // only to show some succesful output if the above succeeds
658 assertEq("Every 3-byte normalized chunk", "|\\r\\n", "|\\r\\n");
659
660 exitTest();
661 }
662
605 private void test_UploadFromStream() throws SQLException, Failure { 663 private void test_UploadFromStream() throws SQLException, Failure {
606 initTest("test_UploadFromStream"); 664 initTest("test_UploadFromStream");
607 prepare(); 665 prepare();
608 UploadHandler handler = new UploadHandler() { 666 UploadHandler handler = new UploadHandler() {
609 final String data = "1|one\n2|two\n3|three\n"; 667 final String data = "1|one\n2|two\n3|three\n";
892 exitTest(); 950 exitTest();
893 } 951 }
894 952
895 953
896 /* utility methods */ 954 /* utility methods */
955 private void say(String message) throws Failure {
956 outBuffer.append(message).append("\n");
957 throw new Failure(message);
958 }
959
897 private void fail(String message) throws Failure { 960 private void fail(String message) throws Failure {
898 outBuffer.append("FAILURE: ").append(message).append("\n"); 961 outBuffer.append("FAILURE: ").append(message).append("\n");
899 throw new Failure(message); 962 throw new Failure(message);
900 } 963 }
901 964