|
29 | 29 | import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
30 | 30 | import static org.junit.jupiter.api.Assertions.assertNotNull;
|
31 | 31 | import static org.junit.jupiter.api.Assertions.assertThrows;
|
| 32 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
32 | 33 |
|
33 | 34 | import java.io.ByteArrayInputStream;
|
34 | 35 | import java.io.ByteArrayOutputStream;
|
|
45 | 46 | import java.util.Arrays;
|
46 | 47 | import java.util.Collection;
|
47 | 48 | import java.util.HashMap;
|
| 49 | +import java.util.List; |
48 | 50 | import java.util.Map;
|
| 51 | +import java.util.concurrent.Executors; |
| 52 | +import java.util.concurrent.Future; |
49 | 53 |
|
50 | 54 | import javax.crypto.Cipher;
|
51 | 55 | import javax.crypto.NoSuchPaddingException;
|
@@ -497,6 +501,67 @@ public void testPerTableFactory() {
|
497 | 501 | assertEquals(2, factory.getCount());
|
498 | 502 | }
|
499 | 503 |
|
| 504 | + @Test |
| 505 | + public void testMultipleThreads() throws Exception { |
| 506 | + testMultipleThreads(WAL); |
| 507 | + testMultipleThreads(TABLE); |
| 508 | + } |
| 509 | + |
| 510 | + private void testMultipleThreads(Scope scope) throws Exception { |
| 511 | + |
| 512 | + byte[] plainText = new byte[1024 * 1024]; |
| 513 | + for (int i = 0; i < plainText.length; i++) { |
| 514 | + plainText[i] = (byte) (i % 128); |
| 515 | + } |
| 516 | + |
| 517 | + AESCryptoService cs = new AESCryptoService(); |
| 518 | + cs.init(getAllCryptoProperties(ConfigMode.CRYPTO_TABLE_ON)); |
| 519 | + CryptoEnvironment encEnv = new CryptoEnvironmentImpl(scope, null, null); |
| 520 | + FileEncrypter encrypter = cs.getFileEncrypter(encEnv); |
| 521 | + byte[] params = encrypter.getDecryptionParameters(); |
| 522 | + |
| 523 | + assertNotNull(params); |
| 524 | + |
| 525 | + ByteArrayOutputStream out = new ByteArrayOutputStream(); |
| 526 | + DataOutputStream dataOut = new DataOutputStream(out); |
| 527 | + OutputStream encrypted = encrypter.encryptStream(dataOut); |
| 528 | + |
| 529 | + assertNotNull(encrypted); |
| 530 | + DataOutputStream cipherOut = new DataOutputStream(encrypted); |
| 531 | + |
| 532 | + cipherOut.write(plainText); |
| 533 | + |
| 534 | + cipherOut.close(); |
| 535 | + dataOut.close(); |
| 536 | + encrypted.close(); |
| 537 | + out.close(); |
| 538 | + byte[] cipherText = out.toByteArray(); |
| 539 | + |
| 540 | + var executor = Executors.newCachedThreadPool(); |
| 541 | + |
| 542 | + List<Future<Boolean>> verifyFutures = new ArrayList<>(); |
| 543 | + |
| 544 | + FileDecrypter decrypter = cs.getFileDecrypter(new CryptoEnvironmentImpl(scope, null, params)); |
| 545 | + |
| 546 | + // verify that each input stream returned by decrypter.decryptStream() is independent when used |
| 547 | + // by multiple threads |
| 548 | + for (int i = 0; i < 32; i++) { |
| 549 | + var future = executor.submit(() -> { |
| 550 | + try (ByteArrayInputStream in = new ByteArrayInputStream(cipherText); |
| 551 | + DataInputStream decrypted = new DataInputStream(decrypter.decryptStream(in))) { |
| 552 | + byte[] dataRead = new byte[plainText.length]; |
| 553 | + decrypted.readFully(dataRead); |
| 554 | + return Arrays.equals(plainText, dataRead); |
| 555 | + } |
| 556 | + }); |
| 557 | + verifyFutures.add(future); |
| 558 | + } |
| 559 | + |
| 560 | + for (var future : verifyFutures) { |
| 561 | + assertTrue(future.get()); |
| 562 | + } |
| 563 | + } |
| 564 | + |
500 | 565 | private ArrayList<Key> testData() {
|
501 | 566 | ArrayList<Key> keys = new ArrayList<>();
|
502 | 567 | keys.add(new Key("a", "cf", "cq"));
|
|
0 commit comments