From 7131e032682be74fb6e151187adbc34d78f0b37a Mon Sep 17 00:00:00 2001
From: Ladislav Thon <lthon@redhat.com>
Date: Fri, 13 Dec 2013 18:38:44 +0100
Subject: [JBPAPP-10724] add tests for quorum HA singleton election policy

---
 testsuite/imports/sections/cluster.xml             |    5 +
 .../HASingletonQuorumElectionPolicyTestCase.java   |  229 ++++++++++++
 .../test/QuorumElectionPolicyUnitTestCase.java     |  103 ++++++
 .../ha-quorum-electionpolicy-jboss-beans.xml       |  377 ++++++++++++++++++++
 4 files changed, 714 insertions(+)
 create mode 100644 testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonQuorumElectionPolicyTestCase.java
 create mode 100644 testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/QuorumElectionPolicyUnitTestCase.java
 create mode 100644 testsuite/src/resources/cluster/hasingleton/electionpolicy/ha-quorum-electionpolicy-jboss-beans.xml

diff --git a/testsuite/imports/sections/cluster.xml b/testsuite/imports/sections/cluster.xml
index af0b257..4585c3a 100755
--- a/testsuite/imports/sections/cluster.xml
+++ b/testsuite/imports/sections/cluster.xml
@@ -100,6 +100,11 @@
    	     file="${build.resources}/cluster/hasingleton/electionpolicy/ha-electionpolicy-jboss-beans.xml"
    	     overwrite="true"/>
    	     
+      <!--beans for testing HASingletonElectionPolicyQuorum -->
+   	<copy todir="${build.lib}"
+   	     file="${build.resources}/cluster/hasingleton/electionpolicy/ha-quorum-electionpolicy-jboss-beans.xml"
+   	     overwrite="true"/>
+ 
    	<!--beans for testing HASingletonControllerBeanUnitTestCase -->
    	<copy todir="${build.lib}"
    	     file="${build.resources}/cluster/hasingleton/ha-singleton-jboss-beans.xml"
diff --git a/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonQuorumElectionPolicyTestCase.java b/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonQuorumElectionPolicyTestCase.java
new file mode 100644
index 0000000..d2a2535
--- /dev/null
+++ b/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/HASingletonQuorumElectionPolicyTestCase.java
@@ -0,0 +1,229 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.util.Properties;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import junit.framework.Test;
+import org.jboss.ha.singleton.examples.HASingletonPojoExample;
+import org.jboss.test.JBossClusteredTestCase;
+
+/**
+ * Tests for HASingletonElectionPolicyQuorum and HASingletonElectionPolicySimpleQuorum.
+ * The testing deployment is under resources/cluster/hasingleton/electionpolicy. Tests both
+ * MBean and Pojo based HA singletons.
+ *
+ * Expected cluster size is always 2, that's what quorum values are based on.
+ *
+ * @author Ladislav Thon <lthon@redhat.com>
+ */
+public class HASingletonQuorumElectionPolicyTestCase extends JBossClusteredTestCase {
+   private final Properties env = new Properties();
+
+   public HASingletonQuorumElectionPolicyTestCase(String name) {
+      super(name);
+      env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+   }
+
+   public static Test suite() throws Exception {
+      return getDeploySetup(HASingletonQuorumElectionPolicyTestCase.class, "ha-quorum-electionpolicy-jboss-beans.xml");
+   }
+
+   public void testMBeanElectionPolicy() throws Exception {
+      // Get MBeanServerConnections
+      MBeanServerConnection[] adaptors = this.getAdaptors();
+      int size = adaptors.length;
+      assertTrue(size == 2);
+
+      // 1st policy is quorum-based & the oldest, where quorum < number of servers => quorum achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_1");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.TRUE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+
+      // 2nd policy is quorum-based & the oldest, where quorum = number of servers => quorum achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_2");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.TRUE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+
+      // 3rd policy is quorum-based & the oldest, where quorum > number of servers => quorum NOT achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_3");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+
+      // 4th policy is quorum-based & choose the youngest, where quorum < number of servers => quorum achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_4");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.TRUE, n2);
+      }
+
+      // 5th policy is quorum-based & choose the youngest, where quorum = number of servers => quorum achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_5");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.TRUE, n2);
+      }
+
+      // 6th policy is quorum-based & choose the youngest, where quorum > number of servers => quorum NOT achieved
+      {
+         ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_6");
+
+         Boolean n1 = (Boolean) adaptors[0].getAttribute(mbean, "MasterNode");
+         Boolean n2 = (Boolean) adaptors[1].getAttribute(mbean, "MasterNode");
+
+         assertEquals(Boolean.FALSE, n1);
+         assertEquals(Boolean.FALSE, n2);
+      }
+   }
+
+   public void testPojoElectionPolicy() throws Exception {
+      String[] namingUrls = getNamingURLs();
+      int size = namingUrls.length;
+      assertTrue(size == 2);   // cluster size must be 2 for 3rd policy test
+
+      // 1st policy is quorum-based & the oldest, where quorum < number of servers => quorum achieved
+      int exampleNumber = 1;
+      shouldHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      // 2nd policy is quorum-based & the oldest, where quorum = number of servers => quorum achieved
+      exampleNumber = 2;
+      shouldHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      // 3rd policy is quorum-based & the oldest, where quorum > number of servers => quorum NOT achieved
+      exampleNumber = 3;
+      shouldNotHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      // 4th policy is quorum-based & choose the youngest, where quorum < number of servers => quorum achieved
+      exampleNumber = 4;
+      shouldNotHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      // 5th policy is quorum-based & choose the youngest, where quorum = number of servers => quorum achieved
+      exampleNumber = 5;
+      shouldNotHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      // 6th policy is quorum-based & choose the youngest, where quorum > number of servers => quorum NOT achieved
+      exampleNumber = 6;
+      shouldNotHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+   }
+
+   private void shouldHaveHaSingletonDeployed(String namingUrl, int exampleNumber) throws Exception {
+      env.setProperty(Context.PROVIDER_URL, namingUrl);
+      Context ctx = new InitialContext(env);
+      HASingletonPojoExample pojo = (HASingletonPojoExample) ctx.lookup("test/cluster/hasingleton/quorum/simplepojo/" + exampleNumber);
+      assertTrue("Pojo in " + namingUrl + " should be deployed as HA singleton", pojo.isMasterNode());
+   }
+
+   private void shouldNotHaveHaSingletonDeployed(String namingUrl, int exampleNumber) throws Exception {
+      env.setProperty(Context.PROVIDER_URL, namingUrl);
+      Context ctx = new InitialContext(env);
+      try {
+         HASingletonPojoExample pojo = (HASingletonPojoExample) ctx.lookup("test/cluster/hasingleton/quorum/simplepojo/" + exampleNumber);
+         fail("Should have thrown a NamingException indicating 'test not bound'");
+      } catch (NamingException ne) {
+      }
+   }
+
+   public void testQuorumStartStopPartition() throws Exception {
+      MBeanServerConnection[] adaptors = getAdaptors();
+      String[] namingUrls = getNamingURLs();
+      assertTrue(adaptors.length == 2); // expecting cluster size to be equal to the quorum
+      assertTrue(namingUrls.length == 2);
+
+      ObjectName mbean = new ObjectName("jboss.examples:service=HASingletonQuorumMBeanExample_2");
+      int exampleNumber = 2;
+
+      assertEquals(Boolean.TRUE, adaptors[0].getAttribute(mbean, "MasterNode"));
+      assertEquals(Boolean.FALSE, adaptors[1].getAttribute(mbean, "MasterNode"));
+      shouldHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      stopPartition(adaptors[1]);
+
+      assertEquals(Boolean.FALSE, adaptors[0].getAttribute(mbean, "MasterNode"));
+      assertEquals(Boolean.FALSE, adaptors[1].getAttribute(mbean, "MasterNode"));
+      shouldNotHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+
+      startPartition(adaptors[1]);
+
+      assertEquals(Boolean.TRUE, adaptors[0].getAttribute(mbean, "MasterNode"));
+      assertEquals(Boolean.FALSE, adaptors[1].getAttribute(mbean, "MasterNode"));
+      shouldHaveHaSingletonDeployed(namingUrls[0], exampleNumber);
+      shouldNotHaveHaSingletonDeployed(namingUrls[1], exampleNumber);
+   }
+
+   protected void startPartition(MBeanServerConnection adaptor) throws Exception {
+      doStartStopPartition(adaptor, "start");
+   }
+
+   protected void stopPartition(MBeanServerConnection adaptor) throws Exception {
+      doStartStopPartition(adaptor, "stop");
+   }
+
+   private void doStartStopPartition(MBeanServerConnection adaptor, String startOrStop) throws Exception {
+      ObjectName partition = new ObjectName("jboss:service=QuorumElectionPolicyTestPartition");
+
+      Object[] params = new Object[0];
+      String[] types = new String[0];
+      adaptor.invoke(partition, startOrStop, params, types);
+
+      Thread.sleep(2000);
+   }
+}
diff --git a/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/QuorumElectionPolicyUnitTestCase.java b/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/QuorumElectionPolicyUnitTestCase.java
new file mode 100644
index 0000000..6c83aca
--- /dev/null
+++ b/testsuite/src/main/org/jboss/test/cluster/defaultcfg/test/QuorumElectionPolicyUnitTestCase.java
@@ -0,0 +1,103 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2013, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.test.cluster.defaultcfg.test;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import junit.framework.TestCase;
+import org.jboss.ha.framework.interfaces.ClusterNode;
+import org.jboss.ha.framework.server.ClusterNodeImpl;
+import org.jboss.ha.singleton.HASingletonElectionPolicyQuorum;
+import org.jboss.ha.singleton.HASingletonElectionPolicySimpleQuorum;
+import org.jgroups.stack.IpAddress;
+
+/**
+ * @author Ladislav Thon <lthon@redhat.com>
+ */
+public class QuorumElectionPolicyUnitTestCase extends TestCase {
+    private InetAddress localAddress;
+
+    @Override
+    protected void setUp() throws UnknownHostException {
+        localAddress = InetAddress.getByName("localhost");
+    }
+
+    public void testQuorumValue() {
+        doTestQuorumValue(new HASingletonElectionPolicyQuorum());
+    }
+
+    public void testQuorumValueSimple() {
+        doTestQuorumValue(new HASingletonElectionPolicySimpleQuorum());
+    }
+
+    public void testAchieveQuorum() {
+        doTestAchieveQuorum(new HASingletonElectionPolicyQuorum());
+    }
+
+    public void testAchieveQuorumSimple() {
+        doTestAchieveQuorum(new HASingletonElectionPolicySimpleQuorum());
+    }
+
+    private void doTestQuorumValue(HASingletonElectionPolicyQuorum policy) {
+        for (int i = 1; i < 4; i++) {
+            policy.setQuorum(i);
+        }
+
+        for (int i = 0; i > -3; i--) {
+            try {
+                policy.setQuorum(i);
+                fail("Expected IllegalArgumentException for quorum value " + i);
+            } catch (IllegalArgumentException expected) {}
+        }
+    }
+
+    private void doTestAchieveQuorum(HASingletonElectionPolicyQuorum policy) {
+        List<ClusterNode> nodes = new ArrayList<ClusterNode>(Arrays.asList(
+                new ClusterNodeImpl(new IpAddress(localAddress, 10000)),
+                new ClusterNodeImpl(new IpAddress(localAddress, 10001)),
+                new ClusterNodeImpl(new IpAddress(localAddress, 10002)),
+                new ClusterNodeImpl(new IpAddress(localAddress, 10003))
+        ));
+
+        policy.setQuorum(2);
+
+        assertNotNull(policy.elect(nodes));
+
+        nodes.remove(3);
+        assertNotNull(policy.elect(nodes));
+
+        nodes.remove(2);
+        assertNotNull(policy.elect(nodes));
+
+        nodes.remove(1);
+        assertNull(policy.elect(nodes));
+
+        nodes.remove(0);
+        assertNull(policy.elect(nodes));
+
+        assertTrue(nodes.isEmpty());
+    }
+}
diff --git a/testsuite/src/resources/cluster/hasingleton/electionpolicy/ha-quorum-electionpolicy-jboss-beans.xml b/testsuite/src/resources/cluster/hasingleton/electionpolicy/ha-quorum-electionpolicy-jboss-beans.xml
new file mode 100644
index 0000000..f46bfab
--- /dev/null
+++ b/testsuite/src/resources/cluster/hasingleton/electionpolicy/ha-quorum-electionpolicy-jboss-beans.xml
@@ -0,0 +1,377 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deployment xmlns="urn:jboss:bean-deployer:2.0">
+
+   <!-- ==================================================================== -->
+   <!-- MBean style HA singleton election definition                         -->
+   <!-- ==================================================================== -->
+
+   <!-- 1st HASingleton, Election policy is quorum-based & the oldest, quorum is less than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+          name="HASingletonQuorumMBeanExample_1">
+       <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_1", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicyQuorum"
+          name="HASingletonQuorumElectionPolicy_1">
+      <property name="quorum">1</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+          name="HASingletonQuorumController_1">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_1", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_1"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_1"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- 2nd HASingleton, Election policy is quorum-based & the oldest, quorum is equal to the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+         name="HASingletonQuorumMBeanExample_2">
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_2", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicyQuorum"
+         name="HASingletonQuorumElectionPolicy_2">
+      <property name="quorum">2</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumController_2">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_2", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_2"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_2"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- 3rd HASingleton, Election policy is quorum-based & the oldest, quorum is greater than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+         name="HASingletonQuorumMBeanExample_3">
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_3", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicyQuorum"
+         name="HASingletonQuorumElectionPolicy_3">
+      <property name="quorum">3</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumController_3">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_3", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_3"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_3"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- 4th HASingleton, Election policy is quorum-based & to choose the youngest, quorum is less than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+         name="HASingletonQuorumMBeanExample_4">
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_4", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicySimpleQuorum"
+         name="HASingletonQuorumElectionPolicySimple_1">
+      <property name="quorum">1</property>
+      <property name="position">-1</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumController_4">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_4", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_1"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_4"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- 5th HASingleton, Election policy is quorum-based & to choose the youngest, quorum is equal to the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+         name="HASingletonQuorumMBeanExample_5">
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_5", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicySimpleQuorum"
+         name="HASingletonQuorumElectionPolicySimple_2">
+      <property name="quorum">2</property>
+      <property name="position">-1</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumController_5">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_5", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_2"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_5"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- 6th HASingleton, Election policy is quorum-based & to choose the youngest, quorum is greater than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonMBeanExample"
+         name="HASingletonQuorumMBeanExample_6">
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.examples:service=HASingletonQuorumMBeanExample_6", exposedInterface=org.jboss.ha.singleton.examples.HASingletonMBeanExampleMBean.class, registerDirectly=true)</annotation>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonElectionPolicySimpleQuorum"
+         name="HASingletonQuorumElectionPolicySimple_3">
+      <property name="quorum">3</property>
+      <property name="position">-1</property>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumController_6">
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="test:service=HASingletonQuorumController_6", exposedInterface=org.jboss.ha.singleton.HASingletonControllerMBean.class, registerDirectly=true)</annotation>
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_3"/></property>
+      <property name="target"><inject bean="HASingletonQuorumMBeanExample_6"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+      <property name="targetStopMethodArgument">true</property>
+   </bean>
+
+   <!-- ==================================================================== -->
+   <!-- Pojo style HA singleton election definition                          -->
+   <!-- ==================================================================== -->
+
+   <!-- 1st HASingleton, Election policy is quorum-based & the oldest, quorum is lower than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+          name="HASingletonQuorumPojoExample_1">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/1</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+          name="HASingletonQuorumControllerForBean_1">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_1"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_1"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+   <!-- 2nd HASingleton, Election policy is quorum-based & the oldest, quorum is equal to the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+         name="HASingletonQuorumPojoExample_2">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/2</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumControllerForBean_2">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_2"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_2"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+   <!-- 3rd HASingleton, Election policy is quorum-based & the oldest, quorum is greater than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+         name="HASingletonQuorumPojoExample_3">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/3</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumControllerForBean_3">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicy_3"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_3"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+   <!-- 4th HASingleton, Election policy is quorum-based & choose the youngest, quorum is less than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+         name="HASingletonQuorumPojoExample_4">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/4</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumControllerForBean_4">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_1"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_4"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+   <!-- 5th HASingleton, Election policy is quorum-based & choose the youngest, quorum is equal to the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+         name="HASingletonQuorumPojoExample_5">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/5</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumControllerForBean_5">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_2"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_5"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+   <!-- 6th HASingleton, Election policy is quorum-based & choose the youngest, quorum is greater than the number of servers -->
+   <bean class="org.jboss.ha.singleton.examples.HASingletonPojoExample"
+         name="HASingletonQuorumPojoExample_6">
+      <constructor><parameter>test/cluster/hasingleton/quorum/simplepojo/6</parameter></constructor>
+   </bean>
+
+   <bean class="org.jboss.ha.singleton.HASingletonController"
+         name="HASingletonQuorumControllerForBean_6">
+
+      <property name="HAPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="clusterPartition"><inject bean="QuorumElectionPolicyTestPartition"/></property>
+      <property name="electionPolicy"><inject bean="HASingletonQuorumElectionPolicySimple_3"/></property>
+      <property name="target"><inject bean="HASingletonQuorumPojoExample_6"/></property>
+      <property name="targetStartMethod">startSingleton</property>
+      <property name="targetStopMethod">stopSingleton</property>
+   </bean>
+
+
+   <bean name="QuorumElectionPolicyTestCacheConfig"
+         class="org.jboss.cache.config.Configuration">
+
+        <!-- When we're installed, register ourself -->
+        <install bean="CacheConfigurationRegistry" method="registerConfiguration">
+          <parameter>quorum-election-policy</parameter>
+          <parameter><this/></parameter>
+        </install>
+
+        <!-- When we're uninstalled, unregister ourself -->
+        <uninstall bean="CacheConfigurationRegistry" method="unregisterConfiguration">
+          <parameter>quorum-election-policy</parameter>
+        </uninstall>
+
+        <!-- The ClusterPartition beans need to wait until we are completely
+             installed and have register ourself -->
+        <supply>QuorumElectionPolicyCacheConfigSupply</supply>
+
+        <!-- Externally injected services -->
+        <property name="runtimeConfig">
+           <bean name="QuorumElectionPolicyTestCacheRuntimeConfig" class="org.jboss.cache.config.RuntimeConfig">
+              <property name="transactionManager"><inject bean="jboss:service=TransactionManager" property="TransactionManager"/></property>
+           </bean>
+        </property>
+
+        <property name="multiplexerStack">${jboss.default.jgroups.stack:udp}</property>
+
+        <!-- Valid isolation levels are
+                              SERIALIZABLE
+                              REPEATABLE_READ (default)
+                              READ_COMMITTED
+                              READ_UNCOMMITTED
+                              NONE
+        -->
+        <property name="isolationLevelString">REPEATABLE_READ</property>
+
+        <!-- Valid modes are LOCAL, REPL_ASYNC and REPL_SYNC -->
+        <property name="cacheModeString">REPL_SYNC</property>
+
+        <!-- Just used for async repl: use a replication queue -->
+        <property name="useReplQueue">false</property>
+
+        <!-- Replication interval for replication queue (in ms) -->
+        <property name="replQueueInterval">0</property>
+
+        <!-- Max number of elements which trigger replication -->
+        <property name="replQueueMaxElements">10</property>
+
+        <!-- Name of cluster. Needs to be the same for all nodes in clusters,
+          in order to find each other -->
+        <property name="clusterName">QuorumElectionPolicyTestPartitionCache</property>
+
+        <!-- Whether or not to fetch state on joining a cluster  -->
+        <property name="fetchInMemoryState">true</property>
+
+        <!-- The max amount of time (in milliseconds) we wait until the
+            initial state (ie. the contents of the cache) are retrieved from
+            existing members in a clustered environment -->
+        <property name="stateRetrievalTimeout">5000</property>
+
+        <!-- Number of milliseconds to wait until all responses for a
+            synchronous call have been received. -->
+        <property name="syncReplTimeout">20000</property>
+
+        <!-- Max number of milliseconds to wait for a lock acquisition -->
+        <property name="lockAcquisitionTimeout">15000</property>
+
+        <property name="exposeManagementStatistics">true</property>
+
+    </bean>
+
+
+   <!-- ==================================================================== -->
+   <!-- Partition used for testing failure to receive state                  -->
+   <!-- ==================================================================== -->
+
+   <bean name="QuorumElectionPolicyCacheHandler"
+         class="org.jboss.ha.framework.server.HAPartitionCacheHandlerImpl">
+         <property name="cacheManager"><inject bean="CacheManager"/></property>
+         <property name="cacheConfigName">quorum-election-policy</property>
+   </bean>
+
+   <bean name="QuorumElectionPolicyTestPartition"
+         class="org.jboss.ha.framework.server.ClusterPartition">
+
+      <depends>jboss:service=Naming</depends>
+
+      <annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss:service=QuorumElectionPolicyTestPartition", exposedInterface=org.jboss.ha.framework.server.ClusterPartitionMBean.class)</annotation>
+
+      <demand>QuorumElectionPolicyCacheConfigSupply</demand>
+
+      <!-- ClusterPartition requires a Cache for state management -->
+      <property name="cacheHandler"><inject bean="QuorumElectionPolicyCacheHandler"/></property>
+
+      <!-- Name of the partition being built -->
+      <property name="partitionName">QuorumElectionPolicyTestPartition</property>
+
+      <!-- The address used to determine the node name -->
+      <property name="nodeAddress">${jboss.bind.address}</property>
+
+      <!-- Max time (in ms) to wait for state transfer to complete. Increase for large states -->
+      <property name="stateTransferTimeout">2000</property>
+
+      <!-- Max time (in ms) to wait for RPC calls to complete. -->
+      <property name="methodCallTimeout">5000</property>
+
+   </bean>
+
+</deployment>
-- 
1.7.9.5

