package com.github.fridujo.rabbitmq.mock; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; import com.rabbitmq.client.AMQP; import com.rabbitmq.client.Consumer; import com.rabbitmq.client.GetResponse; import com.rabbitmq.client.impl.AMQImpl; import com.github.fridujo.rabbitmq.mock.configuration.Configuration; import com.github.fridujo.rabbitmq.mock.exchange.MockDefaultExchange; import com.github.fridujo.rabbitmq.mock.exchange.MockExchange; import com.github.fridujo.rabbitmq.mock.exchange.MockExchangeFactory; public class MockNode implements ReceiverRegistry, TransactionalOperations { private final Configuration configuration = new Configuration(); private final MockExchangeFactory mockExchangeFactory = new MockExchangeFactory(configuration); private final MockDefaultExchange defaultExchange = new MockDefaultExchange(this); private final Map<String, MockExchange> exchanges = new ConcurrentHashMap<>(); private final Map<String, MockQueue> queues = new ConcurrentHashMap<>(); private final RandomStringGenerator consumerTagGenerator = new RandomStringGenerator( "amq.ctag-", "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 22); public MockNode() { exchanges.put(MockDefaultExchange.NAME, defaultExchange); } public boolean basicPublish(String exchangeName, String routingKey, boolean mandatory, boolean immediate, AMQP.BasicProperties props, byte[] body) { MockExchange exchange = getExchangeUnchecked(exchangeName); return exchange.publish(null, routingKey, props, body); } public String basicConsume(String queueName, boolean autoAck, String consumerTag, boolean noLocal, boolean exclusive, Map<String, Object> arguments, Consumer callback, Supplier<Long> deliveryTagSupplier, MockConnection mockConnection) { final String definitiveConsumerTag; if ("".equals(consumerTag)) { definitiveConsumerTag = consumerTagGenerator.generate(); } else { definitiveConsumerTag = consumerTag; } getQueueUnchecked(queueName).basicConsume(definitiveConsumerTag, callback, autoAck, deliveryTagSupplier, mockConnection); return definitiveConsumerTag; } public Optional<MockQueue> getQueue(String name) { return Optional.ofNullable(queues.get(name)); } public AMQP.Exchange.DeclareOk exchangeDeclare(String exchangeName, String type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments) { exchanges.putIfAbsent(exchangeName, mockExchangeFactory.build(exchangeName, type, new AmqArguments(arguments), this)); return new AMQImpl.Exchange.DeclareOk(); } public AMQP.Exchange.DeleteOk exchangeDelete(String exchange) { exchanges.remove(exchange); return new AMQImpl.Exchange.DeleteOk(); } public AMQP.Exchange.BindOk exchangeBind(String destinationName, String sourceName, String routingKey, Map<String, Object> arguments) { MockExchange source = getExchangeUnchecked(sourceName); MockExchange destination = getExchangeUnchecked(destinationName); source.bind(destination.pointer(), routingKey, arguments); return new AMQImpl.Exchange.BindOk(); } public AMQP.Exchange.UnbindOk exchangeUnbind(String destinationName, String sourceName, String routingKey, Map<String, Object> arguments) { MockExchange source = getExchangeUnchecked(sourceName); MockExchange destination = getExchangeUnchecked(destinationName); source.unbind(destination.pointer(), routingKey); return new AMQImpl.Exchange.UnbindOk(); } public AMQP.Queue.DeclareOk queueDeclare(String queueName, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments, MockChannel mockChannel) { queues.putIfAbsent(queueName, new MockQueue(queueName, new AmqArguments(arguments), this, mockChannel)); return new AMQP.Queue.DeclareOk.Builder() .queue(queueName) .build(); } public AMQP.Queue.DeleteOk queueDelete(String queueName, boolean ifUnused, boolean ifEmpty) { Optional<MockQueue> queue = Optional.ofNullable(queues.remove(queueName)); queue.ifPresent(MockQueue::notifyDeleted); return new AMQImpl.Queue.DeleteOk(queue.map(MockQueue::messageCount).orElse(0)); } public AMQP.Queue.BindOk queueBind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments) { MockExchange exchange = getExchangeUnchecked(exchangeName); MockQueue queue = getQueueUnchecked(queueName); exchange.bind(queue.pointer(), routingKey, arguments); return new AMQImpl.Queue.BindOk(); } public AMQP.Queue.UnbindOk queueUnbind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments) { MockExchange exchange = getExchangeUnchecked(exchangeName); MockQueue queue = getQueueUnchecked(queueName); exchange.unbind(queue.pointer(), routingKey); return new AMQImpl.Queue.UnbindOk(); } public AMQP.Queue.PurgeOk queuePurge(String queueName) { MockQueue queue = getQueueUnchecked(queueName); int messageCount = queue.purge(); return new AMQImpl.Queue.PurgeOk(messageCount); } public GetResponse basicGet(String queueName, boolean autoAck, Supplier<Long> deliveryTagSupplier) { MockQueue queue = getQueueUnchecked(queueName); return queue.basicGet(autoAck, deliveryTagSupplier); } public void basicAck(long deliveryTag, boolean multiple) { queues.values().forEach(q -> q.basicAck(deliveryTag, multiple)); } public void basicNack(long deliveryTag, boolean multiple, boolean requeue) { queues.values().forEach(q -> q.basicNack(deliveryTag, multiple, requeue)); } public void basicReject(long deliveryTag, boolean requeue) { queues.values().forEach(q -> q.basicReject(deliveryTag, requeue)); } public void basicCancel(String consumerTag) { queues.values().forEach(q -> q.basicCancel(consumerTag)); } public AMQP.Basic.RecoverOk basicRecover(boolean requeue) { queues.values().forEach(q -> q.basicRecover(requeue)); return new AMQImpl.Basic.RecoverOk(); } @Override public Optional<Receiver> getReceiver(ReceiverPointer receiverPointer) { final Optional<Receiver> receiver; if (receiverPointer.type == ReceiverPointer.Type.EXCHANGE) { receiver = Optional.ofNullable(exchanges.get(receiverPointer.name)); } else { receiver = Optional.ofNullable(queues.get(receiverPointer.name)); } return receiver; } private MockExchange getExchangeUnchecked(String exchangeName) { if (!exchanges.containsKey(exchangeName)) { throw new IllegalArgumentException("No exchange named " + exchangeName); } return exchanges.get(exchangeName); } private MockQueue getQueueUnchecked(String queueName) { if (!queues.containsKey(queueName)) { throw new IllegalArgumentException("No queue named " + queueName); } return queues.get(queueName); } Optional<MockExchange> getExchange(String name) { return Optional.ofNullable(exchanges.get(name)); } public int messageCount(String queueName) { MockQueue queue = getQueueUnchecked(queueName); return queue.messageCount(); } public long consumerCount(String queueName) { MockQueue queue = getQueueUnchecked(queueName); return queue.consumerCount(); } public MockNode restartDeliveryLoops() { queues.values().forEach(MockQueue::restartDeliveryLoop); return this; } public void close(MockConnection mockConnection) { queues.values().forEach(q -> q.close(mockConnection)); } public Configuration getConfiguration() { return configuration; } }