@Test
  public void testCompression() throws Exception {
    final String[] codecs = new String[] {null, "none", "gzip", "snappy"};

    byte[] ratherBigPayload = new byte[2048];
    Arrays.fill(ratherBigPayload, (byte) 65);
    Binder binder = getBinder();

    for (String codec : codecs) {
      DirectChannel moduleOutputChannel = new DirectChannel();
      QueueChannel moduleInputChannel = new QueueChannel();
      Properties props = new Properties();
      if (codec != null) {
        props.put(KafkaMessageChannelBinder.COMPRESSION_CODEC, codec);
      }
      binder.bindProducer("foo.0", moduleOutputChannel, props);
      binder.bindConsumer("foo.0", moduleInputChannel, null);
      Message<?> message =
          org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload)
              .build();
      // Let the consumer actually bind to the producer before sending a msg
      binderBindUnbindLatency();
      moduleOutputChannel.send(message);
      Message<?> inbound = moduleInputChannel.receive(2000);
      assertNotNull(inbound);
      assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
      binder.unbindProducers("foo.0");
      binder.unbindConsumers("foo.0");
    }
  }
  @Test
  public void testCustomPartitionCountOverridesPartitioningIfLarger() throws Exception {

    byte[] ratherBigPayload = new byte[2048];
    Arrays.fill(ratherBigPayload, (byte) 65);
    KafkaTestBinder binder = (KafkaTestBinder) getBinder();

    DirectChannel moduleOutputChannel = new DirectChannel();
    QueueChannel moduleInputChannel = new QueueChannel();
    Properties producerProperties = new Properties();
    producerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "5");
    producerProperties.put(BinderProperties.NEXT_MODULE_COUNT, "3");
    producerProperties.put(BinderProperties.PARTITION_KEY_EXPRESSION, "payload");
    Properties consumerProperties = new Properties();
    consumerProperties.put(BinderProperties.MIN_PARTITION_COUNT, "5");
    long uniqueBindingId = System.currentTimeMillis();
    binder.bindProducer("foo" + uniqueBindingId + ".0", moduleOutputChannel, producerProperties);
    binder.bindConsumer("foo" + uniqueBindingId + ".0", moduleInputChannel, consumerProperties);
    Message<?> message =
        org.springframework.integration.support.MessageBuilder.withPayload(ratherBigPayload)
            .build();
    // Let the consumer actually bind to the producer before sending a msg
    binderBindUnbindLatency();
    moduleOutputChannel.send(message);
    Message<?> inbound = moduleInputChannel.receive(2000);
    assertNotNull(inbound);
    assertArrayEquals(ratherBigPayload, (byte[]) inbound.getPayload());
    Collection<Partition> partitions =
        binder.getCoreBinder().getConnectionFactory().getPartitions("foo" + uniqueBindingId + ".0");
    assertThat(partitions, hasSize(5));
    binder.unbindProducers("foo" + uniqueBindingId + ".0");
    binder.unbindConsumers("foo" + uniqueBindingId + ".0");
  }
  @Test
  public void testXPathRouter() {
    // route to a channel determined by outcome of the xpath expression

    // Build the route
    DirectChannel inputChannel = new DirectChannel();
    inputChannel.setBeanName("input");
    XPathRouter router = new XPathRouter("//subject/text()");
    router.setEvaluateAsString(true);
    inputChannel.subscribe(router);
    QueueChannel testChannel = new QueueChannel();
    GenericApplicationContext context = new GenericApplicationContext();
    context.getBeanFactory().registerSingleton("testChannel", testChannel);

    router.setBeanFactory(context);
    context.refresh();

    // Create message
    Object correlationId = "123-ABC";
    String xmlSource = "<xml><subject>testChannel</subject></xml>";
    Message<String> message =
        MessageBuilder.withPayload(xmlSource).setCorrelationId(correlationId).build();

    // Send and receive message
    inputChannel.send(message);
    Message<?> reply = testChannel.receive(0);
    assertEquals(xmlSource, reply.getPayload());
  }
 @Test
 public void correlationIdCopiedFromMessageId() {
   Message<String> message = MessageBuilder.withPayload("test").build();
   DirectChannel inputChannel = new DirectChannel();
   QueueChannel outputChannel = new QueueChannel(1);
   DefaultMessageSplitter splitter = new DefaultMessageSplitter();
   splitter.setOutputChannel(outputChannel);
   EventDrivenConsumer endpoint = new EventDrivenConsumer(inputChannel, splitter);
   endpoint.start();
   assertTrue(inputChannel.send(message));
   Message<?> reply = outputChannel.receive(0);
   assertEquals(message.getHeaders().getId(), reply.getHeaders().getCorrelationId());
 }
  @Test
  public void testSendAndReceiveBad() throws Exception {
    MessageBus messageBus = getMessageBus();
    DirectChannel moduleOutputChannel = new DirectChannel();
    DirectChannel moduleInputChannel = new DirectChannel();
    messageBus.bindProducer("bad.0", moduleOutputChannel, null);
    messageBus.bindConsumer("bad.0", moduleInputChannel, null);
    Message<?> message =
        MessageBuilder.withPayload("bad").setHeader(MessageHeaders.CONTENT_TYPE, "foo/bar").build();
    final CountDownLatch latch = new CountDownLatch(3);
    moduleInputChannel.subscribe(
        new MessageHandler() {

          @Override
          public void handleMessage(Message<?> message) throws MessagingException {
            latch.countDown();
            throw new RuntimeException("bad");
          }
        });
    moduleOutputChannel.send(message);
    assertTrue(latch.await(10, TimeUnit.SECONDS));
    messageBus.unbindConsumers("bad.0");
    messageBus.unbindProducers("bad.0");
  }
  @SuppressWarnings("unchecked")
  @Test
  public void testBatchingAndCompression() throws Exception {
    RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
    MessageBus bus = getMessageBus();
    Properties properties = new Properties();
    properties.put("deliveryMode", "NON_PERSISTENT");
    properties.put("batchingEnabled", "true");
    properties.put("batchSize", "2");
    properties.put("batchBufferLimit", "100000");
    properties.put("batchTimeout", "30000");
    properties.put("compress", "true");

    DirectChannel output = new DirectChannel();
    output.setBeanName("batchingProducer");
    bus.bindProducer("batching.0", output, properties);

    while (template.receive("xdbus.batching.0") != null) {}

    Log logger =
        spy(
            TestUtils.getPropertyValue(
                bus, "messageBus.compressingPostProcessor.logger", Log.class));
    new DirectFieldAccessor(TestUtils.getPropertyValue(bus, "messageBus.compressingPostProcessor"))
        .setPropertyValue("logger", logger);
    when(logger.isTraceEnabled()).thenReturn(true);

    assertEquals(
        Deflater.BEST_SPEED,
        TestUtils.getPropertyValue(bus, "messageBus.compressingPostProcessor.level"));

    output.send(new GenericMessage<>("foo".getBytes()));
    output.send(new GenericMessage<>("bar".getBytes()));

    Object out = spyOn("batching.0").receive(false);
    assertThat(out, instanceOf(byte[].class));
    assertEquals(
        "\u0000\u0000\u0000\u0003foo\u0000\u0000\u0000\u0003bar", new String((byte[]) out));

    ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
    verify(logger).trace(captor.capture());
    assertThat(captor.getValue().toString(), containsString("Compressed 14 to "));

    QueueChannel input = new QueueChannel();
    input.setBeanName("batchingConsumer");
    bus.bindConsumer("batching.0", input, null);

    output.send(new GenericMessage<>("foo".getBytes()));
    output.send(new GenericMessage<>("bar".getBytes()));

    Message<byte[]> in = (Message<byte[]>) input.receive(10000);
    assertNotNull(in);
    assertEquals("foo", new String(in.getPayload()));
    in = (Message<byte[]>) input.receive(10000);
    assertNotNull(in);
    assertEquals("bar", new String(in.getPayload()));
    assertNull(in.getHeaders().get(AmqpHeaders.DELIVERY_MODE));

    bus.unbindProducers("batching.0");
    bus.unbindConsumers("batching.0");
  }
  @Test
  public void testAutoBindDLQPartioned() throws Exception {
    RabbitAdmin admin = new RabbitAdmin(this.rabbitAvailableRule.getResource());

    MessageBus bus = getMessageBus();
    Properties properties = new Properties();
    properties.put("prefix", "xdbustest.");
    properties.put("autoBindDLQ", "true");
    properties.put("maxAttempts", "1"); // disable retry
    properties.put("requeue", "false");
    properties.put("partitionIndex", "0");
    DirectChannel input0 = new DirectChannel();
    input0.setBeanName("test.input0DLQ");
    bus.bindConsumer("partDLQ.0", input0, properties);
    properties.put("partitionIndex", "1");
    DirectChannel input1 = new DirectChannel();
    input1.setBeanName("test.input1DLQ");
    bus.bindConsumer("partDLQ.0", input1, properties);

    properties.clear();
    properties.put("prefix", "xdbustest.");
    properties.put(
        "partitionKeyExtractorClass",
        "org.springframework.xd.dirt.integration.bus.PartitionTestSupport");
    properties.put(
        "partitionSelectorClass",
        "org.springframework.xd.dirt.integration.bus.PartitionTestSupport");
    properties.put(BusProperties.NEXT_MODULE_COUNT, "2");
    DirectChannel output = new DirectChannel();
    output.setBeanName("test.output");
    bus.bindProducer("partDLQ.0", output, properties);

    final CountDownLatch latch0 = new CountDownLatch(1);
    input0.subscribe(
        new MessageHandler() {

          @Override
          public void handleMessage(Message<?> message) throws MessagingException {
            if (latch0.getCount() <= 0) {
              throw new RuntimeException("dlq");
            }
            latch0.countDown();
          }
        });

    final CountDownLatch latch1 = new CountDownLatch(1);
    input1.subscribe(
        new MessageHandler() {

          @Override
          public void handleMessage(Message<?> message) throws MessagingException {
            if (latch1.getCount() <= 0) {
              throw new RuntimeException("dlq");
            }
            latch1.countDown();
          }
        });

    output.send(new GenericMessage<Integer>(1));
    assertTrue(latch1.await(10, TimeUnit.SECONDS));

    output.send(new GenericMessage<Integer>(0));
    assertTrue(latch0.await(10, TimeUnit.SECONDS));

    output.send(new GenericMessage<Integer>(1));

    RabbitTemplate template = new RabbitTemplate(this.rabbitAvailableRule.getResource());
    template.setReceiveTimeout(10000);

    String streamDLQName = "xdbustest.partDLQ.0.dlq";

    org.springframework.amqp.core.Message received = template.receive(streamDLQName);
    assertNotNull(received);
    assertEquals(1, received.getMessageProperties().getHeaders().get("partition"));

    output.send(new GenericMessage<Integer>(0));
    received = template.receive(streamDLQName);
    assertNotNull(received);
    assertEquals(0, received.getMessageProperties().getHeaders().get("partition"));

    admin.deleteQueue(streamDLQName);
    admin.deleteQueue("xdbustest.partDLQ.0-0");
    admin.deleteQueue("xdbustest.partDLQ.0-1");
    admin.deleteExchange("xdbustest.DLX");
  }