fix failed deletion of test-data with reverse references

This commit is contained in:
Michael Hoennig 2024-06-20 09:26:49 +02:00
parent c565606edf
commit 1b7c6c7abe
3 changed files with 27 additions and 4 deletions

View File

@ -15,7 +15,7 @@ class HsManagedServerHostingAssetValidator extends HsHostingAssetEntityValidator
integerProperty("monit_min_free_ssd").min(1).max(1000).withDefault(5), integerProperty("monit_min_free_ssd").min(1).max(1000).withDefault(5),
integerProperty("monit_max_hdd_usage").unit("%").min(10).max(100).withDefault(95), integerProperty("monit_max_hdd_usage").unit("%").min(10).max(100).withDefault(95),
integerProperty("monit_min_free_hdd").min(1).max(4000).withDefault(10), integerProperty("monit_min_free_hdd").min(1).max(4000).withDefault(10),
// stringProperty("monit_alarm_email").unit("GB").optional() FIXME: via Contact? // stringProperty("monit_alarm_email").unit("GB").optional() TODO.impl: via Contact?
// other settings // other settings
// booleanProperty("fastcgi_small").withDefault(false), TODO.spec: clarify Salt-Grains // booleanProperty("fastcgi_small").withDefault(false), TODO.spec: clarify Salt-Grains

View File

@ -10,8 +10,11 @@ import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRepository;
import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository; import net.hostsharing.hsadminng.hs.office.debitor.HsOfficeDebitorRepository;
import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup; import net.hostsharing.hsadminng.rbac.test.ContextBasedTestWithCleanup;
import net.hostsharing.hsadminng.rbac.test.JpaAttempt; import net.hostsharing.hsadminng.rbac.test.JpaAttempt;
import org.junit.jupiter.api.ClassOrderer;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalServerPort; import org.springframework.boot.test.web.server.LocalServerPort;
@ -28,11 +31,12 @@ import static net.hostsharing.hsadminng.rbac.test.JsonMatcher.lenientlyEquals;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.matchesRegex; import static org.hamcrest.Matchers.matchesRegex;
@Transactional
@SpringBootTest( @SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { HsadminNgApplication.class, JpaAttempt.class } classes = { HsadminNgApplication.class, JpaAttempt.class }
) )
@Transactional @TestClassOrder(ClassOrderer.OrderAnnotation.class) // fail early on fetching problems
class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup { class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup {
@LocalServerPort @LocalServerPort
@ -54,6 +58,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
JpaAttempt jpaAttempt; JpaAttempt jpaAttempt;
@Nested @Nested
@Order(2)
class ListAssets { class ListAssets {
@Test @Test
@ -152,6 +157,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
} }
@Nested @Nested
@Order(3)
class AddAsset { class AddAsset {
@Test @Test
@ -339,6 +345,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
} }
@Nested @Nested
@Order(1)
class GetAsset { class GetAsset {
@Test @Test
@ -410,6 +417,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
} }
@Nested @Nested
@Order(4)
class PatchAsset { class PatchAsset {
@Test @Test
@ -463,6 +471,7 @@ class HsHostingAssetControllerAcceptanceTest extends ContextBasedTestWithCleanup
} }
@Nested @Nested
@Order(5)
class DeleteAsset { class DeleteAsset {
@Test @Test

View File

@ -18,6 +18,8 @@ import org.springframework.transaction.PlatformTransactionManager;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
import static java.lang.System.out; import static java.lang.System.out;
import static java.util.Comparator.comparing; import static java.util.Comparator.comparing;
@ -176,7 +178,7 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
if (!tm.getTransaction(null).isRollbackOnly()) { if (!tm.getTransaction(null).isRollbackOnly()) {
out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".cleanupAndCheckCleanup"); out.println(ContextBasedTestWithCleanup.class.getSimpleName() + ".cleanupAndCheckCleanup");
cleanupTemporaryTestData(); cleanupTemporaryTestData();
deleteLeakedRbacObjects(); repeatUntilTrue(3, this::deleteLeakedRbacObjects);
long rbacObjectCount = assertNoNewRbacObjectsRolesAndGrantsLeaked(); long rbacObjectCount = assertNoNewRbacObjectsRolesAndGrantsLeaked();
out.println("TOTAL OBJECT COUNT (after): " + rbacObjectCount); out.println("TOTAL OBJECT COUNT (after): " + rbacObjectCount);
@ -227,7 +229,8 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
}).assertSuccessful().returnedValue(); }).assertSuccessful().returnedValue();
} }
private void deleteLeakedRbacObjects() { private boolean deleteLeakedRbacObjects() {
final var deletionSuccessful = new AtomicBoolean(true);
rbacObjectRepo.findAll().stream() rbacObjectRepo.findAll().stream()
.filter(o -> o.serialId > latestIntialTestDataSerialId) .filter(o -> o.serialId > latestIntialTestDataSerialId)
.sorted(comparing(o -> o.serialId)) .sorted(comparing(o -> o.serialId))
@ -244,8 +247,10 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
if (exception != null) { if (exception != null) {
out.println("DELETING leaked " + o.objectTable + "#" + o.uuid + " FAILED " + exception); out.println("DELETING leaked " + o.objectTable + "#" + o.uuid + " FAILED " + exception);
deletionSuccessful.set(false);
} }
}); });
return deletionSuccessful.get();
} }
private void assertEqual(final Set<String> before, final Set<String> after) { private void assertEqual(final Set<String> before, final Set<String> after) {
@ -306,6 +311,15 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
"doc/temp/" + name + ".md" "doc/temp/" + name + ".md"
); );
} }
public static boolean repeatUntilTrue(int maxAttempts, Supplier<Boolean> method) {
for (int attempts = 0; attempts < maxAttempts; attempts++) {
if (method.get()) {
return true;
}
}
return false;
}
} }
interface RbacObjectRepository extends Repository<RbacObjectEntity, UUID> { interface RbacObjectRepository extends Repository<RbacObjectEntity, UUID> {