1   /**
2    *  Copyright 2003-2007 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.distribution;
18  
19  import junit.framework.TestCase;
20  import net.sf.ehcache.AbstractCacheTest;
21  import net.sf.ehcache.Cache;
22  import net.sf.ehcache.CacheManager;
23  import net.sf.ehcache.Ehcache;
24  import net.sf.ehcache.Element;
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  
28  import java.net.SocketTimeoutException;
29  import java.rmi.RemoteException;
30  import java.rmi.UnmarshalException;
31  import java.util.ArrayList;
32  import java.util.Date;
33  import java.util.List;
34  
35  /**
36   * Unit tests for RMICachePeer
37   *
38   * Note these tests need a live network interface running in multicast mode to work
39   *
40   * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
41   * @version $Id: RMICacheManagerPeerTest.java 512 2007-07-10 09:18:45Z gregluck $
42   */
43  public class RMICacheManagerPeerTest extends TestCase {
44  
45      private static final Log LOG = LogFactory.getLog(RMICacheManagerPeerTest.class.getName());
46  
47  
48      /**
49       * manager
50       */
51      protected CacheManager manager;
52      private String hostName = "localhost";
53      private Integer port = new Integer(40000);
54      private RMICacheManagerPeerListener peerListener;
55      private Cache cache;
56  
57  
58      /**
59       * {@inheritDoc}
60       *
61       * @throws Exception
62       */
63      protected void setUp() throws Exception {
64          manager = CacheManager.create(AbstractCacheTest.TEST_CONFIG_DIR + "ehcache.xml");
65          cache = new Cache("test", 10, false, false, 10, 10);
66  
67          peerListener = new RMICacheManagerPeerListener(hostName, port, manager, new Integer(2000));
68      }
69  
70      /**
71       * Shutdown the cache
72       */
73      protected void tearDown() throws InterruptedException {
74          Thread.sleep(20);
75          if (peerListener != null) {
76              peerListener.dispose();
77          }
78          manager.shutdown();
79      }
80  
81  
82      /**
83       * Can we create the peer?
84       */
85      public void testCreatePeer() throws RemoteException {
86          for (int i = 0; i < 10; i++) {
87              new RMICachePeer(cache, hostName, port, new Integer(2000));
88          }
89      }
90  
91  
92      /**
93       * See if socket.setSoTimeout(socketTimeoutMillis) works. Should throw a SocketTimeoutException
94       *
95       * @throws RemoteException
96       */
97      public void testFailsIfTimeoutExceeded() throws Exception {
98  
99          RMICachePeer rmiCachePeer = new SlowRMICachePeer(cache, hostName, port, new Integer(1000));
100         peerListener.addCachePeer(cache.getName(), rmiCachePeer);
101         peerListener.init();
102         
103 
104 
105         try {
106             CachePeer cachePeer = new ManualRMICacheManagerPeerProvider().lookupRemoteCachePeer(rmiCachePeer.getUrl());
107             cachePeer.put(new Element("1", new Date()));
108             fail();
109         } catch (UnmarshalException e) {
110             assertEquals(SocketTimeoutException.class, e.getCause().getClass());
111         }
112     }
113 
114     /**
115      * See if socket.setSoTimeout(socketTimeoutMillis) works.
116      * Should not fail because the put takes less than the timeout.
117      *
118      * @throws RemoteException
119      */
120     public void testWorksIfTimeoutNotExceeded() throws Exception {
121 
122         cache = new Cache("test", 10, false, false, 10, 10);
123         RMICachePeer rmiCachePeer = new SlowRMICachePeer(cache, hostName, port, new Integer(2100));
124 
125         peerListener.addCachePeer(cache.getName(), rmiCachePeer);
126         peerListener.init();
127 
128         CachePeer cachePeer = new ManualRMICacheManagerPeerProvider().lookupRemoteCachePeer(rmiCachePeer.getUrl());
129         cachePeer.put(new Element("1", new Date()));
130     }
131 
132     /**
133      * Test send.
134      * <p/>
135      * This is a unit test because it was throwing AbstractMethodError if a method has changed signature,
136      * or NoSuchMethodError is a new one is added. The problem is that rmic needs
137      * to recompile the stub after any changes are made to the CachePeer source, something done by ant
138      * compile but not by the IDE.
139      */
140     public void testSend() throws Exception {
141 
142         cache = new Cache("test", 10, false, false, 10, 10);
143         RMICachePeer rmiCachePeer = new RMICachePeer(cache, hostName, port, new Integer(2100));
144         manager.addCache(cache);
145 
146         peerListener.addCachePeer(cache.getName(), rmiCachePeer);
147         peerListener.init();
148 
149         CachePeer cachePeer = new ManualRMICacheManagerPeerProvider().lookupRemoteCachePeer(rmiCachePeer.getUrl());
150         Element element = new Element("1", new Date());
151         EventMessage eventMessage = new EventMessage(EventMessage.PUT, null, element);
152         List eventMessages = new ArrayList();
153         eventMessages.add(eventMessage);
154         cachePeer.send(eventMessages);
155     }
156 
157 
158     /**
159      * RMICachePeer that breaks in lots of interesting ways.
160      */
161     class SlowRMICachePeer extends RMICachePeer {
162 
163         /**
164          * Constructor
165          * @param cache
166          * @param hostName
167          * @param port
168          * @param socketTimeoutMillis
169          * @throws RemoteException
170          */
171         public SlowRMICachePeer(Ehcache cache, String hostName, Integer port, Integer socketTimeoutMillis)
172                 throws RemoteException {
173             super(cache, hostName, port, socketTimeoutMillis);
174         }
175 
176         /**
177          * Puts an Element into the underlying cache without notifying listeners or updating statistics.
178          *
179          * @param element
180          * @throws java.rmi.RemoteException
181          * @throws IllegalArgumentException
182          * @throws IllegalStateException
183          */
184         public void put(Element element) throws RemoteException, IllegalArgumentException, IllegalStateException {
185             try {
186                 Thread.sleep(2000);
187             } catch (InterruptedException exception) {
188                 LOG.debug(exception.getMessage(), exception);
189             }
190         }
191     }
192 }