View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.transport.tcp.integration;
8   
9   import org.mule.DefaultMuleMessage;
10  import org.mule.api.MuleEventContext;
11  import org.mule.api.endpoint.InboundEndpoint;
12  import org.mule.module.client.MuleClient;
13  import org.mule.tck.functional.EventCallback;
14  import org.mule.tck.functional.FunctionalStreamingTestComponent;
15  import org.mule.tck.junit4.FunctionalTestCase;
16  
17  import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
18  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
19  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicReference;
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.junit.Test;
23  
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertNotNull;
26  import static org.junit.Assert.assertTrue;
27  
28  /**
29   * IMPORTANT - DO NOT RUN THIS TEST IN AN IDE WITH LOG LEVEL OF DEBUG. USE INFO TO
30   * SEE DIAGNOSTICS. OTHERWISE THE CONSOLE OUTPUT WILL BE SIMILAR SIZE TO DATA
31   * TRANSFERRED, CAUSING CONFUSNG AND PROBABLY FATAL MEMORY USE.
32   */
33  public abstract class AbstractStreamingCapacityTestCase extends FunctionalTestCase
34  {
35  
36      public static final long ONE_KB = 1024;
37      public static final long ONE_MB = ONE_KB * ONE_KB;
38      public static final long ONE_GB = ONE_KB * ONE_MB;
39      public static final int MESSAGES = 21;
40  
41      protected final Log logger = LogFactory.getLog(getClass());
42      private long size;
43     
44      public AbstractStreamingCapacityTestCase(long size)
45      {
46          this.size = size;
47      }
48  
49      @Test
50      public void testSend() throws Exception
51      {
52          final CountDownLatch latch = new CountDownLatch(1);
53          final AtomicReference message = new AtomicReference();
54  
55          EventCallback callback = new EventCallback()
56          {
57              public synchronized void eventReceived(MuleEventContext context, Object component)
58              {
59                  try
60                  {
61                      FunctionalStreamingTestComponent ftc = (FunctionalStreamingTestComponent) component;
62                      message.set(ftc.getSummary());
63                      latch.countDown();
64                  }
65                  catch (Exception e)
66                  {
67                      logger.error(e.getMessage(), e);
68                  }
69              }
70          };
71  
72          Object ftc = getComponent("testComponent");
73          assertTrue("FunctionalStreamingTestComponent expected",
74              ftc instanceof FunctionalStreamingTestComponent);
75          assertNotNull(ftc);
76          ((FunctionalStreamingTestComponent) ftc).setEventCallback(callback, size);
77  
78          Runtime runtime = Runtime.getRuntime();
79          runtime.gc(); // i know, i know...
80          long freeStart = runtime.freeMemory();
81          long maxStart = runtime.maxMemory();
82          long timeStart = System.currentTimeMillis();
83  
84          BigInputStream stream = new BigInputStream(size, MESSAGES);
85          MuleClient client = new MuleClient(muleContext);
86          // dynamically get the endpoint to send to
87          client.dispatch(
88              ((InboundEndpoint) client.getMuleContext().getRegistry().lookupObject("testInbound")).getAddress(),
89              new DefaultMuleMessage(stream, muleContext));
90  
91          // if we assume 1MB/sec then we need at least...
92          long pause = Math.max(size / ONE_MB, 60 * 10) + 10;
93          logger.info("Waiting for up to " + pause + " seconds");
94  
95          latch.await(pause, TimeUnit.SECONDS);
96          assertEquals(stream.summary(), message.get());
97  
98          // neither of these memory tests are really reliable, but if we stay with 1.4
99          // i don't
100         // know of anything better.
101         // if these fail in practice i guess we just remove them.
102         long freeEnd = runtime.freeMemory();
103         long delta = freeStart - freeEnd;
104         long timeEnd = System.currentTimeMillis();
105         double speed = size / (double) (timeEnd - timeStart) * 1000 / ONE_MB;
106         logger.info("Transfer speed " + speed + " MB/s (" + size + " B in " + (timeEnd - timeStart) + " ms)");
107 
108         double expectPercent = 10.5; // add a little more wiggle room than 10%, we have seen 10.0x% before
109         double usePercent = 100.0 * delta / size;
110         logger.info("Memory delta " + delta + " B = " + usePercent + "%");
111 
112         String assertMessage = String.format("Expected memory usage to be lower than %f%% but was %f%%",
113             Double.valueOf(expectPercent), Double.valueOf(usePercent));
114         assertTrue(assertMessage, usePercent < expectPercent);
115 
116         long maxEnd = runtime.maxMemory();
117         assertEquals("Max memory shifted", 0, maxEnd - maxStart);
118     }
119 }