test: update all tests for Ed25519 license minting and tier rename

- LicenseServiceTest: mock SigningKeyService, assert signed token format
- VendorTenantServiceTest: add SigningKeyService mock, update mintLicense stubs
- All tests: LOW→STARTER, MID→TEAM, HIGH→BUSINESS, BUSINESS→ENTERPRISE
- Remove all features-related test assertions
- 80/80 tests passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-26 17:33:10 +02:00
parent 7a8960ca46
commit 6c3f21d4db
8 changed files with 116 additions and 92 deletions

View File

@@ -35,7 +35,7 @@ class LicenseControllerTest {
private String createTenantAndGetId() throws Exception {
String slug = "license-tenant-" + System.nanoTime();
var request = new CreateTenantRequest("License Test Org", slug, "MID", null, null);
var request = new CreateTenantRequest("License Test Org", slug, "TEAM", null, null);
var result = mockMvc.perform(post("/api/tenants")
.with(jwt().jwt(j -> j
@@ -60,8 +60,7 @@ class LicenseControllerTest {
new SimpleGrantedAuthority("SCOPE_platform:admin"))))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.token").isNotEmpty())
.andExpect(jsonPath("$.tier").value("MID"))
.andExpect(jsonPath("$.features.correlation").value(true));
.andExpect(jsonPath("$.tier").value("TEAM"));
}
@Test
@@ -78,7 +77,7 @@ class LicenseControllerTest {
.with(jwt().jwt(j -> j.claim("sub", "test-user"))
.authorities(new SimpleGrantedAuthority("SCOPE_platform:admin"))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.tier").value("MID"));
.andExpect(jsonPath("$.tier").value("TEAM"));
}
@Test

View File

@@ -12,8 +12,10 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.time.Duration;
import java.util.Optional;
import java.util.Base64;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
@@ -30,11 +32,26 @@ class LicenseServiceTest {
@Mock
private AuditService auditService;
@Mock
private SigningKeyService signingKeyService;
private LicenseService licenseService;
private KeyPair testKeyPair;
@BeforeEach
void setUp() {
licenseService = new LicenseService(licenseRepository, auditService);
void setUp() throws Exception {
licenseService = new LicenseService(licenseRepository, auditService, signingKeyService);
testKeyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
}
private void stubPrivateKey() {
when(signingKeyService.getPrivateKey()).thenReturn(testKeyPair.getPrivate());
}
private void stubPublicKey() {
when(signingKeyService.getPublicKeyBase64()).thenReturn(
Base64.getEncoder().encodeToString(testKeyPair.getPublic().getEncoded()));
}
private TenantEntity createTenant(Tier tier) {
@@ -65,69 +82,71 @@ class LicenseServiceTest {
}
@Test
void generateLicense_producesUuidToken() {
var tenant = createTenant(Tier.MID);
void generateLicense_producesSignedToken() {
var tenant = createTenant(Tier.TEAM);
stubPrivateKey();
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
var license = licenseService.generateLicense(tenant, Duration.ofDays(365), UUID.randomUUID());
assertThat(license.getToken()).isNotBlank();
// Token must be a valid UUID string
assertThat(UUID.fromString(license.getToken())).isNotNull();
assertThat(license.getTier()).isEqualTo("MID");
}
@Test
void generateLicense_setsCorrectFeaturesForTier() {
var tenant = createTenant(Tier.HIGH);
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID());
assertThat(license.getFeatures()).containsEntry("debugger", true);
assertThat(license.getFeatures()).containsEntry("replay", true);
// Ed25519 signed token contains a '.' separator between payload and signature
assertThat(license.getToken()).contains(".");
assertThat(license.getTier()).isEqualTo("TEAM");
}
@Test
void generateLicense_setsCorrectLimitsForTier() {
var tenant = createTenant(Tier.LOW);
var tenant = createTenant(Tier.STARTER);
stubPrivateKey();
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID());
assertThat(license.getLimits()).containsEntry("max_agents", 3);
assertThat(license.getLimits()).containsEntry("retention_days", 7);
assertThat(license.getLimits()).containsEntry("max_agents", 20);
assertThat(license.getLimits()).containsEntry("max_environments", 2);
assertThat(license.getLimits()).containsEntry("max_execution_retention_days", 7);
}
@Test
void verifyLicenseToken_validTokenReturnsPayload() {
var tenant = createTenant(Tier.MID);
void generateLicense_setsGracePeriodAndLabel() {
var tenant = createTenant(Tier.BUSINESS);
stubPrivateKey();
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
var license = licenseService.generateLicense(tenant, Duration.ofDays(365), UUID.randomUUID());
assertThat(license.getGracePeriodDays()).isEqualTo(LicenseDefaults.DEFAULT_GRACE_PERIOD_DAYS);
assertThat(license.getLabel()).contains("Test Tenant");
}
@Test
void verifyToken_validTokenReturnsLicenseInfo() {
var tenant = createTenant(Tier.TEAM);
stubPrivateKey();
stubPublicKey();
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
var license = licenseService.generateLicense(tenant, Duration.ofDays(30), UUID.randomUUID());
when(licenseRepository.findByToken(license.getToken())).thenReturn(Optional.of(license));
var result = licenseService.verifyToken(license.getToken(), "test");
var payload = licenseService.verifyLicenseToken(license.getToken());
assertThat(payload).isPresent();
assertThat(payload.get().get("tier")).isEqualTo("MID");
assertThat(payload.get().get("tenant_id")).isEqualTo(tenant.getId().toString());
assertThat(result).isPresent();
assertThat(result.get().tenantId()).isEqualTo("test");
}
@Test
void verifyLicenseToken_unknownTokenReturnsEmpty() {
when(licenseRepository.findByToken(any())).thenReturn(Optional.empty());
var payload = licenseService.verifyLicenseToken("unknown-token");
assertThat(payload).isEmpty();
void verifyToken_invalidTokenReturnsEmpty() {
stubPublicKey();
var result = licenseService.verifyToken("invalid-token", "test");
assertThat(result).isEmpty();
}
@Test
void generateLicense_logsAuditEvent() {
var tenant = createTenant(Tier.LOW);
var tenant = createTenant(Tier.STARTER);
var actorId = UUID.randomUUID();
stubPrivateKey();
when(licenseRepository.save(any(LicenseEntity.class))).thenAnswer(inv -> withGeneratedId(inv.getArgument(0)));
licenseService.generateLicense(tenant, Duration.ofDays(30), actorId);

View File

@@ -52,7 +52,7 @@ class TenantPortalControllerTest {
var tenant = new TenantEntity();
tenant.setName(name);
tenant.setSlug(slug);
tenant.setTier(Tier.LOW);
tenant.setTier(Tier.STARTER);
tenant.setStatus(TenantStatus.ACTIVE);
tenant.setLogtoOrgId(orgId);
return tenantRepository.save(tenant);

View File

@@ -85,8 +85,8 @@ class TenantPortalServiceTest {
license.setToken("test-token-" + UUID.randomUUID());
license.setIssuedAt(Instant.now());
license.setExpiresAt(expiresAt);
license.setFeatures(Map.of("feature1", true));
license.setLimits(Map.of("maxApps", 10));
license.setLimits(Map.of("max_apps", 10));
license.setGracePeriodDays(14);
var f = LicenseEntity.class.getDeclaredField("id");
f.setAccessible(true);
f.set(license, UUID.randomUUID());
@@ -97,10 +97,10 @@ class TenantPortalServiceTest {
@Test
void getDashboard_returnsDashboardData() throws Exception {
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE);
tenant.setServerEndpoint("http://server:8080");
var expiresAt = Instant.now().plus(Duration.ofDays(30));
var license = licenseWithId(tenantId, "LOW", expiresAt);
var license = licenseWithId(tenantId, "STARTER", expiresAt);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(serverApiClient.getHealth("http://server:8080")).thenReturn(new ServerHealthResponse(true, "UP"));
@@ -112,22 +112,21 @@ class TenantPortalServiceTest {
assertThat(result.name()).isEqualTo("Acme Corp");
assertThat(result.slug()).isEqualTo("acme-corp");
assertThat(result.tier()).isEqualTo("LOW");
assertThat(result.tier()).isEqualTo("STARTER");
assertThat(result.status()).isEqualTo("ACTIVE");
assertThat(result.serverHealthy()).isTrue();
assertThat(result.serverStatus()).isEqualTo("UP");
assertThat(result.serverEndpoint()).isEqualTo("http://server:8080");
assertThat(result.licenseTier()).isEqualTo("LOW");
assertThat(result.licenseTier()).isEqualTo("STARTER");
assertThat(result.licenseDaysRemaining()).isGreaterThanOrEqualTo(29);
assertThat(result.limits()).isNotEmpty();
assertThat(result.features()).isNotEmpty();
assertThat(result.agentCount()).isEqualTo(3);
assertThat(result.environmentCount()).isEqualTo(1);
}
@Test
void getDashboard_handlesNoServer() throws Exception {
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.PROVISIONING);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.PROVISIONING);
// serverEndpoint is null by default
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
@@ -148,9 +147,9 @@ class TenantPortalServiceTest {
@Test
void getLicense_returnsLicenseData() throws Exception {
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE);
var expiresAt = Instant.now().plus(Duration.ofDays(60));
var license = licenseWithId(tenantId, "LOW", expiresAt);
var license = licenseWithId(tenantId, "STARTER", expiresAt);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.of(license));
@@ -159,18 +158,18 @@ class TenantPortalServiceTest {
assertThat(result).isNotNull();
assertThat(result.id()).isEqualTo(license.getId());
assertThat(result.tier()).isEqualTo("LOW");
assertThat(result.tier()).isEqualTo("STARTER");
assertThat(result.token()).isEqualTo(license.getToken());
assertThat(result.issuedAt()).isEqualTo(license.getIssuedAt());
assertThat(result.expiresAt()).isEqualTo(expiresAt);
assertThat(result.daysRemaining()).isGreaterThanOrEqualTo(59);
assertThat(result.features()).isEqualTo(Map.of("feature1", true));
assertThat(result.limits()).isEqualTo(Map.of("maxApps", 10));
assertThat(result.limits()).isEqualTo(Map.of("max_apps", 10));
assertThat(result.gracePeriodDays()).isEqualTo(14);
}
@Test
void getLicense_returnsNullWhenNoLicense() throws Exception {
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW, TenantStatus.ACTIVE);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER, TenantStatus.ACTIVE);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(licenseService.getActiveLicense(tenantId)).thenReturn(Optional.empty());
@@ -184,7 +183,7 @@ class TenantPortalServiceTest {
@Test
void getSettings_returnsSettingsData() throws Exception {
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.MID, TenantStatus.ACTIVE);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.TEAM, TenantStatus.ACTIVE);
tenant.setServerEndpoint("http://server:8080");
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
@@ -193,7 +192,7 @@ class TenantPortalServiceTest {
assertThat(result.name()).isEqualTo("Acme Corp");
assertThat(result.slug()).isEqualTo("acme-corp");
assertThat(result.tier()).isEqualTo("MID");
assertThat(result.tier()).isEqualTo("TEAM");
assertThat(result.status()).isEqualTo("ACTIVE");
assertThat(result.serverEndpoint()).isEqualTo("https://test.example.com/t/acme-corp/");
assertThat(result.createdAt()).isNull(); // no @PrePersist called in test, createdAt is null

View File

@@ -35,7 +35,7 @@ class TenantControllerTest {
@Test
void createTenant_returns201() throws Exception {
var request = new CreateTenantRequest("Test Org", "test-org-" + System.nanoTime(), "LOW", null, null);
var request = new CreateTenantRequest("Test Org", "test-org-" + System.nanoTime(), "STARTER", null, null);
mockMvc.perform(post("/api/tenants")
.with(jwt().jwt(j -> j
@@ -47,7 +47,7 @@ class TenantControllerTest {
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Test Org"))
.andExpect(jsonPath("$.tier").value("LOW"))
.andExpect(jsonPath("$.tier").value("STARTER"))
.andExpect(jsonPath("$.status").value("PROVISIONING"));
}

View File

@@ -41,7 +41,7 @@ class TenantServiceTest {
@Test
void create_savesNewTenantWithCorrectFields() {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "MID", null, null);
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "TEAM", null, null);
var actorId = UUID.randomUUID();
when(tenantRepository.existsBySlugAndStatusNot("acme-corp", TenantStatus.DELETED)).thenReturn(false);
@@ -51,7 +51,7 @@ class TenantServiceTest {
assertThat(result.getName()).isEqualTo("Acme Corp");
assertThat(result.getSlug()).isEqualTo("acme-corp");
assertThat(result.getTier()).isEqualTo(Tier.MID);
assertThat(result.getTier()).isEqualTo(Tier.TEAM);
assertThat(result.getStatus()).isEqualTo(TenantStatus.PROVISIONING);
}
@@ -82,7 +82,7 @@ class TenantServiceTest {
}
@Test
void create_defaultsToLowTier() {
void create_defaultsToStarterTier() {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", null, null, null);
when(tenantRepository.existsBySlugAndStatusNot("acme-corp", TenantStatus.DELETED)).thenReturn(false);
@@ -90,7 +90,7 @@ class TenantServiceTest {
var result = tenantService.create(request, UUID.randomUUID());
assertThat(result.getTier()).isEqualTo(Tier.LOW);
assertThat(result.getTier()).isEqualTo(Tier.STARTER);
}
@Test

View File

@@ -51,7 +51,7 @@ class VendorTenantControllerTest {
@Test
void listTenants_returnsAllTenants() throws Exception {
String slug = "list-test-" + System.nanoTime();
createTenant("List Test Org", slug, "LOW");
createTenant("List Test Org", slug, "STARTER");
mockMvc.perform(get("/api/vendor/tenants")
.with(jwt().jwt(j -> j
@@ -65,7 +65,7 @@ class VendorTenantControllerTest {
@Test
void createTenant_returns201() throws Exception {
String slug = "create-test-" + System.nanoTime();
var request = new CreateTenantRequest("Create Test Org", slug, "MID", null, null);
var request = new CreateTenantRequest("Create Test Org", slug, "TEAM", null, null);
mockMvc.perform(post("/api/vendor/tenants")
.with(jwt().jwt(j -> j
@@ -78,16 +78,16 @@ class VendorTenantControllerTest {
.andExpect(status().isCreated())
.andExpect(jsonPath("$.name").value("Create Test Org"))
.andExpect(jsonPath("$.slug").value(slug))
.andExpect(jsonPath("$.tier").value("MID"))
.andExpect(jsonPath("$.tier").value("TEAM"))
.andExpect(jsonPath("$.id").isNotEmpty());
}
@Test
void createTenant_returns409ForDuplicateSlug() throws Exception {
String slug = "duplicate-vendor-" + System.nanoTime();
createTenant("First Org", slug, "LOW");
createTenant("First Org", slug, "STARTER");
var request = new CreateTenantRequest("Second Org", slug, "LOW", null, null);
var request = new CreateTenantRequest("Second Org", slug, "STARTER", null, null);
mockMvc.perform(post("/api/vendor/tenants")
.with(jwt().jwt(j -> j
.claim("sub", "test-user")
@@ -102,7 +102,7 @@ class VendorTenantControllerTest {
@Test
void getTenantDetail_returnsDetailWithServerStatus() throws Exception {
String slug = "detail-test-" + System.nanoTime();
String id = createTenant("Detail Test Org", slug, "LOW");
String id = createTenant("Detail Test Org", slug, "STARTER");
mockMvc.perform(get("/api/vendor/tenants/" + id)
.with(jwt().jwt(j -> j
@@ -118,7 +118,7 @@ class VendorTenantControllerTest {
@Test
void suspendTenant_returnsUpdatedStatus() throws Exception {
String slug = "suspend-test-" + System.nanoTime();
String id = createTenant("Suspend Test Org", slug, "LOW");
String id = createTenant("Suspend Test Org", slug, "STARTER");
mockMvc.perform(post("/api/vendor/tenants/" + id + "/suspend")
.with(jwt().jwt(j -> j
@@ -132,7 +132,7 @@ class VendorTenantControllerTest {
@Test
void deleteTenant_returns204() throws Exception {
String slug = "delete-test-" + System.nanoTime();
String id = createTenant("Delete Test Org", slug, "LOW");
String id = createTenant("Delete Test Org", slug, "STARTER");
mockMvc.perform(delete("/api/vendor/tenants/" + id)
.with(jwt().jwt(j -> j
@@ -144,7 +144,7 @@ class VendorTenantControllerTest {
@Test
void createTenant_returns401WithoutAuth() throws Exception {
var request = new CreateTenantRequest("No Auth Org", "no-auth-vendor-" + System.nanoTime(), "LOW", null, null);
var request = new CreateTenantRequest("No Auth Org", "no-auth-vendor-" + System.nanoTime(), "STARTER", null, null);
mockMvc.perform(post("/api/vendor/tenants")
.contentType(MediaType.APPLICATION_JSON)

View File

@@ -9,6 +9,7 @@ import net.siegeln.cameleer.saas.provisioning.TenantDataCleanupService;
import net.siegeln.cameleer.saas.provisioning.TenantDatabaseService;
import net.siegeln.cameleer.saas.license.LicenseEntity;
import net.siegeln.cameleer.saas.license.LicenseService;
import net.siegeln.cameleer.saas.license.SigningKeyService;
import net.siegeln.cameleer.saas.provisioning.ProvisionResult;
import net.siegeln.cameleer.saas.provisioning.TenantProvisioner;
import net.siegeln.cameleer.saas.tenant.TenantEntity;
@@ -52,6 +53,9 @@ class VendorTenantServiceTest {
@Mock
private LicenseService licenseService;
@Mock
private SigningKeyService signingKeyService;
@Mock
private TenantProvisioner tenantProvisioner;
@@ -85,11 +89,11 @@ class VendorTenantServiceTest {
// Pass null for self-proxy initially, then re-create with the instance itself
// (in production, Spring's @Lazy proxy handles this circular ref)
vendorTenantService = new VendorTenantService(
tenantService, tenantRepository, licenseService,
tenantService, tenantRepository, licenseService, signingKeyService,
tenantProvisioner, serverApiClient, logtoClient, logtoConfig,
auditService, provisioningProps, dataCleanupService, tenantDatabaseService, null);
vendorTenantService = new VendorTenantService(
tenantService, tenantRepository, licenseService,
tenantService, tenantRepository, licenseService, signingKeyService,
tenantProvisioner, serverApiClient, logtoClient, logtoConfig,
auditService, provisioningProps, dataCleanupService, tenantDatabaseService, vendorTenantService);
@@ -133,7 +137,7 @@ class VendorTenantServiceTest {
private LicenseEntity licenseWithId(UUID tenantId) throws Exception {
var license = new LicenseEntity();
license.setTenantId(tenantId);
license.setTier("LOW");
license.setTier("STARTER");
license.setToken("test-token-" + UUID.randomUUID());
license.setIssuedAt(Instant.now());
license.setExpiresAt(Instant.now().plus(Duration.ofDays(365)));
@@ -147,9 +151,9 @@ class VendorTenantServiceTest {
@Test
void createAndProvision_createsTenantAndLicense() throws Exception {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null);
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null);
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var license = licenseWithId(tenant.getId());
when(tenantService.create(request, actorId)).thenReturn(tenant);
@@ -167,9 +171,9 @@ class VendorTenantServiceTest {
@Test
void createAndProvision_setsActiveWhenProvisionerSucceeds() throws Exception {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null);
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null);
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var license = licenseWithId(tenant.getId());
when(tenantService.create(request, actorId)).thenReturn(tenant);
@@ -191,9 +195,9 @@ class VendorTenantServiceTest {
@Test
void createAndProvision_setsProvisionErrorOnFailure() throws Exception {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null);
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null);
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var license = licenseWithId(tenant.getId());
when(tenantService.create(request, actorId)).thenReturn(tenant);
@@ -214,9 +218,9 @@ class VendorTenantServiceTest {
@Test
void createAndProvision_worksWithoutProvisioner() throws Exception {
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "LOW", null, null);
var request = new CreateTenantRequest("Acme Corp", "acme-corp", "STARTER", null, null);
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var license = licenseWithId(tenant.getId());
when(tenantService.create(request, actorId)).thenReturn(tenant);
@@ -236,8 +240,8 @@ class VendorTenantServiceTest {
void suspend_stopsContainersAndSetsStatus() throws Exception {
var tenantId = UUID.randomUUID();
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
suspended.setStatus(TenantStatus.SUSPENDED);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
@@ -255,8 +259,8 @@ class VendorTenantServiceTest {
void suspend_skipsStopWhenProvisionerUnavailable() throws Exception {
var tenantId = UUID.randomUUID();
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
var suspended = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
suspended.setStatus(TenantStatus.SUSPENDED);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
@@ -273,7 +277,7 @@ class VendorTenantServiceTest {
void delete_removesContainersRevokesLicenseDeletesOrg() throws Exception {
var tenantId = UUID.randomUUID();
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
tenant.setLogtoOrgId("org-123");
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
@@ -294,17 +298,20 @@ class VendorTenantServiceTest {
void renewLicense_revokesOldAndGeneratesNew() throws Exception {
var tenantId = UUID.randomUUID();
var actorId = UUID.randomUUID();
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.LOW);
var tenant = tenantWithId("Acme Corp", "acme-corp", Tier.STARTER);
tenant.setServerEndpoint("http://server:8080");
var newLicense = licenseWithId(tenantId);
when(tenantService.getById(tenantId)).thenReturn(Optional.of(tenant));
when(licenseService.generateLicense(eq(tenant), any(Duration.class), eq(actorId))).thenReturn(newLicense);
// mintLicense() calls the full generateLicense overload (limits, expiresAt, grace, label, actor)
when(licenseService.generateLicense(eq(tenant), any(java.util.Map.class), any(Instant.class),
any(Integer.class), any(String.class), eq(actorId))).thenReturn(newLicense);
var result = vendorTenantService.renewLicense(tenantId, actorId);
verify(licenseService).revokeLicense(tenantId, actorId);
verify(licenseService).generateLicense(eq(tenant), any(Duration.class), eq(actorId));
verify(licenseService).generateLicense(eq(tenant), any(java.util.Map.class), any(Instant.class),
any(Integer.class), any(String.class), eq(actorId));
verify(serverApiClient).pushLicense("http://server:8080", newLicense.getToken());
assertThat(result).isSameAs(newLicense);
}