blob: bec504a26d51de1fc3f1e817df9a5d106762295f [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.core;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import io.cucumber.java8.En;
import java.util.Arrays;
import java.util.List;
import javax.sql.DataSource;
import org.apache.fineract.infrastructure.core.config.FineractProperties;
import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
import org.apache.fineract.infrastructure.core.service.migration.ExtendedSpringLiquibase;
import org.apache.fineract.infrastructure.core.service.migration.ExtendedSpringLiquibaseFactory;
import org.apache.fineract.infrastructure.core.service.migration.SchemaUpgradeNeededException;
import org.apache.fineract.infrastructure.core.service.migration.TenantDataSourceFactory;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseStateVerifier;
import org.apache.fineract.infrastructure.core.service.migration.TenantDatabaseUpgradeService;
import org.apache.fineract.infrastructure.core.service.migration.TenantPasswordEncryptionTask;
import org.apache.fineract.infrastructure.core.service.tenant.TenantDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.mock.env.MockEnvironment;
public class LiquibaseStepDefinitions implements En {
private TenantDataSourceFactory tenantDataSourceFactory;
private TenantDetailsService tenantDetailsService;
private TenantDatabaseStateVerifier databaseStateVerifier;
@Autowired
private FineractProperties fineractProperties;
private ExtendedSpringLiquibaseFactory liquibaseFactory;
private ExtendedSpringLiquibase initialTenantStoreLiquibase;
private ExtendedSpringLiquibase tenantStoreLiquibase;
private ExtendedSpringLiquibase initialTenantLiquibase;
private ExtendedSpringLiquibase tenantLiquibase;
private ExtendedSpringLiquibase customChangeLogLiquibase;
private FineractPlatformTenant defaultTenant;
private DataSource tenantStoreDataSource;
private TenantDatabaseUpgradeService tenantDatabaseUpgradeService;
private List<FineractPlatformTenant> allTenants;
private SchemaUpgradeNeededException executionException;
private DataSource defaultTenantDataSource;
private Environment environment;
public LiquibaseStepDefinitions() {
Given("Liquibase is disabled with a default tenant", () -> {
initializeLiquibase(false);
});
Given("Liquibase is enabled with a default tenant", () -> {
initializeLiquibase(true);
});
Given("Liquibase runs the very first time for the tenant store", () -> {
given(databaseStateVerifier.isFirstLiquibaseMigration(tenantStoreDataSource)).willReturn(true);
});
Given("A previously Flyway migrated tenant store database on the latest version", () -> {
given(databaseStateVerifier.isFlywayPresent(tenantStoreDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(tenantStoreDataSource)).willReturn(true);
});
Given("A previously Flyway migrated tenant store database on an earlier version", () -> {
given(databaseStateVerifier.isFlywayPresent(tenantStoreDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantStoreOnLatestUpgradableVersion(tenantStoreDataSource)).willReturn(false);
});
Given("Liquibase runs the very first time for the default tenant", () -> {
given(databaseStateVerifier.isFirstLiquibaseMigration(defaultTenantDataSource)).willReturn(true);
});
Given("A previously Flyway migrated default tenant database on the latest version", () -> {
given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(true);
});
Given("A previously Flyway migrated default tenant database on an earlier version", () -> {
given(databaseStateVerifier.isFlywayPresent(defaultTenantDataSource)).willReturn(true);
given(databaseStateVerifier.isTenantOnLatestUpgradableVersion(defaultTenantDataSource)).willReturn(false);
});
When("The database migration process is executed", () -> {
try {
tenantDatabaseUpgradeService.afterPropertiesSet();
} catch (SchemaUpgradeNeededException e) {
executionException = e;
}
});
Then("The database migration did not do anything", () -> {
assertThat(verify(databaseStateVerifier).isLiquibaseDisabled()).isFalse();
verifyNoMoreInteractions(databaseStateVerifier);
verifyNoInteractions(tenantDetailsService, tenantStoreDataSource, liquibaseFactory, tenantDataSourceFactory);
});
Then("The database migration did not do anything, because it is not a write instance", () -> {
verify(databaseStateVerifier).isLiquibaseDisabled();
verifyNoMoreInteractions(databaseStateVerifier);
verifyNoInteractions(tenantDetailsService, tenantStoreDataSource, liquibaseFactory, tenantDataSourceFactory);
});
Then("The tenant store upgrade fails with a schema upgrade needed", () -> {
assertThat(executionException).isNotNull();
verify(liquibaseFactory).create(eq(tenantStoreDataSource), anyString(), anyString());
verifyNoMoreInteractions(liquibaseFactory);
verifyNoInteractions(initialTenantStoreLiquibase, tenantStoreLiquibase, initialTenantLiquibase, tenantLiquibase);
});
Then("The default tenant upgrade fails with a schema upgrade needed", () -> {
assertThat(executionException).isNotNull();
verify(liquibaseFactory).create(eq(tenantStoreDataSource), anyString(), anyString());
verify(liquibaseFactory).create(eq(tenantStoreDataSource), anyString());
verify(liquibaseFactory).create(eq(defaultTenantDataSource), anyString(), anyString(), anyString());
verifyNoMoreInteractions(liquibaseFactory);
verify(initialTenantStoreLiquibase).changeLogSync();
verify(tenantStoreLiquibase).afterPropertiesSet();
verifyNoInteractions(initialTenantLiquibase, tenantLiquibase);
});
Then("The tenant store and the default tenant gets upgraded from scratch", () -> {
verify(initialTenantStoreLiquibase).afterPropertiesSet();
verify(tenantStoreLiquibase).afterPropertiesSet();
verify(initialTenantLiquibase).afterPropertiesSet();
verify(tenantLiquibase).afterPropertiesSet();
});
Then("The tenant store and the default tenant gets synced and then upgraded", () -> {
verify(initialTenantStoreLiquibase).changeLogSync();
verify(tenantStoreLiquibase).afterPropertiesSet();
verify(initialTenantLiquibase).changeLogSync();
verify(tenantLiquibase).afterPropertiesSet();
});
}
private void initializeLiquibase(boolean liquibaseEnabled) {
tenantDataSourceFactory = mock(TenantDataSourceFactory.class);
tenantDetailsService = mock(TenantDetailsService.class);
databaseStateVerifier = mock(TenantDatabaseStateVerifier.class);
environment = new MockEnvironment();
liquibaseFactory = mock(ExtendedSpringLiquibaseFactory.class);
defaultTenant = mock(FineractPlatformTenant.class);
given(defaultTenant.getTenantIdentifier()).willReturn("defaultTenant");
allTenants = List.of(defaultTenant);
tenantStoreDataSource = mock(DataSource.class);
initialTenantLiquibase = mock(ExtendedSpringLiquibase.class);
tenantLiquibase = mock(ExtendedSpringLiquibase.class);
customChangeLogLiquibase = mock(ExtendedSpringLiquibase.class);
initialTenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
tenantStoreLiquibase = mock(ExtendedSpringLiquibase.class);
defaultTenantDataSource = mock(DataSource.class);
TenantPasswordEncryptionTask tenantPasswordEncryptor = mock(TenantPasswordEncryptionTask.class);
given(databaseStateVerifier.isLiquibaseDisabled()).willReturn(!liquibaseEnabled);
given(liquibaseFactory.create(tenantStoreDataSource, "tenant_store_db", "initial_switch")).willReturn(initialTenantStoreLiquibase);
given(liquibaseFactory.create(tenantStoreDataSource, "tenant_store_db")).willReturn(tenantStoreLiquibase);
given(tenantDetailsService.findAllTenants()).willReturn(allTenants);
given(tenantDataSourceFactory.create(defaultTenant)).willReturn(defaultTenantDataSource);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "initial_switch", "defaultTenant"))
.willReturn(initialTenantLiquibase);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "defaultTenant")).willReturn(tenantLiquibase);
given(liquibaseFactory.create(defaultTenantDataSource, "tenant_db", "custom_changelog", "defaultTenant"))
.willReturn(customChangeLogLiquibase);
tenantDatabaseUpgradeService = new TenantDatabaseUpgradeService(tenantDetailsService, tenantStoreDataSource, fineractProperties,
databaseStateVerifier, liquibaseFactory, tenantDataSourceFactory, environment, Arrays.asList(tenantPasswordEncryptor));
}
}