JD-677: migrate to Java 15 and JUnit 5 (#143)

JD-677: migrate to java 15 and JUnit 5
This commit is contained in:
mr-impossibru 2021-09-20 18:16:06 +03:00 committed by GitHub
parent 9b10151756
commit 5a6874671b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 832 additions and 1379 deletions

View File

@ -1,4 +1,4 @@
extraction:
java:
index:
java_version: "11"
java_version: "15"

7
Jenkinsfile vendored
View File

@ -5,12 +5,11 @@ build('fraudbusters', 'java-maven') {
def javaServicePipeline
runStage('load JavaService pipeline') {
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaService.groovy")
javaServicePipeline = load("build_utils/jenkins_lib/pipeJavaServiceInsideDocker.groovy")
}
def serviceName = env.REPO_NAME
def mvnArgs = '-DjvmArgs="-Xmx256m"'
def useJava11 = true
javaServicePipeline(serviceName, useJava11, mvnArgs)
}
javaServicePipeline(serviceName, mvnArgs)
}

@ -1 +1 @@
Subproject commit a7655bc60c877a65cdfe3d9b668021d970d88a76
Subproject commit be44d69fc87b22a0bb82d98d6eae7658d1647f98

View File

@ -7,7 +7,7 @@
<parent>
<groupId>com.rbkmoney</groupId>
<artifactId>service-parent-pom</artifactId>
<version>1.2.10</version>
<version>2.0.8</version>
</parent>
<name>fraudbusters</name>
@ -185,8 +185,8 @@
<!-- Test libs -->
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>2.27.2</version>
<artifactId>wiremock-jre8</artifactId>
<version>2.31.0</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -10,17 +10,11 @@ public class CheckedResultToRiskScoreConverter implements Converter<CheckedResul
@Override
public RiskScore convert(CheckedResultModel checkedResultModel) {
switch (checkedResultModel.getResultModel().getResultStatus()) {
case ACCEPT:
case ACCEPT_AND_NOTIFY:
case NOTIFY:
return RiskScore.low;
case DECLINE:
case DECLINE_AND_NOTIFY:
return RiskScore.fatal;
default:
return RiskScore.high;
}
return switch (checkedResultModel.getResultModel().getResultStatus()) {
case ACCEPT, ACCEPT_AND_NOTIFY, NOTIFY -> RiskScore.low;
case DECLINE, DECLINE_AND_NOTIFY -> RiskScore.fatal;
default -> RiskScore.high;
};
}
}

View File

@ -21,41 +21,15 @@ public class ResultStatusConverter implements Converter<ResultStatus, com.rbkmon
public com.rbkmoney.damsel.fraudbusters.ResultStatus convert(ResultStatus resultStatus) {
var status = new com.rbkmoney.damsel.fraudbusters.ResultStatus();
switch (resultStatus) {
case ACCEPT: {
status.setAccept(new Accept());
break;
}
case ACCEPT_AND_NOTIFY: {
status.setAcceptAndNotify(new AcceptAndNotify());
break;
}
case THREE_DS: {
status.setThreeDs(new ThreeDs());
break;
}
case DECLINE: {
status.setDecline(new Decline());
break;
}
case DECLINE_AND_NOTIFY: {
status.setDeclineAndNotify(new DeclineAndNotify());
break;
}
case HIGH_RISK: {
status.setHighRisk(new HighRisk());
break;
}
case NORMAL: {
status.setNormal(new Normal());
break;
}
case NOTIFY: {
status.setNotify(new Notify());
break;
}
default: {
throw new IllegalArgumentException(UNKNOWN_VALUE);
}
case ACCEPT -> status.setAccept(new Accept());
case ACCEPT_AND_NOTIFY -> status.setAcceptAndNotify(new AcceptAndNotify());
case THREE_DS -> status.setThreeDs(new ThreeDs());
case DECLINE -> status.setDecline(new Decline());
case DECLINE_AND_NOTIFY -> status.setDeclineAndNotify(new DeclineAndNotify());
case HIGH_RISK -> status.setHighRisk(new HighRisk());
case NORMAL -> status.setNormal(new Normal());
case NOTIFY -> status.setNotify(new Notify());
default -> throw new IllegalArgumentException(UNKNOWN_VALUE);
}
return status;
}

View File

@ -11,32 +11,20 @@ public class PaymentFieldValueResolver {
public Optional<String> resolve(String fieldName, CheckedPayment checkedPayment) {
PaymentCheckedField byValue = PaymentCheckedField.valueOf(fieldName);
switch (byValue) {
case IP:
return Optional.of(checkedPayment.getIp());
case BIN:
return Optional.of(checkedPayment.getBin());
case CARD_TOKEN:
return Optional.of(checkedPayment.getCardToken());
case PARTY_ID:
return Optional.of(checkedPayment.getPartyId());
case EMAIL:
return Optional.of(checkedPayment.getEmail());
case PAN:
return Optional.of(checkedPayment.getMaskedPan());
case FINGERPRINT:
return Optional.of(checkedPayment.getFingerprint());
case SHOP_ID:
return Optional.of(checkedPayment.getShopId());
case COUNTRY_BANK:
return Optional.of(checkedPayment.getBankCountry());
case CURRENCY:
return Optional.of(checkedPayment.getCurrency());
case COUNTRY_IP:
return Optional.of(checkedPayment.getPaymentCountry());
default:
return Optional.empty();
}
return switch (byValue) {
case IP -> Optional.of(checkedPayment.getIp());
case BIN -> Optional.of(checkedPayment.getBin());
case CARD_TOKEN -> Optional.of(checkedPayment.getCardToken());
case PARTY_ID -> Optional.of(checkedPayment.getPartyId());
case EMAIL -> Optional.of(checkedPayment.getEmail());
case PAN -> Optional.of(checkedPayment.getMaskedPan());
case FINGERPRINT -> Optional.of(checkedPayment.getFingerprint());
case SHOP_ID -> Optional.of(checkedPayment.getShopId());
case COUNTRY_BANK -> Optional.of(checkedPayment.getBankCountry());
case CURRENCY -> Optional.of(checkedPayment.getCurrency());
case COUNTRY_IP -> Optional.of(checkedPayment.getPaymentCountry());
default -> Optional.empty();
};
}
}

View File

@ -30,52 +30,35 @@ public class DbP2pFieldResolver {
if (field == null) {
throw new UnknownFieldException();
}
switch (field) {
case IP:
return new FieldModel(EventP2PField.ip.name(), model.getIp());
case EMAIL:
return new FieldModel(EventP2PField.email.name(), model.getEmail());
case BIN:
return new FieldModel(EventP2PField.bin.name(), model.getSender().getBin());
case FINGERPRINT:
return new FieldModel(EventP2PField.fingerprint.name(), model.getFingerprint());
case IDENTITY_ID:
return new FieldModel(EventP2PField.identityId.name(), model.getIdentityId());
case CARD_TOKEN_FROM:
return new FieldModel(EventP2PField.cardTokenFrom.name(), model.getSender().getCardToken());
case CARD_TOKEN_TO:
return new FieldModel(EventP2PField.cardTokenTo.name(), model.getReceiver().getCardToken());
case PAN:
return new FieldModel(EventP2PField.maskedPan.name(), model.getSender().getPan());
default:
throw new UnknownFieldException();
}
return switch (field) {
case IP -> new FieldModel(EventP2PField.ip.name(), model.getIp());
case EMAIL -> new FieldModel(EventP2PField.email.name(), model.getEmail());
case BIN -> new FieldModel(EventP2PField.bin.name(), model.getSender().getBin());
case FINGERPRINT -> new FieldModel(EventP2PField.fingerprint.name(), model.getFingerprint());
case IDENTITY_ID -> new FieldModel(EventP2PField.identityId.name(), model.getIdentityId());
case CARD_TOKEN_FROM -> new FieldModel(EventP2PField.cardTokenFrom.name(),
model.getSender().getCardToken());
case CARD_TOKEN_TO -> new FieldModel(EventP2PField.cardTokenTo.name(), model.getReceiver().getCardToken());
case PAN -> new FieldModel(EventP2PField.maskedPan.name(), model.getSender().getPan());
default -> throw new UnknownFieldException();
};
}
public String resolve(P2PCheckedField field) {
if (field == null) {
throw new UnknownFieldException();
}
switch (field) {
case IP:
return EventP2PField.ip.name();
case EMAIL:
return EventP2PField.email.name();
case BIN:
return EventP2PField.bin.name();
case PAN:
return EventP2PField.maskedPan.name();
case FINGERPRINT:
return EventP2PField.fingerprint.name();
case IDENTITY_ID:
return EventP2PField.identityId.name();
case CARD_TOKEN_FROM:
return EventP2PField.cardTokenFrom.name();
case CARD_TOKEN_TO:
return EventP2PField.cardTokenTo.name();
default:
throw new UnknownFieldException();
}
return switch (field) {
case IP -> EventP2PField.ip.name();
case EMAIL -> EventP2PField.email.name();
case BIN -> EventP2PField.bin.name();
case PAN -> EventP2PField.maskedPan.name();
case FINGERPRINT -> EventP2PField.fingerprint.name();
case IDENTITY_ID -> EventP2PField.identityId.name();
case CARD_TOKEN_FROM -> EventP2PField.cardTokenFrom.name();
case CARD_TOKEN_TO -> EventP2PField.cardTokenTo.name();
default -> throw new UnknownFieldException();
};
}
}

View File

@ -9,26 +9,17 @@ public class P2PModelFieldResolver implements FieldResolver<P2PModel, P2PChecked
@Override
public String resolveValue(String fieldName, P2PModel model) {
switch (P2PCheckedField.getByValue(fieldName)) {
case BIN:
return model.getSender().getBin();
case IP:
return model.getIp();
case FINGERPRINT:
return model.getFingerprint();
case EMAIL:
return model.getEmail();
case COUNTRY_BANK:
return model.getSender().getBinCountryCode();
case CARD_TOKEN_FROM:
return model.getSender().getCardToken();
case CARD_TOKEN_TO:
return model.getReceiver().getCardToken();
case PAN:
return model.getSender().getPan();
default:
throw new UnresolvableFieldException(fieldName);
}
return switch (P2PCheckedField.getByValue(fieldName)) {
case BIN -> model.getSender().getBin();
case IP -> model.getIp();
case FINGERPRINT -> model.getFingerprint();
case EMAIL -> model.getEmail();
case COUNTRY_BANK -> model.getSender().getBinCountryCode();
case CARD_TOKEN_FROM -> model.getSender().getCardToken();
case CARD_TOKEN_TO -> model.getReceiver().getCardToken();
case PAN -> model.getSender().getPan();
default -> throw new UnresolvableFieldException(fieldName);
};
}
@Override

View File

@ -30,60 +30,38 @@ public class DatabasePaymentFieldResolver {
if (field == null) {
throw new UnknownFieldException();
}
switch (field) {
case IP:
return new FieldModel(EventField.ip.name(), model.getIp());
case EMAIL:
return new FieldModel(EventField.email.name(), model.getEmail());
case BIN:
return new FieldModel(EventField.bin.name(), model.getBin());
case FINGERPRINT:
return new FieldModel(EventField.fingerprint.name(), model.getFingerprint());
case PARTY_ID:
return new FieldModel(EventField.partyId.name(), model.getPartyId());
case SHOP_ID:
return new FieldModel(EventField.shopId.name(), model.getShopId());
case CARD_TOKEN:
return new FieldModel(EventField.cardToken.name(), model.getCardToken());
case PAN:
return new FieldModel(EventField.maskedPan.name(), model.getPan());
case MOBILE:
return new FieldModel(EventField.mobile.name(), model.isMobile());
case RECURRENT:
return new FieldModel(EventField.recurrent.name(), model.isRecurrent());
default:
throw new UnknownFieldException();
}
return switch (field) {
case IP -> new FieldModel(EventField.ip.name(), model.getIp());
case EMAIL -> new FieldModel(EventField.email.name(), model.getEmail());
case BIN -> new FieldModel(EventField.bin.name(), model.getBin());
case FINGERPRINT -> new FieldModel(EventField.fingerprint.name(), model.getFingerprint());
case PARTY_ID -> new FieldModel(EventField.partyId.name(), model.getPartyId());
case SHOP_ID -> new FieldModel(EventField.shopId.name(), model.getShopId());
case CARD_TOKEN -> new FieldModel(EventField.cardToken.name(), model.getCardToken());
case PAN -> new FieldModel(EventField.maskedPan.name(), model.getPan());
case MOBILE -> new FieldModel(EventField.mobile.name(), model.isMobile());
case RECURRENT -> new FieldModel(EventField.recurrent.name(), model.isRecurrent());
default -> throw new UnknownFieldException();
};
}
public String resolve(PaymentCheckedField field) {
if (field == null) {
throw new UnknownFieldException();
}
switch (field) {
case IP:
return EventField.ip.name();
case EMAIL:
return EventField.email.name();
case BIN:
return EventField.bin.name();
case PAN:
return EventField.maskedPan.name();
case FINGERPRINT:
return EventField.fingerprint.name();
case PARTY_ID:
return EventField.partyId.name();
case SHOP_ID:
return EventField.shopId.name();
case CARD_TOKEN:
return EventField.cardToken.name();
case MOBILE:
return EventField.mobile.name();
case RECURRENT:
return EventField.recurrent.name();
default:
throw new UnknownFieldException();
}
return switch (field) {
case IP -> EventField.ip.name();
case EMAIL -> EventField.email.name();
case BIN -> EventField.bin.name();
case PAN -> EventField.maskedPan.name();
case FINGERPRINT -> EventField.fingerprint.name();
case PARTY_ID -> EventField.partyId.name();
case SHOP_ID -> EventField.shopId.name();
case CARD_TOKEN -> EventField.cardToken.name();
case MOBILE -> EventField.mobile.name();
case RECURRENT -> EventField.recurrent.name();
default -> throw new UnknownFieldException();
};
}
}

View File

@ -9,24 +9,16 @@ public class PaymentModelFieldResolver implements FieldResolver<PaymentModel, Pa
@Override
public String resolveValue(String fieldName, PaymentModel paymentModel) {
switch (PaymentCheckedField.getByValue(fieldName)) {
case BIN:
return paymentModel.getBin();
case IP:
return paymentModel.getIp();
case FINGERPRINT:
return paymentModel.getFingerprint();
case EMAIL:
return paymentModel.getEmail();
case COUNTRY_BANK:
return paymentModel.getBinCountryCode();
case CARD_TOKEN:
return paymentModel.getCardToken();
case PAN:
return paymentModel.getPan();
default:
throw new UnresolvableFieldException(fieldName);
}
return switch (PaymentCheckedField.getByValue(fieldName)) {
case BIN -> paymentModel.getBin();
case IP -> paymentModel.getIp();
case FINGERPRINT -> paymentModel.getFingerprint();
case EMAIL -> paymentModel.getEmail();
case COUNTRY_BANK -> paymentModel.getBinCountryCode();
case CARD_TOKEN -> paymentModel.getCardToken();
case PAN -> paymentModel.getPan();
default -> throw new UnresolvableFieldException(fieldName);
};
}
@Override

View File

@ -16,14 +16,9 @@ public class AbstractGroupCommandListenerExecutor {
protected void execCommand(Command command, Pool<List<String>> pool) {
Group group = command.getCommandBody().getGroup();
switch (command.command_type) {
case CREATE:
createGroup(group, pool);
return;
case DELETE:
pool.remove(group.getGroupId());
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> createGroup(group, pool);
case DELETE -> pool.remove(group.getGroupId());
default -> log.error("Unknown command: {}", command);
}
}

View File

@ -12,27 +12,17 @@ public class AbstractPoolCommandListenerExecutor {
protected <T> void execCommand(Command command, String key, Pool<T> pool, Supplier<T> supplier) {
switch (command.command_type) {
case CREATE:
pool.add(key, supplier.get());
return;
case DELETE:
pool.remove(key);
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> pool.add(key, supplier.get());
case DELETE -> pool.remove(key);
default -> log.error("Unknown command: {}", command);
}
}
protected <T, R> void execCommand(Command command, String key, Pool<R> pool, Function<T, R> function, T param) {
switch (command.command_type) {
case CREATE:
pool.add(key, function.apply(param));
return;
case DELETE:
pool.remove(key);
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> pool.add(key, function.apply(param));
case DELETE -> pool.remove(key);
default -> log.error("Unknown command: {}", command);
}
}

View File

@ -18,14 +18,9 @@ public class AbstractTimeGroupCommandListenerExecutor {
Group group = command.getCommandBody().getGroup();
Long timestamp = TimestampUtil.parseInstantFromString(command.getCommandTime()).toEpochMilli();
switch (command.command_type) {
case CREATE:
createGroup(group, timestamp, pool);
return;
case DELETE:
pool.add(group.getGroupId(), timestamp, null);
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> createGroup(group, timestamp, pool);
case DELETE -> pool.add(group.getGroupId(), timestamp, null);
default -> log.error("Unknown command: {}", command);
}
}

View File

@ -22,14 +22,9 @@ public class AbstractTimePoolCommandListenerExecutor {
HistoricalPool<T> pool,
Supplier<T> supplier) {
switch (command.command_type) {
case CREATE:
pool.add(key, time, supplier.get());
return;
case DELETE:
pool.add(key, time, null);
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> pool.add(key, time, supplier.get());
case DELETE -> pool.add(key, time, null);
default -> log.error("Unknown command: {}", command);
}
}
@ -41,14 +36,9 @@ public class AbstractTimePoolCommandListenerExecutor {
Function<T, R> function,
T param) {
switch (command.command_type) {
case CREATE:
pool.add(key, time, function.apply(param));
return;
case DELETE:
pool.add(key, time, null);
return;
default:
log.error("Unknown command: {}", command);
case CREATE -> pool.add(key, time, function.apply(param));
case DELETE -> pool.add(key, time, null);
default -> log.error("Unknown command: {}", command);
}
}

View File

@ -21,15 +21,15 @@ public class AggregationGeneralRepositoryImpl implements AggregationGeneralRepos
@Override
public Integer countOperationByField(String table, String fieldName, Object value, Long from, Long to) {
String sql = String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? " +
"group by %1$s", fieldName, table);
String sql = String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ?
group by %1$s""", fieldName, table);
List<Object> params = AggregationUtil.generateParams(from, to, value);
log.debug("AggregationGeneralRepositoryImpl countOperationByField sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -41,14 +41,14 @@ public class AggregationGeneralRepositoryImpl implements AggregationGeneralRepos
List<FieldModel> fieldModels) {
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? ", fieldName, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ?""", fieldName, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format(" group by %1$s ", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
String sqlResult = resultSql.toString();
@ -66,14 +66,14 @@ public class AggregationGeneralRepositoryImpl implements AggregationGeneralRepos
List<FieldModel> fieldModels) {
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? ", fieldName, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ?""", fieldName, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
@ -94,15 +94,15 @@ public class AggregationGeneralRepositoryImpl implements AggregationGeneralRepos
String fieldNameCount,
Long from,
Long to) {
String sql = String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? " +
"group by %1$s", fieldNameBy, fieldNameCount, table);
String sql = String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ?
group by %1$s""", fieldNameBy, fieldNameCount, table);
List<Object> params = AggregationUtil.generateParams(from, to, value);
log.debug("AggregationGeneralRepositoryImpl uniqCountOperation sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -112,14 +112,14 @@ public class AggregationGeneralRepositoryImpl implements AggregationGeneralRepos
public Integer uniqCountOperationWithGroupBy(
String table, String fieldNameBy, Object value, String fieldNameCount,
Long from, Long to, List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? ", fieldNameBy, fieldNameCount, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ?""", fieldNameBy, fieldNameCount, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldNameBy));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value);

View File

@ -27,15 +27,15 @@ public class AggregationStatusGeneralRepositoryImpl implements AggregationStatus
Long from,
Long to,
String status) {
String sql = String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? " +
"group by %1$s", fieldName, table);
String sql = String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?
group by %1$s""", fieldName, table);
List<Object> params = AggregationUtil.generateStatusParams(from, to, value, status);
log.debug("AggregationGeneralRepositoryImpl countOperationByField sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -47,14 +47,14 @@ public class AggregationStatusGeneralRepositoryImpl implements AggregationStatus
List<FieldModel> fieldModels, String status) {
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value, status);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? ", fieldName, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?""", fieldName, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format(" group by %1$s ", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
String sqlResult = resultSql.toString();
@ -72,14 +72,14 @@ public class AggregationStatusGeneralRepositoryImpl implements AggregationStatus
List<FieldModel> fieldModels, String status) {
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value, status);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ?", fieldName, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?""", fieldName, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
@ -96,15 +96,15 @@ public class AggregationStatusGeneralRepositoryImpl implements AggregationStatus
public Integer uniqCountOperation(
String table, String fieldNameBy, Object value, String fieldNameCount,
Long from, Long to, String status) {
String sql = String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? " +
"group by %1$s", fieldNameBy, fieldNameCount, table);
String sql = String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?
group by %1$s""", fieldNameBy, fieldNameCount, table);
List<Object> params = AggregationUtil.generateStatusParams(from, to, value, status);
log.debug("AggregationGeneralRepositoryImpl uniqCountOperation sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -114,14 +114,14 @@ public class AggregationStatusGeneralRepositoryImpl implements AggregationStatus
public Integer uniqCountOperationWithGroupBy(
String table, String fieldNameBy, Object value, String fieldNameCount,
Long from, Long to, List<FieldModel> fieldModels, String status) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? ", fieldNameBy, fieldNameCount, table));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?""", fieldNameBy, fieldNameCount, table));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldNameBy));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params = AggregationUtil.generateParams(from, to, fieldModels, value, status);

View File

@ -7,6 +7,7 @@ import net.logstash.logback.encoder.org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.time.Instant;
import java.util.Collections;
@ -18,21 +19,25 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class CommonQueryRepository {
private static final String QUERY = "SELECT cardToken" +
" FROM fraud.payment " +
" WHERE toDateTime(?) - INTERVAL ? YEAR < toDateTime(eventTime) and " +
"toDateTime(?) > toDateTime(eventTime) and status='captured' " +
" and providerId in (%s)" +
" GROUP BY cardToken, currency " +
" HAVING (uniq(id) > 2 and ((sum(amount) > 200000 and currency = 'RUB') " +
" or (sum(amount) > 3000 and (currency = 'EUR' or currency = 'USD')))) " +
" or (uniq(id) > 0 and (sum(amount) > 500000 and currency = 'KZT')) ";
private static final String QUERY = """
SELECT cardToken
FROM fraud.payment
WHERE toDateTime(?) - INTERVAL ? YEAR < toDateTime(eventTime)
and toDateTime(?) > toDateTime(eventTime) and status='captured'
and providerId in (%s)
GROUP BY cardToken, currency
HAVING (uniq(id) > 2 and ((sum(amount) > 200000 and currency = 'RUB')
or (sum(amount) > 3000 and (currency = 'EUR' or currency = 'USD'))))
or (uniq(id) > 0 and (sum(amount) > 500000 and currency = 'KZT'))
""";
private static final String QUERY_WITHDRAWAL = "SELECT distinct cardToken" +
" FROM fraud.withdrawal " +
" WHERE toDateTime(?) - INTERVAL ? YEAR < toDateTime(eventTime) " +
" and toDateTime(?) > toDateTime(eventTime) " +
" and status='succeeded'";
private static final String QUERY_WITHDRAWAL = """
SELECT distinct cardToken
FROM fraud.withdrawal
WHERE toDateTime(?) - INTERVAL ? YEAR < toDateTime(eventTime)
and toDateTime(?) > toDateTime(eventTime)
and status='succeeded'
""";
private final JdbcTemplate longQueryJdbcTemplate;
@ -65,7 +70,8 @@ public class CommonQueryRepository {
List.of(timeHour.getEpochSecond(), timeIntervalYear, timeHour.getEpochSecond()).toArray(),
(rs, rowNum) -> rs.getString(1)
);
log.info("select withdrawal card tokens result size: {}", cardTokensWithdrawal.size());
log.info("select withdrawal card tokens result size: {}",
CollectionUtils.isEmpty(cardTokensWithdrawal) ? 0 : cardTokensWithdrawal.size());
data.addAll(cardTokensWithdrawal);
return data.stream()
.distinct()

View File

@ -26,35 +26,36 @@ import java.util.List;
@RequiredArgsConstructor
public class FraudPaymentRepository implements Repository<FraudPaymentRow>, AggregationRepository {
private static final String INSERT = "INSERT INTO " +
EventSource.FRAUD_EVENTS_FRAUD_PAYMENT.getTable() +
" (timestamp," +
" eventTimeHour," +
" eventTime," +
" id," +
" fraudType ," +
" comment," +
" email," +
" ip," +
" fingerprint," +
" bin," +
" maskedPan," +
" cardToken," +
" paymentSystem," +
" paymentTool," +
" terminal," +
" providerId," +
" bankCountry," +
" partyId," +
" shopId," +
" amount," +
" currency," +
" status," +
" errorReason," +
" errorCode," +
" paymentCountry)" +
" VALUES (?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, " +
"?, ?)";
private static final String INSERT = String.format("""
INSERT INTO
%s
(timestamp,
eventTimeHour,
eventTime,
id,
fraudType ,
comment,
email,
ip,
fingerprint,
bin,
maskedPan,
cardToken,
paymentSystem,
paymentTool,
terminal,
providerId,
bankCountry,
partyId,
shopId,
amount,
currency,
status,
errorReason,
errorCode,
paymentCountry)
VALUES (?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?,?, ?)""",
EventSource.FRAUD_EVENTS_FRAUD_PAYMENT.getTable());
private final AggregationStatusGeneralRepositoryImpl aggregationStatusGeneralRepository;
private final JdbcTemplate jdbcTemplate;
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;

View File

@ -143,14 +143,14 @@ public class FraudResultRepository implements Repository<Event>, PaymentReposito
public Integer countOperationSuccessWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and resultStatus != ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and resultStatus != ?""",
fieldName,
EventSource.FRAUD_EVENTS_UNIQUE.getTable()
));
@ -170,14 +170,14 @@ public class FraudResultRepository implements Repository<Event>, PaymentReposito
EventSource.FRAUD_EVENTS_UNIQUE.getTable(),
errorCode
);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and resultStatus = ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and resultStatus = ?""",
fieldName,
EventSource.FRAUD_EVENTS_UNIQUE.getTable()
));
@ -192,14 +192,14 @@ public class FraudResultRepository implements Repository<Event>, PaymentReposito
public Long sumOperationSuccessWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and resultStatus != ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and resultStatus != ?""",
fieldName,
EventSource.FRAUD_EVENTS_UNIQUE.getTable()
));
@ -219,14 +219,14 @@ public class FraudResultRepository implements Repository<Event>, PaymentReposito
EventSource.FRAUD_EVENTS_UNIQUE.getTable(),
errorCode
);
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and resultStatus = ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and resultStatus = ?""",
fieldName,
EventSource.FRAUD_EVENTS_UNIQUE.getTable()
));

View File

@ -66,15 +66,15 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
@Override
public Integer countOperationByField(String fieldName, Object value, Long from, Long to) {
String sql = String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status != ?" +
"group by %1$s", fieldName, TABLE);
String sql = String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status != ?
group by %1$s""", fieldName, TABLE);
List<Object> params = AggregationUtil.generateStatusParams(from, to, value, PaymentStatus.captured.name());
log.debug("AggregationGeneralRepositoryImpl countOperationByField sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -87,14 +87,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
Long from,
Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status != ? ", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status != ?""", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params =
@ -110,14 +110,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
Long from,
Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status != ? ", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status != ?""", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params =
@ -128,15 +128,15 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
@Override
public Integer uniqCountOperation(String fieldNameBy, Object value, String fieldNameCount, Long from, Long to) {
String sql = String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status != ?" +
"group by %1$s", fieldNameBy, fieldNameCount, TABLE);
String sql = String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status != ?
group by %1$s""", fieldNameBy, fieldNameCount, TABLE);
List<Object> params = AggregationUtil.generateStatusParams(from, to, value, PaymentStatus.captured.name());
log.debug("AggregationGeneralRepositoryImpl uniqCountOperation sql: {} params: {}", sql, params);
return jdbcTemplate.query(sql, params.toArray(), new CountExtractor());
@ -146,14 +146,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
public Integer uniqCountOperationWithGroupBy(
String fieldNameBy, Object value, String fieldNameCount, Long from, Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, uniq(%2$s) as cnt " +
"from %3$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status != ?",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, uniq(%2$s) as cnt
from %3$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status != ?""",
fieldNameBy,
fieldNameCount,
EventSource.FRAUD_EVENTS_PAYMENT.getTable()
@ -171,14 +171,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
public Integer countOperationSuccessWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? ", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?""", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params =
@ -191,14 +191,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
public Integer countOperationErrorWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels, String errorCode) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, count() as cnt " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? and errorCode = ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, count() as cnt
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ? and errorCode = ?""",
fieldName,
EventSource.FRAUD_EVENTS_PAYMENT.getTable()
));
@ -214,14 +214,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
public Long sumOperationSuccessWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? ", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ?""", fieldName, EventSource.FRAUD_EVENTS_PAYMENT.getTable()));
StringBuilder sqlGroupBy = new StringBuilder(String.format("group by %1$s", fieldName));
StringBuilder resultSql = AggregationUtil.appendGroupingFields(fieldModels, sql, sqlGroupBy);
List<Object> params =
@ -234,14 +234,14 @@ public class PaymentRepositoryImpl implements Repository<CheckedPayment>, Paymen
public Long sumOperationErrorWithGroupBy(
String fieldName, Object value, Long from, Long to,
List<FieldModel> fieldModels, String errorCode) {
StringBuilder sql = new StringBuilder(String.format(
"select %1$s, sum(amount) as sum " +
"from %2$s " +
"where timestamp >= ? " +
"and timestamp <= ? " +
"and eventTime >= ? " +
"and eventTime <= ? " +
"and %1$s = ? and status = ? and errorCode = ? ",
StringBuilder sql = new StringBuilder(String.format("""
select %1$s, sum(amount) as sum
from %2$s
where timestamp >= ?
and timestamp <= ?
and eventTime >= ?
and eventTime <= ?
and %1$s = ? and status = ? and errorCode = ?""",
fieldName,
EventSource.FRAUD_EVENTS_PAYMENT.getTable()
));

View File

@ -25,13 +25,15 @@ import java.util.Map;
@RequiredArgsConstructor
public class EventP2PRepository implements Repository<EventP2P>, AggregationRepository {
private static final String INSERT = "INSERT INTO fraud.events_p_to_p " +
"(timestamp, eventTime, eventTimeHour, identityId, transferId, ip, email, " +
"bin, fingerprint, amount, " +
"currency, country, bankCountry, maskedPan, bankName, cardTokenFrom, " +
"cardTokenTo, resultStatus, checkedRule, " +
"checkedTemplate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?," +
" ?, ?, ?)";
private static final String INSERT = """
INSERT INTO fraud.events_p_to_p
(timestamp, eventTime, eventTimeHour, identityId, transferId, ip, email,
bin, fingerprint, amount,
currency, country, bankCountry, maskedPan, bankName, cardTokenFrom,
cardTokenTo, resultStatus, checkedRule,
checkedTemplate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?)
""";
private final JdbcTemplate jdbcTemplate;
private final AggregationGeneralRepository aggregationGeneralRepository;

View File

@ -7,33 +7,34 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ChargeBackQuery {
public static final String SELECT_HISTORY_CHARGEBACK = "" +
"SELECT " +
" eventTime, " +
" partyId, " +
" shopId, " +
" email, " +
" amount as amount, " +
" currency, " +
" id, " +
" bankCountry, " +
" cardToken, " +
" bin, " +
" maskedPan, " +
" paymentSystem, " +
" providerId, " +
" status, " +
" ip, " +
" fingerprint, " +
" terminal, " +
" paymentId, " +
" chargebackCode, " +
" category " +
" FROM " +
EventSource.FRAUD_EVENTS_CHARGEBACK.getTable() +
" WHERE " +
" timestamp >= toDate(:from) " +
" and timestamp <= toDate(:to) " +
" and toDateTime(eventTime) >= toDateTime(:from) " +
" and toDateTime(eventTime) <= toDateTime(:to) ";
public static final String SELECT_HISTORY_CHARGEBACK = String.format("""
SELECT
eventTime,
partyId,
shopId,
email,
amount as amount,
currency,
id,
bankCountry,
cardToken,
bin,
maskedPan,
paymentSystem,
providerId,
status,
ip,
fingerprint,
terminal,
paymentId,
chargebackCode,
category
FROM
%s
WHERE
timestamp >= toDate(:from)
and timestamp <= toDate(:to)
and toDateTime(eventTime) >= toDateTime(:from)
and toDateTime(eventTime) <= toDateTime(:to)""",
EventSource.FRAUD_EVENTS_CHARGEBACK.getTable());
}

View File

@ -7,36 +7,37 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FraudPaymentQuery {
public static final String SELECT_HISTORY_FRAUD_PAYMENT = "" +
"SELECT " +
" eventTime, " +
" partyId, " +
" shopId, " +
" email, " +
" amount as amount, " +
" currency, " +
" id, " +
" cardToken, " +
" bin, " +
" maskedPan, " +
" bankCountry, " +
" fingerprint, " +
" ip, " +
" status, " +
" errorReason, " +
" errorCode, " +
" paymentSystem, " +
" paymentCountry, " +
" paymentTool, " +
" providerId, " +
" terminal, " +
" fraudType, " +
" comment " +
" FROM " +
EventSource.FRAUD_EVENTS_FRAUD_PAYMENT.getTable() +
" WHERE " +
" timestamp >= toDate(:from) " +
" and timestamp <= toDate(:to) " +
" and toDateTime(eventTime) >= toDateTime(:from) " +
" and toDateTime(eventTime) <= toDateTime(:to) ";
public static final String SELECT_HISTORY_FRAUD_PAYMENT = String.format("""
SELECT
eventTime,
partyId,
shopId,
email,
amount as amount,
currency,
id,
cardToken,
bin,
maskedPan,
bankCountry,
fingerprint,
ip,
status,
errorReason,
errorCode,
paymentSystem,
paymentCountry,
paymentTool,
providerId,
terminal,
fraudType,
comment
FROM
%s
WHERE
timestamp >= toDate(:from)
and timestamp <= toDate(:to)
and toDateTime(eventTime) >= toDateTime(:from)
and toDateTime(eventTime) <= toDateTime(:to)""",
EventSource.FRAUD_EVENTS_FRAUD_PAYMENT.getTable());
}

View File

@ -7,33 +7,34 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class FraudResultQuery {
public static final String SELECT_HISTORY_FRAUD_RESULT = "" +
"SELECT " +
" eventTime, " +
" partyId, " +
" shopId, " +
" email, " +
" amount as amount, " +
" currency, " +
" bankCountry, " +
" cardToken, " +
" ip, " +
" fingerprint, " +
" invoiceId, " +
" maskedPan, " +
" bin, " +
" bankName, " +
" paymentId as id, " +
" resultStatus, " +
" checkedRule, " +
" checkedTemplate, " +
" mobile, " +
" recurrent " +
" FROM " +
EventSource.FRAUD_EVENTS_UNIQUE.getTable() +
" WHERE " +
" timestamp >= toDate(:from) " +
" and timestamp <= toDate(:to) " +
" and toDateTime(eventTime) >= toDateTime(:from) " +
" and toDateTime(eventTime) <= toDateTime(:to) ";
public static final String SELECT_HISTORY_FRAUD_RESULT = String.format("""
SELECT
eventTime,
partyId,
shopId,
email,
amount as amount,
currency,
bankCountry,
cardToken,
ip,
fingerprint,
invoiceId,
maskedPan,
bin,
bankName,
paymentId as id,
resultStatus,
checkedRule,
checkedTemplate,
mobile,
recurrent
FROM
%s
WHERE
timestamp >= toDate(:from)
and timestamp <= toDate(:to)
and toDateTime(eventTime) >= toDateTime(:from)
and toDateTime(eventTime) <= toDateTime(:to)""",
EventSource.FRAUD_EVENTS_UNIQUE.getTable());
}

View File

@ -7,36 +7,37 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class PaymentQuery {
public static final String SELECT_HISTORY_PAYMENT = "" +
"SELECT " +
" eventTime, " +
" partyId, " +
" shopId, " +
" email, " +
" amount as amount, " +
" currency, " +
" id, " +
" cardToken, " +
" bin, " +
" maskedPan, " +
" bankCountry, " +
" fingerprint, " +
" ip, " +
" status, " +
" errorReason, " +
" errorCode, " +
" paymentSystem, " +
" paymentCountry, " +
" paymentTool, " +
" providerId, " +
" terminal, " +
" mobile, " +
" recurrent " +
" FROM " +
EventSource.FRAUD_EVENTS_PAYMENT.getTable() +
" WHERE " +
" timestamp >= toDate(:from) " +
" and timestamp <= toDate(:to) " +
" and toDateTime(eventTime) >= toDateTime(:from) " +
" and toDateTime(eventTime) <= toDateTime(:to) ";
public static final String SELECT_HISTORY_PAYMENT = String.format("""
SELECT
eventTime,
partyId,
shopId,
email,
amount as amount,
currency,
id,
cardToken,
bin,
maskedPan,
bankCountry,
fingerprint,
ip,
status,
errorReason,
errorCode,
paymentSystem,
paymentCountry,
paymentTool,
providerId,
terminal,
mobile,
recurrent
FROM
%s
WHERE
timestamp >= toDate(:from)
and timestamp <= toDate(:to)
and toDateTime(eventTime) >= toDateTime(:from)
and toDateTime(eventTime) <= toDateTime(:to)""",
EventSource.FRAUD_EVENTS_PAYMENT.getTable());
}

View File

@ -7,33 +7,34 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RefundQuery {
public static final String SELECT_HISTORY_REFUND = "" +
"SELECT " +
" eventTime, " +
" partyId, " +
" shopId, " +
" email, " +
" amount as amount, " +
" currency, " +
" id, " +
" cardToken, " +
" bin, " +
" maskedPan, " +
" bankCountry, " +
" fingerprint, " +
" ip, " +
" status, " +
" errorReason, " +
" errorCode, " +
" paymentSystem, " +
" providerId, " +
" terminal, " +
" paymentId " +
" FROM " +
EventSource.FRAUD_EVENTS_REFUND.getTable() +
" WHERE " +
" timestamp >= toDate(:from) " +
" and timestamp <= toDate(:to) " +
" and toDateTime(eventTime) >= toDateTime(:from) " +
" and toDateTime(eventTime) <= toDateTime(:to) ";
public static final String SELECT_HISTORY_REFUND = String.format("""
SELECT
eventTime,
partyId,
shopId,
email,
amount as amount,
currency,
id,
cardToken,
bin,
maskedPan,
bankCountry,
fingerprint,
ip,
status,
errorReason,
errorCode,
paymentSystem,
providerId,
terminal,
paymentId
FROM
%s
WHERE
timestamp >= toDate(:from)
and timestamp <= toDate(:to)
and toDateTime(eventTime) >= toDateTime(:from)
and toDateTime(eventTime) <= toDateTime(:to)""",
EventSource.FRAUD_EVENTS_REFUND.getTable());
}

View File

@ -21,15 +21,17 @@ import static com.rbkmoney.fraudbusters.constant.ClickhouseUtilsValue.UNKNOWN;
@RequiredArgsConstructor
public class ChargebackBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
public static final String FIELDS = " timestamp, eventTimeHour, eventTime, " +
"id, " +
"email, ip, fingerprint, " +
"bin, maskedPan, cardToken, paymentSystem, paymentTool , " +
"terminal, providerId, bankCountry, " +
"partyId, shopId, " +
"amount, currency, " +
"status, category, chargebackCode, paymentId, " +
"payerType, tokenProvider";
public static final String FIELDS = """
timestamp, eventTimeHour, eventTime,
id,
email, ip, fingerprint,
bin, maskedPan, cardToken, paymentSystem, paymentTool ,
terminal, providerId, bankCountry,
partyId, shopId,
amount, currency,
status, category, chargebackCode, paymentId,
payerType, tokenProvider
""";
public static final String FIELDS_MARK = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";

View File

@ -11,14 +11,13 @@ import java.util.List;
@RequiredArgsConstructor
public class EventBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
public static final String INSERT = "INSERT INTO fraud.events_unique " +
" (timestamp, eventTimeHour, eventTime, ip, email, bin, fingerprint, shopId, " +
"partyId, resultStatus, amount, " +
"country, checkedRule, bankCountry, currency, invoiceId, maskedPan, bankName," +
" cardToken, paymentId, checkedTemplate," +
"payerType, tokenProvider, mobile, recurrent)" +
" VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " +
"?, ?, ?)";
public static final String INSERT = """
INSERT INTO fraud.events_unique
(timestamp, eventTimeHour, eventTime, ip, email, bin, fingerprint, shopId, partyId, resultStatus, amount,
country, checkedRule, bankCountry, currency, invoiceId, maskedPan, bankName, cardToken,
paymentId, checkedTemplate, payerType, tokenProvider, mobile, recurrent)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""";
private final List<Event> batch;

View File

@ -11,17 +11,19 @@ import java.util.List;
@RequiredArgsConstructor
public class PaymentBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
public static final String FIELDS = " timestamp, eventTimeHour, eventTime, " +
"id, " +
"email, ip, fingerprint, " +
"bin, maskedPan, cardToken, paymentSystem, paymentTool, " +
"terminal, providerId, bankCountry, " +
"partyId, shopId, " +
"amount, currency, " +
"status, errorCode, errorReason, " +
"payerType, tokenProvider, " +
"checkedTemplate, checkedRule, resultStatus, checkedResultsJson, mobile, " +
"recurrent";
public static final String FIELDS = """
timestamp, eventTimeHour, eventTime,
id,
email, ip, fingerprint,
bin, maskedPan, cardToken, paymentSystem, paymentTool,
terminal, providerId, bankCountry,
partyId, shopId,
amount, currency,
status, errorCode, errorReason,
payerType, tokenProvider,
checkedTemplate, checkedRule, resultStatus, checkedResultsJson, mobile,
recurrent
""";
public static final String FIELDS_MARK = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";
@ -73,4 +75,4 @@ public class PaymentBatchPreparedStatementSetter implements BatchPreparedStateme
public int getBatchSize() {
return batch.size();
}
}
}

View File

@ -22,15 +22,11 @@ import static com.rbkmoney.fraudbusters.constant.ClickhouseUtilsValue.UNKNOWN;
@RequiredArgsConstructor
public class RefundBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
public static final String FIELDS = " timestamp, eventTimeHour, eventTime, " +
"id, " +
"email, ip, fingerprint, " +
"bin, maskedPan, cardToken, paymentSystem, paymentTool , " +
"terminal, providerId, bankCountry, " +
"partyId, shopId, " +
"amount, currency, " +
"status, errorCode, errorReason, paymentId, " +
"payerType, tokenProvider";
public static final String FIELDS = """
timestamp, eventTimeHour, eventTime, id, email, ip, fingerprint, bin, maskedPan, cardToken, paymentSystem,
paymentTool, terminal, providerId, bankCountry, partyId, shopId, amount, currency, status, errorCode,
errorReason, paymentId, payerType, tokenProvider
""";
public static final String FIELDS_MARK = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";

View File

@ -17,13 +17,11 @@ import static com.rbkmoney.fraudbusters.constant.ClickhouseUtilsValue.UNKNOWN;
@RequiredArgsConstructor
public class WithdrawalBatchPreparedStatementSetter implements BatchPreparedStatementSetter {
public static final String FIELDS = " timestamp, eventTimeHour, eventTime, " +
"id, " +
"amount, currency, " +
"bin, maskedPan, cardToken, paymentSystem, " +
"terminal, providerId, bankCountry, " +
"identityId, accountId, accountCurrency, " +
"status, errorCode, errorReason";
public static final String FIELDS = """
timestamp, eventTimeHour, eventTime, id, amount, currency, bin, maskedPan, cardToken, paymentSystem,
terminal, providerId, bankCountry, identityId, accountId, accountCurrency, status, errorCode,
errorReason
""";
public static final String FIELDS_MARK = "?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?";

View File

@ -17,17 +17,13 @@ import java.util.List;
@RequiredArgsConstructor
public class PaymentInfoService {
private static final String FIELDS = "timestamp, eventTimeHour, eventTime, " +
"id, " +
"email, ip, fingerprint, " +
"bin, maskedPan, cardToken, paymentSystem, paymentTool, " +
"terminal, providerId, bankCountry, " +
"partyId, shopId, " +
"amount, currency, " +
"status, errorCode, errorReason, " +
"payerType, tokenProvider, " +
"checkedTemplate, checkedRule, resultStatus, checkedResultsJson, mobile, " +
"recurrent";
private static final String FIELDS = """
timestamp, eventTimeHour, eventTime, id, email, ip, fingerprint, bin,
maskedPan, cardToken, paymentSystem, paymentTool, terminal, providerId,
bankCountry, partyId, shopId, amount, currency, status, errorCode, errorReason,
payerType, tokenProvider, checkedTemplate, checkedRule, resultStatus,
checkedResultsJson, mobile, recurrent
""";
private final JdbcTemplate jdbcTemplate;

View File

@ -1,72 +1,46 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.clickhouse.initializer.ChInitializer;
import com.rbkmoney.damsel.fraudbusters.Command;
import com.rbkmoney.damsel.fraudbusters.CommandBody;
import com.rbkmoney.damsel.fraudbusters.TemplateReference;
import com.rbkmoney.fraudbusters.constant.TemplateLevel;
import com.rbkmoney.fraudbusters.pool.Pool;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.antlr.v4.runtime.ParserRuleContext;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.StringUtils;
import org.testcontainers.containers.ClickHouseContainer;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@Slf4j
@ActiveProfiles("full-prod")
@RunWith(SpringRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(webEnvironment = RANDOM_PORT,
classes = FraudBustersApplication.class,
properties = "kafka.listen.result.concurrency=1")
@ContextConfiguration(initializers = DispatchTemplateTest.Initializer.class)
public class DispatchTemplateTest extends IntegrationTest {
public class DispatchTemplateTest extends JUnit5IntegrationTest {
public static final String TEMPLATE = "rule: 12 >= 1\n" +
" -> accept;";
public static final String TEMPLATE = "rule: 12 >= 1 -> accept;";
public static final int TIMEOUT = 20;
@ClassRule
public static EmbeddedKafkaRule kafka = createKafka();
@ClassRule
public static ClickHouseContainer clickHouseContainer =
new ClickHouseContainer("yandex/clickhouse-server:19.17");
@Autowired
private Pool<ParserRuleContext> templatePoolImpl;
@Autowired
private Pool<String> referencePoolImpl;
@Override
protected String getBrokersAsString() {
return kafka.getEmbeddedKafka().getBrokersAsString();
}
@Test
public void testPools() throws ExecutionException, InterruptedException {
@ -107,34 +81,9 @@ public class DispatchTemplateTest extends IntegrationTest {
if (StringUtils.isEmpty(result)) {
return false;
}
Assert.assertEquals(id, result);
assertEquals(id, result);
return true;
});
}
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@SneakyThrows
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("clickhouse.db.url={}", clickHouseContainer.getJdbcUrl());
log.info("kafka.bootstrap.servers={}", kafka.getEmbeddedKafka().getBrokersAsString());
TestPropertyValues.of(
"clickhouse.db.url=" + clickHouseContainer.getJdbcUrl(),
"clickhouse.db.user=" + clickHouseContainer.getUsername(),
"clickhouse.db.password=" + clickHouseContainer.getPassword(),
"kafka.bootstrap.servers=" + kafka.getEmbeddedKafka().getBrokersAsString()
)
.applyTo(configurableApplicationContext.getEnvironment());
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",
"sql/V2__create_events_p2p.sql",
"sql/V3__create_fraud_payments.sql",
"sql/V4__create_payment.sql",
"sql/V5__add_fields.sql",
"sql/V6__add_result_fields_payment.sql",
"sql/V7__add_fields.sql"
));
}
}
}

View File

@ -53,16 +53,18 @@ public class EndToEndIntegrationTest extends JUnit5IntegrationTest {
public static final String PROCESSED = "processed";
public static final String FAILED = "failed";
private static final String TEMPLATE =
"rule:TEMPLATE: count(\"email\", 10, 0, \"party_id\", \"shop_id\") > 1 AND count(\"email\", 10) < 3 " +
"AND sum(\"email\", 10, \"party_id\", \"shop_id\") >= 18000 " +
"AND countSuccess(\"card_token\", 10, \"party_id\", \"shop_id\") > 1 " +
"AND in(countryBy(\"country_bank\"), \"RUS\") " +
"OR sumRefund(\"card_token\", 10, \"party_id\", \"shop_id\") > 0 " +
"OR countRefund(\"card_token\", 10, \"party_id\", \"shop_id\") > 0 " +
"OR countChargeback(\"card_token\", 10, \"party_id\", \"shop_id\") > 0 " +
"OR sumChargeback(\"card_token\", 10, \"party_id\", \"shop_id\") > 0 \n" +
" -> declineAndNotify;";
private static final String TEMPLATE = """
rule:TEMPLATE: count("email", 10, 0, "party_id", "shop_id") > 1
AND count("email", 10) < 3
AND sum("email", 10, "party_id", "shop_id") >= 18000
AND countSuccess("card_token", 10, "party_id", "shop_id") > 1
AND in(countryBy("country_bank"), "RUS")
OR sumRefund("card_token", 10, "party_id", "shop_id") > 0
OR countRefund("card_token", 10, "party_id", "shop_id") > 0
OR countChargeback("card_token", 10, "party_id", "shop_id") > 0
OR sumChargeback("card_token", 10, "party_id", "shop_id") > 0
-> declineAndNotify;
""";
private static final String TEMPLATE_CONCRETE =
"rule:TEMPLATE_CONCRETE: sumSuccess(\"email\", 10) >= 29000 -> decline;";

View File

@ -1,6 +1,5 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.clickhouse.initializer.ChInitializer;
import com.rbkmoney.damsel.fraudbusters.PaymentServiceSrv;
import com.rbkmoney.damsel.fraudbusters.PaymentStatus;
import com.rbkmoney.fraudbusters.repository.FraudPaymentRepositoryTest;
@ -8,61 +7,39 @@ import com.rbkmoney.woody.thrift.impl.http.THClientBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.ClickHouseContainer;
import java.net.URI;
import java.util.List;
import java.util.Map;
import static com.rbkmoney.fraudbusters.util.BeanUtil.createPayment;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@Slf4j
@RunWith(SpringRunner.class)
@ActiveProfiles("full-prod")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(webEnvironment = RANDOM_PORT,
classes = FraudBustersApplication.class,
properties = {"kafka.listen.result.concurrency=1"})
@ContextConfiguration(initializers = FraudPaymentTest.Initializer.class)
public class FraudPaymentTest extends IntegrationTest {
public class FraudPaymentTest extends JUnit5IntegrationTest {
public static final String ID_PAYMENT = "inv";
public static final String EMAIL = "kek@kek.ru";
@ClassRule
public static EmbeddedKafkaRule kafka = createKafka();
@ClassRule
public static ClickHouseContainer clickHouseContainer =
new ClickHouseContainer("yandex/clickhouse-server:19.17");
@Autowired
JdbcTemplate jdbcTemplate;
@LocalServerPort
int serverPort;
@Override
protected String getBrokersAsString() {
return kafka.getEmbeddedKafka().getBrokersAsString();
}
@SneakyThrows
@Test
public void testFraudPayment() {
@ -83,8 +60,8 @@ public class FraudPaymentTest extends IntegrationTest {
//Check join and view working
List<Map<String, Object>> maps = jdbcTemplate.queryForList("SELECT * from fraud.fraud_payment");
Assert.assertEquals(1, maps.size());
Assert.assertEquals(EMAIL, maps.get(0).get("email"));
assertEquals(1, maps.size());
assertEquals(EMAIL, maps.get(0).get("email"));
}
private void insertWithTimeout(
@ -94,28 +71,4 @@ public class FraudPaymentTest extends IntegrationTest {
Thread.sleep(TIMEOUT * 10);
}
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@SneakyThrows
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("clickhouse.db.url={}", clickHouseContainer.getJdbcUrl());
log.info("kafka.bootstrap.servers={}", kafka.getEmbeddedKafka().getBrokersAsString());
TestPropertyValues.of(
"clickhouse.db.url=" + clickHouseContainer.getJdbcUrl(),
"clickhouse.db.user=" + clickHouseContainer.getUsername(),
"clickhouse.db.password=" + clickHouseContainer.getPassword(),
"kafka.bootstrap.servers=" + kafka.getEmbeddedKafka().getBrokersAsString()
)
.applyTo(configurableApplicationContext.getEnvironment());
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",
"sql/V2__create_events_p2p.sql",
"sql/V3__create_fraud_payments.sql",
"sql/V4__create_payment.sql",
"sql/V5__add_fields.sql",
"sql/V6__add_result_fields_payment.sql",
"sql/V7__add_fields.sql"
));
}
}
}

View File

@ -1,223 +0,0 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.damsel.fraudbusters.*;
import com.rbkmoney.damsel.geo_ip.GeoIpServiceSrv;
import com.rbkmoney.damsel.wb_list.WbListServiceSrv;
import com.rbkmoney.fraudbusters.config.properties.KafkaTopics;
import com.rbkmoney.fraudbusters.serde.CommandDeserializer;
import com.rbkmoney.fraudbusters.service.ShopManagementService;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.fraudbusters.util.KeyGenerator;
import com.rbkmoney.fraudbusters.util.ReferenceKeyGenerator;
import com.rbkmoney.kafka.common.serialization.ThriftSerializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringDeserializer;
import org.apache.kafka.common.serialization.StringSerializer;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.mockito.Mockito;
import org.rnorth.ducttape.unreliables.Unreliables;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.context.ContextConfiguration;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import static org.mockito.ArgumentMatchers.any;
@Slf4j
@ContextConfiguration(classes = KafkaTopics.class)
public abstract class IntegrationTest {
protected static final long TIMEOUT = 1000L;
@Value("${kafka.topic.event.sink.initial}")
public String eventSinkTopic;
@Value("${kafka.topic.event.sink.aggregated}")
public String aggregatedEventSink;
@Value("${kafka.topic.fraud.payment}")
public String fraudPaymentTopic;
@Autowired
protected KafkaTopics kafkaTopics;
@MockBean
GeoIpServiceSrv.Iface geoIpServiceSrv;
@MockBean
WbListServiceSrv.Iface wbListServiceSrv;
@MockBean
private ShopManagementService shopManagementService;
protected static EmbeddedKafkaRule createKafka() {
return new EmbeddedKafkaRule(
1,
true,
1,
"wb-list-event-sink",
"result",
"p2p_result",
"fraud_payment",
"payment_event",
"refund_event",
"chargeback_event",
"template",
"full_template",
"template_p2p",
"template_reference",
"full_template_reference",
"template_p2p_reference",
"group_list",
"full_group_list",
"group_p2p_list",
"group_reference",
"full_group_reference",
"group_p2p_reference"
);
}
@Before
public void setUp() {
Mockito.when(shopManagementService.isNewShop(any())).thenReturn(false);
}
public Producer<String, Command> createProducer() {
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, getBrokersAsString());
props.put(ProducerConfig.CLIENT_ID_CONFIG, KeyGenerator.generateKey("client_id_"));
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, ThriftSerializer.class.getName());
props.put(ProducerConfig.RETRIES_CONFIG, 3);
props.put(ProducerConfig.RETRY_BACKOFF_MS_CONFIG, 1000);
return new KafkaProducer<>(props);
}
<T> Consumer<String, T> createConsumer(Class clazz) {
Properties props = new Properties();
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, getBrokersAsString());
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, clazz);
props.put(ConsumerConfig.GROUP_ID_CONFIG, UUID.randomUUID().toString());
props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
return new KafkaConsumer<>(props);
}
void produceTemplate(String localId, String templateString, String topicName)
throws InterruptedException, ExecutionException {
try (Producer<String, Command> producer = createProducer()) {
Command command = crateCommandTemplate(localId, templateString);
ProducerRecord<String, Command> producerRecord = new ProducerRecord<>(topicName, localId, command);
producer.send(producerRecord).get();
}
}
void produceGroup(String localId, List<PriorityId> priorityIds, String topic)
throws InterruptedException, ExecutionException {
try (Producer<String, Command> producer = createProducer()) {
Command command = BeanUtil.createGroupCommand(localId, priorityIds);
ProducerRecord<String, Command> producerRecord = new ProducerRecord<>(topic, localId, command);
producer.send(producerRecord).get();
}
}
void produceReference(boolean isGlobal, String party, String shopId, String idTemplate)
throws InterruptedException, ExecutionException {
try (Producer<String, Command> producer = createProducer()) {
Command command = new Command();
command.setCommandType(CommandType.CREATE);
TemplateReference value = new TemplateReference();
value.setTemplateId(idTemplate);
value.setPartyId(party);
value.setShopId(shopId);
value.setIsGlobal(isGlobal);
command.setCommandBody(CommandBody.reference(value));
command.setCommandTime(LocalDateTime.now().toString());
String key = ReferenceKeyGenerator.generateTemplateKey(value);
ProducerRecord<String, Command> producerRecord =
new ProducerRecord<>(kafkaTopics.getFullReference(), key, command);
producer.send(producerRecord).get();
}
}
void produceP2PReference(boolean isGlobal, String identityId, String idTemplate)
throws InterruptedException, ExecutionException {
try (Producer<String, Command> producer = createProducer()) {
Command command = new Command();
command.setCommandType(CommandType.CREATE);
P2PReference value = new P2PReference();
value.setTemplateId(idTemplate);
value.setIdentityId(identityId);
value.setIsGlobal(isGlobal);
command.setCommandBody(CommandBody.p2p_reference(value));
command.setCommandTime(LocalDateTime.now().toString());
String key = ReferenceKeyGenerator.generateP2PTemplateKey(value);
ProducerRecord<String, Command> producerRecord =
new ProducerRecord<>(kafkaTopics.getP2pReference(), key, command);
producer.send(producerRecord).get();
}
}
void produceReferenceWithWait(boolean isGlobal, String party, String shopId, String idTemplate, int timeout)
throws InterruptedException, ExecutionException {
produceReference(isGlobal, party, shopId, idTemplate);
try (Consumer<String, Object> consumer = createConsumer(CommandDeserializer.class)) {
consumer.subscribe(List.of(kafkaTopics.getFullReference()));
Unreliables.retryUntilTrue(timeout, TimeUnit.SECONDS, () -> {
ConsumerRecords<String, Object> records = consumer.poll(Duration.ofSeconds(1L));
return !records.isEmpty();
});
}
}
void produceGroupReference(String party, String shopId, String idGroup)
throws InterruptedException, ExecutionException {
try (Producer<String, Command> producer = createProducer()) {
Command command = BeanUtil.createGroupReferenceCommand(party, shopId, idGroup);
String key = ReferenceKeyGenerator.generateTemplateKeyByList(party, shopId);
ProducerRecord<String, Command> producerRecord =
new ProducerRecord<>(kafkaTopics.getFullGroupReference(), key, command);
producer.send(producerRecord).get();
}
}
@NotNull
private Command crateCommandTemplate(String localId, String templateString) {
Command command = new Command();
Template template = new Template();
template.setId(localId);
template.setTemplate(templateString.getBytes());
command.setCommandBody(CommandBody.template(template));
command.setCommandType(com.rbkmoney.damsel.fraudbusters.CommandType.CREATE);
command.setCommandTime(LocalDateTime.now().toString());
return command;
}
protected void waitingTopic(String topicName) {
try (Consumer<String, Object> consumer = createConsumer(CommandDeserializer.class)) {
consumer.subscribe(List.of(topicName));
Unreliables.retryUntilTrue(240, TimeUnit.SECONDS, () -> {
ConsumerRecords<String, Object> records = consumer.poll(Duration.ofSeconds(1L));
return !records.isEmpty();
});
}
}
protected abstract String getBrokersAsString();
}

View File

@ -1,6 +1,5 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.clickhouse.initializer.ChInitializer;
import com.rbkmoney.damsel.fraudbusters.Payment;
import com.rbkmoney.damsel.fraudbusters.PaymentServiceSrv;
import com.rbkmoney.damsel.fraudbusters.PaymentStatus;
@ -11,24 +10,15 @@ import com.rbkmoney.woody.thrift.impl.http.THClientBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.ClickHouseContainer;
import java.net.URI;
import java.time.LocalDateTime;
@ -38,39 +28,31 @@ import java.util.UUID;
import java.util.concurrent.ExecutionException;
import static com.rbkmoney.fraudbusters.util.BeanUtil.*;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@Slf4j
@ActiveProfiles("full-prod")
@RunWith(SpringRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = FraudBustersApplication.class,
properties = {"kafka.listen.result.concurrency=1", "kafka.historical.listener.enable=true",
"kafka.aggr.payment.min.bytes=1"})
@ContextConfiguration(initializers = LoadDataIntegrationTest.Initializer.class)
public class LoadDataIntegrationTest extends IntegrationTest {
public class LoadDataIntegrationTest extends JUnit5IntegrationTest {
public static final String PAYMENT_1 = "payment_1";
public static final String PAYMENT_2 = "payment_2";
public static final String PAYMENT_0 = "payment_0";
private static final String TEMPLATE =
"rule:TEMPLATE: " +
"sum(\"card_token\", 1000, \"party_id\", \"shop_id\", \"mobile\") > 0 " +
" and unique(\"email\", \"ip\", 1444, \"recurrent\") < 2 and isRecurrent() == false" +
" and count(\"card_token\", 1000, \"party_id\", \"shop_id\") > 5 -> decline";
private static final String TEMPLATE = """
rule:TEMPLATE: sum("card_token", 1000, "party_id", "shop_id", "mobile") > 0
and unique("email", "ip", 1444, "recurrent") < 2 and isRecurrent() == false
and count("card_token", 1000, "party_id", "shop_id") > 5 -> decline
""";
private static final String TEMPLATE_2 =
"rule:TEMPLATE: count(\"card_token\", 1000, \"party_id\", \"shop_id\") > 2 -> decline;";
private static final String TEMPLATE_CONCRETE =
"rule:TEMPLATE_CONCRETE: count(\"card_token\", 10) > 0 -> accept;";
@ClassRule
public static EmbeddedKafkaRule kafka = createKafka();
@ClassRule
public static ClickHouseContainer clickHouseContainer = new ClickHouseContainer("yandex/clickhouse-server:19.17");
private final String globalRef = UUID.randomUUID().toString();
@Autowired
@ -79,12 +61,7 @@ public class LoadDataIntegrationTest extends IntegrationTest {
@LocalServerPort
int serverPort;
@Override
protected String getBrokersAsString() {
return kafka.getEmbeddedKafka().getBrokersAsString();
}
@Before
@BeforeEach
public void init() throws ExecutionException, InterruptedException, TException {
produceTemplate(globalRef, TEMPLATE, kafkaTopics.getFullTemplate());
produceReference(true, null, null, globalRef);
@ -205,30 +182,4 @@ public class LoadDataIntegrationTest extends IntegrationTest {
insertWithTimeout(client, List.of(createPayment(processed), createPayment(processed2)));
}
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@SneakyThrows
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("clickhouse.db.url={}", clickHouseContainer.getJdbcUrl());
log.info("kafka.bootstrap.servers={}", kafka.getEmbeddedKafka().getBrokersAsString());
TestPropertyValues.of(
"clickhouse.db.url=" + clickHouseContainer.getJdbcUrl(),
"clickhouse.db.user=" + clickHouseContainer.getUsername(),
"clickhouse.db.password=" + clickHouseContainer.getPassword(),
"kafka.bootstrap.servers=" + kafka.getEmbeddedKafka().getBrokersAsString()
)
.applyTo(configurableApplicationContext.getEnvironment());
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",
"sql/V2__create_events_p2p.sql",
"sql/V3__create_fraud_payments.sql",
"sql/V4__create_payment.sql",
"sql/V5__add_fields.sql",
"sql/V6__add_result_fields_payment.sql",
"sql/V7__add_fields.sql",
"sql/V8__create_withdrawal.sql"
));
}
}
}

View File

@ -1,30 +1,18 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.clickhouse.initializer.ChInitializer;
import com.rbkmoney.damsel.domain.RiskScore;
import com.rbkmoney.damsel.p2p_insp.InspectResult;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.woody.thrift.impl.http.THClientBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.ClickHouseContainer;
import java.net.URI;
import java.net.URISyntaxException;
@ -33,45 +21,35 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutionException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@Slf4j
@ActiveProfiles("full-prod")
@RunWith(SpringRunner.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(webEnvironment = RANDOM_PORT,
classes = FraudBustersApplication.class,
properties = "kafka.listen.result.concurrency=1")
@ContextConfiguration(initializers = P2PEndToEndIntegrationTest.Initializer.class)
public class P2PEndToEndIntegrationTest extends IntegrationTest {
public class P2PEndToEndIntegrationTest extends JUnit5IntegrationTest {
public static final long TIMEOUT = 2000L;
public static final String FRAUD = "fraud";
public static final String IDENT_ID = "identId";
private static final String TEMPLATE =
"rule: count(\"email\", 10, 0, \"identity_id\") > 1 AND count(\"email\", 10) < 3 " +
"AND sum(\"email\", 10) >= 18000 " +
"AND count(\"card_token_from\", 10) > 1 " +
"AND in(countryBy(\"country_bank\"), \"RUS\") \n" +
" -> decline;";
private static final String TEMPLATE = """
rule: count("email", 10, 0, "identity_id") > 1 AND count("email", 10) < 3
AND sum("email", 10) >= 18000
AND count("card_token_from", 10) > 1
AND in(countryBy("country_bank"), "RUS")
-> decline;
""";
private static final String SERVICE_P2P_URL = "http://localhost:%s/fraud_p2p_inspector/v1";
@ClassRule
public static EmbeddedKafkaRule kafka = createKafka();
@ClassRule
public static ClickHouseContainer clickHouseContainer = new ClickHouseContainer("yandex/clickhouse-server:19.17");
@LocalServerPort
int serverPort;
@Override
protected String getBrokersAsString() {
return kafka.getEmbeddedKafka().getBrokersAsString();
}
@Before
@BeforeEach
public void init() throws ExecutionException, InterruptedException, SQLException, TException {
String globalRef = UUID.randomUUID().toString();
@ -86,8 +64,7 @@ public class P2PEndToEndIntegrationTest extends IntegrationTest {
@Test
public void testP2P()
throws URISyntaxException, TException, InterruptedException, ExecutionException, NoSuchFieldException,
IllegalAccessException {
throws URISyntaxException, TException, InterruptedException {
THClientBuilder clientBuilder = new THClientBuilder()
.withAddress(new URI(String.format(SERVICE_P2P_URL, serverPort)))
.withNetworkTimeout(300000);
@ -97,38 +74,13 @@ public class P2PEndToEndIntegrationTest extends IntegrationTest {
com.rbkmoney.damsel.p2p_insp.Context p2PContext = BeanUtil.createP2PContext(IDENT_ID, "transfer_1");
InspectResult inspectResult = client.inspectTransfer(p2PContext, List.of(FRAUD));
Assert.assertEquals(RiskScore.high, inspectResult.scores.get(FRAUD));
assertEquals(RiskScore.high, inspectResult.scores.get(FRAUD));
Thread.sleep(TIMEOUT);
p2PContext = BeanUtil.createP2PContext(IDENT_ID, "transfer_1");
inspectResult = client.inspectTransfer(p2PContext, List.of(FRAUD));
Assert.assertEquals(RiskScore.fatal, inspectResult.scores.get(FRAUD));
}
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@SneakyThrows
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("clickhouse.db.url={}", clickHouseContainer.getJdbcUrl());
log.info("kafka.bootstrap.servers={}", kafka.getEmbeddedKafka().getBrokersAsString());
TestPropertyValues.of(
"clickhouse.db.url=" + clickHouseContainer.getJdbcUrl(),
"clickhouse.db.user=" + clickHouseContainer.getUsername(),
"clickhouse.db.password=" + clickHouseContainer.getPassword(),
"kafka.bootstrap.servers=" + kafka.getEmbeddedKafka().getBrokersAsString()
)
.applyTo(configurableApplicationContext.getEnvironment());
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",
"sql/V2__create_events_p2p.sql",
"sql/V3__create_fraud_payments.sql",
"sql/V4__create_payment.sql",
"sql/V5__add_fields.sql",
"sql/V6__add_result_fields_payment.sql",
"sql/V7__add_fields.sql"
));
}
assertEquals(RiskScore.fatal, inspectResult.scores.get(FRAUD));
}
}

View File

@ -1,62 +1,43 @@
package com.rbkmoney.fraudbusters;
import com.rbkmoney.clickhouse.initializer.ChInitializer;
import com.rbkmoney.damsel.domain.RiskScore;
import com.rbkmoney.damsel.proxy_inspector.Context;
import com.rbkmoney.damsel.proxy_inspector.InspectorProxySrv;
import com.rbkmoney.fraudbusters.repository.impl.FraudResultRepository;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.woody.thrift.impl.http.THClientBuilder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.thrift.TException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.test.rule.EmbeddedKafkaRule;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.ClickHouseContainer;
import ru.yandex.clickhouse.ClickHouseDataSource;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@Slf4j
@RunWith(SpringRunner.class)
@ActiveProfiles("full-prod")
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@SpringBootTest(webEnvironment = RANDOM_PORT, classes = FraudBustersApplication.class,
properties = {"kafka.listen.result.concurrency=1", "kafka.historical.listener.enable=true"})
@ContextConfiguration(initializers = PreLoadTest.Initializer.class)
public class PreLoadTest extends IntegrationTest {
public class PreLoadTest extends JUnit5IntegrationTest {
private static final String TEMPLATE = "rule: 12 >= 1\n" +
" -> accept;";
private static final String TEST = "test";
@ClassRule
public static EmbeddedKafkaRule kafka = createKafka();
@ClassRule
public static ClickHouseContainer clickHouseContainer = new ClickHouseContainer("yandex/clickhouse-server:19.17");
@MockBean
ClickHouseDataSource clickHouseDataSource;
@Autowired
@ -69,12 +50,7 @@ public class PreLoadTest extends IntegrationTest {
private InspectorProxySrv.Iface client;
@Override
protected String getBrokersAsString() {
return kafka.getEmbeddedKafka().getBrokersAsString();
}
@Before
@BeforeEach
public void init() throws ExecutionException, InterruptedException {
produceTemplate(TEST, TEMPLATE, kafkaTopics.getFullTemplate());
produceReferenceWithWait(true, null, null, TEST, 10);
@ -95,32 +71,7 @@ public class PreLoadTest extends IntegrationTest {
Context context = BeanUtil.createContext();
RiskScore riskScore = client.inspectPayment(context);
Assert.assertEquals(RiskScore.low, riskScore);
}
public static class Initializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@SneakyThrows
@Override
public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
log.info("clickhouse.db.url={}", clickHouseContainer.getJdbcUrl());
log.info("kafka.bootstrap.servers={}", kafka.getEmbeddedKafka().getBrokersAsString());
TestPropertyValues.of(
"clickhouse.db.url=" + clickHouseContainer.getJdbcUrl(),
"clickhouse.db.user=" + clickHouseContainer.getUsername(),
"clickhouse.db.password=" + clickHouseContainer.getPassword(),
"kafka.bootstrap.servers=" + kafka.getEmbeddedKafka().getBrokersAsString()
)
.applyTo(configurableApplicationContext.getEnvironment());
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",
"sql/V2__create_events_p2p.sql",
"sql/V3__create_fraud_payments.sql",
"sql/V4__create_payment.sql",
"sql/V5__add_fields.sql",
"sql/V6__add_result_fields_payment.sql",
"sql/V7__add_fields.sql"
));
}
assertEquals(RiskScore.low, riskScore);
}
}

View File

@ -2,8 +2,9 @@ package com.rbkmoney.fraudbusters.fraud;
import com.rbkmoney.fraudbusters.fraud.payment.PaymentContextParserImpl;
import com.rbkmoney.fraudo.FraudoPaymentParser;
import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertFalse;
public class PaymentContextParserImplTest {
@ -11,8 +12,7 @@ public class PaymentContextParserImplTest {
@Test
public void parse() {
FraudoPaymentParser.ParseContext parse = fraudContextParser.parse("rule: 3 > 2 AND 1 = 1\n" +
"-> accept;");
Assert.assertFalse(parse.fraud_rule().isEmpty());
FraudoPaymentParser.ParseContext parse = fraudContextParser.parse("rule: 3 > 2 AND 1 = 1 -> accept;");
assertFalse(parse.fraud_rule().isEmpty());
}
}
}

View File

@ -8,18 +8,20 @@ import com.rbkmoney.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldReso
import com.rbkmoney.fraudbusters.repository.AggregationRepository;
import com.rbkmoney.fraudbusters.repository.PaymentRepository;
import com.rbkmoney.fraudo.model.TimeWindow;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class SumAggregatorImplTest {
SumAggregatorImpl sumAggregator;
private SumAggregatorImpl sumAggregator;
@Mock
private PaymentRepository paymentRepository;
@Mock
@ -28,17 +30,12 @@ public class SumAggregatorImplTest {
private AggregationRepository analyticsChargebackRepository;
@Mock
private DatabasePaymentFieldResolver databasePaymentFieldResolver;
private FieldModel modelMock = new FieldModel("name", "value");
@Before
private final FieldModel modelMock = new FieldModel("name", "value");
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
when(databasePaymentFieldResolver.resolve(any(), any())).thenReturn(modelMock);
when(paymentRepository.sumOperationByFieldWithGroupBy(any(), any(), any(), any(), any())).thenReturn(1050100L);
when(paymentRepository.sumOperationSuccessWithGroupBy(any(), any(), any(), any(), any())).thenReturn(1050100L);
when(paymentRepository.sumOperationErrorWithGroupBy(any(), any(), any(), any(), any(), any()))
.thenReturn(1050100L);
sumAggregator = new SumAggregatorImpl(
databasePaymentFieldResolver,
@ -52,6 +49,9 @@ public class SumAggregatorImplTest {
public void sum() {
PaymentModel paymentModel = new PaymentModel();
paymentModel.setAmount(1L);
when(paymentRepository.sumOperationByFieldWithGroupBy(any(), any(), any(), any(), any())).thenReturn(1050100L);
Double some = sumAggregator.sum(
PaymentCheckedField.BIN,
paymentModel,
@ -59,7 +59,7 @@ public class SumAggregatorImplTest {
null
);
Assert.assertEquals(Double.valueOf(1050101), some);
assertEquals(Double.valueOf(1050101), some);
}
@Test
@ -72,30 +72,33 @@ public class SumAggregatorImplTest {
Double sum = sumAggregator.sum(PaymentCheckedField.BIN, paymentModel, timeWindowBuilder.build(), null);
Assert.assertEquals(Double.valueOf(1050101), sum);
assertEquals(Double.valueOf(1050101), sum);
timeWindowBuilder = TimeWindow.builder().startWindowTime(1444L)
.endWindowTime(null);
sum = sumAggregator.sum(PaymentCheckedField.BIN, paymentModel, timeWindowBuilder.build(), null);
Assert.assertEquals(Double.valueOf(1050101), sum);
assertEquals(Double.valueOf(1050101), sum);
}
@Test
public void sumSuccess() {
when(paymentRepository.sumOperationSuccessWithGroupBy(any(), any(), any(), any(), any())).thenReturn(1050100L);
Double some = sumAggregator.sumSuccess(PaymentCheckedField.BIN, new PaymentModel(),
TimeWindow.builder().startWindowTime(1444L).build(), null
);
Assert.assertEquals(Double.valueOf(1050100), some);
assertEquals(Double.valueOf(1050100), some);
}
@Test
public void sumError() {
when(paymentRepository.sumOperationErrorWithGroupBy(any(), any(), any(), any(), any(), any()))
.thenReturn(1050100L);
Double some = sumAggregator.sumError(PaymentCheckedField.BIN, new PaymentModel(),
TimeWindow.builder().startWindowTime(1444L).build(), null, null
);
Assert.assertEquals(Double.valueOf(1050100), some);
assertEquals(Double.valueOf(1050100), some);
}
}
}

View File

@ -12,19 +12,24 @@ import com.rbkmoney.fraudbusters.repository.PaymentRepository;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.Pair;
import org.apache.thrift.TException;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.Instant;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class)
public class InGreyListFinderImplTest {
private static final String PARTY_ID = "partyId";
@ -38,9 +43,8 @@ public class InGreyListFinderImplTest {
@Mock
private PaymentRepository analyticRepository;
@Before
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
inGreyListFinder =
new PaymentInListFinderImpl(wbListServiceSrv, new DatabasePaymentFieldResolver(), analyticRepository);
}
@ -92,7 +96,8 @@ public class InGreyListFinderImplTest {
.setTimeToLive(now.plusSeconds(10L).toString())
.setStartCountTime(now.toString())));
when(wbListServiceSrv.getRowInfo(any())).thenReturn(result);
when(analyticRepository.countOperationByField(any(), any(), any(), any())).thenReturn(4);
when(analyticRepository.countOperationByFieldWithGroupBy(anyString(), any(), anyLong(), anyLong(), anyList()))
.thenReturn(4);
PaymentModel paymentModel = new PaymentModel();
paymentModel.setPartyId(PARTY_ID);
paymentModel.setShopId(SHOP_ID);

View File

@ -9,17 +9,23 @@ import com.rbkmoney.fraudbusters.repository.PaymentRepository;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.Pair;
import org.apache.thrift.TException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
public class PaymentInListFinderImplTest {
public static final String PARTY_ID = "partyId";
@ -34,9 +40,8 @@ public class PaymentInListFinderImplTest {
@Mock
private PaymentRepository paymentRepository;
@Before
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
listFinder = new PaymentInListFinderImpl(wbListServiceSrv, dbPaymentFieldResolver, paymentRepository);
}
@ -47,19 +52,19 @@ public class PaymentInListFinderImplTest {
paymentModel.setPartyId(PARTY_ID);
paymentModel.setShopId(SHOP_ID);
Boolean isInList = listFinder.findInBlackList(List.of(new Pair<>(PaymentCheckedField.IP, VALUE)), paymentModel);
Assert.assertTrue(isInList);
assertTrue(isInList);
}
@Test
public void findInListEmpty() throws TException {
Mockito.when(wbListServiceSrv.isAnyExist(any())).thenReturn(true);
PaymentModel paymentModel = new PaymentModel();
paymentModel.setPartyId(PARTY_ID);
paymentModel.setShopId(SHOP_ID);
Boolean isInList = listFinder.findInBlackList(List.of(new Pair<>(PaymentCheckedField.IP, null)), paymentModel);
Assert.assertFalse(isInList);
assertFalse(isInList);
isInList = listFinder.findInBlackList(List.of(new Pair<>(PaymentCheckedField.IP, "")), paymentModel);
Assert.assertFalse(isInList);
assertFalse(isInList);
verify(wbListServiceSrv, times(0)).isAnyExist(anyList());
}
}
}

View File

@ -5,12 +5,16 @@ import com.rbkmoney.fraudbusters.listener.payment.GroupListener;
import com.rbkmoney.fraudbusters.pool.Pool;
import com.rbkmoney.fraudbusters.pool.PoolImpl;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class GroupListenerTest {
public static final String FIRST_TEMPL = "first_templ";
@ -19,7 +23,7 @@ public class GroupListenerTest {
private Pool<List<String>> groupPoolImpl;
private GroupListener groupListener;
@Before
@BeforeEach
public void init() {
groupPoolImpl = new PoolImpl<>("group");
groupListener = new GroupListener(groupPoolImpl);
@ -29,7 +33,7 @@ public class GroupListenerTest {
public void listenEmptyTemplateIds() {
groupListener.listen(BeanUtil.createGroupCommand(GROUP_1, List.of()));
List<String> strings = groupPoolImpl.get(GROUP_1);
Assert.assertTrue(strings.isEmpty());
assertTrue(strings.isEmpty());
}
@Test
@ -45,19 +49,19 @@ public class GroupListenerTest {
)));
List<String> templateIds = groupPoolImpl.get(GROUP_1);
Assert.assertFalse(templateIds.isEmpty());
assertFalse(templateIds.isEmpty());
Assert.assertEquals(FIRST_TEMPL, templateIds.get(0));
Assert.assertEquals(SECOND_TEMPL, templateIds.get(1));
assertEquals(FIRST_TEMPL, templateIds.get(0));
assertEquals(SECOND_TEMPL, templateIds.get(1));
//check rewrite
groupListener.listen(BeanUtil.createGroupCommand(GROUP_1, List.of()));
templateIds = groupPoolImpl.get(GROUP_1);
Assert.assertTrue(templateIds.isEmpty());
assertTrue(templateIds.isEmpty());
//check rewrite
groupListener.listen(BeanUtil.deleteGroupCommand(GROUP_1, List.of()));
templateIds = groupPoolImpl.get(GROUP_1);
Assert.assertNull(templateIds);
assertNull(templateIds);
}
}
}

View File

@ -5,9 +5,11 @@ import com.rbkmoney.fraudbusters.pool.Pool;
import com.rbkmoney.fraudbusters.pool.PoolImpl;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.fraudbusters.util.ReferenceKeyGenerator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
public class GroupReferenceListenerTest {
@ -18,7 +20,7 @@ public class GroupReferenceListenerTest {
private Pool<String> groupReferencePoolImpl;
private GroupReferenceListener groupReferenceListener;
@Before
@BeforeEach
public void init() {
groupReferencePoolImpl = new PoolImpl<>("group-reference");
groupReferenceListener = new GroupReferenceListener(groupReferencePoolImpl);
@ -28,14 +30,14 @@ public class GroupReferenceListenerTest {
public void listen() {
groupReferenceListener.listen(BeanUtil.createGroupReferenceCommand(PARTY, null, GROUP_REF_1));
String ref = groupReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(PARTY, null));
Assert.assertEquals(GROUP_REF_1, ref);
assertEquals(GROUP_REF_1, ref);
groupReferenceListener.listen(BeanUtil.createGroupReferenceCommand(PARTY, SHOP_ID, GROUP_REF_1));
ref = groupReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(PARTY, SHOP_ID));
Assert.assertEquals(GROUP_REF_1, ref);
assertEquals(GROUP_REF_1, ref);
groupReferenceListener.listen(BeanUtil.createDeleteGroupReferenceCommand(PARTY, SHOP_ID, GROUP_REF_1));
ref = groupReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(PARTY, SHOP_ID));
Assert.assertNull(ref);
assertNull(ref);
}
}
}

View File

@ -5,9 +5,11 @@ import com.rbkmoney.fraudbusters.pool.Pool;
import com.rbkmoney.fraudbusters.pool.PoolImpl;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.fraudbusters.util.ReferenceKeyGenerator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class GroupReferenceP2PListenerTest {
@ -17,20 +19,25 @@ public class GroupReferenceP2PListenerTest {
private Pool<String> groupP2PReferencePoolImpl;
private GroupReferenceP2PListener groupReferenceP2PListener;
@Before
@BeforeEach
public void init() {
groupP2PReferencePoolImpl = new PoolImpl<>("p2p-reference");
groupReferenceP2PListener = new GroupReferenceP2PListener(groupP2PReferencePoolImpl);
}
@Test(expected = UnknownReferenceException.class)
@Test
public void listen() {
groupReferenceP2PListener.listen(BeanUtil.createP2PGroupReferenceCommand(IDENTITY_ID, GROUP_REF_1));
String ref = groupP2PReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(IDENTITY_ID));
Assert.assertEquals(GROUP_REF_1, ref);
groupReferenceP2PListener.listen(BeanUtil.createP2PGroupReferenceCommand(null, GROUP_REF_1));
assertEquals(GROUP_REF_1, ref);
assertThrows(
UnknownReferenceException.class,
() -> groupReferenceP2PListener.listen(BeanUtil.createP2PGroupReferenceCommand(null, GROUP_REF_1))
);
ref = groupP2PReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(IDENTITY_ID));
Assert.assertEquals(GROUP_REF_1, ref);
assertEquals(GROUP_REF_1, ref);
}
}
}

View File

@ -6,9 +6,11 @@ import com.rbkmoney.fraudbusters.pool.Pool;
import com.rbkmoney.fraudbusters.pool.PoolImpl;
import com.rbkmoney.fraudbusters.util.BeanUtil;
import com.rbkmoney.fraudbusters.util.ReferenceKeyGenerator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class TemplateP2PReferenceListenerTest {
@ -20,17 +22,17 @@ public class TemplateP2PReferenceListenerTest {
private Pool<String> templateP2PReferencePoolImpl;
private TemplateP2PReferenceListener templateP2PReferenceListener;
@Before
@BeforeEach
public void init() {
templateP2PReferencePoolImpl = new PoolImpl<>("p2p-template-reference");
templateP2PReferenceListener = new TemplateP2PReferenceListener(templateP2PReferencePoolImpl);
}
@Test(expected = UnknownReferenceException.class)
@Test
public void listen() {
templateP2PReferenceListener.listen(BeanUtil.createP2PTemplateReferenceCommand(IDENTITY_ID, GROUP_REF_1));
String ref = templateP2PReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(IDENTITY_ID));
Assert.assertEquals(GROUP_REF_1, ref);
assertEquals(GROUP_REF_1, ref);
Command p2PTemplateReferenceCommand = BeanUtil.createP2PTemplateReferenceCommand(IDENTITY_ID, GROUP_REF_2);
p2PTemplateReferenceCommand.getCommandBody().getP2pReference().setIsGlobal(true);
@ -38,11 +40,14 @@ public class TemplateP2PReferenceListenerTest {
templateP2PReferenceListener.listen(p2PTemplateReferenceCommand);
ref = templateP2PReferencePoolImpl.get(ReferenceKeyGenerator
.generateP2PTemplateKey(p2PTemplateReferenceCommand.getCommandBody().getP2pReference()));
Assert.assertEquals(GROUP_REF_2, ref);
assertEquals(GROUP_REF_2, ref);
templateP2PReferenceListener.listen(BeanUtil.createP2PTemplateReferenceCommand(null, GROUP_REF_1));
assertThrows(
UnknownReferenceException.class,
() -> templateP2PReferenceListener.listen(BeanUtil.createP2PTemplateReferenceCommand(null, GROUP_REF_1))
);
ref = templateP2PReferencePoolImpl.get(ReferenceKeyGenerator.generateTemplateKeyByList(IDENTITY_ID));
Assert.assertEquals(GROUP_REF_1, ref);
assertEquals(GROUP_REF_1, ref);
}
}
}

View File

@ -22,10 +22,9 @@ import com.rbkmoney.fraudo.constant.ResultStatus;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.util.TestPropertyValues;
@ -34,8 +33,10 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.testcontainers.containers.ClickHouseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.SQLException;
import java.time.Instant;
@ -44,10 +45,11 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j
@RunWith(SpringRunner.class)
@Testcontainers
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {
EventP2PRepository.class,
@ -63,7 +65,7 @@ public class EventP2PRepositoryTest {
private static final String SELECT_COUNT_AS_CNT_FROM_FRAUD_EVENTS_UNIQUE =
"SELECT count() as cnt from fraud.events_p_to_p";
@ClassRule
@Container
public static ClickHouseContainer clickHouseContainer =
new ClickHouseContainer("yandex/clickhouse-server:19.17");
@ -88,7 +90,7 @@ public class EventP2PRepositoryTest {
);
}
@Before
@BeforeEach
public void setUp() throws Exception {
initDb();
}

View File

@ -16,9 +16,8 @@ import com.rbkmoney.fraudbusters.util.TimestampUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.util.TestPropertyValues;
@ -27,18 +26,21 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.testcontainers.containers.ClickHouseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j
@RunWith(SpringRunner.class)
@Testcontainers
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {ClickhouseConfig.class,
DatabasePaymentFieldResolver.class,
@ -53,7 +55,7 @@ public class FraudPaymentRepositoryTest {
private static final String SELECT_COUNT_AS_CNT_FROM_FRAUD_EVENTS_UNIQUE =
"SELECT count() as cnt from fraud.fraud_payment";
@ClassRule
@Container
public static ClickHouseContainer clickHouseContainer =
new ClickHouseContainer("yandex/clickhouse-server:19.17");
@Autowired

View File

@ -19,10 +19,9 @@ import com.rbkmoney.fraudo.constant.ResultStatus;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.util.TestPropertyValues;
@ -31,18 +30,21 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.testcontainers.containers.ClickHouseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.SQLException;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j
@RunWith(SpringRunner.class)
@Testcontainers
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {FraudResultToEventConverter.class, ClickhouseConfig.class,
DatabasePaymentFieldResolver.class, AggregationGeneralRepositoryImpl.class, FraudResultRepository.class,
@ -53,7 +55,7 @@ public class FraudResultRepositoryTest {
private static final String SELECT_COUNT_AS_CNT_FROM_FRAUD_EVENTS_UNIQUE =
"SELECT count() as cnt from fraud.events_unique";
@ClassRule
@Container
public static ClickHouseContainer clickHouseContainer = new ClickHouseContainer("yandex/clickhouse-server:19.17");
@Autowired
FraudResultToEventConverter fraudResultToEventConverter;
@ -66,7 +68,7 @@ public class FraudResultRepositoryTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
@BeforeEach
public void setUp() throws Exception {
ChInitializer.initAllScripts(clickHouseContainer, List.of(
"sql/db_init.sql",

View File

@ -14,9 +14,8 @@ import com.rbkmoney.fraudbusters.repository.impl.PaymentRepositoryImpl;
import com.rbkmoney.fraudbusters.repository.mapper.CheckedPaymentMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.util.TestPropertyValues;
@ -26,18 +25,21 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.testcontainers.containers.ClickHouseContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import java.sql.SQLException;
import java.util.List;
import static com.rbkmoney.fraudbusters.util.BeanUtil.*;
import static org.junit.Assert.assertEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Slf4j
@ActiveProfiles("full-prod")
@RunWith(SpringRunner.class)
@Testcontainers
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {PaymentRepositoryImpl.class, FraudResultToEventConverter.class, ClickhouseConfig.class,
DatabasePaymentFieldResolver.class, AggregationGeneralRepositoryImpl.class, CheckedPaymentMapper.class},
@ -47,7 +49,7 @@ public class PaymentRepositoryTest {
public static final long FROM = 1588761200000L;
public static final long TO = 1588761209000L;
@ClassRule
@Container
public static ClickHouseContainer clickHouseContainer =
new ClickHouseContainer("yandex/clickhouse-server:19.17");
@Autowired
@ -154,3 +156,4 @@ public class PaymentRepositoryTest {
}
}

View File

@ -11,7 +11,9 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Slf4j
class P2PServiceHandlerTest {
@ -57,4 +59,4 @@ class P2PServiceHandlerTest {
.setId(id);
}
}
}

View File

@ -10,7 +10,9 @@ import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static org.junit.Assert.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@Slf4j
class PaymentServiceHandlerTest {

View File

@ -4,23 +4,23 @@ import com.rbkmoney.fraudbusters.config.ClickhouseConfig;
import com.rbkmoney.fraudbusters.fraud.pool.CardTokenPoolImpl;
import com.rbkmoney.fraudbusters.repository.impl.CommonQueryRepository;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@RunWith(SpringRunner.class)
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {ClickhouseConfig.class})
@SpringBootTest(classes = {CardPoolManagementService.class, CardTokenPoolImpl.class,

View File

@ -1,7 +1,6 @@
package com.rbkmoney.fraudbusters.service;
import com.rbkmoney.fraudbusters.domain.CheckedResultModel;
import com.rbkmoney.fraudbusters.domain.ConcreteResultModel;
import com.rbkmoney.fraudbusters.exception.InvalidTemplateException;
import com.rbkmoney.fraudbusters.fraud.FraudContextParser;
import com.rbkmoney.fraudbusters.fraud.model.PaymentModel;

View File

@ -1,15 +1,14 @@
package com.rbkmoney.fraudbusters.service;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import com.rbkmoney.damsel.fraudbusters.MerchantInfo;
import com.rbkmoney.damsel.fraudbusters.ReferenceInfo;
import com.rbkmoney.fraudbusters.config.RestTemplateConfig;
import com.rbkmoney.fraudbusters.config.properties.DefaultTemplateProperties;
import com.rbkmoney.fraudbusters.repository.impl.AggregationGeneralRepositoryImpl;
import com.rbkmoney.fraudbusters.repository.impl.FraudResultRepository;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
@ -17,12 +16,13 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@RunWith(SpringRunner.class)
@WireMockTest(httpPort = 8089)
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
@ContextConfiguration(classes = {ShopManagementService.class,
AggregationGeneralRepositoryImpl.class,
@ -32,9 +32,6 @@ import static org.mockito.Mockito.*;
DefaultTemplateProperties.class})
public class ShopManagementServiceTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
@MockBean
KafkaTemplate<String, ReferenceInfo> kafkaTemplate;
@MockBean

View File

@ -8,16 +8,19 @@ import com.rbkmoney.fraudbusters.stream.impl.RuleApplierImpl;
import com.rbkmoney.fraudbusters.stream.impl.TemplateVisitorImpl;
import com.rbkmoney.fraudbusters.util.ReferenceKeyGenerator;
import com.rbkmoney.fraudo.constant.ResultStatus;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(MockitoExtension.class)
public class TemplateVisitorImplTest {
public static final String PARTY_ID = "party_id";
@ -32,10 +35,8 @@ public class TemplateVisitorImplTest {
private Pool<String> referencePoolImpl;
private Pool<String> groupReferencePoolImpl;
@Before
@BeforeEach
public void init() {
MockitoAnnotations.initMocks(this);
groupPoolImpl = new PoolImpl<>("group");
referencePoolImpl = new PoolImpl<>("reference");
groupReferencePoolImpl = new PoolImpl<>("group-reference");
@ -51,8 +52,8 @@ public class TemplateVisitorImplTest {
paymentModel.setPartyId(PARTY_ID);
CheckedResultModel visit = templateVisitor.visit(paymentModel);
Assert.assertEquals("RULE_NOT_CHECKED", visit.getCheckedTemplate());
Assert.assertEquals(ResultStatus.THREE_DS, visit.getResultModel().getResultStatus());
assertEquals("RULE_NOT_CHECKED", visit.getCheckedTemplate());
assertEquals(ResultStatus.THREE_DS, visit.getResultModel().getResultStatus());
//check group party pool
List<String> templateIds = List.of(TEMPLATE_1);
@ -64,21 +65,20 @@ public class TemplateVisitorImplTest {
Mockito.when(ruleApplier.applyForAny(paymentModel, templateIds)).thenReturn(Optional.of(checkedResultModel));
visit = templateVisitor.visit(paymentModel);
Assert.assertEquals(TRUE_TEMPL, visit.getCheckedTemplate());
assertEquals(TRUE_TEMPL, visit.getCheckedTemplate());
Mockito.when(ruleApplier.applyForAny(paymentModel, templateIds)).thenReturn(Optional.empty());
visit = templateVisitor.visit(paymentModel);
Assert.assertEquals("RULE_NOT_CHECKED", visit.getCheckedTemplate());
Assert.assertEquals(ResultStatus.THREE_DS, visit.getResultModel().getResultStatus());
assertEquals("RULE_NOT_CHECKED", visit.getCheckedTemplate());
assertEquals(ResultStatus.THREE_DS, visit.getResultModel().getResultStatus());
//check party pool
referencePoolImpl.add(key, TEMPLATE_1);
Mockito.when(ruleApplier.apply(paymentModel, TEMPLATE_1))
.thenReturn(Optional.of(checkedResultModel));
Mockito.when(ruleApplier.apply(paymentModel, null)).thenReturn(Optional.empty());
Mockito.when(ruleApplier.apply(paymentModel, TEMPLATE_1)).thenReturn(Optional.of(checkedResultModel));
visit = templateVisitor.visit(paymentModel);
Assert.assertEquals(TRUE_TEMPL, visit.getCheckedTemplate());
assertEquals(TRUE_TEMPL, visit.getCheckedTemplate());
}
}
}

View File

@ -1,31 +1,33 @@
package com.rbkmoney.fraudbusters.util;
import com.rbkmoney.fraudbusters.exception.UnknownReferenceException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ReferenceKeyGeneratorTest {
@Test
public void generateTemplateKey() {
String key = ReferenceKeyGenerator.generateTemplateKey("partyId", "shopId");
Assert.assertEquals("partyId_shopId", key);
assertEquals("partyId_shopId", key);
key = ReferenceKeyGenerator.generateTemplateKey("partyId", null);
Assert.assertEquals("partyId", key);
assertEquals("partyId", key);
key = ReferenceKeyGenerator.generateTemplateKey(null, "shopId");
Assert.assertEquals("DEFAULT", key);
assertEquals("DEFAULT", key);
}
@Test(expected = UnknownReferenceException.class)
@Test
public void testGenerateTemplateKey() {
String key = ReferenceKeyGenerator.generateTemplateKeyByList("partyId", "shopId");
Assert.assertEquals("partyId_shopId", key);
assertEquals("partyId_shopId", key);
key = ReferenceKeyGenerator.generateTemplateKeyByList("partyId", null);
Assert.assertEquals("partyId", key);
assertEquals("partyId", key);
key = ReferenceKeyGenerator.generateTemplateKeyByList();
assertThrows(UnknownReferenceException.class, ReferenceKeyGenerator::generateTemplateKeyByList);
}
}
}