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.issues;
8   
9   import org.mule.api.MuleMessage;
10  import org.mule.module.client.MuleClient;
11  import org.mule.tck.junit4.FunctionalTestCase;
12  import org.mule.tck.junit4.rule.DynamicPort;
13  import org.mule.transport.tcp.protocols.LengthProtocol;
14  
15  import java.io.BufferedInputStream;
16  import java.io.InputStream;
17  import java.net.InetSocketAddress;
18  import java.net.ServerSocket;
19  import java.net.Socket;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
24  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
25  import org.junit.Rule;
26  import org.junit.Test;
27  
28  import static org.junit.Assert.assertEquals;
29  
30  public class KeepSendSocketOpenMule1491TestCase extends FunctionalTestCase
31  {
32      
33      protected static String TEST_TCP_MESSAGE = "Test TCP Request";
34  
35      @Rule
36      public DynamicPort dynamicPort1 = new DynamicPort("port1");
37  
38      @Rule
39      public DynamicPort dynamicPort2 = new DynamicPort("port2");
40  
41      @Rule
42      public DynamicPort dynamicPort3 = new DynamicPort("port3");
43  
44      @Override
45      protected String getConfigResources()
46      {
47          return "tcp-keep-send-socket-open.xml";
48      }
49  
50      @Test
51      public void testSend() throws Exception
52      {
53          MuleClient client = new MuleClient(muleContext);
54          
55          Map<String, Object> props = new HashMap<String, Object>();
56          MuleMessage result = client.send("clientEndpoint", TEST_TCP_MESSAGE, props);
57          assertEquals(TEST_TCP_MESSAGE + " Received", result.getPayloadAsString());
58          
59          // try an extra message in case it's a problem on repeat
60          result = client.send("clientEndpoint", TEST_TCP_MESSAGE, props);
61          assertEquals(TEST_TCP_MESSAGE + " Received", result.getPayloadAsString());
62      }
63  
64      private void useServer(String endpoint, int port, int count) throws Exception
65      {
66          SimpleServerSocket server = new SimpleServerSocket(port);
67          try
68          {
69              new Thread(server).start();
70              MuleClient client = new MuleClient(muleContext);
71              client.send(endpoint, "Hello", null);
72              client.send(endpoint, "world", null);
73              assertEquals(count, server.getCount());
74          }
75          finally
76          {
77              server.close();
78          }
79      }
80  
81      @Test
82      public void testOpen() throws Exception
83      {
84          useServer("tcp://localhost:" + dynamicPort2.getNumber() + "?connector=openConnectorLength", dynamicPort2.getNumber(), 1);
85      }
86  
87      @Test
88      public void testClose() throws Exception
89      {
90          useServer("tcp://localhost:" + dynamicPort3.getNumber() + "?connector=closeConnectorLength", dynamicPort3.getNumber(), 2);
91      }
92  
93      @SuppressWarnings("synthetic-access")
94      private class SimpleServerSocket implements Runnable
95      { 
96          private ServerSocket server;
97          AtomicBoolean running = new AtomicBoolean(true);
98          AtomicInteger count = new AtomicInteger(0);
99  
100         public SimpleServerSocket(int port) throws Exception
101         {
102             server = new ServerSocket();
103             logger.debug("starting server");
104             server.bind(new InetSocketAddress("localhost", port), 3);
105         }
106 
107         public int getCount()
108         {
109             return count.get();
110         }
111 
112         public void run()
113         {
114             try
115             {
116                 LengthProtocol protocol = new LengthProtocol();
117                 while (true)
118                 {
119                     Socket socket = server.accept();
120                     logger.debug("have connection " + count);
121                     count.incrementAndGet();
122                     InputStream stream = new BufferedInputStream(socket.getInputStream());
123                     // repeat for as many messages as we receive until null received
124                     while (true)
125                     {
126                         Object read = protocol.read(stream);
127                         if (null == read)
128                         {
129                             break;
130                         }
131                         String msg = new String((byte[]) read);
132                         logger.debug("read: " + msg);
133                         logger.debug("writing reply");
134                         protocol.write(socket.getOutputStream(), "ok");
135                     }
136                 }
137             }
138             catch (Exception e)
139             {
140                 // an exception is expected during shutdown
141                 if (running.get())
142                 {
143                     throw new RuntimeException(e);
144                 }
145             }
146         }
147 
148         public void close()
149         {
150             try
151             {
152                 running.set(false);
153                 server.close();
154             }
155             catch (Exception e)
156             {
157                 // no-op
158             }
159         }
160     }
161 
162 }