test legacy-id-triggers #149

Merged
hsh-michaelhoennig merged 3 commits from feature/test-legacy-id-triggers into master 2025-01-22 10:08:22 +01:00
13 changed files with 70 additions and 39 deletions

View File

@ -104,21 +104,32 @@ alias gw-check='. .aliases; . .tc-environment; gw test check -x pitest'
# You can also re-run all these tests, which will take ~20min: `gw-test --all --rerun` # You can also re-run all these tests, which will take ~20min: `gw-test --all --rerun`
# This will always use the environment from `.tc-environment`. # This will always use the environment from `.tc-environment`.
# #
function _gwTest1() {
echo
printf -- '=%0.s' {1..80}; echo
echo "RUNNING gw $@"
printf -- '-%0.s' {1..80}; echo
./gradlew "$@"
printf -- '-%0.s' {1..80}; echo
echo "DONE gw $@"
}
function _gwTest() { function _gwTest() {
. .aliases; . .aliases;
. .tc-environment; . .tc-environment;
rm /tmp/gwTest.tmp
if [ "$1" == "--all" ]; then if [ "$1" == "--all" ]; then
shift # to remove the --all from $@ shift # to remove the --all from $@
# delierately in separate gradlew-calls to avoid Testcontains-PostgreSQL problem spillover # delierately in separate gradlew-calls to avoid Testcontains-PostgreSQL problem spillover
./gradlew unitTest "$@" && time (_gwTest1 unitTest "$@" &&
./gradlew officeIntegrationTest bookingIntegrationTest hostingIntegrationTest "$@" && _gwTest1 officeIntegrationTest bookingIntegrationTest hostingIntegrationTest "$@" &&
./gradlew scenarioTest "$@" && _gwTest1 scenarioTest "$@" &&
./gradlew importOfficeData importHostingAssets "$@"; _gwTest1 importOfficeData importHostingAssets "$@");
elif [ $# -eq 0 ] || [[ $1 == -* ]]; then elif [ $# -eq 0 ] || [[ $1 == -* ]]; then
./gradlew test "$@"; time _gwTest1 test "$@";
else else
./gradlew "$@"; time _gwTest1 "$@";
fi fi
printf -- '=%0.s' {1..80}; echo
} }
alias gw-test=_gwTest alias gw-test=_gwTest

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset michael.hoennig:hs-office-contact-MIGRATION-mapping endDelimiter:--// --changeset michael.hoennig:hs-office-contact-MIGRATION-legacy-mapping endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_office.contact_legacy_id CREATE TABLE hs_office.contact_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_office.contact(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_office.contact(uuid),
contact_id integer NOT NULL contact_id integer UNIQUE NOT NULL
); );
--// --//

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset michael.hoennig:hs-office-partner-MIGRATION-mapping endDelimiter:--// --changeset michael.hoennig:hs-office-partner-MIGRATION-legacy-mapping endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_office.partner_legacy_id CREATE TABLE hs_office.partner_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_office.partner(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_office.partner(uuid),
bp_id integer NOT NULL bp_id integer UNIQUE NOT NULL
); );
--// --//

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset michael.hoennig:hs-office-sepamandate-MIGRATION-mapping endDelimiter:--// --changeset michael.hoennig:hs-office-sepamandate-MIGRATION-legacy-mapping endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_office.sepamandate_legacy_id CREATE TABLE hs_office.sepamandate_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_office.sepamandate(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_office.sepamandate(uuid),
sepa_mandate_id integer NOT NULL sepa_mandate_id integer UNIQUE NOT NULL
); );
--// --//

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset michael.hoennig:hs-office-coopshares-MIGRATION-mapping endDelimiter:--// --changeset michael.hoennig:hs-office-coopshares-MIGRATION-legacy-mapping endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_office.coopsharetx_legacy_id CREATE TABLE hs_office.coopsharetx_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_office.coopsharetx(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_office.coopsharetx(uuid),
member_share_id integer NOT NULL member_share_id integer UNIQUE NOT NULL
); );
--// --//

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset michael.hoennig:hs-office-coopassets-MIGRATION-mapping endDelimiter:--// --changeset michael.hoennig:hs-office-coopassets-MIGRATION-legacy-mapping endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_office.coopassettx_legacy_id CREATE TABLE hs_office.coopassettx_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_office.coopassettx(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_office.coopassettx(uuid),
member_asset_id integer NOT NULL member_asset_id integer UNIQUE NOT NULL
); );
--// --//

View File

@ -4,13 +4,13 @@
-- Once we don't need the external remote views anymore, create revert changesets. -- Once we don't need the external remote views anymore, create revert changesets.
-- ============================================================================ -- ============================================================================
--changeset hs-hosting-asset-MIGRATION-mapping:1 endDelimiter:--// --changeset hs-hosting-asset-MIGRATION-legacy-mapping:1 endDelimiter:--//
-- ---------------------------------------------------------------------------- -- ----------------------------------------------------------------------------
CREATE TABLE hs_hosting.asset_legacy_id CREATE TABLE hs_hosting.asset_legacy_id
( (
uuid uuid NOT NULL REFERENCES hs_hosting.asset(uuid), uuid uuid PRIMARY KEY NOT NULL REFERENCES hs_hosting.asset(uuid),
legacy_id integer NOT NULL legacy_id integer NOT NULL -- not unique because we sometimes create multiple asset types for the same legacy asset
); );
--// --//

View File

@ -1,10 +1,10 @@
package net.hostsharing.hsadminng.hs.office.contact; package net.hostsharing.hsadminng.hs.office.contact;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.mapper.Array;
import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository; import net.hostsharing.hsadminng.rbac.grant.RawRbacGrantRepository;
import net.hostsharing.hsadminng.rbac.role.RawRbacRoleRepository; import net.hostsharing.hsadminng.rbac.role.RawRbacRoleRepository;
import net.hostsharing.hsadminng.mapper.Array; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.RandomStringUtils;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
@ -12,8 +12,8 @@ import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
@ -29,7 +29,7 @@ import static net.hostsharing.hsadminng.rbac.test.JpaAttempt.attempt;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest @DataJpaTest
@Import( { Context.class, JpaAttempt.class }) @Import({ Context.class, JpaAttempt.class })
@Tag("officeIntegrationTest") @Tag("officeIntegrationTest")
class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithCleanup { class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithCleanup {
@ -62,7 +62,8 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
// when // when
final var result = attempt(em, () -> toCleanup(contactRepo.save( final var result = attempt(
em, () -> toCleanup(contactRepo.save(
hsOfficeContact("a new contact", "contact-admin@www.example.com")))); hsOfficeContact("a new contact", "contact-admin@www.example.com"))));
// then // then
@ -79,7 +80,8 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
final var count = contactRepo.count(); final var count = contactRepo.count();
// when // when
final var result = attempt(em, () -> toCleanup(contactRepo.save( final var result = attempt(
em, () -> toCleanup(contactRepo.save(
hsOfficeContact("another new contact", "another-new-contact@example.com")))); hsOfficeContact("another new contact", "another-new-contact@example.com"))));
// then // then
@ -87,6 +89,7 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeContactRbacEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeContactRbacEntity::getUuid).isNotNull();
assertThatContactIsPersisted(result.returnedValue()); assertThatContactIsPersisted(result.returnedValue());
assertThat(contactRepo.count()).isEqualTo(count + 1); assertThat(contactRepo.count()).isEqualTo(count + 1);
assertHasLegacyId(result.returnedValue(), "contact_id");
} }
@Test @Test
@ -97,7 +100,8 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll()); final var initialGrantNames = distinctGrantDisplaysOf(rawGrantRepo.findAll());
// when // when
attempt(em, () -> toCleanup(contactRepo.save( attempt(
em, () -> toCleanup(contactRepo.save(
hsOfficeContact("another new contact", "another-new-contact@example.com"))) hsOfficeContact("another new contact", "another-new-contact@example.com")))
).assumeSuccessful(); ).assumeSuccessful();
@ -300,7 +304,8 @@ class HsOfficeContactRbacRepositoryIntegrationTest extends ContextBasedTestWithC
private HsOfficeContactRbacEntity givenSomeTemporaryContact(final String createdByUser) { private HsOfficeContactRbacEntity givenSomeTemporaryContact(final String createdByUser) {
final var random = RandomStringUtils.randomAlphabetic(12); final var random = RandomStringUtils.randomAlphabetic(12);
return givenSomeTemporaryContact(createdByUser, () -> return givenSomeTemporaryContact(
createdByUser, () ->
hsOfficeContact( hsOfficeContact(
"some temporary contact #" + random, "some temporary contact #" + random,
"some-temporary-contact" + random + "@example.com")); "some-temporary-contact" + random + "@example.com"));

View File

@ -83,6 +83,7 @@ class HsOfficeCoopAssetsTransactionRepositoryIntegrationTest extends ContextBase
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeCoopAssetsTransactionEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeCoopAssetsTransactionEntity::getUuid).isNotNull();
assertThatCoopAssetsTransactionIsPersisted(result.returnedValue()); assertThatCoopAssetsTransactionIsPersisted(result.returnedValue());
assertThat(coopAssetsTransactionRepo.count()).isEqualTo(count + 1); assertThat(coopAssetsTransactionRepo.count()).isEqualTo(count + 1);
assertHasLegacyId(result.returnedValue(), "member_asset_id");
} }
@Test @Test

View File

@ -82,6 +82,7 @@ class HsOfficeCoopSharesTransactionRepositoryIntegrationTest extends ContextBase
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeCoopSharesTransactionEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeCoopSharesTransactionEntity::getUuid).isNotNull();
assertThatCoopSharesTransactionIsPersisted(result.returnedValue()); assertThatCoopSharesTransactionIsPersisted(result.returnedValue());
assertThat(coopSharesTransactionRepo.count()).isEqualTo(count + 1); assertThat(coopSharesTransactionRepo.count()).isEqualTo(count + 1);
assertHasLegacyId(result.returnedValue(), "member_share_id");
} }
@Test @Test

View File

@ -98,6 +98,7 @@ class HsOfficePartnerRbacRepositoryIntegrationTest extends ContextBasedTestWithC
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePartnerRbacEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficePartnerRbacEntity::getUuid).isNotNull();
assertThatPartnerIsPersisted(result.returnedValue()); assertThatPartnerIsPersisted(result.returnedValue());
assertThat(partnerRepo.count()).isEqualTo(count + 1); assertThat(partnerRepo.count()).isEqualTo(count + 1);
assertHasLegacyId(result.returnedValue(), "bp_id");
} }
@Test @Test

View File

@ -89,6 +89,7 @@ class HsOfficeSepaMandateRepositoryIntegrationTest extends ContextBasedTestWithC
assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeSepaMandateEntity::getUuid).isNotNull(); assertThat(result.returnedValue()).isNotNull().extracting(HsOfficeSepaMandateEntity::getUuid).isNotNull();
assertThatSepaMandateIsPersisted(result.returnedValue()); assertThatSepaMandateIsPersisted(result.returnedValue());
assertThat(sepaMandateRepo.count()).isEqualTo(count + 1); assertThat(sepaMandateRepo.count()).isEqualTo(count + 1);
assertHasLegacyId(result.returnedValue(), "sepa_mandate_id");
} }
@Test @Test

View File

@ -1,6 +1,7 @@
package net.hostsharing.hsadminng.rbac.context; package net.hostsharing.hsadminng.rbac.context;
import net.hostsharing.hsadminng.context.Context; import net.hostsharing.hsadminng.context.Context;
import net.hostsharing.hsadminng.persistence.BaseEntity;
import net.hostsharing.hsadminng.rbac.grant.RbacGrantsDiagramService; import net.hostsharing.hsadminng.rbac.grant.RbacGrantsDiagramService;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInfo;
@ -9,6 +10,7 @@ import org.springframework.context.annotation.Import;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext; import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Table;
import java.sql.Timestamp; import java.sql.Timestamp;
@Import(RbacGrantsDiagramService.class) @Import(RbacGrantsDiagramService.class)
@ -59,7 +61,6 @@ public abstract class ContextBasedTest {
""").executeUpdate(); """).executeUpdate();
} }
protected void historicalContext(final Timestamp txTimestamp) { protected void historicalContext(final Timestamp txTimestamp) {
// set local cannot be used with query parameters // set local cannot be used with query parameters
em.createNativeQuery(""" em.createNativeQuery("""
@ -70,4 +71,14 @@ public abstract class ContextBasedTest {
""").executeUpdate(); """).executeUpdate();
} }
protected void assertHasLegacyId(final BaseEntity<?> entity, final String legacyIdColumnName) {
final var table = entity.getClass().getAnnotation(Table.class);
final var legacyIdTable = table.schema() + "." + table.name().replace("_rv", "") + "_legacy_id";
em.createNativeQuery("SELECT " + legacyIdColumnName +
" FROM " + legacyIdTable +
" WHERE uuid = '" + entity.getUuid() + "'", Long.class)
.getSingleResult(); // fails if there is 0 or more than 1 result
// that the legacyId is unique is checked by a DB constraint, if applicable
}
} }