From a2d44cdd9a1e03235b43fd96add3dd22d7401576 Mon Sep 17 00:00:00 2001 From: pkupczyk <piotr.kupczyk@id.ethz.ch> Date: Fri, 22 Mar 2024 13:30:17 +0100 Subject: [PATCH] SSDM-13578 : 2PT : Database and V3 Implementation - integration tests --- .../asapi/v3/TransactionCoordinatorApi.java | 2 +- .../systemtests/Integration2PCTest.java | 212 +++++++++++++++++- 2 files changed, 201 insertions(+), 13 deletions(-) diff --git a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/TransactionCoordinatorApi.java b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/TransactionCoordinatorApi.java index 6c798a12851..b97909d2d7d 100644 --- a/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/TransactionCoordinatorApi.java +++ b/server-application-server/source/java/ch/ethz/sis/openbis/generic/server/asapi/v3/TransactionCoordinatorApi.java @@ -161,7 +161,7 @@ public class TransactionCoordinatorApi extends AbstractTransactionNodeApi implem @Override public String getParticipantId() { - return getApplicationServer().getParticipantId(); + return ITransactionCoordinatorApi.APPLICATION_SERVER_PARTICIPANT_ID; } @Override public void beginTransaction(final UUID transactionId, final String sessionToken, final String interactiveSessionKey, diff --git a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java index a0b8f4d9f8a..d69a81f7f1f 100644 --- a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java +++ b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java @@ -86,6 +86,9 @@ public class Integration2PCTest extends AbstractIntegrationTest WriteData writeData = createWriteData(); openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5); + WriteData writeData2 = createWriteData(); + openBISWithTr.getAfsServerFacade().write(writeData2.owner, writeData2.source, 0L, writeData2.bytes, writeData2.md5); + SpaceCreation spaceCreation = createSpaceCreation(); SpacePermId spaceId = openBISWithTr.createSpaces(List.of(spaceCreation)).get(0); @@ -160,6 +163,38 @@ public class Integration2PCTest extends AbstractIntegrationTest assertNull(noTrSpaceAfter); assertNull(noTrProjectAfter); assertNull(noTrExperimentAfter); + + try + { + openBISWithTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + fail(); + } catch (Exception expected) + { + } + + try + { + openBISWithNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + fail(); + } catch (Exception expected) + { + } + + try + { + openBISWithTr.getAfsServerFacade().read(writeData2.owner, writeData2.source, 0L, writeData2.bytes.length); + fail(); + } catch (Exception expected) + { + } + + try + { + openBISWithNoTr.getAfsServerFacade().read(writeData2.owner, writeData2.source, 0L, writeData2.bytes.length); + fail(); + } catch (Exception expected) + { + } } else { // both the transaction session and the non-transaction session see the created entities after the commit @@ -174,8 +209,14 @@ public class Integration2PCTest extends AbstractIntegrationTest byte[] trBytesRead = openBISWithTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); byte[] noTrBytesRead = openBISWithNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); - assertEquals(new String(trBytesRead, StandardCharsets.UTF_8), writeData.content); - assertEquals(new String(noTrBytesRead, StandardCharsets.UTF_8), writeData.content); + assertEquals(trBytesRead, writeData.bytes); + assertEquals(noTrBytesRead, writeData.bytes); + + byte[] trBytesRead2 = openBISWithTr.getAfsServerFacade().read(writeData2.owner, writeData2.source, 0L, writeData2.bytes.length); + byte[] noTrBytesRead2 = openBISWithNoTr.getAfsServerFacade().read(writeData2.owner, writeData2.source, 0L, writeData2.bytes.length); + + assertEquals(trBytesRead2, writeData2.bytes); + assertEquals(noTrBytesRead2, writeData2.bytes); } } @@ -240,7 +281,7 @@ public class Integration2PCTest extends AbstractIntegrationTest assertNotNull(createdSpace); byte[] bytesRead = openBISNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); - assertEquals(new String(bytesRead, StandardCharsets.UTF_8), writeData.content); + assertEquals(bytesRead, writeData.bytes); } @Test @@ -302,7 +343,7 @@ public class Integration2PCTest extends AbstractIntegrationTest assertNotNull(createdSpace); byte[] bytesRead = openBISNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); - assertEquals(new String(bytesRead, StandardCharsets.UTF_8), writeData.content); + assertEquals(bytesRead, writeData.bytes); } @Test @@ -475,7 +516,7 @@ public class Integration2PCTest extends AbstractIntegrationTest assertNotNull(createdSpace); byte[] bytesRead = openBISNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); - assertEquals(new String(bytesRead, StandardCharsets.UTF_8), writeData.content); + assertEquals(bytesRead, writeData.bytes); } @Test @@ -528,7 +569,148 @@ public class Integration2PCTest extends AbstractIntegrationTest assertNotNull(createdSpace); byte[] bytesRead = openBISNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); - assertEquals(new String(bytesRead, StandardCharsets.UTF_8), writeData.content); + assertEquals(bytesRead, writeData.bytes); + } + + @Test + public void testASOnlyTransactionCommit() + { + testASOnlyTransaction(false); + } + + @Test + public void testASOnlyTransactionRollback() + { + testASOnlyTransaction(true); + } + + private void testASOnlyTransaction(boolean rollback) + { + // make AFS always fail to make sure it does not interrupt AS only transaction + setAfsServerProxyInterceptor((method, defaultAction) -> + { + throw new RuntimeException("Test AFS exception"); + }); + + OpenBIS openBISWithTr = createOpenBIS(); + OpenBIS openBISWithNoTr = createOpenBIS(); + + openBISWithTr.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY); + + openBISWithTr.login(USER, PASSWORD); + openBISWithNoTr.login(USER, PASSWORD); + + UUID transactionId = openBISWithTr.beginTransaction(); + + SpaceCreation spaceCreation = createSpaceCreation(); + SpacePermId spaceId = openBISWithTr.createSpaces(List.of(spaceCreation)).get(0); + + assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED)); + + Space trSpaceBefore = openBISWithTr.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId); + Space noTrSpaceBefore = openBISWithNoTr.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId); + + assertNotNull(trSpaceBefore); + assertNull(noTrSpaceBefore); + + if (rollback) + { + openBISWithTr.rollbackTransaction(); + } else + { + openBISWithTr.commitTransaction(); + } + + assertTransactions(getTransactionCoordinator().getTransactionMap()); + + Space trSpaceAfter = openBISWithTr.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId); + Space noTrSpaceAfter = openBISWithNoTr.getSpaces(Collections.singletonList(spaceId), new SpaceFetchOptions()).get(spaceId); + + if (rollback) + { + // neither the transaction session nor the non-transaction session see the created entities after the rollback + assertNull(trSpaceAfter); + assertNull(noTrSpaceAfter); + } else + { + // both the transaction session and the non-transaction session see the created entities after the commit + assertNotNull(trSpaceAfter); + assertNotNull(noTrSpaceAfter); + } + } + + @Test + public void testAFSOnlyTransactionCommit() + { + testAFSOnlyTransaction(false); + } + + @Test + public void testAFSOnlyTransactionRollback() + { + testAFSOnlyTransaction(true); + } + + private void testAFSOnlyTransaction(boolean rollback) + { + // make AS always fail to make sure it does not interrupt AS only transaction + setApplicationServerProxyInterceptor((method, defaultAction) -> + { + throw new RuntimeException("Test AS exception"); + }); + + OpenBIS openBISWithTr = createOpenBIS(); + OpenBIS openBISWithNoTr = createOpenBIS(); + + openBISWithTr.setInteractiveSessionKey(TEST_INTERACTIVE_SESSION_KEY); + + openBISWithTr.login(USER, PASSWORD); + openBISWithNoTr.login(USER, PASSWORD); + + UUID transactionId = openBISWithTr.beginTransaction(); + + WriteData writeData = createWriteData(); + openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5); + + assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED)); + + if (rollback) + { + openBISWithTr.rollbackTransaction(); + } else + { + openBISWithTr.commitTransaction(); + } + + assertTransactions(getTransactionCoordinator().getTransactionMap()); + + if (rollback) + { + // neither the transaction session nor the non-transaction session see the created entities after the rollback + try + { + openBISWithTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + fail(); + } catch (Exception expected) + { + } + + try + { + openBISWithNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + fail(); + } catch (Exception expected) + { + } + } else + { + // both the transaction session and the non-transaction session see the created entities after the commit + byte[] trBytesRead = openBISWithTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + byte[] noTrBytesRead = openBISWithNoTr.getAfsServerFacade().read(writeData.owner, writeData.source, 0L, writeData.bytes.length); + + assertEquals(trBytesRead, writeData.bytes); + assertEquals(noTrBytesRead, writeData.bytes); + } } @Test @@ -537,7 +719,7 @@ public class Integration2PCTest extends AbstractIntegrationTest // make commit fail at both AS and AFS (prepare will succeed) setApplicationServerProxyInterceptor((method, defaultAction) -> { - if (method != null && method.equals("commitTransaction")) + if (method != null && (method.equals("commitTransaction") || method.equals("commitRecoveredTransaction"))) { throw new RuntimeException("Test commit exception"); } else @@ -586,6 +768,9 @@ public class Integration2PCTest extends AbstractIntegrationTest openBISWithNotCommittedTransaction.getAfsServerFacade() .write(writeDataNotCommitted.owner, writeDataNotCommitted.source, 0L, writeDataNotCommitted.bytes, writeDataNotCommitted.md5); + // let's wait for the task that tries to finish failed or abandoned transactions runs + Thread.sleep(WAITING_TIME_FOR_FINISHING_TRANSACTIONS); + // check transactions state before the crash assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(committedTransactionId, TransactionStatus.COMMIT_STARTED), @@ -637,7 +822,7 @@ public class Integration2PCTest extends AbstractIntegrationTest byte[] committedBytesRead = openBISNoTr.getAfsServerFacade().read(writeDataCommitted.owner, writeDataCommitted.source, 0L, writeDataCommitted.bytes.length); - assertEquals(new String(committedBytesRead, StandardCharsets.UTF_8), writeDataCommitted.content); + assertEquals(committedBytesRead, writeDataCommitted.bytes); notCommittedSpace = openBISNoTr.getSpaces(List.of(spaceIdNotCommitted), new SpaceFetchOptions()).get(spaceIdNotCommitted); assertNull(notCommittedSpace); @@ -687,20 +872,23 @@ public class Integration2PCTest extends AbstractIntegrationTest } } - private static SpaceCreation createSpaceCreation(){ + private static SpaceCreation createSpaceCreation() + { SpaceCreation spaceCreation = new SpaceCreation(); spaceCreation.setCode(ENTITY_CODE_PREFIX + UUID.randomUUID()); return spaceCreation; } - private static ProjectCreation createProjectCreation(String spaceCode){ + private static ProjectCreation createProjectCreation(String spaceCode) + { ProjectCreation projectCreation = new ProjectCreation(); projectCreation.setSpaceId(new SpacePermId(spaceCode)); projectCreation.setCode(ENTITY_CODE_PREFIX + UUID.randomUUID()); return projectCreation; } - private static ExperimentCreation createExperimentCreation(String spaceCode, String projectCode, String experimentTypeCode){ + private static ExperimentCreation createExperimentCreation(String spaceCode, String projectCode, String experimentTypeCode) + { ExperimentCreation experimentCreation = new ExperimentCreation(); experimentCreation.setProjectId(new ProjectIdentifier(spaceCode, projectCode)); experimentCreation.setCode(ENTITY_CODE_PREFIX + UUID.randomUUID()); @@ -713,7 +901,7 @@ public class Integration2PCTest extends AbstractIntegrationTest WriteData writeData = new WriteData(); writeData.owner = "test-owner-" + UUID.randomUUID(); writeData.source = "test-source-" + UUID.randomUUID(); - writeData.content = "test-content"; + writeData.content = "test-content-" + UUID.randomUUID(); writeData.bytes = writeData.content.getBytes(StandardCharsets.UTF_8); writeData.md5 = calculateMD5(writeData.bytes); return writeData; -- GitLab