diff --git a/src/dist/cfg/log4j2.xml b/src/dist/cfg/log4j2.xml index 226fec133..2cdcf89eb 100644 --- a/src/dist/cfg/log4j2.xml +++ b/src/dist/cfg/log4j2.xml @@ -512,6 +512,11 @@ + + + + diff --git a/src/main/kotlin/com/lykke/matching/engine/config/spring/DatabaseAccessorConfig.kt b/src/main/kotlin/com/lykke/matching/engine/config/spring/DatabaseAccessorConfig.kt index c2aa2e10a..180eea8e7 100644 --- a/src/main/kotlin/com/lykke/matching/engine/config/spring/DatabaseAccessorConfig.kt +++ b/src/main/kotlin/com/lykke/matching/engine/config/spring/DatabaseAccessorConfig.kt @@ -62,6 +62,11 @@ open class DatabaseAccessorConfig { open fun cashTransferPreprocessorPersistenceManager(cashTransferOperationsPreprocessorRedisConnection: Optional): PersistenceManager { return persistenceManagerFactory.get(cashTransferOperationsPreprocessorRedisConnection) } + + @Bean + open fun marketOrderPreprocessorPersistenceManager(marketOrderOrderPreprocessorRedisConnection: Optional): PersistenceManager { + return persistenceManagerFactory.get(marketOrderOrderPreprocessorRedisConnection) + } // diff --git a/src/main/kotlin/com/lykke/matching/engine/config/spring/LoggerConfig.kt b/src/main/kotlin/com/lykke/matching/engine/config/spring/LoggerConfig.kt index 1ba35d650..66f976edf 100644 --- a/src/main/kotlin/com/lykke/matching/engine/config/spring/LoggerConfig.kt +++ b/src/main/kotlin/com/lykke/matching/engine/config/spring/LoggerConfig.kt @@ -34,6 +34,11 @@ open class LoggerConfig { return LoggerFactory.getLogger("AppStarter") } + @Bean + open fun marketOrderPreProcessingLogger(): ThrottlingLogger { + return ThrottlingLogger.getLogger("MarketOrderPreProcessingLogger") + } + @Bean open fun singleLimitOrderPreProcessingLogger(): ThrottlingLogger { return ThrottlingLogger.getLogger("SingleLimitOrderPreProcessing") diff --git a/src/main/kotlin/com/lykke/matching/engine/config/spring/RedisConfig.kt b/src/main/kotlin/com/lykke/matching/engine/config/spring/RedisConfig.kt index 802f9f94f..1cf59ff95 100644 --- a/src/main/kotlin/com/lykke/matching/engine/config/spring/RedisConfig.kt +++ b/src/main/kotlin/com/lykke/matching/engine/config/spring/RedisConfig.kt @@ -67,6 +67,11 @@ open class RedisConfig { open fun cashTransferOperationsPreprocessorRedisConnection(): RedisConnection? { return redisConnectionFactory.getConnection("cashTransferOperationsPreprocessorRedisConnection") } + + @Bean + fun marketOrderOrderPreprocessorRedisConnection(): RedisConnection? { + return redisConnectionFactory.getConnection("marketOrderPreprocessorRedisConnection") + } // // diff --git a/src/main/kotlin/com/lykke/matching/engine/daos/MarketOrder.kt b/src/main/kotlin/com/lykke/matching/engine/daos/MarketOrder.kt index cfa506e65..4ceea9541 100644 --- a/src/main/kotlin/com/lykke/matching/engine/daos/MarketOrder.kt +++ b/src/main/kotlin/com/lykke/matching/engine/daos/MarketOrder.kt @@ -13,7 +13,7 @@ class MarketOrder(id: String, volume: BigDecimal, var price: BigDecimal?, status: String, - statusDate: Date, + statusDate: Date?, createdAt: Date, registered: Date?, var matchedAt: Date?, diff --git a/src/main/kotlin/com/lykke/matching/engine/daos/context/MarketOrderContext.kt b/src/main/kotlin/com/lykke/matching/engine/daos/context/MarketOrderContext.kt new file mode 100644 index 000000000..58cdc6a64 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/daos/context/MarketOrderContext.kt @@ -0,0 +1,19 @@ +package com.lykke.matching.engine.daos.context + +import com.lykke.matching.engine.daos.Asset +import com.lykke.matching.engine.daos.AssetPair +import com.lykke.matching.engine.daos.v2.FeeInstruction +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction +import com.lykke.matching.engine.deduplication.ProcessedMessage +import java.math.BigDecimal + +class MarketOrderContext(val messageId: String, + val assetPair: AssetPair?, + val baseAsset: Asset?, + val quotingAsset: Asset?, + val fee: FeeInstruction?, + val fees: List, + val marketPriceDeviationThreshold: BigDecimal?, + val processedMessage: ProcessedMessage, + val marketOrder: MarketOrder) \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/data/MarketOrderParsedData.kt b/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/data/MarketOrderParsedData.kt new file mode 100644 index 000000000..5f4f7ae49 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/data/MarketOrderParsedData.kt @@ -0,0 +1,5 @@ +package com.lykke.matching.engine.incoming.parsers.data + +import com.lykke.matching.engine.messages.MessageWrapper + +class MarketOrderParsedData(messageWrapper: MessageWrapper): ParsedData(messageWrapper) \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/impl/MarketOrderContextParser.kt b/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/impl/MarketOrderContextParser.kt new file mode 100644 index 000000000..75c91c2ec --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/incoming/parsers/impl/MarketOrderContextParser.kt @@ -0,0 +1,86 @@ +package com.lykke.matching.engine.incoming.parsers.impl + +import com.lykke.matching.engine.daos.AssetPair +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction +import com.lykke.matching.engine.daos.v2.FeeInstruction +import com.lykke.matching.engine.deduplication.ProcessedMessage +import com.lykke.matching.engine.fee.listOfFee +import com.lykke.matching.engine.holders.ApplicationSettingsHolder +import com.lykke.matching.engine.holders.AssetsPairsHolder +import com.lykke.matching.engine.holders.UUIDHolder +import com.lykke.matching.engine.incoming.parsers.ContextParser +import com.lykke.matching.engine.incoming.parsers.data.MarketOrderParsedData +import com.lykke.matching.engine.messages.MessageWrapper +import com.lykke.matching.engine.messages.ProtocolMessages +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.daos.context.MarketOrderContext +import com.lykke.matching.engine.holders.AssetsHolder +import org.springframework.stereotype.Component +import java.math.BigDecimal +import java.util.* + +@Component +class MarketOrderContextParser(private val assetsPairsHolder: AssetsPairsHolder, + private val assetsHolder: AssetsHolder, + private val uuidHolder: UUIDHolder, + private val applicationSettingsHolder: ApplicationSettingsHolder) : ContextParser { + override fun parse(messageWrapper: MessageWrapper): MarketOrderParsedData { + val protoMessage = parse(messageWrapper.byteArray) + + messageWrapper.messageId = if (protoMessage.hasMessageId()) protoMessage.messageId else protoMessage.uid + messageWrapper.timestamp = protoMessage.timestamp + messageWrapper.parsedMessage = protoMessage + messageWrapper.id = protoMessage.uid + val processedMessage = ProcessedMessage(messageWrapper.type, messageWrapper.timestamp!!, messageWrapper.messageId!!) + messageWrapper.processedMessage = processedMessage + + messageWrapper.context = getContext(messageWrapper.messageId!!, protoMessage, processedMessage) + + return MarketOrderParsedData(messageWrapper) + } + + private fun getContext(messageId: String, message: ProtocolMessages.MarketOrder, processedMessage: ProcessedMessage): MarketOrderContext { + val assetPair = assetsPairsHolder.getAssetPairAllowNulls(message.assetPairId) + val marketOrder = getMarketOrder(message) + return MarketOrderContext(messageId, + assetPair, + getBaseAsset(marketOrder, assetPair)?.let { assetsHolder.getAssetAllowNulls(it) }, + getQuotingAsset(marketOrder, assetPair)?.let { assetsHolder.getAssetAllowNulls(it) }, + getFeeInstruction(message), + getFeeInstructions(message), + assetPair?.marketOrderPriceDeviationThreshold + ?: applicationSettingsHolder.marketOrderPriceDeviationThreshold(message.assetPairId), + processedMessage, + marketOrder) + } + + private fun getMarketOrder(message: ProtocolMessages.MarketOrder): MarketOrder { + val feeInstruction = getFeeInstruction(message) + val feeInstructions = getFeeInstructions(message) + + return MarketOrder(uuidHolder.getNextValue(), message.uid, message.assetPairId, message.clientId, BigDecimal.valueOf(message.volume), null, + OrderStatus.Processing.name, null, Date(message.timestamp), null, null, message.straight, BigDecimal.valueOf(message.reservedLimitVolume), + feeInstruction, listOfFee(feeInstruction, feeInstructions)) + } + + private fun getFeeInstruction(message: ProtocolMessages.MarketOrder): FeeInstruction? { + return if (message.hasFee()) FeeInstruction.create(message.fee) else null + } + + private fun getFeeInstructions(message: ProtocolMessages.MarketOrder): List { + return NewFeeInstruction.create(message.feesList) + } + + private fun getBaseAsset(order: MarketOrder, assetPair: AssetPair?): String? { + return if (order.isStraight()) assetPair?.baseAssetId else assetPair?.quotingAssetId + } + + private fun getQuotingAsset(order: MarketOrder, assetPair: AssetPair?): String? { + return if (order.isStraight()) assetPair?.quotingAssetId else assetPair?.baseAssetId + } + + private fun parse(array: ByteArray): ProtocolMessages.MarketOrder { + return ProtocolMessages.MarketOrder.parseFrom(array) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessor.kt b/src/main/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessor.kt new file mode 100644 index 000000000..7b76dabb6 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessor.kt @@ -0,0 +1,138 @@ +package com.lykke.matching.engine.incoming.preprocessor.impl + +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.holders.MessageProcessingStatusHolder +import com.lykke.matching.engine.incoming.parsers.data.MarketOrderParsedData +import com.lykke.matching.engine.incoming.parsers.impl.MarketOrderContextParser +import com.lykke.matching.engine.incoming.preprocessor.AbstractMessagePreprocessor +import com.lykke.matching.engine.messages.MessageStatus +import com.lykke.matching.engine.messages.MessageWrapper +import com.lykke.matching.engine.daos.context.MarketOrderContext +import com.lykke.matching.engine.database.PersistenceManager +import com.lykke.matching.engine.database.common.entity.PersistenceData +import com.lykke.matching.engine.deduplication.ProcessedMessagesCache +import com.lykke.matching.engine.holders.MessageSequenceNumberHolder +import com.lykke.matching.engine.messages.MessageType +import com.lykke.matching.engine.messages.ProtocolMessages +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades +import com.lykke.matching.engine.outgoing.messages.v2.builders.EventFactory +import com.lykke.matching.engine.services.MessageSender +import com.lykke.matching.engine.services.validators.impl.OrderValidationException +import com.lykke.matching.engine.services.validators.input.MarketOrderInputValidator +import com.lykke.matching.engine.utils.order.MessageStatusUtils +import com.lykke.utils.logging.MetricsLogger +import com.lykke.utils.logging.ThrottlingLogger +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Qualifier +import org.springframework.stereotype.Component +import java.util.* +import java.util.concurrent.BlockingQueue + +@Component +class MarketOrderPreprocessor(marketOrderContextParser: MarketOrderContextParser, + preProcessedMessageQueue: BlockingQueue, + private val messageProcessingStatusHolder: MessageProcessingStatusHolder, + private val rabbitSwapQueue: BlockingQueue, + private val messageSender: MessageSender, + private val processedMessagesCache: ProcessedMessagesCache, + private val marketOrderPreprocessorPersistenceManager: PersistenceManager, + private val messageSequenceNumberHolder: MessageSequenceNumberHolder, + @Qualifier("marketOrderPreProcessingLogger") + private val logger: ThrottlingLogger) : + AbstractMessagePreprocessor(marketOrderContextParser, + messageProcessingStatusHolder, + preProcessedMessageQueue, + logger) { + + private companion object { + private val METRICS_LOGGER = MetricsLogger.getLogger() + } + + @Autowired + private lateinit var marketOrderInputValidator: MarketOrderInputValidator + + override fun preProcessParsedData(parsedData: MarketOrderParsedData): Boolean { + val marketOrderContext = parsedData.messageWrapper.context as MarketOrderContext + + if (messageProcessingStatusHolder.isTradeDisabled(marketOrderContext.assetPair)) { + writeResponse(parsedData.messageWrapper, MessageStatus.MESSAGE_PROCESSING_DISABLED) + return false + } + + if (!validateData(marketOrderContext, parsedData.messageWrapper)) { + return false + } + + return true + } + + private fun validateData(marketOrderContext: MarketOrderContext, messageWrapper: MessageWrapper): Boolean { + try { + marketOrderInputValidator.performValidation(marketOrderContext) + } catch (e: OrderValidationException) { + processInvalidData(messageWrapper, marketOrderContext, e.orderStatus, e.message) + return false + } + + return true + } + + private fun writeResponse(messageWrapper: MessageWrapper, order: MarketOrder, status: MessageStatus, reason: String? = null) { + val marketOrderResponse = ProtocolMessages.MarketOrderResponse.newBuilder() + .setStatus(status.type) + if (order.price != null) { + marketOrderResponse.price = order.price!!.toDouble() + } else if (reason != null) { + marketOrderResponse.statusReason = reason + } + messageWrapper.writeMarketOrderResponse(marketOrderResponse) + } + + private fun writeErrorResponse(messageWrapper: MessageWrapper, + order: MarketOrder, + statusReason: String? = null) { + writeResponse(messageWrapper, order, MessageStatusUtils.toMessageStatus(order.status), statusReason) + } + + fun processInvalidData(messageWrapper: MessageWrapper, + context: MarketOrderContext, + status: OrderStatus, + message: String) { + val marketOrder = context.marketOrder + marketOrder.updateStatus(status, Date()) + logger.info("Input validation failed messageId: ${context.messageId}, details: $message") + + + //todo: Should we send RMQ notification ? + sendErrorNotification(messageWrapper, context.marketOrder, Date()) + saveProcessedMessage(context) + + writeErrorResponse(messageWrapper, marketOrder, message) + } + + private fun saveProcessedMessage(context: MarketOrderContext) { + + val persistSuccess = marketOrderPreprocessorPersistenceManager.persist(PersistenceData(context.processedMessage)) + if (!persistSuccess) { + throw Exception("Persistence error") + } + + processedMessagesCache.addMessage(context.processedMessage) + } + + private fun sendErrorNotification(messageWrapper: MessageWrapper, + order: MarketOrder, + now: Date) { + order.register(Date()) + val marketOrderWithTrades = MarketOrderWithTrades(messageWrapper.messageId!!, order) + rabbitSwapQueue.put(marketOrderWithTrades) + val outgoingMessage = EventFactory.createExecutionEvent(messageSequenceNumberHolder.getNewValue(), + messageWrapper.messageId!!, + messageWrapper.id!!, + now, + MessageType.MARKET_ORDER, + marketOrderWithTrades) + messageSender.sendMessage(outgoingMessage) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/services/MarketOrderService.kt b/src/main/kotlin/com/lykke/matching/engine/services/MarketOrderService.kt index 047562794..ddd917602 100644 --- a/src/main/kotlin/com/lykke/matching/engine/services/MarketOrderService.kt +++ b/src/main/kotlin/com/lykke/matching/engine/services/MarketOrderService.kt @@ -2,9 +2,6 @@ package com.lykke.matching.engine.services import com.lykke.matching.engine.balance.BalanceException import com.lykke.matching.engine.daos.* -import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction -import com.lykke.matching.engine.fee.listOfFee -import com.lykke.matching.engine.holders.AssetsPairsHolder import com.lykke.matching.engine.matching.MatchingEngine import com.lykke.matching.engine.messages.MessageStatus import com.lykke.matching.engine.messages.MessageType @@ -19,31 +16,25 @@ import com.lykke.matching.engine.order.OrderStatus.LeadToNegativeSpread import com.lykke.matching.engine.order.OrderStatus.Matched import com.lykke.matching.engine.order.OrderStatus.NoLiquidity import com.lykke.matching.engine.order.OrderStatus.NotEnoughFunds -import com.lykke.matching.engine.order.OrderStatus.Processing import com.lykke.matching.engine.order.OrderStatus.ReservedVolumeGreaterThanBalance import com.lykke.matching.engine.order.OrderStatus.TooHighPriceDeviation import com.lykke.matching.engine.services.validators.impl.OrderValidationException import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades -import com.lykke.matching.engine.services.validators.MarketOrderValidator import com.lykke.matching.engine.utils.PrintUtils import com.lykke.matching.engine.utils.NumberUtils import com.lykke.matching.engine.utils.order.MessageStatusUtils -import com.lykke.matching.engine.daos.v2.FeeInstruction -import com.lykke.matching.engine.deduplication.ProcessedMessage -import com.lykke.matching.engine.holders.MessageProcessingStatusHolder -import com.lykke.matching.engine.holders.ApplicationSettingsHolder import com.lykke.matching.engine.holders.MessageSequenceNumberHolder -import com.lykke.matching.engine.holders.UUIDHolder import com.lykke.matching.engine.order.process.StopOrderBookProcessor import com.lykke.matching.engine.order.process.common.MatchingResultHandlingHelper import com.lykke.matching.engine.order.process.context.MarketOrderExecutionContext import com.lykke.matching.engine.order.transaction.ExecutionContextFactory import com.lykke.matching.engine.order.ExecutionDataApplyService +import com.lykke.matching.engine.daos.context.MarketOrderContext import com.lykke.matching.engine.outgoing.messages.v2.builders.EventFactory +import com.lykke.matching.engine.services.validators.business.MarketOrderBusinessValidator import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Service -import java.math.BigDecimal import java.util.Date import java.util.concurrent.BlockingQueue @@ -57,12 +48,8 @@ class MarketOrderService @Autowired constructor( private val genericLimitOrderService: GenericLimitOrderService, private val rabbitSwapQueue: BlockingQueue, private val messageSequenceNumberHolder: MessageSequenceNumberHolder, - private val messageSender: MessageSender, - private val assetsPairsHolder: AssetsPairsHolder, - private val marketOrderValidator: MarketOrderValidator, - private val applicationSettingsHolder: ApplicationSettingsHolder, - private val messageProcessingStatusHolder: MessageProcessingStatusHolder, - private val uuidHolder: UUIDHolder) : AbstractService { + private val marketOrderBusinessValidator: MarketOrderBusinessValidator, + private val messageSender: MessageSender) : AbstractService { companion object { private val LOGGER = LoggerFactory.getLogger(MarketOrderService::class.java.name) private val STATS_LOGGER = LoggerFactory.getLogger("${MarketOrderService::class.java.name}.stats") @@ -74,39 +61,25 @@ class MarketOrderService @Autowired constructor( override fun processMessage(messageWrapper: MessageWrapper) { val startTime = System.nanoTime() - if (messageWrapper.parsedMessage == null) { - parseMessage(messageWrapper) - } - - val parsedMessage = messageWrapper.parsedMessage!! as ProtocolMessages.MarketOrder - - val assetPair = assetsPairsHolder.getAssetPairAllowNulls(parsedMessage.assetPairId) - val now = Date() - val feeInstruction: FeeInstruction? - val feeInstructions: List? - if (messageProcessingStatusHolder.isTradeDisabled(assetPair)) { - writeResponse(messageWrapper, MessageStatus.MESSAGE_PROCESSING_DISABLED) - return - } + val context = messageWrapper.context as MarketOrderContext + val order = context.marketOrder + order.register(now) - feeInstruction = if (parsedMessage.hasFee()) FeeInstruction.create(parsedMessage.fee) else null - feeInstructions = NewFeeInstruction.create(parsedMessage.feesList) - LOGGER.debug("Got market order messageId: ${messageWrapper.messageId}, " + - "id: ${parsedMessage.uid}, client: ${parsedMessage.clientId}, " + - "asset: ${parsedMessage.assetPairId}, volume: ${NumberUtils.roundForPrint(parsedMessage.volume)}, " + - "straight: ${parsedMessage.straight}, fee: $feeInstruction, fees: $feeInstructions") + val assetPair = context.assetPair - val order = MarketOrder(uuidHolder.getNextValue(), parsedMessage.uid, parsedMessage.assetPairId, parsedMessage.clientId, BigDecimal.valueOf(parsedMessage.volume), null, - Processing.name, now, Date(parsedMessage.timestamp), now, null, parsedMessage.straight, BigDecimal.valueOf(parsedMessage.reservedLimitVolume), - feeInstruction, listOfFee(feeInstruction, feeInstructions)) + LOGGER.debug("Got market order messageId: ${messageWrapper.messageId}, " + + "id: ${messageWrapper.id}, client: ${order.clientId}, " + + "asset: ${order.assetPairId}, volume: ${NumberUtils.roundForPrint(order.volume)}, " + + "straight: ${order.straight}, fee: $order.fee, fees: ${order.fees}") try { - marketOrderValidator.performValidation(order, getOrderBook(order), feeInstruction, feeInstructions) + marketOrderBusinessValidator.performValidation(order) } catch (e: OrderValidationException) { order.updateStatus(e.orderStatus, now) sendErrorNotification(messageWrapper, order, now) + LOGGER.info("Business validation failed for order: $order") writeErrorResponse(messageWrapper, order, e.message) return } @@ -124,7 +97,7 @@ class MarketOrderService @Autowired constructor( val matchingResult = matchingEngine.match(order, getOrderBook(order), messageWrapper.messageId!!, - priceDeviationThreshold = assetPair.marketOrderPriceDeviationThreshold ?: applicationSettingsHolder.marketOrderPriceDeviationThreshold(assetPair.assetPairId), + priceDeviationThreshold = context.marketPriceDeviationThreshold, executionContext = executionContext) marketOrderExecutionContext.matchingResult = matchingResult @@ -218,11 +191,6 @@ class MarketOrderService @Autowired constructor( private fun getOrderBook(order: MarketOrder) = genericLimitOrderService.getOrderBook(order.assetPairId).getOrderBook(!order.isBuySide()) - - private fun parse(array: ByteArray): ProtocolMessages.MarketOrder { - return ProtocolMessages.MarketOrder.parseFrom(array) - } - private fun writePersistenceErrorResponse(messageWrapper: MessageWrapper, order: MarketOrder) { val message = "Unable to save result data" LOGGER.error("$order: $message") @@ -262,12 +230,7 @@ class MarketOrderService @Autowired constructor( } override fun parseMessage(messageWrapper: MessageWrapper) { - val message = parse(messageWrapper.byteArray) - messageWrapper.messageId = if (message.hasMessageId()) message.messageId else message.uid - messageWrapper.timestamp = message.timestamp - messageWrapper.parsedMessage = message - messageWrapper.id = message.uid - messageWrapper.processedMessage = ProcessedMessage(messageWrapper.type, messageWrapper.timestamp!!, messageWrapper.messageId!!) + //do nothing } override fun writeResponse(messageWrapper: MessageWrapper, status: MessageStatus) { diff --git a/src/main/kotlin/com/lykke/matching/engine/services/validators/business/MarketOrderBusinessValidator.kt b/src/main/kotlin/com/lykke/matching/engine/services/validators/business/MarketOrderBusinessValidator.kt new file mode 100644 index 000000000..0c12162c6 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/services/validators/business/MarketOrderBusinessValidator.kt @@ -0,0 +1,7 @@ +package com.lykke.matching.engine.services.validators.business + +import com.lykke.matching.engine.daos.MarketOrder + +interface MarketOrderBusinessValidator { + fun performValidation(order: MarketOrder) +} diff --git a/src/main/kotlin/com/lykke/matching/engine/services/validators/business/impl/MarketOrderBusinessValidatorImpl.kt b/src/main/kotlin/com/lykke/matching/engine/services/validators/business/impl/MarketOrderBusinessValidatorImpl.kt new file mode 100644 index 000000000..9a2db70a0 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/services/validators/business/impl/MarketOrderBusinessValidatorImpl.kt @@ -0,0 +1,21 @@ +package com.lykke.matching.engine.services.validators.business.impl + +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.services.GenericLimitOrderService +import com.lykke.matching.engine.services.validators.business.MarketOrderBusinessValidator +import com.lykke.matching.engine.services.validators.impl.OrderValidationException +import org.springframework.stereotype.Component + +@Component +class MarketOrderBusinessValidatorImpl(private val genericLimitOrderService: GenericLimitOrderService) : MarketOrderBusinessValidator { + override fun performValidation(order: MarketOrder) { + isOrderBookValid(order) + } + + private fun isOrderBookValid(order: MarketOrder) { + if (genericLimitOrderService.getOrderBook(order.assetPairId).getOrderBook(!order.isBuySide()).size == 0) { + throw OrderValidationException(OrderStatus.NoLiquidity) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/services/validators/impl/MarketOrderValidatorImpl.kt b/src/main/kotlin/com/lykke/matching/engine/services/validators/impl/MarketOrderValidatorImpl.kt deleted file mode 100644 index 9f030d0ce..000000000 --- a/src/main/kotlin/com/lykke/matching/engine/services/validators/impl/MarketOrderValidatorImpl.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.lykke.matching.engine.services.validators.impl - -import com.lykke.matching.engine.daos.v2.FeeInstruction -import com.lykke.matching.engine.daos.MarketOrder -import com.lykke.matching.engine.daos.LimitOrder -import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction -import com.lykke.matching.engine.fee.checkFee -import com.lykke.matching.engine.holders.ApplicationSettingsHolder -import com.lykke.matching.engine.holders.AssetsHolder -import com.lykke.matching.engine.holders.AssetsPairsHolder -import com.lykke.matching.engine.order.OrderStatus -import com.lykke.matching.engine.services.validators.MarketOrderValidator -import com.lykke.matching.engine.services.validators.common.OrderValidationUtils -import com.lykke.matching.engine.utils.NumberUtils -import org.slf4j.LoggerFactory -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.stereotype.Component -import java.math.BigDecimal -import java.util.concurrent.PriorityBlockingQueue - -@Component -class MarketOrderValidatorImpl -@Autowired constructor(private val assetsPairsHolder: AssetsPairsHolder, - private val assetsHolder: AssetsHolder, - private val applicationSettingsHolder: ApplicationSettingsHolder) : MarketOrderValidator { - - companion object { - private val LOGGER = LoggerFactory.getLogger(MarketOrderValidatorImpl::class.java.name) - } - - override fun performValidation(order: MarketOrder, orderBook: PriorityBlockingQueue, - feeInstruction: FeeInstruction?, feeInstructions: List?) { - isAssetKnown(order) - isAssetEnabled(order) - isVolumeValid(order) - isFeeValid(feeInstruction, feeInstructions, order) - isOrderBookValid(order, orderBook) - isVolumeAccuracyValid(order) - isPriceAccuracyValid(order) - } - - private fun isOrderBookValid(order: MarketOrder, orderBook: PriorityBlockingQueue) { - if (orderBook.size == 0) { - LOGGER.info("No liquidity, no orders in order book, for $order") - throw OrderValidationException(OrderStatus.NoLiquidity) - } - } - - private fun isFeeValid(feeInstruction: FeeInstruction?, feeInstructions: List?, order: MarketOrder) { - - if (!checkFee(feeInstruction, feeInstructions)) { - LOGGER.error("Invalid fee (order id: ${order.id}, order externalId: ${order.externalId})") - throw OrderValidationException(OrderStatus.InvalidFee) - } - } - - private fun isVolumeValid(order: MarketOrder) { - if (NumberUtils.equalsIgnoreScale(BigDecimal.ZERO, order.volume)) { - val message = "volume can not be equal to zero" - LOGGER.info(message) - throw OrderValidationException(OrderStatus.InvalidVolume, message) - } - - if (!OrderValidationUtils.checkMinVolume(order, assetsPairsHolder.getAssetPair(order.assetPairId))) { - LOGGER.info("Too small volume for $order") - throw OrderValidationException(OrderStatus.TooSmallVolume) - } - - val assetPair = getAssetPair(order) - if (order.isStraight() && assetPair.maxVolume != null && order.getAbsVolume() > assetPair.maxVolume) { - LOGGER.info("Too large volume for $order") - throw OrderValidationException(OrderStatus.InvalidVolume) - } - if (!order.isStraight() && assetPair.maxValue != null && order.getAbsVolume() > assetPair.maxValue) { - LOGGER.info("Too large value for $order") - throw OrderValidationException(OrderStatus.InvalidValue) - } - } - - private fun isAssetEnabled(order: MarketOrder) { - val assetPair = getAssetPair(order) - if (applicationSettingsHolder.isAssetDisabled(assetPair.baseAssetId) - || applicationSettingsHolder.isAssetDisabled(assetPair.quotingAssetId)) { - LOGGER.info("Disabled asset $order") - throw OrderValidationException(OrderStatus.DisabledAsset) - } - } - - private fun isAssetKnown(order: MarketOrder) { - try { - getAssetPair(order) - } catch (e: Exception) { - LOGGER.warn("Exception fetching asset", e) - LOGGER.info("Unknown asset: ${order.assetPairId}") - throw OrderValidationException(OrderStatus.UnknownAsset, order.assetPairId) - } - } - - private fun isVolumeAccuracyValid(order: MarketOrder) { - val baseAssetVolumeAccuracy = assetsHolder.getAsset(getBaseAsset(order)).accuracy - val volumeAccuracyValid = NumberUtils.isScaleSmallerOrEqual(order.volume, baseAssetVolumeAccuracy) - - if (!volumeAccuracyValid) { - LOGGER.info("Volume accuracy invalid form base assetId: $baseAssetVolumeAccuracy, volume: ${order.volume}") - throw OrderValidationException(OrderStatus.InvalidVolumeAccuracy) - } - } - - private fun isPriceAccuracyValid(order: MarketOrder) { - val price = order.price ?: return - - val priceAccuracyValid = NumberUtils.isScaleSmallerOrEqual(price, getAssetPair(order).accuracy) - - if (!priceAccuracyValid) { - LOGGER.info("Invalid order accuracy, ${order.assetPairId}, price: ${order.price}") - throw OrderValidationException(OrderStatus.InvalidPriceAccuracy) - } - } - - private fun getBaseAsset(order: MarketOrder): String { - val assetPair = getAssetPair(order) - return if (order.isStraight()) assetPair.baseAssetId else assetPair.quotingAssetId - } - - private fun getAssetPair(order: MarketOrder) = assetsPairsHolder.getAssetPair(order.assetPairId) -} \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/services/validators/input/MarketOrderInputValidator.kt b/src/main/kotlin/com/lykke/matching/engine/services/validators/input/MarketOrderInputValidator.kt new file mode 100644 index 000000000..5249ee4f0 --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/services/validators/input/MarketOrderInputValidator.kt @@ -0,0 +1,7 @@ +package com.lykke.matching.engine.services.validators.input + +import com.lykke.matching.engine.daos.context.MarketOrderContext + +interface MarketOrderInputValidator { + fun performValidation(marketOrderContext: MarketOrderContext) +} \ No newline at end of file diff --git a/src/main/kotlin/com/lykke/matching/engine/services/validators/input/impl/MarketOrderInputValidatorImpl.kt b/src/main/kotlin/com/lykke/matching/engine/services/validators/input/impl/MarketOrderInputValidatorImpl.kt new file mode 100644 index 000000000..fd7156c2c --- /dev/null +++ b/src/main/kotlin/com/lykke/matching/engine/services/validators/input/impl/MarketOrderInputValidatorImpl.kt @@ -0,0 +1,89 @@ +package com.lykke.matching.engine.services.validators.input.impl + +import com.lykke.matching.engine.daos.Asset +import com.lykke.matching.engine.daos.AssetPair +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.daos.context.MarketOrderContext +import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction +import com.lykke.matching.engine.daos.v2.FeeInstruction +import com.lykke.matching.engine.fee.checkFee +import com.lykke.matching.engine.holders.ApplicationSettingsHolder +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.services.validators.common.OrderValidationUtils +import com.lykke.matching.engine.services.validators.impl.OrderValidationException +import com.lykke.matching.engine.services.validators.input.MarketOrderInputValidator +import com.lykke.matching.engine.utils.NumberUtils +import org.springframework.stereotype.Component +import java.math.BigDecimal + +@Component +class MarketOrderInputValidatorImpl(private val applicationSettingsHolder: ApplicationSettingsHolder): MarketOrderInputValidator { + override fun performValidation(marketOrderContext: MarketOrderContext) { + val order = marketOrderContext.marketOrder + + val assetPair= marketOrderContext.assetPair + isAssetKnown(order, assetPair) + isAssetEnabled(order, assetPair!!) + isVolumeValid(order, assetPair) + isFeeValid(marketOrderContext.fee, marketOrderContext.fees, order) + isVolumeAccuracyValid(order, marketOrderContext.baseAsset!!) + isPriceAccuracyValid(order, assetPair) + } + + private fun isFeeValid(feeInstruction: FeeInstruction?, feeInstructions: List?, order: MarketOrder) { + if (!checkFee(feeInstruction, feeInstructions)) { + throw OrderValidationException(OrderStatus.InvalidFee, + "Invalid fee (order id: ${order.id}, order externalId: ${order.externalId})") + } + } + + private fun isVolumeValid(order: MarketOrder, assetPair: AssetPair) { + if (NumberUtils.equalsIgnoreScale(BigDecimal.ZERO, order.volume)) { + throw OrderValidationException(OrderStatus.InvalidVolume, "Volume can not be equal to zero") + } + + if (!OrderValidationUtils.checkMinVolume(order, assetPair)) { + throw OrderValidationException(OrderStatus.TooSmallVolume, "Too small volume for $order") + } + + if (order.isStraight() && assetPair.maxVolume != null && order.getAbsVolume() > assetPair.maxVolume) { + throw OrderValidationException(OrderStatus.InvalidVolume, "Too large volume for $order") + } + if (!order.isStraight() && assetPair.maxValue != null && order.getAbsVolume() > assetPair.maxValue) { + throw OrderValidationException(OrderStatus.InvalidValue, "Too large value for $order") + } + } + + private fun isAssetEnabled(order: MarketOrder, assetPair: AssetPair) { + if (applicationSettingsHolder.isAssetDisabled(assetPair.baseAssetId) + || applicationSettingsHolder.isAssetDisabled(assetPair.quotingAssetId)) { + throw OrderValidationException(OrderStatus.DisabledAsset, "Disabled asset $order") + } + } + + private fun isAssetKnown(order: MarketOrder, assetPair: AssetPair?) { + if (assetPair == null) { + throw OrderValidationException(OrderStatus.UnknownAsset, "Unknown asset: ${order.assetPairId}") + } + } + + private fun isVolumeAccuracyValid(order: MarketOrder, baseAsset: Asset) { + val baseAssetVolumeAccuracy = baseAsset.accuracy + val volumeAccuracyValid = NumberUtils.isScaleSmallerOrEqual(order.volume, baseAssetVolumeAccuracy) + + if (!volumeAccuracyValid) { + throw OrderValidationException(OrderStatus.InvalidVolumeAccuracy, + "Volume accuracy invalid form base assetId: $baseAssetVolumeAccuracy, volume: ${order.volume}") + } + } + + private fun isPriceAccuracyValid(order: MarketOrder, assetPair: AssetPair) { + val price = order.price ?: return + + val priceAccuracyValid = NumberUtils.isScaleSmallerOrEqual(price, assetPair.accuracy) + + if (!priceAccuracyValid) { + throw OrderValidationException(OrderStatus.InvalidPriceAccuracy, "Invalid order accuracy, ${order.assetPairId}, price: ${order.price}") + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/lykke/matching/engine/AbstractTest.kt b/src/test/kotlin/com/lykke/matching/engine/AbstractTest.kt index bb4f3f7d3..37ffad83d 100644 --- a/src/test/kotlin/com/lykke/matching/engine/AbstractTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/AbstractTest.kt @@ -18,6 +18,7 @@ import com.lykke.matching.engine.outgoing.messages.v2.events.common.BalanceUpdat import com.lykke.matching.engine.services.* import com.lykke.matching.engine.utils.NumberUtils import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent +import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.assertEquals import com.lykke.matching.engine.utils.order.MinVolumeOrderCanceller import org.junit.After @@ -144,6 +145,9 @@ abstract class AbstractTest { @Autowired protected lateinit var multiLimitOrderCancelService: MultiLimitOrderCancelService + @Autowired + protected lateinit var messageBuilder: MessageBuilder + protected open fun initServices() { testWalletDatabaseAccessor = balancesDatabaseAccessorsHolder.primaryAccessor as TestWalletDatabaseAccessor stopOrderDatabaseAccessor = stopOrdersDatabaseAccessorsHolder.primaryAccessor as TestStopOrderBookDatabaseAccessor diff --git a/src/test/kotlin/com/lykke/matching/engine/config/TestApplicationContext.kt b/src/test/kotlin/com/lykke/matching/engine/config/TestApplicationContext.kt index a85765a26..c0cc99648 100644 --- a/src/test/kotlin/com/lykke/matching/engine/config/TestApplicationContext.kt +++ b/src/test/kotlin/com/lykke/matching/engine/config/TestApplicationContext.kt @@ -21,6 +21,7 @@ import com.lykke.matching.engine.incoming.parsers.ContextParser import com.lykke.matching.engine.incoming.parsers.impl.* import com.lykke.matching.engine.incoming.preprocessor.impl.CashInOutPreprocessor import com.lykke.matching.engine.incoming.preprocessor.impl.CashTransferPreprocessor +import com.lykke.matching.engine.incoming.preprocessor.impl.MarketOrderPreprocessor import com.lykke.matching.engine.incoming.preprocessor.impl.SingleLimitOrderPreprocessor import com.lykke.matching.engine.matching.MatchingEngine import com.lykke.matching.engine.messages.MessageWrapper @@ -50,20 +51,20 @@ import com.lykke.matching.engine.services.MessageSender import com.lykke.matching.engine.services.MultiLimitOrderService import com.lykke.matching.engine.services.ReservedCashInOutOperationService import com.lykke.matching.engine.services.* -import com.lykke.matching.engine.services.validators.MarketOrderValidator import com.lykke.matching.engine.services.validators.ReservedCashInOutOperationValidator import com.lykke.matching.engine.services.validators.business.* import com.lykke.matching.engine.services.validators.business.impl.* -import com.lykke.matching.engine.services.validators.impl.MarketOrderValidatorImpl import com.lykke.matching.engine.services.validators.impl.ReservedCashInOutOperationValidatorImpl import com.lykke.matching.engine.services.validators.input.LimitOrderInputValidator import com.lykke.matching.engine.services.validators.input.CashInOutOperationInputValidator import com.lykke.matching.engine.services.validators.input.CashTransferOperationInputValidator import com.lykke.matching.engine.services.validators.input.LimitOrderCancelOperationInputValidator +import com.lykke.matching.engine.services.validators.input.MarketOrderInputValidator import com.lykke.matching.engine.services.validators.input.impl.CashInOutOperationInputValidatorImpl import com.lykke.matching.engine.services.validators.input.impl.CashTransferOperationInputValidatorImpl import com.lykke.matching.engine.services.validators.input.impl.LimitOrderInputValidatorImpl import com.lykke.matching.engine.services.validators.input.impl.LimitOrderCancelOperationInputValidatorImpl +import com.lykke.matching.engine.services.validators.input.impl.MarketOrderInputValidatorImpl import com.lykke.matching.engine.services.validators.settings.SettingValidator import com.lykke.matching.engine.services.validators.settings.impl.DisabledFunctionalitySettingValidator import com.lykke.matching.engine.services.validators.settings.impl.MessageProcessingSwitchSettingValidator @@ -279,12 +280,6 @@ open class TestApplicationContext { outgoingEventProcessor) } - @Bean - open fun marketOrderValidator(assetsPairsHolder: AssetsPairsHolder, - assetsHolder: AssetsHolder, - applicationSettingsHolder: ApplicationSettingsHolder): MarketOrderValidator { - return MarketOrderValidatorImpl(assetsPairsHolder, assetsHolder, applicationSettingsHolder) - } @Bean open fun assetPairsCache(testDictionariesDatabaseAccessor: DictionariesDatabaseAccessor, @@ -396,11 +391,10 @@ open class TestApplicationContext { executionDataApplyService: ExecutionDataApplyService, matchingResultHandlingHelper: MatchingResultHandlingHelper, genericLimitOrderService: GenericLimitOrderService, - assetsPairsHolder: AssetsPairsHolder, + marketOrderBusinessValidator: MarketOrderBusinessValidator, marketOrderWithTrades: BlockingQueue, messageSequenceNumberHolder: MessageSequenceNumberHolder, messageSender: MessageSender, - marketOrderValidator: MarketOrderValidator, applicationSettingsHolder: ApplicationSettingsHolder, messageProcessingStatusHolder: MessageProcessingStatusHolder, uuidHolder: UUIDHolder): MarketOrderService { @@ -412,12 +406,8 @@ open class TestApplicationContext { genericLimitOrderService, marketOrderWithTrades, messageSequenceNumberHolder, - messageSender, - assetsPairsHolder, - marketOrderValidator, - applicationSettingsHolder, - messageProcessingStatusHolder, - uuidHolder) + marketOrderBusinessValidator, + messageSender) } @Bean @@ -533,11 +523,42 @@ open class TestApplicationContext { ThrottlingLogger.getLogger("cashInOut")) } + @Bean + open fun marketOrderPreprocessor(marketOrderContextParser: MarketOrderContextParser, + preProcessedMessageQueue: BlockingQueue, + messageProcessingStatusHolder: MessageProcessingStatusHolder, + rabbitSwapQueue: BlockingQueue, + messageSender: MessageSender, + processedMessagesCache: ProcessedMessagesCache, + marketOrderPreprocessorPersistenceManager: PersistenceManager, + messageSequenceNumberHolder: MessageSequenceNumberHolder): MarketOrderPreprocessor { + return MarketOrderPreprocessor(marketOrderContextParser, + preProcessedMessageQueue, + messageProcessingStatusHolder, + rabbitSwapQueue, + messageSender, + processedMessagesCache, + marketOrderPreprocessorPersistenceManager, + messageSequenceNumberHolder, + ThrottlingLogger.getLogger("test")) + } + @Bean open fun cashTransferInitializer(assetsHolder: AssetsHolder, uuidHolder: UUIDHolder): CashTransferContextParser { return CashTransferContextParser(assetsHolder, uuidHolder) } + @Bean + open fun marketOrderContextParser(assetsPairsHolder: AssetsPairsHolder, + assetsHolder: AssetsHolder, + uuidHolder: UUIDHolder, + applicationSettingsHolder: ApplicationSettingsHolder): MarketOrderContextParser { + return MarketOrderContextParser(assetsPairsHolder, + assetsHolder, + uuidHolder, + applicationSettingsHolder) + } + @Bean open fun healthMonitor(): HealthMonitor { return Mockito.mock(HealthMonitor::class.java) { @@ -571,9 +592,10 @@ open class TestApplicationContext { cashInOutContextParser: CashInOutContextParser, singleLimitOrderContextParser: SingleLimitOrderContextParser, limitOrderCancelOperationContextParser: ContextParser, - limitOrderMassCancelOperationContextParser: ContextParser): MessageBuilder { + limitOrderMassCancelOperationContextParser: ContextParser, + marketOrderContextParser: MarketOrderContextParser): MessageBuilder { return MessageBuilder(singleLimitOrderContextParser, cashInOutContextParser, cashTransferContextParser, - limitOrderCancelOperationContextParser, limitOrderMassCancelOperationContextParser) + limitOrderCancelOperationContextParser, limitOrderMassCancelOperationContextParser, marketOrderContextParser) } @Bean @@ -613,6 +635,18 @@ open class TestApplicationContext { ThrottlingLogger.getLogger("limitOrder")) } + @Bean + open fun marketOrderInputValidator(assetsPairsHolder: AssetsPairsHolder, + assetsHolder: AssetsHolder, + applicationSettingsHolder: ApplicationSettingsHolder): MarketOrderInputValidator { + return MarketOrderInputValidatorImpl(applicationSettingsHolder) + } + + @Bean + open fun marketOrderBusinessValidator(genericLimitOrderService: GenericLimitOrderService): MarketOrderBusinessValidator { + return MarketOrderBusinessValidatorImpl(genericLimitOrderService) + } + @Bean open fun limitOrderInputValidator(applicationSettingsHolder: ApplicationSettingsHolder): LimitOrderInputValidator { return LimitOrderInputValidatorImpl(applicationSettingsHolder) diff --git a/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessorTest.kt b/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessorTest.kt new file mode 100644 index 000000000..72e10d79c --- /dev/null +++ b/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/MarketOrderPreprocessorTest.kt @@ -0,0 +1,91 @@ +package com.lykke.matching.engine.incoming.preprocessor.impl + +import com.lykke.matching.engine.AbstractTest +import com.lykke.matching.engine.config.TestApplicationContext +import com.lykke.matching.engine.daos.Asset +import com.lykke.matching.engine.daos.AssetPair +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades +import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderRejectReason +import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderType +import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent +import com.lykke.matching.engine.utils.MessageBuilder +import org.junit.Test +import org.junit.runner.RunWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.junit4.SpringRunner +import java.math.BigDecimal +import kotlin.test.assertEquals + +@RunWith(SpringRunner::class) +@SpringBootTest(classes = [(TestApplicationContext::class)]) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class MarketOrderPreprocessorTest: AbstractTest() { + + @Autowired + private lateinit var marketOrderPreprocessor: MarketOrderPreprocessor + + @Test + fun testValidateMessageIsPushedFromPreprocessorDataInvalid() { + testBackOfficeDatabaseAccessor.addAsset(Asset("USD", 2)) + testBackOfficeDatabaseAccessor.addAsset(Asset("EUR", 2)) + testDictionariesDatabaseAccessor.addAssetPair(AssetPair("EURUSD", "EUR", "USD", 5, BigDecimal.valueOf(0.1), BigDecimal.valueOf(0.2))) + initServices() + + marketOrderPreprocessor.preProcess(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 0.09))) + assertEquals(1, rabbitSwapListener.getCount()) + var marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades + assertEquals(OrderStatus.TooSmallVolume.name, marketOrderReport.order.status) + + var event = clientsEventsQueue.poll() as ExecutionEvent + var marketOrder = event.orders.single { it.orderType == OrderType.MARKET } + assertEquals(com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus.REJECTED, marketOrder.status) + assertEquals(OrderRejectReason.TOO_SMALL_VOLUME, marketOrder.rejectReason) + + //straight = false + marketOrderPreprocessor.preProcess(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = -0.19, straight = false))) + assertEquals(1, rabbitSwapListener.getCount()) + marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades + assertEquals(OrderStatus.TooSmallVolume.name, marketOrderReport.order.status) + + event = clientsEventsQueue.poll() as ExecutionEvent + marketOrder = event.orders.single { it.orderType == OrderType.MARKET } + assertEquals(com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus.REJECTED, marketOrder.status) + assertEquals(OrderRejectReason.TOO_SMALL_VOLUME, marketOrder.rejectReason) + } + + @Test + fun testNotStraightOrderMaxValue() { + testDictionariesDatabaseAccessor.addAssetPair(AssetPair("BTCUSD", "BTC", "USD", 8, + maxValue = BigDecimal.valueOf(10000))) + assetPairsCache.update() + + marketOrderPreprocessor.preProcess(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = 10001.0, straight = false))) + + assertEquals(1, clientsEventsQueue.size) + val event = clientsEventsQueue.poll() as ExecutionEvent + assertEquals(1, event.orders.size) + val eventOrder = event.orders.single() + assertEquals(com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus.REJECTED, eventOrder.status) + assertEquals(OrderRejectReason.INVALID_VALUE, eventOrder.rejectReason) + } + + @Test + fun testStraightOrderMaxVolume() { + testBalanceHolderWrapper.updateBalance("Client1", "BTC", 1.1) + testDictionariesDatabaseAccessor.addAssetPair(AssetPair("BTCUSD", "BTC", "USD", 8, + maxVolume = BigDecimal.valueOf(1.0))) + assetPairsCache.update() + + marketOrderPreprocessor.preProcess(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = -1.1))) + + assertEquals(1, clientsEventsQueue.size) + val event = clientsEventsQueue.poll() as ExecutionEvent + assertEquals(1, event.orders.size) + val eventOrder = event.orders.single() + assertEquals(com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus.REJECTED, eventOrder.status) + assertEquals(OrderRejectReason.INVALID_VOLUME, eventOrder.rejectReason) + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/SingleLimitOrderPreprocessorTest.kt b/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/SingleLimitOrderPreprocessorTest.kt index 9968730a0..8766f4f69 100644 --- a/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/SingleLimitOrderPreprocessorTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/incoming/preprocessor/impl/SingleLimitOrderPreprocessorTest.kt @@ -24,9 +24,6 @@ class SingleLimitOrderPreprocessorTest: AbstractTest() { @Autowired private lateinit var singleLimitOrderPreprocessor: SingleLimitOrderPreprocessor - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Test fun testOrderWithUnknownAssetPair() { val messageWrapper = messageBuilder.buildLimitOrderWrapper(MessageBuilder.buildLimitOrder(assetId = "UnknownAssetPair")) diff --git a/src/test/kotlin/com/lykke/matching/engine/performance/AbstractPerformanceTest.kt b/src/test/kotlin/com/lykke/matching/engine/performance/AbstractPerformanceTest.kt index 9224e5fb7..17c98c527 100644 --- a/src/test/kotlin/com/lykke/matching/engine/performance/AbstractPerformanceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/performance/AbstractPerformanceTest.kt @@ -25,6 +25,7 @@ import com.lykke.matching.engine.holders.StopOrdersDatabaseAccessorsHolder import com.lykke.matching.engine.holders.TestUUIDHolder import com.lykke.matching.engine.incoming.parsers.impl.LimitOrderCancelOperationContextParser import com.lykke.matching.engine.incoming.parsers.impl.LimitOrderMassCancelOperationContextParser +import com.lykke.matching.engine.incoming.parsers.impl.MarketOrderContextParser import com.lykke.matching.engine.matching.MatchingEngine import com.lykke.matching.engine.notification.BalanceUpdateHandlerTest import com.lykke.matching.engine.order.ExecutionDataApplyService @@ -49,8 +50,8 @@ import com.lykke.matching.engine.outgoing.senders.impl.SpecializedEventSendersHo import com.lykke.matching.engine.outgoing.senders.impl.OutgoingEventProcessorImpl import com.lykke.matching.engine.services.* import com.lykke.matching.engine.services.validators.business.impl.LimitOrderBusinessValidatorImpl +import com.lykke.matching.engine.services.validators.business.impl.MarketOrderBusinessValidatorImpl import com.lykke.matching.engine.services.validators.business.impl.StopOrderBusinessValidatorImpl -import com.lykke.matching.engine.services.validators.impl.MarketOrderValidatorImpl import com.lykke.matching.engine.services.validators.input.impl.LimitOrderInputValidatorImpl import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.utils.logging.ThrottlingLogger @@ -192,7 +193,8 @@ abstract class AbstractPerformanceTest { cashInOutContextParser, cashTransferContextParser, LimitOrderCancelOperationContextParser(), - LimitOrderMassCancelOperationContextParser()) + LimitOrderMassCancelOperationContextParser(), + MarketOrderContextParser(assetsPairsHolder, assetsHolder, uuidHolder, applicationSettingsHolder)) genericStopLimitOrderService = GenericStopLimitOrderService(stopOrdersDatabaseAccessorsHolder, expiryOrdersQueue) @@ -253,7 +255,7 @@ abstract class AbstractPerformanceTest { messageProcessingStatusHolder, uuidHolder) - val marketOrderValidator = MarketOrderValidatorImpl(assetsPairsHolder, assetsHolder, applicationSettingsHolder) + val marketOrderValidator = MarketOrderBusinessValidatorImpl(genericLimitOrderService) marketOrderService = MarketOrderService(matchingEngine, executionContextFactory, stopOrderBookProcessor, @@ -262,12 +264,8 @@ abstract class AbstractPerformanceTest { genericLimitOrderService, rabbitSwapQueue, messageSequenceNumberHolder, - messageSender, - assetsPairsHolder, marketOrderValidator, - applicationSettingsHolder, - messageProcessingStatusHolder, - uuidHolder) + messageSender) startEventProcessorThread(outgoingEventData, "OutgoingEventData") startEventProcessorThread(rabbitEventsQueue, "ExecutionEventProcessor") diff --git a/src/test/kotlin/com/lykke/matching/engine/performance/MarketOrderPerformanceTest.kt b/src/test/kotlin/com/lykke/matching/engine/performance/MarketOrderPerformanceTest.kt index 162dbe341..04dd84523 100644 --- a/src/test/kotlin/com/lykke/matching/engine/performance/MarketOrderPerformanceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/performance/MarketOrderPerformanceTest.kt @@ -53,7 +53,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { primaryOrdersDatabaseAccessor.addLimitOrder(MessageBuilder.buildLimitOrder(price = 1.5, volume = 1000.0, clientId = "Client1")) initServices() - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder())) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder())) } return counter.getAverageTime() } @@ -65,7 +65,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { primaryOrdersDatabaseAccessor.addLimitOrder(MessageBuilder.buildLimitOrder(price = 1.5, volume = 1000.0, clientId = "Client2")) initServices() - counter.executeAction {marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1000.0)))} + counter.executeAction {marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1000.0)))} return counter.getAverageTime() } @@ -77,7 +77,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { initServices() - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1500.0))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1500.0))) } return counter.getAverageTime() } @@ -90,7 +90,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client2", "USD", 1500.0) testBalanceHolderWrapper.updateBalance("Client3", "EUR", 2000.0) - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -2000.0))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -2000.0))) } return counter.getAverageTime() } @@ -100,7 +100,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { primaryOrdersDatabaseAccessor.addLimitOrder(MessageBuilder.buildLimitOrder(price = 1.5, volume = 1000.0, clientId = "Client3")) initServices() - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } return counter.getAverageTime() } @@ -113,9 +113,9 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { 5, BigDecimal.valueOf(0.1), BigDecimal.valueOf(0.2))) initServices() - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 0.09))) } - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = -0.19, straight = false))) } - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 0.2, straight = false))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 0.09))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = -0.19, straight = false))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 0.2, straight = false))) } return counter.getAverageTime() } @@ -130,7 +130,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 1000.0) - counter.executeAction {marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0)))} + counter.executeAction {marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0)))} return counter.getAverageTime() } @@ -145,7 +145,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 0.1) testBalanceHolderWrapper.updateBalance("Client4", "JPY", 100.0) - counter.executeAction {marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 10.0, straight = false)))} + counter.executeAction {marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 10.0, straight = false)))} return counter.getAverageTime() } @@ -157,8 +157,8 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { initServices() testBalanceHolderWrapper.updateBalance("Client3", "USD", 1500.0) - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) } return counter.getAverageTime() } @@ -173,7 +173,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client3", "USD", 150.0) testBalanceHolderWrapper.updateBalance("Client4", "EUR", 1000.0) - counter.executeAction {marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0)))} + counter.executeAction {marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0)))} return counter.getAverageTime() } @@ -191,7 +191,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client1", "SLR", 100000.0) testBalanceHolderWrapper.updateBalance("Client4", "BTC", 31.95294) - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "SLRBTC", volume = 25000.0, straight = true))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "SLRBTC", volume = 25000.0, straight = true))) } return counter.getAverageTime() } @@ -204,7 +204,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client3", "EUR", 500.0) testBalanceHolderWrapper.updateBalance("Client4", "USD", 750.0) - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -750.0, straight = false))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -750.0, straight = false))) } return counter.getAverageTime() } @@ -218,7 +218,7 @@ class MarketOrderPerformanceTest: AbstractPerformanceTest() { testBalanceHolderWrapper.updateBalance("Client3", "EUR", 3000.0) testBalanceHolderWrapper.updateBalance("Client4", "USD", 2000.0) - counter.executeAction { marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1490.0, straight = false))) } + counter.executeAction { marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1490.0, straight = false))) } return counter.getAverageTime() } } \ No newline at end of file diff --git a/src/test/kotlin/com/lykke/matching/engine/services/CashInOutOperationServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/CashInOutOperationServiceTest.kt index 1fc81a797..4679dbb2d 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/CashInOutOperationServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/CashInOutOperationServiceTest.kt @@ -20,7 +20,6 @@ import com.lykke.matching.engine.outgoing.messages.v2.enums.MessageType as Outgo import com.lykke.matching.engine.outgoing.messages.v2.events.CashInEvent import com.lykke.matching.engine.outgoing.messages.v2.events.CashOutEvent import com.lykke.matching.engine.outgoing.messages.v2.events.ReservedBalanceUpdateEvent -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildFeeInstruction import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildFeeInstructions import com.lykke.matching.engine.utils.assertEquals @@ -48,9 +47,6 @@ class CashInOutOperationServiceTest : AbstractTest() { @Autowired private lateinit var testReservedCashOperationListener: TestReservedCashOperationListener - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var reservedCashInOutOperationService: ReservedCashInOutOperationService diff --git a/src/test/kotlin/com/lykke/matching/engine/services/ClientMultiLimitOrderTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/ClientMultiLimitOrderTest.kt index fd4f9db1f..6508a9ed6 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/ClientMultiLimitOrderTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/ClientMultiLimitOrderTest.kt @@ -59,9 +59,6 @@ class ClientMultiLimitOrderTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var testSettingDatabaseAccessor: TestSettingsDatabaseAccessor diff --git a/src/test/kotlin/com/lykke/matching/engine/services/FeeTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/FeeTest.kt index 5e5b6875b..ca01b544a 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/FeeTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/FeeTest.kt @@ -12,10 +12,8 @@ import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderRejectReason import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus as OutgoingOrderStatus import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -27,7 +25,6 @@ import org.springframework.test.context.junit4.SpringRunner import java.math.BigDecimal import kotlin.test.assertEquals import com.lykke.matching.engine.utils.assertEquals -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.TestConfiguration import kotlin.test.assertNull @@ -36,9 +33,6 @@ import kotlin.test.assertNull @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class FeeTest: AbstractTest() { - @Autowired - private lateinit var messageBuilder: MessageBuilder - @TestConfiguration open class Config { @@ -220,7 +214,7 @@ class FeeTest: AbstractTest() { initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client2", assetId = "BTCUSD", volume = -0.005, fees = listOf( buildLimitOrderFeeInstruction( @@ -391,7 +385,7 @@ class FeeTest: AbstractTest() { balanceUpdateHandlerTest.clear() testClientLimitOrderListener.clear() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client1", assetId = "BTCUSD", volume = 0.05, fees = listOf(buildLimitOrderFeeInstruction( type = FeeType.CLIENT_FEE, @@ -422,7 +416,7 @@ class FeeTest: AbstractTest() { balanceUpdateHandlerTest.clear() testClientLimitOrderListener.clear() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client1", assetId = "BTCUSD", volume = -750.0, straight = false, fees = listOf(buildLimitOrderFeeInstruction( type = FeeType.CLIENT_FEE, diff --git a/src/test/kotlin/com/lykke/matching/engine/services/InvalidBalanceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/InvalidBalanceTest.kt index e127745f5..69fdc429d 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/InvalidBalanceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/InvalidBalanceTest.kt @@ -15,10 +15,8 @@ import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderRejectReason import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus as OutgoingOrderStatus import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderWrapper import org.junit.Before import org.junit.Test @@ -43,9 +41,6 @@ class InvalidBalanceTest : AbstractTest() { private lateinit var testSettingDatabaseAccessor: TestSettingsDatabaseAccessor - @Autowired - private lateinit var messageBuilder: MessageBuilder - @TestConfiguration open class Config { @@ -134,7 +129,7 @@ class InvalidBalanceTest : AbstractTest() { initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "ETHUSD", volume = 0.00001))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "ETHUSD", volume = 0.00001))) assertEquals(0, testTrustedClientsLimitOrderListener.getCount()) assertEquals(1, testClientLimitOrderListener.getCount()) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderCancelServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderCancelServiceTest.kt index 559306012..d5d726210 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderCancelServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderCancelServiceTest.kt @@ -46,9 +46,6 @@ class LimitOrderCancelServiceTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(uid = "5", price = 100.0)) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderMassCancelServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderMassCancelServiceTest.kt index c6e02012d..32217bcc4 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderMassCancelServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderMassCancelServiceTest.kt @@ -63,9 +63,6 @@ class LimitOrderMassCancelServiceTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { diff --git a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceDustTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceDustTest.kt index 6332a6c8b..141d4e1e0 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceDustTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceDustTest.kt @@ -56,9 +56,6 @@ class LimitOrderServiceDustTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testBalanceHolderWrapper.updateBalance("Client1", "BTC", 1000.0) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceTest.kt index 38f15c966..a0e881b8a 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/LimitOrderServiceTest.kt @@ -26,7 +26,6 @@ import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrderFeeInstruction import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.NumberUtils import com.lykke.matching.engine.utils.assertEquals import com.lykke.matching.engine.utils.getSetting @@ -73,9 +72,6 @@ class LimitOrderServiceTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var expiryOrdersQueue: ExpiryOrdersQueue @@ -751,7 +747,7 @@ class LimitOrderServiceTest : AbstractTest() { assertEquals(BigDecimal.valueOf(2000.0), testWalletDatabaseAccessor.getBalance("Client1", "USD")) assertEquals(BigDecimal.valueOf(1347.72), testWalletDatabaseAccessor.getReservedBalance("Client1", "USD")) - marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -10.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -10.0))) assertEquals(1, testClientLimitOrderListener.getCount()) result = testClientLimitOrderListener.getQueue().poll() as LimitOrdersReport @@ -1022,7 +1018,7 @@ class LimitOrderServiceTest : AbstractTest() { initServices() - marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 10.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 10.0))) assertEquals(1, rabbitSwapListener.getCount()) var marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -1044,7 +1040,7 @@ class LimitOrderServiceTest : AbstractTest() { clearMessageQueues() - marketOrderService.processMessage(MessageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 10.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(MessageBuilder.buildMarketOrder(volume = 10.0))) assertEquals(1, rabbitSwapListener.getCount()) marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -1423,7 +1419,7 @@ class LimitOrderServiceTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(assetId = "BTCUSD", price = 5000.0, volume = 0.01, clientId = "Client1"))) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = 50.01, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = 50.01, straight = false))) val result = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades assertEquals(2, result.trades.size) @@ -1455,7 +1451,7 @@ class LimitOrderServiceTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(assetId = "BTCUSD", price = 5000.0, volume = -0.01, clientId = "Client1"))) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -50.01, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -50.01, straight = false))) val result = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades assertEquals(0, result.trades.size) @@ -1518,13 +1514,13 @@ class LimitOrderServiceTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(uid = "order1", clientId = client, assetId = "BTCUSD", volume = -0.00947867, price = 10550.0))) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client2", assetId = "BTCUSD", volume = -100.0, straight = false ))) assertNotNull(testOrderDatabaseAccessor.getOrders("BTCUSD", false).firstOrNull { it.externalId == "order1" }) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client2", assetId = "BTCUSD", volume = -100.0, straight = false ))) assertBalance(client, "BTC", reserved = 0.0) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderServiceTest.kt index cf29e019e..0dab9cef9 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderServiceTest.kt @@ -10,7 +10,6 @@ import com.lykke.matching.engine.daos.fee.v2.NewLimitOrderFeeInstruction import com.lykke.matching.engine.daos.setting.AvailableSettingGroup import com.lykke.matching.engine.database.BackOfficeDatabaseAccessor import com.lykke.matching.engine.database.TestBackOfficeDatabaseAccessor -import com.lykke.matching.engine.database.TestSettingsDatabaseAccessor import com.lykke.matching.engine.deduplication.ProcessedMessage import com.lykke.matching.engine.messages.MessageType import com.lykke.matching.engine.order.OrderStatus @@ -24,16 +23,13 @@ import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderRejectReason import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderType import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.NumberUtils import com.lykke.matching.engine.utils.assertEquals import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean @@ -72,9 +68,6 @@ class MarketOrderServiceTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testDictionariesDatabaseAccessor.addAssetPair(AssetPair("EURUSD", "EUR", "USD", 5)) @@ -101,7 +94,7 @@ class MarketOrderServiceTest : AbstractTest() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(price = 526.531, volume = -0.5, clientId = "Client2", assetId = "ETHUSD")) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "ETHUSD", straight = false, volume = -401.9451))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "ETHUSD", straight = false, volume = -401.9451))) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades assertEquals(Matched.name, marketOrderReport.order.status) @@ -117,7 +110,7 @@ class MarketOrderServiceTest : AbstractTest() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(price = 1.5, volume = 1000.0, clientId = "Client1")) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder())) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder())) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -141,7 +134,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "EUR", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1000.0))) val result = testClientLimitOrderListener.getQueue().poll() as LimitOrdersReport assertEquals(2, result.orders.size) assertEquals(OrderStatus.Cancelled.name, result.orders.find { NumberUtils.equalsIgnoreScale(it.order.price, BigDecimal.valueOf(1.6)) }?.order?.status) @@ -159,7 +152,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "EUR", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1500.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -1500.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -178,7 +171,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "EUR", 2000.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -2000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "EURUSD", volume = -2000.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades assertEquals(NoLiquidity.name, marketOrderReport.order.status) @@ -196,7 +189,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 900.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades assertEquals(NotEnoughFunds.name, marketOrderReport.order.status) @@ -207,42 +200,7 @@ class MarketOrderServiceTest : AbstractTest() { assertEquals(OrderRejectReason.NOT_ENOUGH_FUNDS, marketOrder.rejectReason) } - @Test - fun testSmallVolume() { - testBackOfficeDatabaseAccessor.addAsset(Asset("USD", 2)) - testBackOfficeDatabaseAccessor.addAsset(Asset("EUR", 2)) - testDictionariesDatabaseAccessor.addAssetPair(AssetPair("EURUSD", "EUR", "USD", 5, BigDecimal.valueOf(0.1), BigDecimal.valueOf(0.2))) - initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(volume = 0.09))) - assertEquals(1, rabbitSwapListener.getCount()) - var marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades - assertEquals(TooSmallVolume.name, marketOrderReport.order.status) - - var event = clientsEventsQueue.poll() as ExecutionEvent - var marketOrder = event.orders.single { it.orderType == OrderType.MARKET } - assertEquals(OutgoingOrderStatus.REJECTED, marketOrder.status) - assertEquals(OrderRejectReason.TOO_SMALL_VOLUME, marketOrder.rejectReason) - - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(volume = -0.19, straight = false))) - assertEquals(1, rabbitSwapListener.getCount()) - marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades - assertEquals(TooSmallVolume.name, marketOrderReport.order.status) - - event = clientsEventsQueue.poll() as ExecutionEvent - marketOrder = event.orders.single { it.orderType == OrderType.MARKET } - assertEquals(OutgoingOrderStatus.REJECTED, marketOrder.status) - assertEquals(OrderRejectReason.TOO_SMALL_VOLUME, marketOrder.rejectReason) - - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(volume = 0.2, straight = false))) - assertEquals(1, rabbitSwapListener.getCount()) - marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades - assertTrue(TooSmallVolume.name != marketOrderReport.order.status) - - event = clientsEventsQueue.poll() as ExecutionEvent - marketOrder = event.orders.single { it.orderType == OrderType.MARKET } - assertTrue(OrderRejectReason.TOO_SMALL_VOLUME != marketOrder.rejectReason) - } @Test fun testMatchOneToOne() { @@ -254,7 +212,7 @@ class MarketOrderServiceTest : AbstractTest() { assertEquals(BigDecimal.valueOf(1500.0), testWalletDatabaseAccessor.getReservedBalance("Client3", "USD")) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -305,7 +263,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "JPY", 100.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 10.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 10.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -346,7 +304,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "USD", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) assertEquals(1, rabbitSwapListener.getCount()) var marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -362,7 +320,7 @@ class MarketOrderServiceTest : AbstractTest() { balancesHolder.updateBalance( ProcessedMessage(MessageType.CASH_IN_OUT_OPERATION.type, System.currentTimeMillis(), "test"), 0, "Client4", "EUR", BigDecimal.valueOf(1000.0)) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) assertEquals(1, rabbitSwapListener.getCount()) marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -393,7 +351,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 1000.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1000.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -434,7 +392,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 7500.02) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "LKKEUR", volume = 50000.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "LKKEUR", volume = 50000.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -464,7 +422,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 12.67565686) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCLKK", volume = 50000.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCLKK", volume = 50000.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -493,7 +451,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "GBP", 982.78) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "LKKGBP", volume = -982.78, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "LKKGBP", volume = -982.78, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -527,7 +485,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 31.95294) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC", volume = 25000.0, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC", volume = 25000.0, straight = true))) assertEquals(BigDecimal.valueOf(2.21816), testWalletDatabaseAccessor.getBalance("Client1", "BTC")) assertEquals(BigDecimal.valueOf(75000.0), testWalletDatabaseAccessor.getBalance("Client1", "SLR")) @@ -542,7 +500,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 0.00036983) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCCHF", volume = -0.00036983, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCCHF", volume = -0.00036983, straight = true))) assertEquals(BigDecimal.valueOf(0.00036983), testWalletDatabaseAccessor.getBalance("Client1", "BTC")) assertEquals(BigDecimal.valueOf(99999.71), testWalletDatabaseAccessor.getBalance("Client1", "CHF")) @@ -557,7 +515,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 750.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -750.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -750.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -587,7 +545,7 @@ class MarketOrderServiceTest : AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 2000.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1490.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1490.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -628,7 +586,7 @@ class MarketOrderServiceTest : AbstractTest() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(assetId = "BTCCHF", price = 4136.9, volume = -0.06450525, clientId = "Client1")) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "BTCCHF", volume = 0.3))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "BTCCHF", volume = 0.3))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -661,7 +619,7 @@ class MarketOrderServiceTest : AbstractTest() { initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) assertEquals(1, testOrderDatabaseAccessor.getOrders("EURUSD", true).size) @@ -706,7 +664,7 @@ class MarketOrderServiceTest : AbstractTest() { initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) assertBalance("Client1", "USD", 1000.0, 0.0) } @@ -722,7 +680,7 @@ class MarketOrderServiceTest : AbstractTest() { initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(assetId = "EURUSD", volume = -2.0, clientId = "Client2"))) assertEquals(1, balanceUpdateHandlerTest.balanceUpdateQueue.size) assertEquals(0, (balanceUpdateHandlerTest.balanceUpdateQueue.poll() as BalanceUpdate).balances.filter { it.id == "Client1" }.size) @@ -743,7 +701,7 @@ class MarketOrderServiceTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(assetId = "BTCEUR", price = 4999.0, volume = 0.01, clientId = "Client3"))) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCEUR", volume = -0.01000199))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCEUR", volume = -0.01000199))) assertEquals(1, clientsEventsQueue.size) val event = clientsEventsQueue.poll() as ExecutionEvent @@ -766,7 +724,7 @@ class MarketOrderServiceTest : AbstractTest() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(clientId = "Client2", assetId = "BTCUSD", volume = 1.0, price = 10001.0)) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = -1.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = -1.0))) assertEquals(1, clientsEventsQueue.size) val event = clientsEventsQueue.poll() as ExecutionEvent @@ -778,39 +736,6 @@ class MarketOrderServiceTest : AbstractTest() { assertOrderBookSize("BTCUSD", true, 1) } - @Test - fun testNotStraightOrderMaxValue() { - testDictionariesDatabaseAccessor.addAssetPair(AssetPair("BTCUSD", "BTC", "USD", 8, - maxValue = BigDecimal.valueOf(10000))) - assetPairsCache.update() - - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = 10001.0, straight = false))) - - assertEquals(1, clientsEventsQueue.size) - val event = clientsEventsQueue.poll() as ExecutionEvent - assertEquals(1, event.orders.size) - val eventOrder = event.orders.single() - assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) - assertEquals(OrderRejectReason.INVALID_VALUE, eventOrder.rejectReason) - } - - @Test - fun testStraightOrderMaxVolume() { - testBalanceHolderWrapper.updateBalance("Client1", "BTC", 1.1) - testDictionariesDatabaseAccessor.addAssetPair(AssetPair("BTCUSD", "BTC", "USD", 8, - maxVolume = BigDecimal.valueOf(1.0))) - assetPairsCache.update() - - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = -1.1))) - - assertEquals(1, clientsEventsQueue.size) - val event = clientsEventsQueue.poll() as ExecutionEvent - assertEquals(1, event.orders.size) - val eventOrder = event.orders.single() - assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) - assertEquals(OrderRejectReason.INVALID_VOLUME, eventOrder.rejectReason) - } - @Test fun testNotStraightOrderMaxVolume() { testBalanceHolderWrapper.updateBalance("Client1", "BTC", 1.1) @@ -821,7 +746,7 @@ class MarketOrderServiceTest : AbstractTest() { testOrderBookWrapper.addLimitOrder(buildLimitOrder(clientId = "Client2", assetId = "BTCUSD", volume = 1.1, price = 10000.0)) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = 11000.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = 11000.0, straight = false))) assertEquals(1, clientsEventsQueue.size) val event = clientsEventsQueue.poll() as ExecutionEvent @@ -842,7 +767,7 @@ class MarketOrderServiceTest : AbstractTest() { applicationSettingsCache.createOrUpdateSettingValue(AvailableSettingGroup.MO_PRICE_DEVIATION_THRESHOLD, "EURUSD", "0.0", true) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) var eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single() assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) assertEquals(OrderRejectReason.TOO_HIGH_PRICE_DEVIATION, eventOrder.rejectReason) @@ -851,7 +776,7 @@ class MarketOrderServiceTest : AbstractTest() { applicationSettingsCache.createOrUpdateSettingValue(AvailableSettingGroup.MO_PRICE_DEVIATION_THRESHOLD, "EURUSD", "0.04", true) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single() assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) assertEquals(OrderRejectReason.TOO_HIGH_PRICE_DEVIATION, eventOrder.rejectReason) @@ -863,7 +788,7 @@ class MarketOrderServiceTest : AbstractTest() { assetPairsCache.update() clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single() assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) assertEquals(OrderRejectReason.TOO_HIGH_PRICE_DEVIATION, eventOrder.rejectReason) @@ -874,7 +799,7 @@ class MarketOrderServiceTest : AbstractTest() { assetPairsCache.update() clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "EURUSD", volume = 2.0))) eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single { it.orderType == OrderType.MARKET } assertEquals(OutgoingOrderStatus.MATCHED, eventOrder.status) } @@ -888,7 +813,7 @@ class MarketOrderServiceTest : AbstractTest() { applicationSettingsCache.createOrUpdateSettingValue(AvailableSettingGroup.MO_PRICE_DEVIATION_THRESHOLD, "EURUSD", "0.0", true) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) var eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single() assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) assertEquals(OrderRejectReason.TOO_HIGH_PRICE_DEVIATION, eventOrder.rejectReason) @@ -896,7 +821,7 @@ class MarketOrderServiceTest : AbstractTest() { applicationSettingsCache.createOrUpdateSettingValue(AvailableSettingGroup.MO_PRICE_DEVIATION_THRESHOLD, "EURUSD", "0.04", true) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single() assertEquals(OutgoingOrderStatus.REJECTED, eventOrder.status) assertEquals(OrderRejectReason.TOO_HIGH_PRICE_DEVIATION, eventOrder.rejectReason) @@ -904,7 +829,7 @@ class MarketOrderServiceTest : AbstractTest() { applicationSettingsCache.createOrUpdateSettingValue(AvailableSettingGroup.MO_PRICE_DEVIATION_THRESHOLD, "EURUSD", "0.05", true) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client1", assetId = "EURUSD", volume = -2.0))) eventOrder = (clientsEventsQueue.single() as ExecutionEvent).orders.single { it.orderType == OrderType.MARKET } assertEquals(OutgoingOrderStatus.MATCHED, eventOrder.status) } @@ -922,7 +847,7 @@ class MarketOrderServiceTest : AbstractTest() { )) testOrderBookWrapper.addLimitOrder(buildLimitOrder(clientId = "Client1", assetId = "BTCUSD", volume = -0.1, price = 6000.0)) - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -1000.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -1000.0, straight = false))) assertEquals(1, clientsEventsQueue.size) val event = clientsEventsQueue.poll() as ExecutionEvent diff --git a/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderService_Dust_Test.kt b/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderService_Dust_Test.kt index b71b890fa..5b667d88c 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderService_Dust_Test.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/MarketOrderService_Dust_Test.kt @@ -14,7 +14,6 @@ import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderType import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -83,7 +82,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 0.020009) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -0.02))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -0.02))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -124,7 +123,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.14441494999999982) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 88.23, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 88.23, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -165,7 +164,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.033407) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 20.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 20.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -209,7 +208,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.00092519) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.54, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.54, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -253,7 +252,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 0.02001) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 20.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 20.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -294,7 +293,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.0000272, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.0000272, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -314,7 +313,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.01) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC1", volume = 127.87, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC1", volume = 127.87, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -350,7 +349,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.01) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC1", volume = -0.01, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "SLRBTC1", volume = -0.01, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -386,7 +385,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.02001) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.0000272, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.0000272, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -405,7 +404,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 0.02001) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1LKK", volume = 0.01, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1LKK", volume = 0.01, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -424,7 +423,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "LKK", 500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1LKK", volume = -0.01, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1LKK", volume = -0.01, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -443,7 +442,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "BTC1", 10.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.04997355, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.04997355, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -473,7 +472,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 10.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.04997355, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.04997355, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -503,7 +502,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client3", "BTC1", 10.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.0499727, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = 0.0499727, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -533,7 +532,7 @@ class MarketOrderService_Dust_Test: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC1", 10.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.0499727, straight = true))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTC1USD", volume = -0.0499727, straight = true))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades diff --git a/src/test/kotlin/com/lykke/matching/engine/services/MinRemainingVolumeTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/MinRemainingVolumeTest.kt index c421e9ab8..1cd3f0cba 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/MinRemainingVolumeTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/MinRemainingVolumeTest.kt @@ -12,16 +12,13 @@ import com.lykke.matching.engine.order.OrderStatus import com.lykke.matching.engine.outgoing.messages.LimitOrdersReport import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus as OutgoingOrderStatus import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderWrapper import com.lykke.matching.engine.utils.getSetting import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean @@ -59,9 +56,6 @@ class MinRemainingVolumeTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testBalanceHolderWrapper.updateBalance("Client1", "BTC", 1.0) @@ -137,7 +131,7 @@ class MinRemainingVolumeTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(clientId = "Client1", assetId = "BTCUSD", volume = 0.1, price = 6800.0))) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -0.2))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client2", assetId = "BTCUSD", volume = -0.2))) assertOrderBookSize("BTCUSD", true, 1) assertBalance("Client1", "USD", reserved = 680.0) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/MultiLimitOrderServiceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/MultiLimitOrderServiceTest.kt index 6782f05b7..21fc9405d 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/MultiLimitOrderServiceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/MultiLimitOrderServiceTest.kt @@ -73,9 +73,6 @@ class MultiLimitOrderServiceTest: AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var reservedVolumesRecalculator: ReservedVolumesRecalculator diff --git a/src/test/kotlin/com/lykke/matching/engine/services/NegativePriceTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/NegativePriceTest.kt index 40747e8a1..425401d42 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/NegativePriceTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/NegativePriceTest.kt @@ -47,9 +47,6 @@ class NegativePriceTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testBalanceHolderWrapper.updateBalance("Client", "USD", 1.0) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/OrderBookMaxSizeTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/OrderBookMaxSizeTest.kt index a1da0af2b..38d0e0775 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/OrderBookMaxSizeTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/OrderBookMaxSizeTest.kt @@ -14,15 +14,12 @@ import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderRejectReason import com.lykke.matching.engine.outgoing.messages.v2.enums.OrderStatus import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent import com.lykke.matching.engine.socket.TestClientHandler -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderWrapper import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean @@ -51,9 +48,6 @@ class OrderBookMaxSizeTest : AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { testBackOfficeDatabaseAccessor.addAsset(Asset("USD", 2)) @@ -168,7 +162,7 @@ class OrderBookMaxSizeTest : AbstractTest() { fun testMarketOrder() { setMaxSizeOrderBook() - val messageWrapper = buildMarketOrderWrapper( + val messageWrapper = messageBuilder.buildMarketOrderWrapper( buildMarketOrder(clientId = "Client1", assetId = "BTCUSD", volume = 0.1) ) marketOrderService.processMessage(messageWrapper) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/PersistenceErrorTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/PersistenceErrorTest.kt index de74331d8..caa523c61 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/PersistenceErrorTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/PersistenceErrorTest.kt @@ -9,10 +9,8 @@ import com.lykke.matching.engine.database.BackOfficeDatabaseAccessor import com.lykke.matching.engine.database.TestBackOfficeDatabaseAccessor import com.lykke.matching.engine.database.TestSettingsDatabaseAccessor import com.lykke.matching.engine.order.OrderStatus -import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderCancelWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderWrapper import com.lykke.matching.engine.utils.getSetting @@ -20,7 +18,6 @@ import org.junit.After import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean @@ -59,9 +56,6 @@ class PersistenceErrorTest : AbstractTest() { private val clientIds = listOf("Client1", "Client2", "Client3", "TrustedClient") - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Before fun setUp() { clientIds.forEach { clientId -> @@ -169,13 +163,13 @@ class PersistenceErrorTest : AbstractTest() { @Test fun testMarketOrder() { - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client2", assetId = "EURUSD", volume = -0.9 ))) assertMarketOrderResult() // Uncompleted limit order has min volume - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder( + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder( clientId = "Client2", assetId = "EURUSD", volume = -0.96 ))) assertMarketOrderResult() diff --git a/src/test/kotlin/com/lykke/matching/engine/services/RoundingTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/RoundingTest.kt index a6c41197b..9e7b02fb1 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/RoundingTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/RoundingTest.kt @@ -9,7 +9,6 @@ import com.lykke.matching.engine.order.OrderStatus import com.lykke.matching.engine.outgoing.messages.MarketOrderWithTrades import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -24,8 +23,6 @@ import kotlin.test.assertNotNull import com.lykke.matching.engine.utils.assertEquals import kotlin.test.assertEquals - - @RunWith(SpringRunner::class) @SpringBootTest(classes = [(TestApplicationContext::class), (RoundingTest.Config::class)]) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) @@ -67,7 +64,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = 1.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = 1.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -95,7 +92,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -123,7 +120,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = 1.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = 1.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -151,7 +148,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURUSD", volume = -1.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -179,7 +176,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "CHF", 1.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCCHF", volume = -0.38, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCCHF", volume = -0.38, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -207,7 +204,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 1.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 1.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -235,7 +232,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -1.0))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -1.0))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -263,7 +260,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 1.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = 1.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -291,7 +288,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "USD", 1500.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -1.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCUSD", volume = -1.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -321,7 +318,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "LKK", 50800.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCLKK", volume = -50800.0, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCLKK", volume = -50800.0, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -340,7 +337,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "EUR", 0.00999999999999999) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 1.16, straight = false))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "EURJPY", volume = 1.16, straight = false))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -354,7 +351,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 1.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCEUR", volume = -0.0001))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCEUR", volume = -0.0001))) assertEquals(1, rabbitSwapListener.getCount()) val marketOrderReport = rabbitSwapListener.getQueue().poll() as MarketOrderWithTrades @@ -382,7 +379,7 @@ class RoundingTest: AbstractTest() { testBalanceHolderWrapper.updateBalance("Client4", "BTC", 1.0) initServices() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCEUR", volume = -0.00043722))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client4", assetId = "BTCEUR", volume = -0.00043722))) val limitOrder = testOrderDatabaseAccessor.getOrders("BTCEUR", true).singleOrNull() assertNotNull(limitOrder) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/StopLimitOrderTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/StopLimitOrderTest.kt index ebaecfc79..c9a24d6b8 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/StopLimitOrderTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/StopLimitOrderTest.kt @@ -20,7 +20,6 @@ import com.lykke.matching.engine.outgoing.messages.v2.events.ExecutionEvent import com.lykke.matching.engine.utils.MessageBuilder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildLimitOrder import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrder -import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMarketOrderWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderCancelWrapper import com.lykke.matching.engine.utils.MessageBuilder.Companion.buildMultiLimitOrderWrapper import com.lykke.matching.engine.utils.assertEquals @@ -67,9 +66,6 @@ class StopLimitOrderTest : AbstractTest() { @Autowired private lateinit var testSettingsDatabaseAccessor: TestSettingsDatabaseAccessor - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var expiryOrdersQueue: ExpiryOrdersQueue @@ -414,7 +410,7 @@ class StopLimitOrderTest : AbstractTest() { singleLimitOrderService.processMessage(messageBuilder.buildLimitOrderWrapper(buildLimitOrder(clientId = "Client2", assetId = "BTCUSD", volume = -0.2, price = 10000.0, uid = "TwoTradesOrder"))) clearMessageQueues() - marketOrderService.processMessage(buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "BTCUSD", volume = 0.2))) + marketOrderService.processMessage(messageBuilder.buildMarketOrderWrapper(buildMarketOrder(clientId = "Client3", assetId = "BTCUSD", volume = 0.2))) assertStopOrderBookSize("BTCUSD", true, 0) assertOrderBookSize("BTCUSD", false, 1) diff --git a/src/test/kotlin/com/lykke/matching/engine/services/validator/business/MarketOrderBusinessValidatorTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/validator/business/MarketOrderBusinessValidatorTest.kt new file mode 100644 index 000000000..d0ab49259 --- /dev/null +++ b/src/test/kotlin/com/lykke/matching/engine/services/validator/business/MarketOrderBusinessValidatorTest.kt @@ -0,0 +1,83 @@ +package com.lykke.matching.engine.services.validator.business + +import com.lykke.matching.engine.config.TestApplicationContext +import com.lykke.matching.engine.daos.FeeType +import com.lykke.matching.engine.daos.LimitOrder +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction +import com.lykke.matching.engine.messages.ProtocolMessages +import com.lykke.matching.engine.order.OrderStatus +import com.lykke.matching.engine.services.AssetOrderBook +import com.lykke.matching.engine.services.validator.input.MarketOrderInputValidatorTest +import com.lykke.matching.engine.services.validators.business.MarketOrderBusinessValidator +import com.lykke.matching.engine.services.validators.impl.OrderValidationException +import org.junit.Test +import org.junit.runner.RunWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.junit4.SpringRunner +import java.math.BigDecimal +import java.util.* +import java.util.concurrent.PriorityBlockingQueue +import kotlin.test.assertEquals + +@RunWith(SpringRunner::class) +@SpringBootTest(classes = [(TestApplicationContext::class), (MarketOrderInputValidatorTest.Config::class)]) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) +class MarketOrderBusinessValidatorTest { + + @Autowired + private lateinit var marketOrderBusinessValidator: MarketOrderBusinessValidator + + @Test(expected = OrderValidationException::class) + fun invalidOrderBook() { + //given + val marketOrderBuilder = getDefaultMarketOrderBuilder() + val order = toMarketOrder(marketOrderBuilder.build()) + + //when + try { + marketOrderBusinessValidator.performValidation(order) + } catch (e: OrderValidationException) { + assertEquals(OrderStatus.NoLiquidity, e.orderStatus) + throw e + } + } + + private fun toMarketOrder(message: ProtocolMessages.MarketOrder): MarketOrder { + val now = Date() + return MarketOrder(UUID.randomUUID().toString(), message.uid, message.assetPairId, message.clientId, BigDecimal.valueOf(message.volume), null, + OrderStatus.Processing.name, now, Date(message.timestamp), now, null, message.straight, BigDecimal.valueOf(message.reservedLimitVolume), + NewFeeInstruction.create(message.fee), listOf(NewFeeInstruction.create(message.fee))) + } + + private fun getOrderBook(isBuy: Boolean): PriorityBlockingQueue { + val assetOrderBook = AssetOrderBook(MarketOrderInputValidatorTest.ASSET_PAIR_ID) + val now = Date() + assetOrderBook.addOrder(LimitOrder("test", "test", + MarketOrderInputValidatorTest.ASSET_PAIR_ID, MarketOrderInputValidatorTest.CLIENT_NAME, BigDecimal.valueOf(1.0), BigDecimal.valueOf(1.0), + OrderStatus.InOrderBook.name, now, now, now, BigDecimal.valueOf(1.0), now, BigDecimal.valueOf(1.0), + null, null, null, null, null, null, null, null, + null, null, null, null)) + + return assetOrderBook.getOrderBook(isBuy) + } + + private fun getDefaultMarketOrderBuilder(): ProtocolMessages.MarketOrder.Builder { + return ProtocolMessages.MarketOrder.newBuilder() + .setUid(MarketOrderInputValidatorTest.OPERATION_ID) + .setAssetPairId("EURUSD") + .setTimestamp(System.currentTimeMillis()) + .setClientId(MarketOrderInputValidatorTest.CLIENT_NAME) + .setVolume(1.0) + .setStraight(true) + .setFee(getFeeInstruction()) + } + + private fun getFeeInstruction(): ProtocolMessages.Fee { + return ProtocolMessages.Fee.newBuilder() + .setType(FeeType.NO_FEE.externalId) + .build() + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/lykke/matching/engine/services/validator/MarketOrderValidatorTest.kt b/src/test/kotlin/com/lykke/matching/engine/services/validator/input/MarketOrderInputValidatorTest.kt similarity index 65% rename from src/test/kotlin/com/lykke/matching/engine/services/validator/MarketOrderValidatorTest.kt rename to src/test/kotlin/com/lykke/matching/engine/services/validator/input/MarketOrderInputValidatorTest.kt index 8077327de..09c3152f2 100644 --- a/src/test/kotlin/com/lykke/matching/engine/services/validator/MarketOrderValidatorTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/services/validator/input/MarketOrderInputValidatorTest.kt @@ -1,18 +1,26 @@ -package com.lykke.matching.engine.services.validator +package com.lykke.matching.engine.services.validator.input +import com.lykke.matching.engine.AbstractTest import com.lykke.matching.engine.config.TestApplicationContext -import com.lykke.matching.engine.daos.* +import com.lykke.matching.engine.daos.Asset +import com.lykke.matching.engine.daos.AssetPair +import com.lykke.matching.engine.daos.FeeType +import com.lykke.matching.engine.daos.LimitOrder +import com.lykke.matching.engine.daos.MarketOrder +import com.lykke.matching.engine.daos.context.MarketOrderContext import com.lykke.matching.engine.daos.fee.v2.NewFeeInstruction import com.lykke.matching.engine.daos.setting.AvailableSettingGroup import com.lykke.matching.engine.database.BackOfficeDatabaseAccessor import com.lykke.matching.engine.database.TestBackOfficeDatabaseAccessor -import com.lykke.matching.engine.database.TestSettingsDatabaseAccessor import com.lykke.matching.engine.database.TestDictionariesDatabaseAccessor +import com.lykke.matching.engine.database.TestSettingsDatabaseAccessor +import com.lykke.matching.engine.holders.AssetsHolder +import com.lykke.matching.engine.holders.AssetsPairsHolder import com.lykke.matching.engine.messages.ProtocolMessages import com.lykke.matching.engine.order.OrderStatus -import com.lykke.matching.engine.services.validators.impl.OrderValidationException import com.lykke.matching.engine.services.AssetOrderBook -import com.lykke.matching.engine.services.validators.MarketOrderValidator +import com.lykke.matching.engine.services.validators.impl.OrderValidationException +import com.lykke.matching.engine.services.validators.input.MarketOrderInputValidator import com.lykke.matching.engine.utils.getSetting import org.junit.Test import org.junit.runner.RunWith @@ -29,10 +37,9 @@ import java.util.concurrent.PriorityBlockingQueue import kotlin.test.assertEquals @RunWith(SpringRunner::class) -@SpringBootTest(classes = [(TestApplicationContext::class), (MarketOrderValidatorTest.Config::class)]) +@SpringBootTest(classes = [(TestApplicationContext::class), (MarketOrderInputValidatorTest.Config::class)]) @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) -class MarketOrderValidatorTest { - +class MarketOrderInputValidatorTest: AbstractTest() { companion object { val CLIENT_NAME = "Client" val OPERATION_ID = "test" @@ -57,7 +64,7 @@ class MarketOrderValidatorTest { @Bean open fun testDictionariesDatabaseAccessor(): TestDictionariesDatabaseAccessor { val testDictionariesDatabaseAccessor = TestDictionariesDatabaseAccessor() - testDictionariesDatabaseAccessor.addAssetPair(AssetPair( ASSET_PAIR_ID, BASE_ASSET_ID, QUOTING_ASSET_ID, 2, BigDecimal.valueOf(0.9))) + testDictionariesDatabaseAccessor.addAssetPair(AssetPair(ASSET_PAIR_ID, BASE_ASSET_ID, QUOTING_ASSET_ID, 2, BigDecimal.valueOf(0.9))) return testDictionariesDatabaseAccessor } @@ -71,10 +78,13 @@ class MarketOrderValidatorTest { } @Autowired - private lateinit var marketOrderValidator: MarketOrderValidator + private lateinit var marketOrderInputValidator: MarketOrderInputValidator @Autowired - private lateinit var testDictionariesDatabaseAccessor: TestDictionariesDatabaseAccessor + private lateinit var assetsHolder: AssetsHolder + + @Autowired + private lateinit var assetsPairsHolder: AssetsPairsHolder @Test(expected = OrderValidationException::class) fun testUnknownAsset() { @@ -85,7 +95,7 @@ class MarketOrderValidatorTest { //when try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } catch (e: OrderValidationException) { assertEquals(OrderStatus.UnknownAsset, e.orderStatus) throw e @@ -98,11 +108,11 @@ class MarketOrderValidatorTest { val marketOrderBuilder = getDefaultMarketOrderBuilder() marketOrderBuilder.assetPairId = "BTCUSD" val order = toMarketOrder(marketOrderBuilder.build()) - testDictionariesDatabaseAccessor.addAssetPair(AssetPair( "BTCUSD", "BTC", "USD", 2)) + testDictionariesDatabaseAccessor.addAssetPair(AssetPair("BTCUSD", "BTC", "USD", 2)) //when try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } catch (e: OrderValidationException) { assertEquals(OrderStatus.DisabledAsset, e.orderStatus) throw e @@ -118,7 +128,7 @@ class MarketOrderValidatorTest { //when try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } catch (e: OrderValidationException) { assertEquals(OrderStatus.TooSmallVolume, e.orderStatus) throw e @@ -129,33 +139,17 @@ class MarketOrderValidatorTest { fun testInvalidFee() { //given val marketOrderBuilder = getDefaultMarketOrderBuilder() - val order = toMarketOrder(marketOrderBuilder.build()) + val order = toMarketOrder(marketOrderBuilder.build(), getInvalidFee()) //when try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), - NewFeeInstruction.create(getInvalidFee()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } catch (e: OrderValidationException) { assertEquals(OrderStatus.InvalidFee, e.orderStatus) throw e } } - @Test(expected = OrderValidationException::class) - fun invalidOrderBook() { - //given - val marketOrderBuilder = getDefaultMarketOrderBuilder() - val order = toMarketOrder(marketOrderBuilder.build()) - - //when - try { - marketOrderValidator.performValidation(order, AssetOrderBook(ASSET_PAIR_ID).getOrderBook(order.isBuySide()), - NewFeeInstruction.create(getFeeInstruction()), null) - } catch (e: OrderValidationException) { - assertEquals(OrderStatus.NoLiquidity, e.orderStatus) - throw e - } - } @Test(expected = OrderValidationException::class) fun testInvalidVolumeAccuracy() { @@ -166,29 +160,13 @@ class MarketOrderValidatorTest { //when try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } catch (e: OrderValidationException) { assertEquals(OrderStatus.InvalidVolumeAccuracy, e.orderStatus) throw e } } - @Test(expected = OrderValidationException::class) - fun testInvalidPriceAccuracy() { - //given - val marketOrderBuilder = getDefaultMarketOrderBuilder() - val order = toMarketOrder(marketOrderBuilder.build()) - order.price = BigDecimal.valueOf(1.1111) - - //when - try { - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) - } catch (e: OrderValidationException) { - assertEquals(OrderStatus.InvalidPriceAccuracy, e.orderStatus) - throw e - } - } - @Test fun testValidData() { //given @@ -196,28 +174,20 @@ class MarketOrderValidatorTest { val order = toMarketOrder(marketOrderBuilder.build()) //when - marketOrderValidator.performValidation(order, getOrderBook(order.isBuySide()), NewFeeInstruction.create(getFeeInstruction()), null) + marketOrderInputValidator.performValidation(getOrderContext(order)) } - private fun toMarketOrder(message: ProtocolMessages.MarketOrder): MarketOrder { + private fun getOrderContext(order: MarketOrder): MarketOrderContext { + return messageBuilder.buildMarketOrderWrapper(order).context as MarketOrderContext + } + + private fun toMarketOrder(message: ProtocolMessages.MarketOrder, fee: ProtocolMessages.Fee? = null): MarketOrder { val now = Date() return MarketOrder(UUID.randomUUID().toString(), message.uid, message.assetPairId, message.clientId, BigDecimal.valueOf(message.volume), null, OrderStatus.Processing.name, now, Date(message.timestamp), now, null, message.straight, BigDecimal.valueOf(message.reservedLimitVolume), - NewFeeInstruction.create(message.fee), listOf(NewFeeInstruction.create(message.fee))) + NewFeeInstruction.create(fee ?: message.fee), emptyList()) } - private fun getOrderBook(isBuy: Boolean): PriorityBlockingQueue { - val assetOrderBook = AssetOrderBook(ASSET_PAIR_ID) - val now = Date() - assetOrderBook.addOrder(LimitOrder("test", "test", - ASSET_PAIR_ID, CLIENT_NAME, BigDecimal.valueOf(1.0), BigDecimal.valueOf(1.0), - OrderStatus.InOrderBook.name, now, now, now, BigDecimal.valueOf(1.0), now, BigDecimal.valueOf(1.0), - null, null, null, null, null, null, null, null, - null, null, null, null)) - - return assetOrderBook.getOrderBook(isBuy) - } - private fun getDefaultMarketOrderBuilder(): ProtocolMessages.MarketOrder.Builder { return ProtocolMessages.MarketOrder.newBuilder() .setUid(OPERATION_ID) @@ -230,13 +200,13 @@ class MarketOrderValidatorTest { } private fun getFeeInstruction(): ProtocolMessages.Fee { - return ProtocolMessages.Fee.newBuilder() + return ProtocolMessages.Fee.newBuilder() .setType(FeeType.NO_FEE.externalId) .build() } private fun getInvalidFee(): ProtocolMessages.Fee { - return ProtocolMessages.Fee.newBuilder() + return ProtocolMessages.Fee.newBuilder() .setType(FeeType.EXTERNAL_FEE.externalId) .build() } diff --git a/src/test/kotlin/com/lykke/matching/engine/utils/MessageBuilder.kt b/src/test/kotlin/com/lykke/matching/engine/utils/MessageBuilder.kt index 56eefa4ff..b1594d0e0 100644 --- a/src/test/kotlin/com/lykke/matching/engine/utils/MessageBuilder.kt +++ b/src/test/kotlin/com/lykke/matching/engine/utils/MessageBuilder.kt @@ -13,6 +13,7 @@ import com.lykke.matching.engine.incoming.parsers.data.LimitOrderMassCancelOpera import com.lykke.matching.engine.incoming.parsers.ContextParser import com.lykke.matching.engine.incoming.parsers.impl.CashInOutContextParser import com.lykke.matching.engine.incoming.parsers.impl.CashTransferContextParser +import com.lykke.matching.engine.incoming.parsers.impl.MarketOrderContextParser import com.lykke.matching.engine.incoming.parsers.impl.SingleLimitOrderContextParser import com.lykke.matching.engine.messages.MessageType import com.lykke.matching.engine.messages.MessageWrapper @@ -28,8 +29,9 @@ class MessageBuilder(private var singleLimitOrderContextParser: SingleLimitOrder private val cashInOutContextParser: CashInOutContextParser, private val cashTransferContextParser: CashTransferContextParser, private val limitOrderCancelOperationContextParser: ContextParser, - private val limitOrderMassCancelOperationContextParser: ContextParser) { -companion object { + private val limitOrderMassCancelOperationContextParser: ContextParser, + private val marketOrderContextParser: MarketOrderContextParser) { + companion object { fun buildLimitOrder(uid: String = UUID.randomUUID().toString(), assetId: String = "EURUSD", clientId: String = "Client1", @@ -58,24 +60,6 @@ companion object { null, null) - fun buildMarketOrderWrapper(order: MarketOrder): MessageWrapper { - val builder = ProtocolMessages.MarketOrder.newBuilder() - .setUid(UUID.randomUUID().toString()) - .setTimestamp(order.createdAt.time) - .setClientId(order.clientId) - .setAssetPairId(order.assetPairId) - .setVolume(order.volume.toDouble()) - .setStraight(order.straight) - order.fee?.let { - builder.setFee(buildFee(it)) - } - order.fees?.forEach { - builder.addFees(buildFee(it)) - } - return MessageWrapper("Test", MessageType.MARKET_ORDER.type, builder - .build().toByteArray(), TestClientHandler() - ) - } fun buildFee(fee: FeeInstruction): ProtocolMessages.Fee { val builder = ProtocolMessages.Fee.newBuilder().setType(fee.type.externalId) @@ -204,9 +188,6 @@ companion object { return multiOrderBuilder.build() } - - - fun buildMultiLimitOrderCancelWrapper(clientId: String, assetPairId: String, isBuy: Boolean): MessageWrapper = MessageWrapper("Test", MessageType.MULTI_LIMIT_ORDER_CANCEL.type, ProtocolMessages.MultiLimitOrderCancel.newBuilder() .setUid(UUID.randomUUID().toString()) .setTimestamp(Date().time) @@ -273,6 +254,24 @@ companion object { } } + fun buildMarketOrderWrapper(order: MarketOrder): MessageWrapper { + val builder = ProtocolMessages.MarketOrder.newBuilder() + .setUid(UUID.randomUUID().toString()) + .setTimestamp(order.createdAt.time) + .setClientId(order.clientId) + .setAssetPairId(order.assetPairId) + .setVolume(order.volume.toDouble()) + .setStraight(order.straight) + order.fee?.let { + builder.setFee(buildFee(it)) + } + order.fees?.forEach { + builder.addFees(buildFee(it)) + } + return marketOrderContextParser.parse(MessageWrapper("Test", MessageType.MARKET_ORDER.type, builder + .build().toByteArray(), TestClientHandler())).messageWrapper + } + fun buildTransferWrapper(fromClientId: String, toClientId: String, assetId: String, diff --git a/src/test/kotlin/com/lykke/matching/engine/utils/order/AllOrdersCancellerTest.kt b/src/test/kotlin/com/lykke/matching/engine/utils/order/AllOrdersCancellerTest.kt index 575c4284c..7277b9bb8 100644 --- a/src/test/kotlin/com/lykke/matching/engine/utils/order/AllOrdersCancellerTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/utils/order/AllOrdersCancellerTest.kt @@ -57,9 +57,6 @@ class AllOrdersCancellerTest: AbstractTest() { } } - @Autowired - private lateinit var messageBuilder: MessageBuilder - @Autowired private lateinit var allOrdersCanceller: AllOrdersCanceller diff --git a/src/test/kotlin/com/lykke/matching/engine/utils/order/MinVolumeOrderCancellerTest.kt b/src/test/kotlin/com/lykke/matching/engine/utils/order/MinVolumeOrderCancellerTest.kt index 7cae40287..d32a820bb 100644 --- a/src/test/kotlin/com/lykke/matching/engine/utils/order/MinVolumeOrderCancellerTest.kt +++ b/src/test/kotlin/com/lykke/matching/engine/utils/order/MinVolumeOrderCancellerTest.kt @@ -36,9 +36,6 @@ import kotlin.test.assertNull @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) class MinVolumeOrderCancellerTest : AbstractTest() { - @Autowired - private lateinit var messageBuilder: MessageBuilder - @TestConfiguration open class Config {