P2p change (#19)

* Generalize interfaces

* Add tests for p2p

* Add currency function

* Added naming lists

* Change logic exception
This commit is contained in:
Kostya 2019-10-30 16:30:39 +03:00 committed by GitHub
parent 90a88facbe
commit d714889a6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 965 additions and 490 deletions

View File

@ -11,7 +11,7 @@
</parent>
<artifactId>fraudo</artifactId>
<version>0.0.8-SNAPSHOT</version>
<version>0.0.9-SNAPSHOT</version>
<properties>
<hamcrest.junit.version>2.0.0.0</hamcrest.junit.version>

View File

@ -25,10 +25,12 @@ expression
| in_white_list #inWhiteListExpression
| in_black_list #inBlackListExpression
| in_grey_list #inGreyListExpression
| in_list #inListExpression
| like #likeFunctionExpression
| country #countryFunctionExpression
| country_by #countryByFunctionExpression
| amount #amountFunctionExpression
| currency #currencyFunctionExpression
| IDENTIFIER #identifierExpression
| DECIMAL #decimalExpression
| STRING #stringExpression
@ -50,6 +52,10 @@ amount
: 'amount' LPAREN RPAREN
;
currency
: 'currency' LPAREN RPAREN
;
count
: 'count' LPAREN STRING time_window (group_by)? RPAREN
;
@ -94,6 +100,10 @@ in_grey_list
: 'inGreyList' LPAREN string_list RPAREN
;
in_list
: 'inList' LPAREN STRING DELIMETER string_list RPAREN
;
like
: 'like' LPAREN STRING DELIMETER STRING RPAREN
;

View File

@ -1,26 +1,15 @@
package com.rbkmoney.fraudo.aggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.TimeWindow;
import java.util.List;
public interface CountAggregator {
public interface CountAggregator<T, U> {
@Deprecated
Integer count(CheckedField checkedField, FraudModel model, Long timeInMinutes);
Integer count(U checkedField, T model, TimeWindow timeWindow, List<U> fields);
Integer count(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, List<CheckedField> fields);
Integer countSuccess(U checkedField, T model, TimeWindow timeWindow, List<U> fields);
@Deprecated
Integer countSuccess(CheckedField checkedField, FraudModel model, Long timeInMinutes);
Integer countSuccess(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, List<CheckedField> fields);
@Deprecated
Integer countError(CheckedField checkedField, FraudModel model, Long timeInMinutes, String errorCode);
Integer countError(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, String errorCode, List<CheckedField> fields);
Integer countError(U checkedField, T model, TimeWindow timeWindow, String errorCode, List<U> fields);
}

View File

@ -1,26 +1,15 @@
package com.rbkmoney.fraudo.aggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.TimeWindow;
import java.util.List;
public interface SumAggregator {
public interface SumAggregator<T, U> {
@Deprecated
Double sum(CheckedField checkedField, FraudModel model, Long timeInMinutes);
Double sum(U checkedField, T model, TimeWindow timeWindow, List<U> fields);
Double sum(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, List<CheckedField> fields);
Double sumSuccess(U checkedField, T model, TimeWindow timeWindow, List<U> fields);
@Deprecated
Double sumSuccess(CheckedField checkedField, FraudModel model, Long timeInMinutes);
Double sumSuccess(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, List<CheckedField> fields);
@Deprecated
Double sumError(CheckedField checkedField, FraudModel model, Long timeInMinutes, String errorCode);
Double sumError(CheckedField checkedField, FraudModel model, TimeWindow timeWindow, String errorCode, List<CheckedField> fields);
Double sumError(U checkedField, T model, TimeWindow timeWindow, String errorCode, List<U> fields);
}

View File

@ -1,16 +1,11 @@
package com.rbkmoney.fraudo.aggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.TimeWindow;
import java.util.List;
public interface UniqueValueAggregator {
public interface UniqueValueAggregator<T, U> {
@Deprecated
Integer countUniqueValue(CheckedField countField, FraudModel fraudModel, CheckedField onField, Long time);
Integer countUniqueValue(CheckedField countField, FraudModel fraudModel, CheckedField onField, TimeWindow timeWindow, List<CheckedField> fields);
Integer countUniqueValue(U countField, T payoutModel, U onField, TimeWindow timeWindow, List<U> fields);
}

View File

@ -0,0 +1,36 @@
package com.rbkmoney.fraudo.constant;
import java.util.HashMap;
import java.util.Map;
public enum P2PCheckedField {
EMAIL("email"),
IP("ip"),
FINGERPRINT("fingerprint"),
COUNTRY_BANK("country_bank"),
BIN("bin"),
PAN("pan"),
CURRENCY("currency"),
IDENTITY_ID("identity_id"),
CARD_TOKEN_FROM("card_token_from"),
CARD_TOKEN_TO("card_token_to");
private String value;
private static Map<String, P2PCheckedField> valueMap = new HashMap<>();
static {
for (P2PCheckedField value : P2PCheckedField.values()) {
valueMap.put(value.value, value);
}
}
P2PCheckedField(String value) {
this.value = value;
}
public static P2PCheckedField getByValue(String value) {
return valueMap.get(value);
}
}

View File

@ -3,7 +3,7 @@ package com.rbkmoney.fraudo.constant;
import java.util.HashMap;
import java.util.Map;
public enum CheckedField {
public enum PaymentCheckedField {
EMAIL("email"),
IP("ip"),
@ -12,24 +12,25 @@ public enum CheckedField {
COUNTRY_IP("country_ip"),
BIN("bin"),
PAN("pan"),
CURRENCY("currency"),
SHOP_ID("shop_id"),
PARTY_ID("party_id"),
CARD_TOKEN("card_token");
private String value;
private static Map<String, CheckedField> valueMap = new HashMap<>();
private static Map<String, PaymentCheckedField> valueMap = new HashMap<>();
static {
for (CheckedField value : CheckedField.values()) {
for (PaymentCheckedField value : PaymentCheckedField.values()) {
valueMap.put(value.value, value);
}
}
CheckedField(String value) {
PaymentCheckedField(String value) {
this.value = value;
}
public static CheckedField getByValue(String value) {
public static PaymentCheckedField getByValue(String value) {
return valueMap.get(value);
}

View File

@ -0,0 +1,10 @@
package com.rbkmoney.fraudo.exception;
public class NotValidContextException extends RuntimeException {
private static final String ERROR_MESSAGE = "Context is not valid!";
public NotValidContextException() {
super(ERROR_MESSAGE);
}
}

View File

@ -1,29 +1,39 @@
package com.rbkmoney.fraudo.factory;
import com.rbkmoney.fraudo.FraudoVisitor;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.visitor.*;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.visitor.CountVisitor;
import com.rbkmoney.fraudo.visitor.CustomFuncVisitor;
import com.rbkmoney.fraudo.visitor.ListVisitor;
import com.rbkmoney.fraudo.visitor.SumVisitor;
import com.rbkmoney.fraudo.visitor.impl.*;
public class FastFraudVisitorFactory implements FraudVisitorFactory {
public class FastFraudVisitorFactory<T extends BaseModel, U> implements FraudVisitorFactory<T, U> {
@Override
public FraudoVisitor<Object> createVisitor(FraudModel model,
CountAggregator countAggregator,
SumAggregator sumAggregator,
UniqueValueAggregator uniqueValueAggregator,
CountryResolver countryResolver,
InListFinder blackListFinder,
InListFinder whiteListFinder,
InListFinder greyListFinder) {
CountVisitorImpl countVisitor = new CountVisitorImpl(model, countAggregator);
SumVisitorImpl sumVisitor = new SumVisitorImpl(model, sumAggregator);
ListVisitorImpl listVisitor = new ListVisitorImpl(model, blackListFinder, whiteListFinder, greyListFinder);
CustomFuncVisitorImpl customFuncVisitor = new CustomFuncVisitorImpl(model, uniqueValueAggregator, countryResolver);
return new FastFraudVisitorImpl(countVisitor, sumVisitor, listVisitor, customFuncVisitor);
public FastFraudVisitorImpl<T> createVisitor(
CountAggregator<T, U> countAggregator,
SumAggregator<T, U> sumAggregator,
UniqueValueAggregator<T, U> uniqueValueAggregator,
CountryResolver<U> countryResolver,
InListFinder<T, U> listFinder,
FieldResolver<T, U> fieldResolver,
GroupByModelResolver<T, U> groupByModelResolver) {
CountVisitor<T> countVisitor = new CountVisitorImpl<>(countAggregator, fieldResolver, groupByModelResolver);
SumVisitor<T> sumVisitor = new SumVisitorImpl<>(sumAggregator, fieldResolver, groupByModelResolver);
ListVisitor<T> listVisitor = new ListVisitorImpl<>(listFinder, fieldResolver);
CustomFuncVisitor<T> customFuncVisitor = new CustomFuncVisitorImpl<>(
uniqueValueAggregator,
countryResolver,
fieldResolver,
groupByModelResolver);
return new FastFraudVisitorImpl<>(countVisitor, sumVisitor, listVisitor, customFuncVisitor);
}
}

View File

@ -1,22 +1,22 @@
package com.rbkmoney.fraudo.factory;
import com.rbkmoney.fraudo.FraudoVisitor;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.visitor.impl.FastFraudVisitorImpl;
public interface FraudVisitorFactory {
public interface FraudVisitorFactory<T, U> {
FraudoVisitor<Object> createVisitor(FraudModel model,
CountAggregator countAggregator,
SumAggregator sumAggregator,
UniqueValueAggregator uniqueValueAggregator,
CountryResolver countryResolver,
InListFinder blackListFinder,
InListFinder whiteListFinder,
InListFinder greyListFinder);
FastFraudVisitorImpl createVisitor(CountAggregator<T, U> countAggregator,
SumAggregator<T, U> sumAggregator,
UniqueValueAggregator<T, U> uniqueValueAggregator,
CountryResolver<U> countryResolver,
InListFinder<T, U> listFinder,
FieldResolver<T, U> fieldPairResolver,
GroupByModelResolver<T, U> groupByModelResolver);
}

View File

@ -1,13 +1,18 @@
package com.rbkmoney.fraudo.finder;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.Pair;
import java.util.List;
public interface InListFinder {
public interface InListFinder<T, U> {
Boolean findInList(String partyId, String shopId, CheckedField field, String value);
Boolean findInBlackList(List<Pair<U, String>> fields, T model);
Boolean findInList(String partyId, String shopId, List<CheckedField> fields, List<String> value);
Boolean findInWhiteList(List<Pair<U, String>> fields, T model);
Boolean findInGreyList(List<Pair<U, String>> fields, T model);
Boolean findInList(String name, List<Pair<U, String>> fields, T model);
}

View File

@ -0,0 +1,14 @@
package com.rbkmoney.fraudo.model;
import lombok.Data;
@Data
public class BaseModel {
private String ip;
private String email;
private String fingerprint;
private Long amount;
private String currency;
}

View File

@ -1,15 +0,0 @@
package com.rbkmoney.fraudo.model;
import com.rbkmoney.fraudo.constant.CheckedField;
import lombok.Builder;
import lombok.Data;
import java.util.List;
@Data
@Builder
public class GroupByModel {
private List<CheckedField> checkedFields;
}

View File

@ -0,0 +1,15 @@
package com.rbkmoney.fraudo.model;
import lombok.Data;
@Data
public class P2PModel extends BaseModel {
private String bin;
private String pan;
private String country;
private String cardTokenFrom;
private String cardTokenTo;
private String identityId;
}

View File

@ -0,0 +1,15 @@
package com.rbkmoney.fraudo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pair<T, U> {
private T first;
private U second;
}

View File

@ -1,19 +1,19 @@
package com.rbkmoney.fraudo.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Data
public class FraudModel {
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class PaymentModel extends BaseModel {
private String ip;
private String email;
private String bin;
private String pan;
private String binCountryCode;
private String cardToken;
private String fingerprint;
private String shopId;
private String partyId;
private Long amount;
}

View File

@ -1,11 +1,9 @@
package com.rbkmoney.fraudo.resolver;
import com.rbkmoney.fraudo.constant.CheckedField;
public interface CountryResolver {
public interface CountryResolver<T> {
String UNKNOWN_VALUE = "unknown";
String resolveCountry(CheckedField checkedField, String value);
String resolveCountry(T checkedField, String value);
}

View File

@ -1,30 +1,19 @@
package com.rbkmoney.fraudo.resolver;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.exception.UnresolvableFieldException;
import com.rbkmoney.fraudo.model.FraudModel;
public class FieldResolver {
import com.rbkmoney.fraudo.model.Pair;
public static String resolveString(String fieldName, FraudModel fraudModel) {
switch (CheckedField.getByValue(fieldName)) {
case BIN:
return fraudModel.getBin();
case IP:
return fraudModel.getIp();
case FINGERPRINT:
return fraudModel.getFingerprint();
case EMAIL:
return fraudModel.getEmail();
case COUNTRY_BANK:
return fraudModel.getBinCountryCode();
case CARD_TOKEN:
return fraudModel.getCardToken();
case PAN:
return fraudModel.getPan();
default:
throw new UnresolvableFieldException(fieldName);
}
public interface FieldResolver<T, U> {
String resolveValue(String fieldName, T model);
U resolveName(String fieldName);
default Pair<U, String> resolve(String fieldName, T model) {
return new Pair<>(
resolveName(fieldName),
resolveValue(fieldName, model)
);
}
}

View File

@ -1,26 +1,29 @@
package com.rbkmoney.fraudo.resolver;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.RequiredArgsConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class GroupByModelResolver {
@RequiredArgsConstructor
public class GroupByModelResolver<T, U> implements GroupFieldsResolver<U> {
public static List<CheckedField> resolve(FraudoParser.Group_byContext groupByContext) {
List<CheckedField> checkedFields = new ArrayList<>();
private final FieldResolver<T, U> fieldResolver;
public List<U> resolve(FraudoParser.Group_byContext groupByContext) {
List<U> fields = new ArrayList<>();
if (groupByContext != null
&& groupByContext.string_list() != null
&& groupByContext.string_list().STRING() != null
&& !groupByContext.string_list().STRING().isEmpty()) {
checkedFields = groupByContext.string_list().STRING().stream()
.map(terminalNode -> CheckedField.getByValue(TextUtil.safeGetText(terminalNode)))
fields = groupByContext.string_list().STRING().stream()
.map(terminalNode -> fieldResolver.resolveName(TextUtil.safeGetText(terminalNode)))
.collect(Collectors.toList());
}
return checkedFields;
return fields;
}
}

View File

@ -0,0 +1,11 @@
package com.rbkmoney.fraudo.resolver;
import com.rbkmoney.fraudo.FraudoParser;
import java.util.List;
public interface GroupFieldsResolver<T> {
List<T> resolve(FraudoParser.Group_byContext groupByContext);
}

View File

@ -3,10 +3,13 @@ package com.rbkmoney.fraudo.resolver;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.model.TimeWindow;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.List;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TimeWindowResolver {
public static TimeWindow resolve(FraudoParser.Time_windowContext ctx) {

View File

@ -0,0 +1,39 @@
package com.rbkmoney.fraudo.resolver.p2p;
import com.rbkmoney.fraudo.constant.P2PCheckedField;
import com.rbkmoney.fraudo.exception.UnresolvableFieldException;
import com.rbkmoney.fraudo.model.P2PModel;
import com.rbkmoney.fraudo.resolver.FieldResolver;
public class P2PModelFieldResolver implements FieldResolver<P2PModel, P2PCheckedField> {
@Override
public String resolveValue(String fieldName, P2PModel model) {
switch (P2PCheckedField.getByValue(fieldName)) {
case BIN:
return model.getBin();
case IP:
return model.getIp();
case FINGERPRINT:
return model.getFingerprint();
case EMAIL:
return model.getEmail();
case COUNTRY_BANK:
return model.getCountry();
case CARD_TOKEN_FROM:
return model.getCardTokenFrom();
case CARD_TOKEN_TO:
return model.getCardTokenTo();
case PAN:
return model.getPan();
default:
throw new UnresolvableFieldException(fieldName);
}
}
@Override
public P2PCheckedField resolveName(String fieldName) {
return P2PCheckedField.getByValue(fieldName);
}
}

View File

@ -0,0 +1,37 @@
package com.rbkmoney.fraudo.resolver.payout;
import com.rbkmoney.fraudo.constant.PaymentCheckedField;
import com.rbkmoney.fraudo.exception.UnresolvableFieldException;
import com.rbkmoney.fraudo.model.PaymentModel;
import com.rbkmoney.fraudo.resolver.FieldResolver;
public class PaymentModelFieldResolver implements FieldResolver<PaymentModel, PaymentCheckedField> {
@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);
}
}
@Override
public PaymentCheckedField resolveName(String fieldName) {
return PaymentCheckedField.getByValue(fieldName);
}
}

View File

@ -1,7 +1,7 @@
package com.rbkmoney.fraudo.utils.key.generator;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.constant.PaymentCheckedField;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
@ -19,7 +19,7 @@ public class CommonKeyGenerator {
return new StringBuilder()
.append(parseTree)
.append(countTarget)
.append(CheckedField.getByValue(countTarget))
.append(PaymentCheckedField.getByValue(countTarget))
.append(timeWindowContext != null ? timeWindowContext.children : "")
.append(groupByContext != null ? groupByContext.string_list().children : "")
.toString();
@ -36,7 +36,7 @@ public class CommonKeyGenerator {
.append(parseTree)
.append(target)
.append(errorCode)
.append(CheckedField.getByValue(target))
.append(PaymentCheckedField.getByValue(target))
.append(timeWindowContext != null ? timeWindowContext.children : "")
.append(groupByContext != null ? groupByContext.string_list().children : "")
.toString();

View File

@ -0,0 +1,13 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoParser;
public interface CountVisitor<T> {
Integer visitCount(FraudoParser.CountContext ctx, T model);
Integer visitCountSuccess(FraudoParser.Count_successContext ctx, T model);
Integer visitCountError(FraudoParser.Count_errorContext ctx, T model);
}

View File

@ -1,41 +0,0 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoBaseVisitor;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class CountVisitorImpl extends FraudoBaseVisitor<Object> {
private final FraudModel fraudModel;
private final CountAggregator countAggregator;
@Override
public Object visitCount(com.rbkmoney.fraudo.FraudoParser.CountContext ctx) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return (double) countAggregator.count(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), GroupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Object visitCount_success(FraudoParser.Count_successContext ctx) {
String countTarget = ctx.STRING().getText();
return (double) countAggregator.countSuccess(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), GroupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Object visitCount_error(FraudoParser.Count_errorContext ctx) {
String countTarget = TextUtil.safeGetText(ctx.STRING(0));
String errorCode = TextUtil.safeGetText(ctx.STRING(1));
return (double) countAggregator.countError(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), errorCode, GroupByModelResolver.resolve(ctx.group_by()));
}
}

View File

@ -0,0 +1,15 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoParser;
public interface CustomFuncVisitor<T> {
String visitCountryBy(FraudoParser.Country_byContext ctx, T model);
boolean visitIn(FraudoParser.InContext ctx, T model);
boolean visitLike(FraudoParser.LikeContext ctx, T model);
Integer visitUnique(FraudoParser.UniqueContext ctx, T model);
}

View File

@ -1,64 +0,0 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoBaseVisitor;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class CustomFuncVisitorImpl extends FraudoBaseVisitor<Object> {
private final FraudModel fraudModel;
private final UniqueValueAggregator uniqueValueAggregator;
private final CountryResolver countryResolver;
@Override
public Object visitCountry_by(FraudoParser.Country_byContext ctx) {
String fieldName = TextUtil.safeGetText(ctx.STRING());
String fieldValue = FieldResolver.resolveString(fieldName, fraudModel);
return countryResolver.resolveCountry(CheckedField.getByValue(fieldName), fieldValue);
}
@Override
public Object visitIn(FraudoParser.InContext ctx) {
final String fieldValue;
if (ctx.STRING() != null && ctx.STRING().getText() != null && !ctx.STRING().getText().isEmpty()) {
String field = TextUtil.safeGetText(ctx.STRING());
fieldValue = FieldResolver.resolveString(field, fraudModel);
} else {
String fieldName = TextUtil.safeGetText(ctx.country_by().STRING());
String value = FieldResolver.resolveString(fieldName, fraudModel);
fieldValue = countryResolver.resolveCountry(CheckedField.getByValue(fieldName), value);
}
return ctx.string_list().STRING().stream()
.anyMatch(s -> fieldValue.equals(TextUtil.safeGetText(s)));
}
@Override
public Object visitLike(FraudoParser.LikeContext ctx) {
String fieldName = TextUtil.safeGetText(ctx.STRING(0));
String fieldValue = FieldResolver.resolveString(fieldName, fraudModel);
String pattern = TextUtil.safeGetText(ctx.STRING(1));
return fieldValue.matches(pattern);
}
@Override
public Object visitUnique(FraudoParser.UniqueContext ctx) {
String field = TextUtil.safeGetText(ctx.STRING(0));
String fieldBy = TextUtil.safeGetText(ctx.STRING(1));
return (double) uniqueValueAggregator.countUniqueValue(CheckedField.getByValue(field), fraudModel,
CheckedField.getByValue(fieldBy), TimeWindowResolver.resolve(ctx.time_window()), GroupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Object visitAmount(FraudoParser.AmountContext ctx) {
return (double) fraudModel.getAmount();
}
}

View File

@ -0,0 +1,15 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoParser;
public interface ListVisitor<T> {
Boolean visitInWhiteList(FraudoParser.In_white_listContext ctx, T model);
Boolean visitInBlackList(FraudoParser.In_black_listContext ctx, T model);
Boolean visitInGreyList(FraudoParser.In_grey_listContext ctx, T model);
Boolean visitInList(FraudoParser.In_listContext ctx, T model);
}

View File

@ -1,52 +0,0 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoBaseVisitor;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.RequiredArgsConstructor;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class ListVisitorImpl extends FraudoBaseVisitor<Object> {
private final FraudModel fraudModel;
private final InListFinder blackListFinder;
private final InListFinder whiteListFinder;
private final InListFinder greyListFinder;
@Override
public Object visitIn_white_list(FraudoParser.In_white_listContext ctx) {
return findInList(ctx.string_list().STRING(), whiteListFinder);
}
@Override
public Object visitIn_black_list(FraudoParser.In_black_listContext ctx) {
return findInList(ctx.string_list().STRING(), blackListFinder);
}
@Override
public Object visitIn_grey_list(FraudoParser.In_grey_listContext ctx) {
return findInList(ctx.string_list().STRING(), greyListFinder);
}
private Object findInList(List<TerminalNode> nodes, InListFinder listFinder) {
List<String> fields = nodes.stream()
.map(TextUtil::safeGetText)
.collect(Collectors.toList());
List<String> values = fields.stream()
.map(field -> FieldResolver.resolveString(field, fraudModel))
.collect(Collectors.toList());
List<CheckedField> checkedFields = fields.stream()
.map(CheckedField::getByValue)
.collect(Collectors.toList());
return listFinder.findInList(fraudModel.getPartyId(), fraudModel.getShopId(),
checkedFields, values);
}
}

View File

@ -0,0 +1,13 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoParser;
public interface SumVisitor<T> {
Double visitSum(FraudoParser.SumContext ctx, T model);
Double visitSumSuccess(FraudoParser.Sum_successContext ctx, T model);
Double visitSumError(FraudoParser.Sum_errorContext ctx, T model);
}

View File

@ -1,41 +0,0 @@
package com.rbkmoney.fraudo.visitor;
import com.rbkmoney.fraudo.FraudoBaseVisitor;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.constant.CheckedField;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class SumVisitorImpl extends FraudoBaseVisitor<Object> {
private final FraudModel fraudModel;
private final SumAggregator sumAggregator;
@Override
public Object visitSum(FraudoParser.SumContext ctx) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return sumAggregator.sum(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), GroupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Object visitSum_success(FraudoParser.Sum_successContext ctx) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return sumAggregator.sumSuccess(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), GroupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Object visitSum_error(FraudoParser.Sum_errorContext ctx) {
String countTarget = TextUtil.safeGetText(ctx.STRING(0));
String errorCode = TextUtil.safeGetText(ctx.STRING(1));
return sumAggregator.sumError(CheckedField.getByValue(countTarget), fraudModel,
TimeWindowResolver.resolve(ctx.time_window()), errorCode, GroupByModelResolver.resolve(ctx.group_by()));
}
}

View File

@ -0,0 +1,54 @@
package com.rbkmoney.fraudo.visitor.impl;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupFieldsResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import com.rbkmoney.fraudo.visitor.CountVisitor;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class CountVisitorImpl<T, U> implements CountVisitor<T> {
private final CountAggregator<T, U> countAggregator;
private final FieldResolver<T, U> fieldResolver;
private final GroupFieldsResolver<U> groupFieldsResolver;
@Override
public Integer visitCount(com.rbkmoney.fraudo.FraudoParser.CountContext ctx, T model) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return countAggregator.count(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
groupFieldsResolver.resolve(ctx.group_by())
);
}
@Override
public Integer visitCountSuccess(FraudoParser.Count_successContext ctx, T model) {
String countTarget = ctx.STRING().getText();
return countAggregator.countSuccess(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
groupFieldsResolver.resolve(ctx.group_by())
);
}
@Override
public Integer visitCountError(FraudoParser.Count_errorContext ctx, T model) {
String countTarget = TextUtil.safeGetText(ctx.STRING(0));
String errorCode = TextUtil.safeGetText(ctx.STRING(1));
return countAggregator.countError(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
errorCode,
groupFieldsResolver.resolve(ctx.group_by())
);
}
}

View File

@ -0,0 +1,65 @@
package com.rbkmoney.fraudo.visitor.impl;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.model.Pair;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import com.rbkmoney.fraudo.visitor.CustomFuncVisitor;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class CustomFuncVisitorImpl<T, U> implements CustomFuncVisitor<T> {
private final UniqueValueAggregator<T, U> uniqueValueAggregator;
private final CountryResolver<U> countryResolver;
private final FieldResolver<T, U> fieldResolver;
private final GroupByModelResolver<T, U> groupByModelResolver;
@Override
public String visitCountryBy(FraudoParser.Country_byContext ctx, T model) {
String fieldName = TextUtil.safeGetText(ctx.STRING());
Pair<U, String> resolve = fieldResolver.resolve(fieldName, model);
return countryResolver.resolveCountry(resolve.getFirst(), resolve.getSecond());
}
@Override
public boolean visitIn(FraudoParser.InContext ctx, T model) {
final String fieldValue;
if (ctx.STRING() != null && ctx.STRING().getText() != null && !ctx.STRING().getText().isEmpty()) {
String field = TextUtil.safeGetText(ctx.STRING());
fieldValue = fieldResolver.resolve(field, model).getSecond();
} else {
String fieldName = TextUtil.safeGetText(ctx.country_by().STRING());
Pair<U, String> resolve = fieldResolver.resolve(fieldName, model);
fieldValue = countryResolver.resolveCountry(resolve.getFirst(), resolve.getSecond());
}
return ctx.string_list().STRING().stream()
.anyMatch(s -> fieldValue.equals(TextUtil.safeGetText(s)));
}
@Override
public boolean visitLike(FraudoParser.LikeContext ctx, T model) {
String fieldName = TextUtil.safeGetText(ctx.STRING(0));
String fieldValue = fieldResolver.resolve(fieldName, model).getSecond();
String pattern = TextUtil.safeGetText(ctx.STRING(1));
return fieldValue.matches(pattern);
}
@Override
public Integer visitUnique(FraudoParser.UniqueContext ctx, T model) {
String field = TextUtil.safeGetText(ctx.STRING(0));
String fieldBy = TextUtil.safeGetText(ctx.STRING(1));
return uniqueValueAggregator.countUniqueValue(
fieldResolver.resolveName(field),
model,
fieldResolver.resolveName(fieldBy),
TimeWindowResolver.resolve(ctx.time_window()),
groupByModelResolver.resolve(ctx.group_by())
);
}
}

View File

@ -1,15 +1,22 @@
package com.rbkmoney.fraudo.visitor;
package com.rbkmoney.fraudo.visitor.impl;
import com.rbkmoney.fraudo.FraudoBaseVisitor;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.exception.NotImplementedOperatorException;
import com.rbkmoney.fraudo.exception.NotValidContextException;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.BaseModel;
import com.rbkmoney.fraudo.model.ResultModel;
import com.rbkmoney.fraudo.utils.TextUtil;
import com.rbkmoney.fraudo.utils.key.generator.*;
import com.rbkmoney.fraudo.visitor.CountVisitor;
import com.rbkmoney.fraudo.visitor.CustomFuncVisitor;
import com.rbkmoney.fraudo.visitor.ListVisitor;
import com.rbkmoney.fraudo.visitor.SumVisitor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.antlr.v4.runtime.tree.ParseTree;
import java.util.ArrayList;
import java.util.HashMap;
@ -18,14 +25,31 @@ import java.util.Map;
@Slf4j
@RequiredArgsConstructor
public class FastFraudVisitorImpl extends FraudoBaseVisitor<Object> {
public class FastFraudVisitorImpl<T extends BaseModel> extends FraudoBaseVisitor<Object> {
private Map<String, Object> localFuncCache = new HashMap<>();
private ThreadLocal<Map<String, Object>> localFuncCache;
private ThreadLocal<T> threadLocalModel;
private final CountVisitorImpl countVisitor;
private final SumVisitorImpl sumVisitor;
private final ListVisitorImpl listVisitor;
private final CustomFuncVisitorImpl customFuncVisitor;
private final CountVisitor<T> countVisitor;
private final SumVisitor<T> sumVisitor;
private final ListVisitor<T> listVisitor;
private final CustomFuncVisitor<T> customFuncVisitor;
public Object visit(ParseTree tree, T model) {
if (model == null) {
log.error("Model is not init!");
throw new NotValidContextException();
}
localFuncCache = ThreadLocal.withInitial(HashMap::new);
threadLocalModel = ThreadLocal.withInitial(() -> model);
Object visit = super.visit(tree);
localFuncCache.remove();
threadLocalModel.remove();
return visit;
}
@Override
public Object visitFraud_rule(FraudoParser.Fraud_ruleContext ctx) {
@ -34,11 +58,11 @@ public class FastFraudVisitorImpl extends FraudoBaseVisitor<Object> {
return ResultStatus.getByValue((String) super.visit(ctx.result()));
}
} catch (Exception e) {
log.warn("Error when FastFraudVisitorImpl visitFraud_rule e: ", e);
log.error("Error when FastFraudVisitorImpl visitFraud_rule e: ", e);
if (ctx.catch_result() != null && ctx.catch_result().getText() != null) {
return ResultStatus.getByValue(ctx.catch_result().getText());
}
return ResultStatus.THREE_DS;
return ResultStatus.NOTIFY;
}
return ResultStatus.NORMAL;
}
@ -49,12 +73,12 @@ public class FastFraudVisitorImpl extends FraudoBaseVisitor<Object> {
for (FraudoParser.Fraud_ruleContext fraudRuleContext : ctx.fraud_rule()) {
ResultStatus result = (ResultStatus) visitFraud_rule(fraudRuleContext);
String key = RuleKeyGenerator.generateRuleKey(fraudRuleContext);
if (ResultStatus.NOTIFY.equals(result)) {
notifications.add(key);
} else if (result != null && !ResultStatus.NORMAL.equals(result)) {
return new ResultModel(result, key, notifications);
} else if (result == null) {
if (result == null) {
throw new UnknownResultException(fraudRuleContext.getText());
} else if (result == ResultStatus.NOTIFY) {
notifications.add(key);
} else if (result != ResultStatus.NORMAL) {
return new ResultModel(result, key, notifications);
}
}
return new ResultModel(ResultStatus.NORMAL, notifications);
@ -119,79 +143,113 @@ public class FastFraudVisitorImpl extends FraudoBaseVisitor<Object> {
@Override
public Object visitCount(FraudoParser.CountContext ctx) {
String key = CountKeyGenerator.generate(ctx);
return localFuncCache.computeIfAbsent(key, s -> countVisitor.visitCount(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> Double.valueOf(countVisitor.visitCount(ctx, threadLocalModel.get()))
);
}
@Override
public Object visitCount_success(FraudoParser.Count_successContext ctx) {
String key = CountKeyGenerator.generateSuccessKey(ctx);
return localFuncCache.computeIfAbsent(key, s -> countVisitor.visitCount_success(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> Double.valueOf(countVisitor.visitCountSuccess(ctx, threadLocalModel.get()))
);
}
@Override
public Object visitCount_error(FraudoParser.Count_errorContext ctx) {
String key = CountKeyGenerator.generateErrorKey(ctx);
return localFuncCache.computeIfAbsent(key, s -> countVisitor.visitCount_error(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> Double.valueOf(countVisitor.visitCountError(ctx, threadLocalModel.get()))
);
}
@Override
public Object visitSum(FraudoParser.SumContext ctx) {
String key = SumKeyGenerator.generate(ctx);
return localFuncCache.computeIfAbsent(key, s -> sumVisitor.visitSum(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> sumVisitor.visitSum(ctx, threadLocalModel.get())
);
}
@Override
public Object visitSum_success(FraudoParser.Sum_successContext ctx) {
String key = SumKeyGenerator.generateSuccessKey(ctx);
return localFuncCache.computeIfAbsent(key, s -> sumVisitor.visitSum_success(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> sumVisitor.visitSumSuccess(ctx, threadLocalModel.get())
);
}
@Override
public Object visitSum_error(FraudoParser.Sum_errorContext ctx) {
String key = SumKeyGenerator.generateErrorKey(ctx);
return localFuncCache.computeIfAbsent(key, s -> sumVisitor.visitSum_error(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> sumVisitor.visitSumError(ctx, threadLocalModel.get())
);
}
@Override
public Object visitCountry_by(FraudoParser.Country_byContext ctx) {
String key = CountryKeyGenerator.generate(ctx);
return localFuncCache.computeIfAbsent(key, s -> customFuncVisitor.visitCountry_by(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> customFuncVisitor.visitCountryBy(ctx, threadLocalModel.get())
);
}
@Override
public Object visitIn(FraudoParser.InContext ctx) {
return customFuncVisitor.visitIn(ctx);
return customFuncVisitor.visitIn(ctx, threadLocalModel.get());
}
@Override
public Object visitLike(FraudoParser.LikeContext ctx) {
return customFuncVisitor.visitLike(ctx);
return customFuncVisitor.visitLike(ctx, threadLocalModel.get());
}
@Override
public Object visitUnique(FraudoParser.UniqueContext ctx) {
String key = UniqueKeyGenerator.generate(ctx);
return localFuncCache.computeIfAbsent(key, s -> customFuncVisitor.visitUnique(ctx));
return localFuncCache.get().computeIfAbsent(
key,
s -> Double.valueOf(customFuncVisitor.visitUnique(ctx, threadLocalModel.get()))
);
}
@Override
public Object visitIn_white_list(FraudoParser.In_white_listContext ctx) {
return listVisitor.visitIn_white_list(ctx);
return listVisitor.visitInWhiteList(ctx, threadLocalModel.get());
}
@Override
public Object visitIn_black_list(FraudoParser.In_black_listContext ctx) {
return listVisitor.visitIn_black_list(ctx);
return listVisitor.visitInBlackList(ctx, threadLocalModel.get());
}
@Override
public Object visitIn_grey_list(FraudoParser.In_grey_listContext ctx) {
return listVisitor.visitIn_grey_list(ctx);
return listVisitor.visitInGreyList(ctx, threadLocalModel.get());
}
@Override
public Object visitIn_list(FraudoParser.In_listContext ctx) {
return listVisitor.visitInList(ctx, threadLocalModel.get());
}
@Override
public Object visitAmount(FraudoParser.AmountContext ctx) {
return customFuncVisitor.visitAmount(ctx);
return Double.valueOf(threadLocalModel.get().getAmount());
}
@Override
public Object visitCurrency(FraudoParser.CurrencyContext ctx) {
return threadLocalModel.get().getCurrency();
}
private boolean asBoolean(FraudoParser.ExpressionContext ctx) {

View File

@ -0,0 +1,57 @@
package com.rbkmoney.fraudo.visitor.impl;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.Pair;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import com.rbkmoney.fraudo.visitor.ListVisitor;
import lombok.RequiredArgsConstructor;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
@RequiredArgsConstructor
public class ListVisitorImpl<T, U> implements ListVisitor<T> {
private final InListFinder<T, U> listFinder;
private final FieldResolver<T, U> fieldResolver;
@Override
public Boolean visitInWhiteList(FraudoParser.In_white_listContext ctx, T model) {
return findInList(ctx.string_list().STRING(), model, listFinder::findInWhiteList);
}
@Override
public Boolean visitInBlackList(FraudoParser.In_black_listContext ctx, T model) {
return findInList(ctx.string_list().STRING(), model, listFinder::findInBlackList);
}
@Override
public Boolean visitInGreyList(FraudoParser.In_grey_listContext ctx, T model) {
return findInList(ctx.string_list().STRING(), model, listFinder::findInGreyList);
}
@Override
public Boolean visitInList(FraudoParser.In_listContext ctx, T model) {
List<Pair<U, String>> checkedFields = initCheckedFields(model, ctx.string_list().STRING());
String name = TextUtil.safeGetText(ctx.STRING());
return listFinder.findInList(name, checkedFields, model);
}
private List<Pair<U, String>> initCheckedFields(T model, List<TerminalNode> string) {
List<String> fields = string.stream()
.map(TextUtil::safeGetText)
.collect(Collectors.toList());
return fields.stream()
.map(s -> fieldResolver.resolve(s, model))
.collect(Collectors.toList());
}
private Boolean findInList(List<TerminalNode> nodes, T model, BiPredicate<List<Pair<U, String>>, T> biPredicate) {
List<Pair<U, String>> checkedFields = initCheckedFields(model, nodes);
return biPredicate.test(checkedFields, model);
}
}

View File

@ -0,0 +1,52 @@
package com.rbkmoney.fraudo.visitor.impl;
import com.rbkmoney.fraudo.FraudoParser;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.TimeWindowResolver;
import com.rbkmoney.fraudo.utils.TextUtil;
import com.rbkmoney.fraudo.visitor.SumVisitor;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class SumVisitorImpl<T, U> implements SumVisitor<T> {
private final SumAggregator<T, U> sumAggregator;
private final FieldResolver<T, U> fieldResolver;
private final GroupByModelResolver<T, U> groupByModelResolver;
@Override
public Double visitSum(FraudoParser.SumContext ctx, T model) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return sumAggregator.sum(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
groupByModelResolver.resolve(ctx.group_by())
);
}
@Override
public Double visitSumSuccess(FraudoParser.Sum_successContext ctx, T model) {
String countTarget = TextUtil.safeGetText(ctx.STRING());
return sumAggregator.sumSuccess(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
groupByModelResolver.resolve(ctx.group_by()));
}
@Override
public Double visitSumError(FraudoParser.Sum_errorContext ctx, T model) {
String countTarget = TextUtil.safeGetText(ctx.STRING(0));
String errorCode = TextUtil.safeGetText(ctx.STRING(1));
return sumAggregator.sumError(
fieldResolver.resolveName(countTarget),
model,
TimeWindowResolver.resolve(ctx.time_window()),
errorCode,
groupByModelResolver.resolve(ctx.group_by()));
}
}

View File

@ -1,61 +0,0 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.factory.FastFraudVisitorFactory;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.ResultModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.mockito.Mock;
import java.io.IOException;
import java.io.InputStream;
public class AbstractFraudoTest {
public static final String TEST_GMAIL_RU = "test@gmail.ru";
@Mock
CountAggregator countAggregator;
@Mock
SumAggregator sumAggregator;
@Mock
UniqueValueAggregator uniqueValueAggregator;
@Mock
CountryResolver countryResolver;
@Mock
InListFinder whiteListFinder;
@Mock
InListFinder blackListFinder;
@Mock
InListFinder greyListFinder;
protected ResultModel parseAndVisit(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoParser.ParseContext parse = getParseContext(resourceAsStream);
return invokeParse(parse);
}
protected ResultModel invokeParse(com.rbkmoney.fraudo.FraudoParser.ParseContext parse) {
FraudModel model = new FraudModel();
return invoke(parse, model);
}
protected ResultModel invoke(com.rbkmoney.fraudo.FraudoParser.ParseContext parse, FraudModel model) {
return (ResultModel) new FastFraudVisitorFactory()
.createVisitor(model, countAggregator, sumAggregator, uniqueValueAggregator, countryResolver,
blackListFinder, whiteListFinder, greyListFinder)
.visit(parse);
}
protected com.rbkmoney.fraudo.FraudoParser.ParseContext getParseContext(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoLexer lexer = new com.rbkmoney.fraudo.FraudoLexer(new ANTLRInputStream(resourceAsStream));
com.rbkmoney.fraudo.FraudoParser parser = new com.rbkmoney.fraudo.FraudoParser(new CommonTokenStream(lexer));
return parser.parse();
}
}

View File

@ -0,0 +1,68 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.constant.P2PCheckedField;
import com.rbkmoney.fraudo.factory.FastFraudVisitorFactory;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.P2PModel;
import com.rbkmoney.fraudo.model.ResultModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.p2p.P2PModelFieldResolver;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.mockito.Mock;
import java.io.IOException;
import java.io.InputStream;
public class AbstractP2PTest {
@Mock
CountAggregator<P2PModel, P2PCheckedField> countAggregator;
@Mock
SumAggregator<P2PModel, P2PCheckedField> sumAggregator;
@Mock
UniqueValueAggregator<P2PModel, P2PCheckedField> uniqueValueAggregator;
@Mock
CountryResolver<P2PCheckedField> countryResolver;
@Mock
InListFinder<P2PModel, P2PCheckedField> listFinder;
private P2PModelFieldResolver fieldResolver = new P2PModelFieldResolver();
private GroupByModelResolver<P2PModel, P2PCheckedField> groupByModelResolver = new GroupByModelResolver<>(fieldResolver);
ResultModel parseAndVisit(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoParser.ParseContext parse = getParseContext(resourceAsStream);
return invokeParse(parse);
}
ResultModel invokeParse(com.rbkmoney.fraudo.FraudoParser.ParseContext parse) {
P2PModel model = new P2PModel();
return invoke(parse, model);
}
ResultModel invoke(com.rbkmoney.fraudo.FraudoParser.ParseContext parse, P2PModel model) {
return (ResultModel) new FastFraudVisitorFactory<P2PModel, P2PCheckedField>()
.createVisitor(
countAggregator,
sumAggregator,
uniqueValueAggregator,
countryResolver,
listFinder,
fieldResolver,
groupByModelResolver)
.visit(parse, model);
}
com.rbkmoney.fraudo.FraudoParser.ParseContext getParseContext(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoLexer lexer = new com.rbkmoney.fraudo.FraudoLexer(new ANTLRInputStream(resourceAsStream));
com.rbkmoney.fraudo.FraudoParser parser = new com.rbkmoney.fraudo.FraudoParser(new CommonTokenStream(lexer));
return parser.parse();
}
}

View File

@ -0,0 +1,68 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.aggregator.CountAggregator;
import com.rbkmoney.fraudo.aggregator.SumAggregator;
import com.rbkmoney.fraudo.aggregator.UniqueValueAggregator;
import com.rbkmoney.fraudo.constant.PaymentCheckedField;
import com.rbkmoney.fraudo.factory.FastFraudVisitorFactory;
import com.rbkmoney.fraudo.finder.InListFinder;
import com.rbkmoney.fraudo.model.PaymentModel;
import com.rbkmoney.fraudo.model.ResultModel;
import com.rbkmoney.fraudo.resolver.CountryResolver;
import com.rbkmoney.fraudo.resolver.FieldResolver;
import com.rbkmoney.fraudo.resolver.GroupByModelResolver;
import com.rbkmoney.fraudo.resolver.payout.PaymentModelFieldResolver;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.mockito.Mock;
import java.io.IOException;
import java.io.InputStream;
public class AbstractPaymentTest {
@Mock
CountAggregator<PaymentModel, PaymentCheckedField> countAggregator;
@Mock
SumAggregator<PaymentModel, PaymentCheckedField> sumAggregator;
@Mock
UniqueValueAggregator<PaymentModel, PaymentCheckedField> uniqueValueAggregator;
@Mock
CountryResolver<PaymentCheckedField> countryResolver;
@Mock
InListFinder<PaymentModel, PaymentCheckedField> inListFinder;
private FieldResolver<PaymentModel, PaymentCheckedField> fieldResolver = new PaymentModelFieldResolver();
private GroupByModelResolver<PaymentModel, PaymentCheckedField> groupByModelResolver = new GroupByModelResolver<>(fieldResolver);
ResultModel parseAndVisit(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoParser.ParseContext parse = getParseContext(resourceAsStream);
return invokeParse(parse);
}
ResultModel invokeParse(com.rbkmoney.fraudo.FraudoParser.ParseContext parse) {
PaymentModel model = new PaymentModel();
return invoke(parse, model);
}
ResultModel invoke(com.rbkmoney.fraudo.FraudoParser.ParseContext parse, PaymentModel model) {
return (ResultModel) new FastFraudVisitorFactory<PaymentModel, PaymentCheckedField>()
.createVisitor(
countAggregator,
sumAggregator,
uniqueValueAggregator,
countryResolver,
inListFinder,
fieldResolver,
groupByModelResolver)
.visit(parse, model);
}
com.rbkmoney.fraudo.FraudoParser.ParseContext getParseContext(InputStream resourceAsStream) throws IOException {
com.rbkmoney.fraudo.FraudoLexer lexer = new com.rbkmoney.fraudo.FraudoLexer(new ANTLRInputStream(resourceAsStream));
com.rbkmoney.fraudo.FraudoParser parser = new com.rbkmoney.fraudo.FraudoParser(new CommonTokenStream(lexer));
return parser.parse();
}
}

View File

@ -2,10 +2,8 @@ package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.InputStream;
@ -14,7 +12,7 @@ import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
public class CountTest extends AbstractFraudoTest {
public class CountTest extends AbstractPaymentTest {
@Before
public void init() {

View File

@ -2,7 +2,7 @@ package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.PaymentModel;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Before;
import org.junit.Test;
@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
public class CustomTest extends AbstractFraudoTest {
public class CustomTest extends AbstractPaymentTest {
public static final String TEST_GMAIL_RU = "test@gmail.ru";
@ -79,7 +79,7 @@ public class CustomTest extends AbstractFraudoTest {
public void inTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/in.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setEmail(TEST_GMAIL_RU);
ResultModel result = invoke(parseContext, model);
assertEquals(ResultStatus.ACCEPT, result.getResultStatus());
@ -91,7 +91,7 @@ public class CustomTest extends AbstractFraudoTest {
when(countryResolver.resolveCountry(any(), anyString())).thenReturn("RU");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
ResultModel result = invoke(parseContext, model);
assertEquals(ResultStatus.ACCEPT, result.getResultStatus());
}
@ -100,10 +100,15 @@ public class CustomTest extends AbstractFraudoTest {
public void amountTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/amount.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setAmount(56L);
model.setCurrency("RUB");
ResultModel result = invoke(parseContext, model);
assertEquals(ResultStatus.ACCEPT, result.getResultStatus());
model.setCurrency("USD");
result = invoke(parseContext, model);
assertEquals(ResultStatus.NORMAL, result.getResultStatus());
}
@Test
@ -119,7 +124,7 @@ public class CustomTest extends AbstractFraudoTest {
public void likeTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/like.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setEmail(TEST_GMAIL_RU);
model.setBin("553619");
model.setPan("9137");
@ -135,7 +140,7 @@ public class CustomTest extends AbstractFraudoTest {
public void inNotTest() throws Exception {
InputStream resourceAsStream = CustomTest.class.getResourceAsStream("/rules/in_not.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setEmail(TEST_GMAIL_RU);
ResultModel result = invoke(parseContext, model);
assertEquals(ResultStatus.NORMAL, result.getResultStatus());

View File

@ -1,8 +1,6 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Assert;
import org.junit.Before;
@ -14,7 +12,7 @@ import java.io.InputStream;
import static org.mockito.Matchers.*;
public class ListTest extends AbstractFraudoTest {
public class ListTest extends AbstractPaymentTest {
@Before
public void init() {
@ -25,13 +23,13 @@ public class ListTest extends AbstractFraudoTest {
public void whiteBlackListTest() throws Exception {
InputStream resourceAsStream = ListTest.class.getResourceAsStream("/rules/whitelist.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
Mockito.when(whiteListFinder.findInList(anyString(), anyString(), anyList(), anyList())).thenReturn(true);
Mockito.when(inListFinder.findInWhiteList(anyList(), anyObject())).thenReturn(true);
ResultModel result = invokeParse(parseContext);
Assert.assertEquals(ResultStatus.DECLINE, result.getResultStatus());
resourceAsStream = ListTest.class.getResourceAsStream("/rules/blacklist.frd");
parseContext = getParseContext(resourceAsStream);
Mockito.when(blackListFinder.findInList(anyString(), anyString(), anyList(), anyList())).thenReturn(true);
Mockito.when(inListFinder.findInBlackList(anyList(), anyObject())).thenReturn(true);
result = invokeParse(parseContext);
Assert.assertEquals(ResultStatus.NORMAL, result.getResultStatus());
Assert.assertEquals(1, result.getNotificationsRule().size());
@ -41,7 +39,16 @@ public class ListTest extends AbstractFraudoTest {
public void greyListTest() throws Exception {
InputStream resourceAsStream = ListTest.class.getResourceAsStream("/rules/greyList.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
Mockito.when(greyListFinder.findInList(anyString(), anyString(), anyList(), anyList())).thenReturn(true);
Mockito.when(inListFinder.findInGreyList(anyList(), anyObject())).thenReturn(true);
ResultModel result = invokeParse(parseContext);
Assert.assertEquals(ResultStatus.ACCEPT, result.getResultStatus());
}
@Test
public void namingListTest() throws Exception {
InputStream resourceAsStream = ListTest.class.getResourceAsStream("/rules/namingList.frd");
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
Mockito.when(inListFinder.findInList(anyString(), anyList(), anyObject())).thenReturn(true);
ResultModel result = invokeParse(parseContext);
Assert.assertEquals(ResultStatus.ACCEPT, result.getResultStatus());
}

View File

@ -0,0 +1,101 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.model.P2PModel;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
import java.io.InputStream;
import java.util.concurrent.CountDownLatch;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.when;
public class P2PTest extends AbstractP2PTest {
public static final long TIME_CALL_AGGR_FUNC = 200L;
public static final long MILLISTIME_FAST_FUNC = 10L;
public static final long TIME_CALLING = 200L;
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
@Test
public void timingTest() throws Exception {
InputStream resourceAsStream = P2PTest.class.getResourceAsStream("/rules/p2p_template.frd");
CountDownLatch countDownLatch = new CountDownLatch(1);
mockAggr(countDownLatch);
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
P2PModel model = new P2PModel();
model.setAmount(MILLISTIME_FAST_FUNC);
model.setBin("444443");
model.setCardTokenFrom("13213");
long start = System.currentTimeMillis();
ResultModel result = invoke(parseContext, model);
long executionTime = System.currentTimeMillis() - start;
assertEquals(ResultStatus.NORMAL, result.getResultStatus());
assertEquals(0, countDownLatch.getCount());
assertTrue(executionTime < TIME_CALL_AGGR_FUNC + 1 + TIME_CALLING);
System.out.println("executionTime=" + executionTime);
}
private void mockAggr(CountDownLatch countDownLatch) {
when(countAggregator.count(any(), any(), any(), any()))
.thenAnswer((Answer<Integer>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
countDownLatch.countDown();
return 1;
});
when(countAggregator.countSuccess(any(), any(), any(), any()))
.thenAnswer((Answer<Integer>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
countDownLatch.countDown();
return 1;
});
when(sumAggregator.sum(any(), any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
});
when(sumAggregator.sumSuccess(any(), any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
});
when(listFinder.findInBlackList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(listFinder.findInWhiteList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(listFinder.findInGreyList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(listFinder.findInList(anyString(), anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(countryResolver.resolveCountry(anyObject(), anyString()))
.thenAnswer((Answer<String>) invocationOnMock -> "RUS");
}
}

View File

@ -1,7 +1,7 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.PaymentModel;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Before;
import org.junit.Test;
@ -16,7 +16,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.when;
public class RealTimerTest extends AbstractFraudoTest {
public class RealTimerTest extends AbstractPaymentTest {
public static final long TIME_CALL_AGGR_FUNC = 200L;
public static final long MILLISTIME_FAST_FUNC = 10L;
@ -29,13 +29,13 @@ public class RealTimerTest extends AbstractFraudoTest {
@Test
public void timingTest() throws Exception {
InputStream resourceAsStream = RealTimerTest.class.getResourceAsStream("/rules/real_template.frd");
InputStream resourceAsStream = RealTimerTest.class.getResourceAsStream("/rules/payment_template.frd");
CountDownLatch countDownLatch = new CountDownLatch(1);
mockAggr(countDownLatch);
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setAmount(MILLISTIME_FAST_FUNC);
model.setBin("444443");
@ -57,7 +57,7 @@ public class RealTimerTest extends AbstractFraudoTest {
com.rbkmoney.fraudo.FraudoParser.ParseContext parseContext = getParseContext(resourceAsStream);
FraudModel model = new FraudModel();
PaymentModel model = new PaymentModel();
model.setAmount(MILLISTIME_FAST_FUNC);
model.setBin("444443");
@ -79,71 +79,40 @@ public class RealTimerTest extends AbstractFraudoTest {
countDownLatch.countDown();
return 1;
});
when(countAggregator.count(any(), any(), any()))
.thenAnswer((Answer<Integer>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
countDownLatch.countDown();
return 1;
});
when(countAggregator.countSuccess(any(), any(), any(), any()))
.thenAnswer((Answer<Integer>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
countDownLatch.countDown();
return 1;
});
when(countAggregator.countSuccess(any(), any(), any()))
.thenAnswer((Answer<Integer>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
countDownLatch.countDown();
return 1;
});
when(sumAggregator.sum(any(), any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
});
when(sumAggregator.sum(any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
});
when(sumAggregator.sumSuccess(any(), any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
});
when(sumAggregator.sumSuccess(any(), any(), any()))
.thenAnswer((Answer<Double>) invocationOnMock -> {
Thread.sleep(TIME_CALL_AGGR_FUNC);
return 10000.0;
when(inListFinder.findInWhiteList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(inListFinder.findInGreyList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(inListFinder.findInBlackList(anyList(), anyObject()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(whiteListFinder.findInList(anyString(), anyString(), anyList(), anyList()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(greyListFinder.findInList(anyString(), anyString(), anyList(), anyList()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(greyListFinder.findInList(anyString(), anyString(), anyObject(), anyString()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(blackListFinder.findInList(anyString(), anyString(), anyObject(), anyString()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(blackListFinder.findInList(anyString(), anyString(), anyList(), anyList()))
.thenAnswer((Answer<Boolean>) invocationOnMock -> {
Thread.sleep(MILLISTIME_FAST_FUNC);
return false;
});
when(countryResolver.resolveCountry(anyObject(), anyString()))
.thenAnswer((Answer<String>) invocationOnMock -> "RUS");
}

View File

@ -1,8 +1,6 @@
package com.rbkmoney.fraudo;
import com.rbkmoney.fraudo.constant.ResultStatus;
import com.rbkmoney.fraudo.exception.UnknownResultException;
import com.rbkmoney.fraudo.model.FraudModel;
import com.rbkmoney.fraudo.model.ResultModel;
import org.junit.Assert;
import org.junit.Before;
@ -14,7 +12,7 @@ import java.io.InputStream;
import static org.mockito.Matchers.*;
public class SumTest extends AbstractFraudoTest {
public class SumTest extends AbstractPaymentTest {
@Before
public void init() {

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<root level="warn">
<appender-ref ref="CONSOLE"/>
</root>
<logger name="com.rbkmoney" level="ALL"/>
</configuration>

View File

@ -1,2 +1,2 @@
rule: amount() < 100
rule: amount() < 100 AND currency() == "RUB"
-> accept;

View File

@ -0,0 +1,2 @@
rule: inList("test", "email")
-> accept;

View File

@ -0,0 +1,12 @@
rule:amount_limit70k:amount()>5000->decline;
rule:grey:inGreyList("card_token_from","email")->accept;
rule:white:inWhiteList("email","fingerprint","card_token_from","bin","ip")->accept;
rule:black:inBlackList("email","fingerprint","card_token_from","bin","ip")->decline;
rule:tur_bk:in("bin","444444") AND amount()<77000 ->accept;
rule:tur_bin2:in("bin","444444") AND count("card_token_from",1440,"party_id")<12->accept;
rule:bad_countries:in(countryBy("country_bank"),"AUS")->decline;
rule:amount_country801R:amount()>8100 AND in(countryBy("country_bank"),"HND")->decline;
rule:amount_country2100R:amount()>12000 AND in(countryBy("country_bank"),"RUS")->decline;
rule:amount_country3500R:amount()>31000 AND in(countryBy("country_bank"),"PER","BRA")->decline;
rule:tur_low:count("card_token_from",1440,"party_id")<21 AND amount()<33000 AND in(countryBy("country_bank"),"UZB")->accept;
rule:cards_test_count_3:unique("fingerprint","card_token_from",1440)>3 AND not in(countryBy("country_bank"),"UZB")->decline;