|
3 | 3 | import org.testng.annotations.Test; |
4 | 4 |
|
5 | 5 | import java.io.IOException; |
| 6 | +import java.io.RandomAccessFile; |
| 7 | +import java.net.URI; |
6 | 8 | import java.nio.charset.StandardCharsets; |
7 | 9 | import java.nio.file.Files; |
8 | 10 | import java.nio.file.Path; |
9 | 11 | import java.sql.Connection; |
10 | 12 | import java.sql.DriverManager; |
11 | 13 | import java.sql.ResultSet; |
12 | 14 | import java.sql.Statement; |
| 15 | +import java.util.Map; |
| 16 | +import java.util.Optional; |
13 | 17 |
|
14 | 18 | import static org.testng.Assert.assertEquals; |
15 | 19 | import static org.testng.Assert.assertFalse; |
@@ -74,6 +78,42 @@ public void incompleteLegacySchemaDoesNotReplaceExistingDatabase() throws Except |
74 | 78 | assertEquals(Files.readString(target, StandardCharsets.UTF_8), "working database"); |
75 | 79 | } |
76 | 80 |
|
| 81 | + @Test |
| 82 | + public void corruptDatabaseWithValidSchemaDoesNotReplaceExistingDatabase() throws Exception { |
| 83 | + Path dir = Files.createTempDirectory("jassdoc-corrupt-download-"); |
| 84 | + Path target = dir.resolve("jassdoc-latest.db"); |
| 85 | + Path downloaded = dir.resolve("download.tmp"); |
| 86 | + Files.writeString(target, "working database", StandardCharsets.UTF_8); |
| 87 | + int pageSize; |
| 88 | + int indexRootPage; |
| 89 | + try (Connection conn = DriverManager.getConnection("jdbc:sqlite:" + downloaded.toAbsolutePath()); |
| 90 | + Statement statement = conn.createStatement()) { |
| 91 | + statement.execute("CREATE TABLE docs(name TEXT, documentation TEXT)"); |
| 92 | + for (int i = 0; i < 1_000; i++) { |
| 93 | + statement.execute("INSERT INTO docs VALUES ('name" + i + "', '" |
| 94 | + + "documentation".repeat(40) + "')"); |
| 95 | + } |
| 96 | + statement.execute("CREATE INDEX docs_name_idx ON docs(name)"); |
| 97 | + try (ResultSet result = statement.executeQuery("PRAGMA page_size")) { |
| 98 | + assertTrue(result.next()); |
| 99 | + pageSize = result.getInt(1); |
| 100 | + } |
| 101 | + try (ResultSet result = statement.executeQuery( |
| 102 | + "SELECT rootpage FROM sqlite_master WHERE name = 'docs_name_idx'")) { |
| 103 | + assertTrue(result.next()); |
| 104 | + indexRootPage = result.getInt(1); |
| 105 | + } |
| 106 | + } |
| 107 | + try (RandomAccessFile file = new RandomAccessFile(downloaded.toFile(), "rw")) { |
| 108 | + file.seek((long) (indexRootPage - 1) * pageSize); |
| 109 | + file.write(new byte[32]); |
| 110 | + } |
| 111 | + |
| 112 | + assertThrows(IOException.class, |
| 113 | + () -> new JassDocService().installDownloadedDatabase(downloaded, target)); |
| 114 | + assertEquals(Files.readString(target, StandardCharsets.UTF_8), "working database"); |
| 115 | + } |
| 116 | + |
77 | 117 | @Test |
78 | 118 | public void restoreOverwritesAResidualPartialTarget() throws IOException { |
79 | 119 | Path dir = Files.createTempDirectory("jassdoc-restore-"); |
@@ -116,6 +156,22 @@ public void proxyBypassSupportsStandardHostForms() { |
116 | 156 | "github.com", "localhost, example.com")); |
117 | 157 | } |
118 | 158 |
|
| 159 | + @Test |
| 160 | + public void standardProxyMatchesRequestProtocol() throws Exception { |
| 161 | + Map<String, String> settings = Map.of( |
| 162 | + "HTTPS_PROXY", "http://secure-proxy.example:8443", |
| 163 | + "HTTP_PROXY", "http://plain-proxy.example:8080"); |
| 164 | + |
| 165 | + assertEquals(JassDocService.selectProxySetting( |
| 166 | + URI.create("https://github.com/example").toURL(), |
| 167 | + name -> Optional.ofNullable(settings.get(name))).orElseThrow(), |
| 168 | + "http://secure-proxy.example:8443"); |
| 169 | + assertEquals(JassDocService.selectProxySetting( |
| 170 | + URI.create("http://mirror.example/jass.db").toURL(), |
| 171 | + name -> Optional.ofNullable(settings.get(name))).orElseThrow(), |
| 172 | + "http://plain-proxy.example:8080"); |
| 173 | + } |
| 174 | + |
119 | 175 | @Test |
120 | 176 | public void unsupportedTlsProxyIsRejectedExplicitly() { |
121 | 177 | IOException error = expectThrows(IOException.class, |
|
0 commit comments