From c86a82ae18a4a16a511c847b9082171b74cb7341 Mon Sep 17 00:00:00 2001 From: Ivan Nikolaev-Axenov Date: Fri, 4 Oct 2024 17:45:28 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-758 ControlServiceTest added, testcontainers added to pom.xml --- clearing-parent/control-service/pom.xml | 13 ++ .../control/model/ResultContainer.java | 3 + .../control/service/ControlService.java | 25 ++- .../config/TestDataSourceConfiguration.java | 52 ++++++ .../control/service/ControlServiceTest.java | 171 ++++++++++++++++++ .../src/test/resources/.gitkeep | 0 6 files changed, 256 insertions(+), 8 deletions(-) create mode 100644 clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/config/TestDataSourceConfiguration.java create mode 100644 clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/service/ControlServiceTest.java create mode 100644 clearing-parent/control-service/src/test/resources/.gitkeep diff --git a/clearing-parent/control-service/pom.xml b/clearing-parent/control-service/pom.xml index 56887fec3..7f82a12c8 100644 --- a/clearing-parent/control-service/pom.xml +++ b/clearing-parent/control-service/pom.xml @@ -18,6 +18,7 @@ 5.5.2 7.0.1 + 1.20.2 @@ -83,6 +84,18 @@ test-clearing test + + org.testcontainers + testcontainers + ${testcontainers.version} + test + + + org.testcontainers + postgresql + ${testcontainers.version} + test + diff --git a/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/model/ResultContainer.java b/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/model/ResultContainer.java index 152373461..3386e8034 100644 --- a/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/model/ResultContainer.java +++ b/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/model/ResultContainer.java @@ -58,6 +58,9 @@ public class ResultContainer { this.quantityDifference = quantityDifference; } + public ResultContainer() { + } + public Long getSessionId() { return sessionId; } diff --git a/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/service/ControlService.java b/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/service/ControlService.java index 783a4a908..94d08a768 100644 --- a/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/service/ControlService.java +++ b/clearing-parent/control-service/src/main/java/ru/spcex/clearing/control/service/ControlService.java @@ -4,6 +4,7 @@ import com.opencsv.bean.StatefulBeanToCsv; import com.opencsv.bean.StatefulBeanToCsvBuilder; import com.opencsv.exceptions.CsvDataTypeMismatchException; import com.opencsv.exceptions.CsvRequiredFieldEmptyException; +import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; @@ -33,7 +34,7 @@ public class ControlService { resultDirectory = Path.of(settings.getResultDirectory()); } - public void generalControl(SessionType sessionType) { + public File generalControl(SessionType sessionType) { log.info("Starting general control with session type {}", sessionType); ResultContainer resultContainer = switch (sessionType) { @@ -48,34 +49,41 @@ public class ControlService { if (resultContainer.getQuantityDifference() != 0) { resultContainer.setSessionType(sessionType); - writeToCsvFile(resultContainer); + return writeToCsvFile(resultContainer); } + + return null; } - public void internalControl(Long sessionId) { + public File internalControl(Long sessionId) { log.info("Starting internal control with session id {}", sessionId); ResultContainer resultContainer = controlRepository.getInternalCountDiff(sessionId); if (resultContainer.getQuantityDifference() != 0) { resultContainer.setSessionId(sessionId); - writeToCsvFile(resultContainer); + return writeToCsvFile(resultContainer); } + + return null; } - public void internalControlFinl(Long sessionId) { + public File internalControlFinl(Long sessionId) { log.info("Starting internal control FINL with session id {}", sessionId); ResultContainer resultContainer = controlRepository.getFinlInternalCountDiff(sessionId); if (resultContainer.getQuantityDifference() != 0) { resultContainer.setSessionId(sessionId); - writeToCsvFile(resultContainer); + return writeToCsvFile(resultContainer); } + + return null; } - private void writeToCsvFile(ResultContainer resultContainer) { - try (Writer writer = new FileWriter(resultDirectory.resolve("result-" + Instant.now().getEpochSecond() + ".csv").toFile())) { + private File writeToCsvFile(ResultContainer resultContainer) { + File resultFile = resultDirectory.resolve("result-" + Instant.now().toEpochMilli() + ".csv").toFile(); + try (Writer writer = new FileWriter(resultFile)) { CustomMappingStrategy mappingStrategy = new CustomMappingStrategy<>(); mappingStrategy.setType(ResultContainer.class); @@ -86,5 +94,6 @@ public class ControlService { } catch (CsvRequiredFieldEmptyException | CsvDataTypeMismatchException | IOException e) { log.error(e.getMessage(), e); } + return resultFile; } } diff --git a/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/config/TestDataSourceConfiguration.java b/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/config/TestDataSourceConfiguration.java new file mode 100644 index 000000000..cb8929fd7 --- /dev/null +++ b/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/config/TestDataSourceConfiguration.java @@ -0,0 +1,52 @@ +package ru.spcex.clearing.control.config; + +import com.mchange.v2.c3p0.ComboPooledDataSource; +import java.beans.PropertyVetoException; +import javax.sql.DataSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.testcontainers.containers.PostgreSQLContainer; +import ru.spcex.clearing.control.config.settings.ControlServiceSettings; + +@Configuration +public class TestDataSourceConfiguration { + private final ControlServiceSettings settings; + + public TestDataSourceConfiguration(ControlServiceSettings settings) { + this.settings = settings; + } + + @Bean + public DataSource getDataSource() { + PostgreSQLContainer postgres = new PostgreSQLContainer<>(PostgreSQLContainer.IMAGE); + postgres.start(); + + ComboPooledDataSource cpds = new ComboPooledDataSource(); + try { + cpds.setDriverClass(postgres.getDriverClassName()); + cpds.setJdbcUrl(postgres.getJdbcUrl()); + cpds.setUser(postgres.getUsername()); + cpds.setPassword(postgres.getPassword()); + + cpds.setMaxPoolSize(100); + cpds.setMinPoolSize(50); + cpds.setAcquireIncrement(5); + } catch (PropertyVetoException e) { + throw new RuntimeException(e); + } + + return cpds; + } + + @Bean + public JdbcTemplate getJdbcTemplate() { + return new JdbcTemplate(getDataSource()); + } + + @Bean + public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() { + return new NamedParameterJdbcTemplate(getDataSource()); + } +} diff --git a/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/service/ControlServiceTest.java b/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/service/ControlServiceTest.java new file mode 100644 index 000000000..ee5370176 --- /dev/null +++ b/clearing-parent/control-service/src/test/java/ru/spcex/clearing/control/service/ControlServiceTest.java @@ -0,0 +1,171 @@ +package ru.spcex.clearing.control.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.opencsv.CSVReader; +import com.opencsv.exceptions.CsvException; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.List; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import ru.spcex.clearing.control.config.TestDataSourceConfiguration; +import ru.spcex.clearing.control.config.settings.ControlServiceSettings; +import ru.spcex.clearing.control.mapper.ResultContainerMapper; +import ru.spcex.clearing.control.model.ResultContainer; +import ru.spcex.clearing.control.repository.ControlRepository; +import ru.spcex.platform.enumeration.SessionType; + +@SpringBootTest(classes = { + TestDataSourceConfiguration.class, + ControlService.class, + ControlRepository.class, + ResultContainerMapper.class, + ControlServiceSettings.class +}, properties = { + "control-service.result-directory=src/test/resources" +}) +@EnableConfigurationProperties +class ControlServiceTest { + @Autowired + private ControlService controlService; + @Autowired + private JdbcTemplate jdbcTemplate; + + @BeforeEach + void setUp() { + jdbcTemplate.execute("DROP TABLE IF EXISTS s_trades"); + jdbcTemplate.execute("DROP TABLE IF EXISTS execution_deposit"); + jdbcTemplate.execute("DROP TABLE IF EXISTS execution_fond"); + jdbcTemplate.execute("DROP TABLE IF EXISTS execution_currency"); + jdbcTemplate.execute("DROP TABLE IF EXISTS payment_instruction"); + jdbcTemplate.execute("DROP TABLE IF EXISTS s_df03"); + + jdbcTemplate.execute("create table s_trades(id bigint not null primary key, created_at timestamp, updated_at timestamp, trade_num bigint, operation varchar(40), class_code varchar(255), trade_date date, sec_code varchar(255), accruedint numeric(72, 18), accruedint2 numeric(72, 18), lower_discount numeric(72, 18), order_num bigint, price numeric(72, 18), price2 numeric(72, 18), repo_rate numeric(72, 18), repo_value numeric(72, 18), repo2_value numeric(72, 18), start_discount numeric(72, 18), ts_commission numeric(72, 18), upper_discount numeric(72, 18), value numeric(72, 18), yield numeric(72, 18), qty numeric(72, 18), qty_pcs numeric(72, 18), trade_date_time timestamp, repo_term bigint, clearing_commission numeric(72, 18), exchange_commission numeric(72, 18), tech_center_commission numeric(72, 18), account varchar(50), broker_ref varchar(34), client_code varchar(255), settle_code varchar(50), user_id varchar(32), exchange_code varchar(64), firm_id varchar(255), firm_name varchar(255), cp_firm_id varchar(255), cp_firm_name varchar(255), class_name varchar(255), sec_name varchar(255), settle_date date, settle_currency varchar(4), trade_currency varchar(4), trade_time_ms bigint, bank_acc_id varchar(12), section varchar(4));"); + jdbcTemplate.execute("create table execution_deposit(exchange_execution_id bigint,exchange_execution_time timestamp,trading_date date,trading_clearing_registry_id bigint,party_trading_clearing_registry varchar(20),market varchar(8),price numeric(72, 18),lots numeric(72, 2),quantity numeric(72, 2),first_leg_amount numeric(72, 2),second_leg_amount numeric(72, 2),interest_amount numeric(72, 2),side varchar(4),settlement_currency varchar(4),company_id bigint,duration bigint,first_leg_settlement_date date,second_leg_settlement_date date,first_leg_settlement_code varchar(12),second_leg_settlement_code varchar(12),security_full_name varchar(255),security_symbol varchar(255),security_code varchar(255),security_id bigint,contract varchar(255),counter_party_id bigint,counter_party_trading_clearing_registry_id bigint,counter_party_trading_clearing_registry varchar(20),coverage_status varchar(4),session_id bigint,id bigint not null primary key, created_at timestamp, updated_at timestamp, clearing_date date);"); + jdbcTemplate.execute("create table execution_fond(id bigint not null primary key, created_at timestamp, updated_at timestamp, clearing_date date, exchange_execution_id bigint, side varchar(4), market varchar(4), trading_date date, security_symbol varchar(255), security_id bigint, interest_amount numeric(72, 2), exchange_order_id bigint, price numeric(72, 18), settlement_amount numeric(72, 2), lots numeric(72, 2), quantity numeric(72, 2), exchange_execution_time timestamp, duration bigint, trading_clearing_registry_id bigint, party_trading_clearing_registry varchar(20), comment varchar(255), client_code_id bigint, settlement_code varchar(12), company_id bigint, counter_party_id bigint, counter_party_trading_clearing_registry_id bigint, counter_party_trading_clearing_registry varchar(20), security_full_name varchar(255), settlement_date date, settlement_currency varchar(4), exchange_execution_microseconds timestamp, coverage_status varchar(4), session_id bigint);"); + jdbcTemplate.execute("create table execution_currency( exchange_execution_id bigint, exchange_execution_time timestamp, exchange_execution_microseconds timestamp, trading_date date, settlement_date date, settlement_code varchar(12), security_id bigint, security_symbol varchar(255), security_name varchar(255), company_id bigint, party_trading_clearing_registry_id bigint, party_trading_clearing_registry varchar(20), counter_party_id bigint, counter_party_trading_clearing_registry_id bigint, counter_party_trading_clearing_registry varchar(20), market varchar(4), price numeric(72, 18), lots numeric(72, 2), settlement_amount numeric(72, 2), quantity numeric(72, 2), side varchar(4), currency_code varchar(4), settlement_organization varchar(255), coverage_status varchar(4), session_id bigint, clearing_date date, id bigint not null primary key, created_at timestamp, updated_at timestamp);"); + jdbcTemplate.execute("create table payment_instruction( sender_id bigint, addressee_id bigint, payee_bic varchar(255), adressee_bic varchar(255), payee_bank_name varchar(255), addressee_bank_name varchar(255), payment_date timestamp, payment_purpose varchar(255), settlement_date date, credit_leg_amount numeric(72, 18), debit_leg_amount numeric(72, 18), credit_leg_account_id bigint, credit_cs_account varchar(255), credit_leg_account varchar(50), debit_leg_account_id bigint, debit_cs_account varchar(255), debit_leg_account varchar(50), credit_leg_direction varchar(4), debit_leg_direction varchar(4), credit_leg_currency_code varchar(4), debit_leg_currency_code varchar(4), credit_leg_security_id bigint, debit_leg_security_id bigint, transaction_status varchar(4), document_number varchar(255), id bigint not null primary key, created_at timestamp, updated_at timestamp, clearing_date date, session_id bigint);"); + jdbcTemplate.execute("create table s_df03( id bigint not null primary key, seg_type varchar(1), doc_type varchar(4), docnm_ref varchar(16), docnmprev varchar(16), c_acc_deb varchar(35), sbanknam1 varchar(35), sbanknam2 varchar(35), sbanknam3 varchar(35), sbanknam4 varchar(35), sbanknam5 varchar(35), c_acc_cred varchar(35), rbanknam1 varchar(35), rbanknam2 varchar(35), rbanknam3 varchar(35), rbanknam4 varchar(35), rbanknam5 varchar(35), pay_date varchar(8), pay_val varchar(12), sum_deb varchar(22), specif_1 varchar(255), imp_result varchar(3), file_name varchar(255), generation_time timestamp, generation_id bigint, payment_instruction_id bigint);"); + + jdbcTemplate.execute("insert into s_trades (id, created_at, section) values (1, NOW(), 'FINL'), (2, NOW(), 'FOND'), (3, NOW(), 'CURR');"); + jdbcTemplate.execute("insert into execution_deposit (id, created_at) values (1, NOW()), (2, NOW());"); + jdbcTemplate.execute("insert into execution_fond (id, created_at) values (1, NOW()), (2, NOW());"); + jdbcTemplate.execute("insert into execution_currency (id, created_at) values (1, NOW()), (2, NOW());"); + jdbcTemplate.execute("insert into payment_instruction (id, created_at, session_id) values (1, NOW(), 1), (2, NOW(), 1);"); + jdbcTemplate.execute("insert into s_df03 (id, generation_time, payment_instruction_id) values (1, NOW(), 1), (2, NOW(), 1);"); + } + + @Test + void generalControl_shouldReturnFINLCSVFile() { + ResultContainer resultContainer = new ResultContainer(null, SessionType.FINL, "s_trades", 3L, "execution_deposit", 2L, 1L); + + File resultFile = controlService.generalControl(SessionType.FINL); + assertThat(resultFile).isNotNull(); + + ResultContainer actual; + try (Reader reader = new FileReader(resultFile); + CSVReader csvReader = new CSVReader(reader)) { + actual = parseResultContainer(csvReader.readAll()); + } catch (IOException | CsvException e) { + throw new RuntimeException(e); + } + resultFile.delete(); + + assertThat(actual).isEqualTo(resultContainer); + } + + @Test + void generalControl_shouldReturnIPOBCSVFile() { + ResultContainer resultContainer = new ResultContainer(null, SessionType.IPOB, "s_trades", 1L, "execution_fond", 2L, -1L); + + File resultFile = controlService.generalControl(SessionType.IPOB); + assertThat(resultFile).isNotNull(); + + ResultContainer actual; + try (Reader reader = new FileReader(resultFile); + CSVReader csvReader = new CSVReader(reader)) { + actual = parseResultContainer(csvReader.readAll()); + } catch (IOException | CsvException e) { + throw new RuntimeException(e); + } + resultFile.delete(); + + assertThat(actual).isEqualTo(resultContainer); + } + + @Test + void generalControl_shouldReturnCURRCSVFile() { + ResultContainer resultContainer = new ResultContainer(null, SessionType.CURR, "s_trades", 1L, "execution_currency", 2L, -1L); + + File resultFile = controlService.generalControl(SessionType.CURR); + assertThat(resultFile).isNotNull(); + + ResultContainer actual; + try (Reader reader = new FileReader(resultFile); + CSVReader csvReader = new CSVReader(reader)) { + actual = parseResultContainer(csvReader.readAll()); + } catch (IOException | CsvException e) { + throw new RuntimeException(e); + } + resultFile.delete(); + + assertThat(actual).isEqualTo(resultContainer); + } + + @Test + void internalControl_shouldReturnInternalControlCSVFile() { + ResultContainer resultContainer = new ResultContainer(1L, null, null, 1L, null, 2L, 3L); + + File resultFile = controlService.internalControl(1L); + assertThat(resultFile).isNotNull(); + + ResultContainer actual; + try (Reader reader = new FileReader(resultFile); + CSVReader csvReader = new CSVReader(reader)) { + actual = parseResultContainer(csvReader.readAll()); + } catch (IOException | CsvException e) { + throw new RuntimeException(e); + } + resultFile.delete(); + + assertThat(actual).isEqualTo(resultContainer); + } + + @Test + void internalControlFinl_shouldReturnInternalControlCSVFile() { + ResultContainer resultContainer = new ResultContainer(1L, null, "payment_instruction", 2L, "s_df03", 3L, -1L); + + File resultFile = controlService.internalControlFinl(1L); + assertThat(resultFile).isNotNull(); + + ResultContainer actual; + try (Reader reader = new FileReader(resultFile); + CSVReader csvReader = new CSVReader(reader)) { + actual = parseResultContainer(csvReader.readAll()); + } catch (IOException | CsvException e) { + throw new RuntimeException(e); + } + resultFile.delete(); + + assertThat(actual).isEqualTo(resultContainer); + } + + private ResultContainer parseResultContainer(List rows) { + ResultContainer actual = new ResultContainer(); + actual.setSessionId(rows.get(1)[0].isBlank() ? null : Long.valueOf(rows.get(1)[0])); + actual.setSessionType(rows.get(1)[1].isBlank() ? null : SessionType.valueOf(rows.get(1)[1])); + actual.setFirstTableTitle(rows.get(1)[2].isBlank() ? null : rows.get(1)[2]); + actual.setFirstTableRecordQuantity(rows.get(1)[3].isBlank() ? null : Long.valueOf(rows.get(1)[3])); + actual.setSecondTableRecordTitle(rows.get(1)[4].isBlank() ? null : rows.get(1)[4]); + actual.setSecondTableRecordQuantity(rows.get(1)[5].isBlank() ? null : Long.valueOf(rows.get(1)[5])); + actual.setQuantityDifference(rows.get(1)[6].isBlank() ? null : Long.valueOf(rows.get(1)[6])); + return actual; + } +} \ No newline at end of file diff --git a/clearing-parent/control-service/src/test/resources/.gitkeep b/clearing-parent/control-service/src/test/resources/.gitkeep new file mode 100644 index 000000000..e69de29bb