PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jgroups-2.10.0/tests/junit/org/jgroups/tests/ChannelTestBase.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 588 lines | 438 code | 91 blank | 59 comment | 58 complexity | 4cbe258103a10c8803aacfc8c59d222b MD5 | raw file
  1. package org.jgroups.tests;
  2. import org.jgroups.*;
  3. import org.jgroups.logging.Log;
  4. import org.jgroups.logging.LogFactory;
  5. import org.jgroups.protocols.BasicTCP;
  6. import org.jgroups.protocols.TCPPING;
  7. import org.jgroups.protocols.TP;
  8. import org.jgroups.protocols.UDP;
  9. import org.jgroups.protocols.pbcast.FLUSH;
  10. import org.jgroups.stack.Protocol;
  11. import org.jgroups.stack.ProtocolStack;
  12. import org.jgroups.stack.IpAddress;
  13. import org.jgroups.util.ResourceManager;
  14. import org.jgroups.util.Util;
  15. import org.jgroups.util.StackType;
  16. import org.testng.AssertJUnit;
  17. import org.testng.annotations.AfterClass;
  18. import org.testng.annotations.BeforeMethod;
  19. import org.testng.annotations.BeforeClass;
  20. import org.testng.annotations.Optional;
  21. import org.testng.annotations.Parameters;
  22. import org.testng.annotations.Test;
  23. import java.io.InputStream;
  24. import java.io.OutputStream;
  25. import java.lang.reflect.Field;
  26. import java.lang.reflect.Modifier;
  27. import java.net.InetAddress;
  28. import java.util.*;
  29. import java.util.concurrent.Semaphore;
  30. import java.util.concurrent.TimeUnit;
  31. import java.util.regex.Matcher;
  32. import java.util.regex.Pattern;
  33. /**
  34. * @author Bela Ban
  35. * @author Vladimir Blagojevic
  36. * @author <a href="mailto://brian.stansberry@jboss.com">Brian Stansberry</a>
  37. * @version $Id$
  38. */
  39. @Test(groups = "base", sequential = true)
  40. public class ChannelTestBase {
  41. protected String channel_conf = "udp.xml";
  42. protected boolean use_blocking = false;
  43. protected boolean use_flush = false;
  44. private String bind_addr = null;
  45. protected final Log log = LogFactory.getLog(this.getClass());
  46. @BeforeClass
  47. @Parameters(value = { "channel.conf", "use_blocking" })
  48. protected void initializeBase(@Optional("udp.xml") String chconf, @Optional("false") String use_blocking) throws Exception {
  49. Test annotation = this.getClass().getAnnotation(Test.class);
  50. // this should never ever happen!
  51. if (annotation == null)
  52. throw new Exception("Test is not marked with @Test annotation");
  53. StackType type=Util.getIpStackType();
  54. bind_addr=type == StackType.IPv6 ? "::1" : "127.0.0.1";
  55. List<String> groups = Arrays.asList(annotation.groups());
  56. boolean testRequiresFlush = groups.contains(Global.FLUSH);
  57. this.use_blocking = testRequiresFlush || Boolean.parseBoolean(use_blocking);
  58. this.use_flush = testRequiresFlush;
  59. this.channel_conf = chconf;
  60. boolean ignore_systemprops=Util.isBindAddressPropertyIgnored();
  61. bind_addr = Util.getProperty(new String[]{Global.BIND_ADDR, Global.BIND_ADDR_OLD}, null, "bind_addr",
  62. ignore_systemprops, bind_addr);
  63. // bind_addr = Util.getBindAddress(null).getHostAddress();
  64. }
  65. @BeforeMethod
  66. protected static void startTestHeader(java.lang.reflect.Method m) {
  67. System.out.println("\n================ Starting test " + m.getName()
  68. + " ================\n");
  69. }
  70. @AfterClass(alwaysRun = true)
  71. protected void nullifyInstanceFields() {
  72. for (Class<?> current = this.getClass(); current.getSuperclass() != null; current = current.getSuperclass()) {
  73. Field[] fields = current.getDeclaredFields();
  74. for (Field f : fields) {
  75. try {
  76. if (!Modifier.isStatic(f.getModifiers()) && !f.getDeclaringClass().isPrimitive()) {
  77. f.setAccessible(true);
  78. f.set(this, null);
  79. }
  80. } catch (Exception e) {
  81. }
  82. }
  83. }
  84. }
  85. protected String getBindAddress() {
  86. return bind_addr;
  87. }
  88. protected boolean useBlocking() {
  89. return use_blocking;
  90. }
  91. protected void setUseBlocking(boolean flag) {
  92. use_blocking = flag;
  93. }
  94. protected boolean useFlush() {
  95. return use_flush;
  96. }
  97. protected final static void assertTrue(boolean condition) {
  98. Util.assertTrue(condition);
  99. }
  100. protected final static void assertTrue(String message, boolean condition) {
  101. Util.assertTrue(message, condition);
  102. }
  103. protected final static void assertFalse(boolean condition) {
  104. Util.assertFalse(condition);
  105. }
  106. protected final static void assertFalse(String message, boolean condition) {
  107. Util.assertFalse(message, condition);
  108. }
  109. protected final static void assertEquals(String message, Object val1, Object val2) {
  110. Util.assertEquals(message, val1, val2);
  111. }
  112. protected final static void assertEquals(Object val1, Object val2) {
  113. Util.assertEquals(null, val1, val2);
  114. }
  115. protected final static void assertNotNull(String message, Object val) {
  116. Util.assertNotNull(message, val);
  117. }
  118. protected final static void assertNotNull(Object val) {
  119. Util.assertNotNull(null, val);
  120. }
  121. protected final static void assertNull(String message, Object val) {
  122. Util.assertNull(message, val);
  123. }
  124. protected final static void assertNull(Object val) {
  125. Util.assertNotNull(null, val);
  126. }
  127. /**
  128. * Creates a channel and modifies the configuration such that no other channel will able to join
  129. * this one even if they have the same cluster name (if unique = true). This is done by
  130. * modifying mcast_addr and mcast_port with UDP, and by changing TCP.start_port, TCP.port_range
  131. * and TCPPING.initial_hosts with TCP. Mainly used to run TestNG tests concurrently. Note that
  132. * MuxChannels are not currently supported.
  133. *
  134. * @param num
  135. * The number of channels we will create. Only important (for port_range) with TCP,
  136. * ignored by UDP
  137. * @return
  138. * @throws Exception
  139. */
  140. protected JChannel createChannel(boolean unique, int num) throws Exception {
  141. return (JChannel) new DefaultChannelTestFactory().createChannel(unique, num);
  142. }
  143. protected JChannel createChannel(boolean unique, int num, String name) throws Exception {
  144. JChannel ch=(JChannel)new DefaultChannelTestFactory().createChannel(unique, num);
  145. ch.setName(name);
  146. return ch;
  147. }
  148. protected JChannel createChannel() throws Exception {
  149. return new DefaultChannelTestFactory().createChannel();
  150. }
  151. protected JChannel createChannel(boolean unique) throws Exception {
  152. return createChannel(unique, 2);
  153. }
  154. protected JChannel createChannel(JChannel ch) throws Exception {
  155. return (JChannel) new DefaultChannelTestFactory().createChannel(ch);
  156. }
  157. protected JChannel createChannel(JChannel ch, String name) throws Exception {
  158. JChannel retval=(JChannel) new DefaultChannelTestFactory().createChannel(ch);
  159. retval.setName(name);
  160. return retval;
  161. }
  162. protected static String getUniqueClusterName() {
  163. return getUniqueClusterName(null);
  164. }
  165. protected static String getUniqueClusterName(String base_name) {
  166. return ResourceManager.getUniqueClusterName(base_name);
  167. }
  168. /**
  169. * Default channel factory used in junit tests
  170. */
  171. protected class DefaultChannelTestFactory {
  172. public JChannel createChannel() throws Exception {
  173. return createChannel(channel_conf);
  174. }
  175. public Channel createChannel(boolean unique, int num) throws Exception {
  176. JChannel c = createChannel(channel_conf);
  177. if (unique) {
  178. makeUnique(c, num);
  179. }
  180. if (log.isDebugEnabled()) {
  181. log.debug("Modifying channel resources:");
  182. logChannelResources(c);
  183. }
  184. return c;
  185. }
  186. public Channel createChannel(final JChannel ch) throws Exception {
  187. Map<Integer, Object> channelOptions = new HashMap<Integer, Object>();
  188. boolean useBlocking = (Boolean) ch.getOpt(Channel.BLOCK);
  189. channelOptions.put(Channel.BLOCK, useBlocking);
  190. log.info("Using configuration file " + channel_conf);
  191. JChannel retval = new JChannel(ch);
  192. for (Map.Entry<Integer, Object> entry : channelOptions.entrySet()) {
  193. Integer key = entry.getKey();
  194. Object value = entry.getValue();
  195. retval.setOpt(key, value);
  196. }
  197. if (useFlush())
  198. Util.addFlush(retval, new FLUSH());
  199. if (log.isDebugEnabled()) {
  200. log.debug("Creating cloned channel with resources:");
  201. logChannelResources(retval);
  202. }
  203. return retval;
  204. }
  205. private JChannel createChannel(String configFile) throws Exception {
  206. Map<Integer, Object> channelOptions = new HashMap<Integer, Object>();
  207. channelOptions.put(Channel.BLOCK, useBlocking());
  208. log.info("Using configuration file " + configFile);
  209. JChannel ch = new JChannel(configFile);
  210. for (Map.Entry<Integer, Object> entry : channelOptions.entrySet()) {
  211. Integer key = entry.getKey();
  212. Object value = entry.getValue();
  213. ch.setOpt(key, value);
  214. }
  215. if (useFlush())
  216. Util.addFlush(ch, new FLUSH());
  217. if (log.isDebugEnabled()) {
  218. log.debug("Creating channel with resources:");
  219. logChannelResources(ch);
  220. }
  221. return ch;
  222. }
  223. protected void makeUnique(Channel channel, int num) throws Exception {
  224. String str = Util.getProperty(new String[] { Global.UDP_MCAST_ADDR,
  225. "jboss.partition.udpGroup" }, null, "mcast_addr", false, null);
  226. if (str != null)
  227. makeUnique(channel, num, str);
  228. else
  229. makeUnique(channel, num, null);
  230. }
  231. protected void makeUnique(Channel channel, int num, String mcast_address) throws Exception {
  232. ProtocolStack stack = channel.getProtocolStack();
  233. Protocol transport = stack.getTransport();
  234. if (transport instanceof UDP) {
  235. short mcast_port = ResourceManager.getNextMulticastPort(InetAddress.getByName(bind_addr));
  236. ((UDP) transport).setMulticastPort(mcast_port);
  237. if (mcast_address != null) {
  238. ((UDP) transport).setMulticastAddress(InetAddress.getByName(mcast_address));
  239. } else {
  240. String mcast_addr = ResourceManager.getNextMulticastAddress();
  241. ((UDP) transport).setMulticastAddress(InetAddress.getByName(mcast_addr));
  242. }
  243. } else if (transport instanceof BasicTCP) {
  244. List<Short> ports = ResourceManager.getNextTcpPorts(InetAddress.getByName(bind_addr), num);
  245. ((TP) transport).setBindPort(ports.get(0));
  246. ((TP) transport).setPortRange(num);
  247. Protocol ping = stack.findProtocol(TCPPING.class);
  248. if (ping == null)
  249. throw new IllegalStateException("TCP stack must consist of TCP:TCPPING - other config are not supported");
  250. List<String> initial_hosts = new LinkedList<String>();
  251. for (short port : ports) {
  252. initial_hosts.add(bind_addr + "[" + port + "]");
  253. }
  254. String tmp = Util.printListWithDelimiter(initial_hosts, ",");
  255. List<IpAddress> init_hosts = Util.parseCommaDelimitedHosts(tmp, 1);
  256. ((TCPPING) ping).setInitialHosts(init_hosts);
  257. } else {
  258. throw new IllegalStateException("Only UDP and TCP are supported as transport protocols");
  259. }
  260. }
  261. }
  262. /*
  263. * Writes the shared channel resources used by this channel to the log (debugging).
  264. */
  265. protected void logChannelResources(Channel ch) {
  266. ProtocolStack stack = ch.getProtocolStack();
  267. Protocol transport = stack.getTransport();
  268. if (transport instanceof UDP) {
  269. log.debug("(udp.mcast_addr, udp.mcast_port) = ("
  270. + ((UDP) transport).getMulticastAddress() + ", "
  271. + ((UDP) transport).getMulticastPort() + ")");
  272. } else if (transport instanceof BasicTCP) {
  273. log.debug("(tcp.bind_port, tcp.port_range) = (" + ((TP) transport).getBindPort() + ", "
  274. + ((TP) transport).getPortRange() + ")");
  275. } else {
  276. throw new IllegalStateException("Only UDP and TCP are supported as transport protocols");
  277. }
  278. }
  279. interface EventSequence {
  280. List<Object> getEvents();
  281. String getName();
  282. }
  283. /**
  284. * Base class for all aplications using channel
  285. */
  286. protected abstract class ChannelApplication extends ExtendedReceiverAdapter implements
  287. EventSequence, Runnable {
  288. protected Channel channel;
  289. protected Thread thread;
  290. protected Throwable exception;
  291. protected List<Object> events;
  292. public ChannelApplication(String name) throws Exception {
  293. channel = createChannel(true, 4);
  294. init(name);
  295. }
  296. public ChannelApplication(JChannel copySource, String name) throws Exception {
  297. channel = createChannel(copySource);
  298. init(name);
  299. }
  300. protected void init(String name) {
  301. events = Collections.synchronizedList(new LinkedList<Object>());
  302. channel.setName(name);
  303. channel.setReceiver(this);
  304. }
  305. /**
  306. * Method allowing implementation of specific test application level logic
  307. *
  308. * @throws Exception
  309. */
  310. protected abstract void useChannel() throws Exception;
  311. public void run() {
  312. try {
  313. useChannel();
  314. } catch (Exception e) {
  315. log.error(channel.getName() + ": " + e.getLocalizedMessage(), e);
  316. exception = e; // Save it for the test to check
  317. }
  318. }
  319. public List<Address> getMembers() {
  320. List<Address> result = null;
  321. View v = channel.getView();
  322. if (v != null) {
  323. result = v.getMembers();
  324. }
  325. return result;
  326. }
  327. public Address getLocalAddress() {
  328. return channel.getAddress();
  329. }
  330. public void start() {
  331. thread = new Thread(this, getName());
  332. thread.start();
  333. }
  334. public Channel getChannel() {
  335. return channel;
  336. }
  337. public String getName() {
  338. return channel != null ? channel.getName() : "n/a";
  339. }
  340. public void cleanup() {
  341. if (thread != null && thread.isAlive())
  342. thread.interrupt();
  343. try {
  344. channel.close();
  345. } catch (Throwable t) {
  346. log.warn("Exception while closing channel " + getName(), t);
  347. }
  348. }
  349. public List<Object> getEvents() {
  350. return events;
  351. }
  352. public void block() {
  353. events.add(new BlockEvent());
  354. }
  355. public byte[] getState() {
  356. events.add(new GetStateEvent(null, null));
  357. return null;
  358. }
  359. public void getState(OutputStream ostream) {
  360. events.add(new GetStateEvent(null, null));
  361. }
  362. public byte[] getState(String state_id) {
  363. events.add(new GetStateEvent(null, state_id));
  364. return null;
  365. }
  366. public void getState(String state_id, OutputStream ostream) {
  367. events.add(new GetStateEvent(null, state_id));
  368. }
  369. public void setState(byte[] state) {
  370. events.add(new SetStateEvent(null, null));
  371. }
  372. public void setState(InputStream istream) {
  373. events.add(new SetStateEvent(null, null));
  374. }
  375. public void setState(String state_id, byte[] state) {
  376. events.add(new SetStateEvent(null, null));
  377. }
  378. public void setState(String state_id, InputStream istream) {
  379. events.add(new SetStateEvent(null, null));
  380. }
  381. public void unblock() {
  382. events.add(new UnblockEvent());
  383. }
  384. public void viewAccepted(View new_view) {
  385. events.add(new_view);
  386. log.info(getLocalAddress() + ": view=" + new_view);
  387. }
  388. }
  389. /**
  390. * Channel with semaphore allows application to go through fine-grained synchronous step
  391. * control.
  392. * <p/>
  393. * PushChannelApplicationWithSemaphore application will not proceed to useChannel() until it
  394. * acquires permit from semphore. After useChannel() completes the acquired permit will be
  395. * released. Test driver should control how semaphore tickets are given and acquired.
  396. */
  397. protected abstract class PushChannelApplicationWithSemaphore extends ChannelApplication {
  398. protected Semaphore semaphore;
  399. public PushChannelApplicationWithSemaphore(String name, Semaphore semaphore)
  400. throws Exception {
  401. super(name);
  402. this.semaphore = semaphore;
  403. }
  404. public PushChannelApplicationWithSemaphore(JChannel copySource, String name,
  405. Semaphore semaphore) throws Exception {
  406. super(copySource, name);
  407. this.semaphore = semaphore;
  408. }
  409. public void run() {
  410. boolean acquired = false;
  411. try {
  412. acquired = semaphore.tryAcquire(60000L, TimeUnit.MILLISECONDS);
  413. if (!acquired)
  414. throw new Exception(channel.getAddress() + ": cannot acquire semaphore");
  415. useChannel();
  416. } catch (Exception e) {
  417. exception = e; // Save it for the test to check
  418. } finally {
  419. if (acquired) {
  420. semaphore.release();
  421. }
  422. }
  423. }
  424. }
  425. protected static void checkEventStateTransferSequence(EventSequence receiver) {
  426. List<Object> events = receiver.getEvents();
  427. assertNotNull(events);
  428. final String validSequence = "([b][vgs]*[u])+";
  429. // translate the eventTrace to an eventString
  430. try {
  431. assertTrue("Invalid event sequence " + events, validateEventString(
  432. translateEventTrace(events), validSequence));
  433. } catch (Exception e) {
  434. AssertJUnit.fail("Invalid event sequence " + events);
  435. }
  436. }
  437. /**
  438. * Method for translating event traces into event strings, where each event in the trace is
  439. * represented by a letter.
  440. */
  441. protected static String translateEventTrace(List<Object> et) throws Exception {
  442. StringBuilder eventString = new StringBuilder();
  443. for (Iterator<Object> it = et.iterator(); it.hasNext();) {
  444. Object obj = it.next();
  445. if (obj instanceof BlockEvent)
  446. eventString.append("b");
  447. else if (obj instanceof UnblockEvent)
  448. eventString.append("u");
  449. else if (obj instanceof SetStateEvent)
  450. eventString.append("s");
  451. else if (obj instanceof GetStateEvent)
  452. eventString.append("g");
  453. else if (obj instanceof View)
  454. eventString.append("v");
  455. else
  456. throw new Exception("Unrecognized event type in event trace");
  457. }
  458. String s = eventString.toString();
  459. // if it ends with block, strip it out because it will be regarded as error sequence
  460. while (s.endsWith("b")) {
  461. s = s.substring(0, s.length() - 1);
  462. }
  463. return s;
  464. }
  465. /**
  466. * Method for validating event strings against event string specifications, where a
  467. * specification is a regular expression involving event symbols. e.g. [b]([sgv])[u]
  468. */
  469. protected static boolean validateEventString(String eventString, String spec) {
  470. Pattern pattern = null;
  471. Matcher matcher = null;
  472. // set up the regular expression specification
  473. pattern = Pattern.compile(spec);
  474. // set up the actual event string
  475. matcher = pattern.matcher(eventString);
  476. // check if the actual string satisfies the specification
  477. if (matcher.find()) {
  478. // a match has been found, but we need to check that the whole event string
  479. // matches, and not just a substring
  480. if (!(matcher.start() == 0 && matcher.end() == eventString.length())) {
  481. // match on full eventString not found
  482. System.err
  483. .println("event string invalid (proper substring matched): event string = "
  484. + eventString
  485. + ", specification = "
  486. + spec
  487. + "matcher.start() "
  488. + matcher.start()
  489. + " matcher.end() " + matcher.end());
  490. return false;
  491. }
  492. } else {
  493. return false;
  494. }
  495. return true;
  496. }
  497. }