You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by ki...@apache.org on 2012/10/25 01:14:59 UTC

[40/42] Refactoring the package names and removing jsql parser

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/model/TestConstraint.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/model/TestConstraint.java b/helix-core/src/test/java/org/apache/helix/model/TestConstraint.java
new file mode 100644
index 0000000..99bf8ae
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/model/TestConstraint.java
@@ -0,0 +1,266 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.model;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.helix.TestHelper;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.PropertyKey.Builder;
+import org.apache.helix.manager.zk.ZKHelixDataAccessor;
+import org.apache.helix.manager.zk.ZkBaseDataAccessor;
+import org.apache.helix.model.ClusterConstraints;
+import org.apache.helix.model.Message;
+import org.apache.helix.model.ClusterConstraints.ConstraintAttribute;
+import org.apache.helix.model.ClusterConstraints.ConstraintItem;
+import org.apache.helix.model.ClusterConstraints.ConstraintType;
+import org.apache.helix.model.Message.MessageType;
+import org.apache.log4j.Logger;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TestConstraint extends ZkUnitTestBase
+{
+  private static Logger LOG = Logger.getLogger(TestConstraint.class);
+
+  @Test
+  public void testMsgConstraint()
+  {
+    String className = getShortClassName();
+    System.out.println("START testMsgConstraint() at "
+        + new Date(System.currentTimeMillis()));
+
+    String clusterName = "CLUSTER_" + className + "_msg";
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+    ZNRecord record = new ZNRecord("testMsgConstraint");
+
+    // constraint0:
+    // "MESSAGE_TYPE=STATE_TRANSITION,CONSTRAINT_VALUE=ANY"
+    record.setMapField("constraint0", new TreeMap<String, String>());
+    record.getMapField("constraint0").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint0").put("CONSTRAINT_VALUE", "ANY");
+    ConstraintItem constraint0 = new ConstraintItem(record.getMapField("constraint0"));
+
+    // constraint1:
+    // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,CONSTRAINT_VALUE=ANY"
+    record.setMapField("constraint1", new TreeMap<String, String>());
+    record.getMapField("constraint1").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint1").put("TRANSITION", "OFFLINE-SLAVE");
+    record.getMapField("constraint1").put("CONSTRAINT_VALUE", "50");
+    ConstraintItem constraint1 = new ConstraintItem(record.getMapField("constraint1"));
+
+    // constraint2:
+    // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=.*,RESOURCE=TestDB,CONSTRAINT_VALUE=2";
+    record.setMapField("constraint2", new TreeMap<String, String>());
+    record.getMapField("constraint2").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint2").put("TRANSITION", "OFFLINE-SLAVE");
+    record.getMapField("constraint2").put("INSTANCE", ".*");
+    record.getMapField("constraint2").put("RESOURCE", "TestDB");
+    record.getMapField("constraint2").put("CONSTRAINT_VALUE", "2");
+    ConstraintItem constraint2 = new ConstraintItem(record.getMapField("constraint2"));
+
+    // constraint3:
+    // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=localhost_12918,RESOURCE=.*,CONSTRAINT_VALUE=1";
+    record.setMapField("constraint3", new TreeMap<String, String>());
+    record.getMapField("constraint3").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint3").put("TRANSITION", "OFFLINE-SLAVE");
+    record.getMapField("constraint3").put("INSTANCE", "localhost_12919");
+    record.getMapField("constraint3").put("RESOURCE", ".*");
+    record.getMapField("constraint3").put("CONSTRAINT_VALUE", "1");
+    ConstraintItem constraint3 = new ConstraintItem(record.getMapField("constraint3"));
+
+    // constraint4:
+    // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=.*,RESOURCE=.*,CONSTRAINT_VALUE=10"
+    record.setMapField("constraint4", new TreeMap<String, String>());
+    record.getMapField("constraint4").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint4").put("TRANSITION", "OFFLINE-SLAVE");
+    record.getMapField("constraint4").put("INSTANCE", ".*");
+    record.getMapField("constraint4").put("RESOURCE", ".*");
+    record.getMapField("constraint4").put("CONSTRAINT_VALUE", "10");
+    ConstraintItem constraint4 = new ConstraintItem(record.getMapField("constraint4"));
+
+    // constraint5:
+    // "MESSAGE_TYPE=STATE_TRANSITION,TRANSITION=OFFLINE-SLAVE,INSTANCE=localhost_12918,RESOURCE=TestDB,CONSTRAINT_VALUE=5"
+    record.setMapField("constraint5", new TreeMap<String, String>());
+    record.getMapField("constraint5").put("MESSAGE_TYPE", "STATE_TRANSITION");
+    record.getMapField("constraint5").put("TRANSITION", "OFFLINE-SLAVE");
+    record.getMapField("constraint5").put("INSTANCE", "localhost_12918");
+    record.getMapField("constraint5").put("RESOURCE", "TestDB");
+    record.getMapField("constraint5").put("CONSTRAINT_VALUE", "5");
+    ConstraintItem constraint5 = new ConstraintItem(record.getMapField("constraint5"));
+
+    ZKHelixDataAccessor accessor =
+        new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient));
+    Builder keyBuilder = accessor.keyBuilder();
+
+    accessor.setProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString()),
+                         new ClusterConstraints(record));
+
+    record =
+        accessor.getProperty(keyBuilder.constraint(ConstraintType.MESSAGE_CONSTRAINT.toString()))
+                .getRecord();
+    ClusterConstraints constraint = new ClusterConstraints(record);
+    // System.out.println("constraint: " + constraint);
+
+    // message1
+    Message msg1 =
+        createMessage(MessageType.STATE_TRANSITION,
+                      "msgId-001",
+                      "OFFLINE",
+                      "SLAVE",
+                      "TestDB",
+                      "localhost_12918");
+
+    Map<ConstraintAttribute, String> msgAttr =
+        ClusterConstraints.toConstraintAttributes(msg1);
+    Set<ConstraintItem> matches = constraint.match(msgAttr);
+    System.out.println(msg1 + " matches(" + matches.size() + "): " + matches);
+    Assert.assertEquals(matches.size(), 5);
+    Assert.assertTrue(contains(matches, constraint0));
+    Assert.assertTrue(contains(matches, constraint1));
+    Assert.assertTrue(contains(matches, constraint2));
+    Assert.assertTrue(contains(matches, constraint4));
+    Assert.assertTrue(contains(matches, constraint5));
+
+    // message2
+    Message msg2 =
+        createMessage(MessageType.STATE_TRANSITION,
+                      "msgId-002",
+                      "OFFLINE",
+                      "SLAVE",
+                      "TestDB",
+                      "localhost_12919");
+
+    msgAttr = ClusterConstraints.toConstraintAttributes(msg2);
+    matches = constraint.match(msgAttr);
+    System.out.println(msg2 + " matches(" + matches.size() + "): " + matches);
+    Assert.assertEquals(matches.size(), 5);
+    Assert.assertTrue(contains(matches, constraint0));
+    Assert.assertTrue(contains(matches, constraint1));
+    Assert.assertTrue(contains(matches, constraint2));
+    Assert.assertTrue(contains(matches, constraint3));
+    Assert.assertTrue(contains(matches, constraint4));
+
+    System.out.println("END testMsgConstraint() at "
+        + new Date(System.currentTimeMillis()));
+  }
+
+  @Test
+  public void testStateConstraint()
+  {
+    String className = getShortClassName();
+    System.out.println("START testStateConstraint() at "
+        + new Date(System.currentTimeMillis()));
+
+    String clusterName = "CLUSTER_" + className + "_state";
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+    ZNRecord record = new ZNRecord("testStateConstraint");
+
+    // constraint0:
+    // "STATE=MASTER,CONSTRAINT_VALUE=1"
+    record.setMapField("constraint0", new TreeMap<String, String>());
+    record.getMapField("constraint0").put("STATE", "MASTER");
+    record.getMapField("constraint0").put("CONSTRAINT_VALUE", "1");
+    ConstraintItem constraint0 = new ConstraintItem(record.getMapField("constraint0"));
+
+    // constraint1:
+    // "STATE=MASTER,RESOURCE=TestDB,CONSTRAINT_VALUE=5"
+    record.setMapField("constraint1", new TreeMap<String, String>());
+    record.getMapField("constraint1").put("STATE", "MASTER");
+    record.getMapField("constraint1").put("RESOURCE", "TestDB");
+    record.getMapField("constraint1").put("CONSTRAINT_VALUE", "1");
+    ConstraintItem constraint1 = new ConstraintItem(record.getMapField("constraint1"));
+
+    // constraint2:
+    // "STATE=MASTER,RESOURCE=.*,CONSTRAINT_VALUE=2"
+    record.setMapField("constraint2", new TreeMap<String, String>());
+    record.getMapField("constraint2").put("STATE", "MASTER");
+    record.getMapField("constraint2").put("RESOURCE", ".*");
+    record.getMapField("constraint2").put("CONSTRAINT_VALUE", "2");
+    ConstraintItem constraint2 = new ConstraintItem(record.getMapField("constraint2"));
+
+    ZKHelixDataAccessor accessor =
+        new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient));
+    Builder keyBuilder = accessor.keyBuilder();
+
+    accessor.setProperty(keyBuilder.constraint(ConstraintType.STATE_CONSTRAINT.toString()),
+                         new ClusterConstraints(record));
+
+    record =
+        accessor.getProperty(keyBuilder.constraint(ConstraintType.STATE_CONSTRAINT.toString()))
+                .getRecord();
+    ClusterConstraints constraint = new ClusterConstraints(record);
+    // System.out.println("constraint: " + constraint);
+
+    // state1: hit rule2
+    Map<ConstraintAttribute, String> stateAttr1 =
+        new HashMap<ConstraintAttribute, String>();
+    stateAttr1.put(ConstraintAttribute.STATE, "MASTER");
+    stateAttr1.put(ConstraintAttribute.RESOURCE, "TestDB");
+
+    Set<ConstraintItem> matches = constraint.match(stateAttr1);
+    System.out.println(stateAttr1 + " matches(" + matches.size() + "): " + matches);
+    Assert.assertEquals(matches.size(), 3);
+    Assert.assertTrue(contains(matches, constraint0));
+    Assert.assertTrue(contains(matches, constraint1));
+    Assert.assertTrue(contains(matches, constraint2));
+
+    // matches = selectConstraints(matches, stateAttr1);
+    // System.out.println(stateAttr1 + " matches(" + matches.size() + "): " + matches);
+    // Assert.assertEquals(matches.size(), 2);
+    // Assert.assertTrue(contains(matches, constraint0));
+    // Assert.assertTrue(contains(matches, constraint1));
+
+    // state2: not hit any rules
+    Map<ConstraintAttribute, String> stateAttr2 =
+        new HashMap<ConstraintAttribute, String>();
+    stateAttr2.put(ConstraintAttribute.STATE, "MASTER");
+    stateAttr2.put(ConstraintAttribute.RESOURCE, "MyDB");
+
+    matches = constraint.match(stateAttr2);
+    System.out.println(stateAttr2 + " matches(" + matches.size() + "): " + matches);
+    Assert.assertEquals(matches.size(), 2);
+    Assert.assertTrue(contains(matches, constraint0));
+    Assert.assertTrue(contains(matches, constraint2));
+
+    // matches = selectConstraints(matches, stateAttr2);
+    // System.out.println(stateAttr2 + " matches(" + matches.size() + "): " + matches);
+    // Assert.assertEquals(matches.size(), 2);
+    // Assert.assertTrue(contains(matches, constraint0));
+    // Assert.assertTrue(contains(matches, constraint2));
+
+    System.out.println("END testStateConstraint() at "
+        + new Date(System.currentTimeMillis()));
+  }
+
+  private boolean contains(Set<ConstraintItem> constraints, ConstraintItem constraint)
+  {
+    for (ConstraintItem item : constraints)
+    {
+      if (item.toString().equals(constraint.toString()))
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/model/TestIdealState.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/model/TestIdealState.java b/helix-core/src/test/java/org/apache/helix/model/TestIdealState.java
new file mode 100644
index 0000000..551c9df
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/model/TestIdealState.java
@@ -0,0 +1,61 @@
+package org.apache.helix.model;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.helix.TestHelper;
+import org.apache.helix.model.IdealState;
+import org.apache.helix.model.IdealState.IdealStateModeProperty;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TestIdealState
+{
+  @Test
+  public void testGetInstanceSet()
+  {
+    String className = TestHelper.getTestClassName();
+    String methodName = TestHelper.getTestMethodName();
+    String testName = className + "_" + methodName;
+    System.out.println("START " + testName + " at "
+        + new Date(System.currentTimeMillis()));
+
+
+    IdealState idealState = new IdealState("idealState");
+    idealState.getRecord().setListField("TestDB_0", Arrays.asList("node_1", "node_2"));
+    Map<String, String> instanceState = new HashMap<String, String>();
+    instanceState.put("node_3", "MASTER");
+    instanceState.put("node_4", "SLAVE");
+    idealState.getRecord().setMapField("TestDB_1", instanceState);
+
+    // test AUTO mode
+    idealState.setIdealStateMode(IdealStateModeProperty.AUTO.toString());
+    Set<String> instances = idealState.getInstanceSet("TestDB_0");
+//    System.out.println("instances: " + instances);
+    Assert.assertEquals(instances.size(), 2, "Should contain node_1 and node_2");
+    Assert.assertTrue(instances.contains("node_1"), "Should contain node_1 and node_2");
+    Assert.assertTrue(instances.contains("node_2"), "Should contain node_1 and node_2");
+
+    instances = idealState.getInstanceSet("TestDB_nonExist_auto");
+    Assert.assertEquals(instances, Collections.emptySet(), "Should get empty set");
+    
+    // test CUSTOMIZED mode
+    idealState.setIdealStateMode(IdealStateModeProperty.CUSTOMIZED.toString());
+    instances = idealState.getInstanceSet("TestDB_1");
+//    System.out.println("instances: " + instances);
+    Assert.assertEquals(instances.size(), 2, "Should contain node_3 and node_4");
+    Assert.assertTrue(instances.contains("node_3"), "Should contain node_3 and node_4");
+    Assert.assertTrue(instances.contains("node_4"), "Should contain node_3 and node_4");
+
+    instances = idealState.getInstanceSet("TestDB_nonExist_custom");
+    Assert.assertEquals(instances, Collections.emptySet(), "Should get empty set");
+    
+    System.out.println("END " + testName + " at "
+        + new Date(System.currentTimeMillis()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/monitoring/TestParticipantMonitor.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/TestParticipantMonitor.java b/helix-core/src/test/java/org/apache/helix/monitoring/TestParticipantMonitor.java
new file mode 100644
index 0000000..6512343
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/TestParticipantMonitor.java
@@ -0,0 +1,155 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+  package org.apache.helix.monitoring;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerNotification;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.apache.helix.monitoring.ParticipantMonitor;
+import org.apache.helix.monitoring.StateTransitionContext;
+import org.apache.helix.monitoring.StateTransitionDataPoint;
+import org.apache.helix.monitoring.mbeans.ClusterMBeanObserver;
+import org.apache.log4j.Logger;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestParticipantMonitor
+{
+  static Logger _logger = Logger.getLogger(TestParticipantMonitor.class);
+
+  class ParticipantMonitorListener extends ClusterMBeanObserver
+  {
+    Map<String, Map<String, Object>> _beanValueMap = new HashMap<String, Map<String, Object>>();
+
+    public ParticipantMonitorListener(String domain)
+        throws InstanceNotFoundException, IOException,
+        MalformedObjectNameException, NullPointerException
+    {
+      super(domain);
+      init();
+    }
+
+    void init()
+    {
+      try
+      {
+        Set<ObjectInstance> existingInstances = _server.queryMBeans(new ObjectName(_domain+":Cluster=cluster,*"), null);
+        for(ObjectInstance instance : existingInstances)
+        {
+          String mbeanName = instance.getObjectName().toString();
+          // System.out.println("mbeanName: " + mbeanName);
+          addMBean(instance.getObjectName());
+        }
+      }
+      catch (Exception e)
+      {
+        _logger.warn("fail to get all existing mbeans in " + _domain, e);
+      }
+    }
+
+    @Override
+    public void onMBeanRegistered(MBeanServerConnection server,
+        MBeanServerNotification mbsNotification)
+    {
+      addMBean(mbsNotification.getMBeanName());
+    }
+
+    void addMBean(ObjectName beanName)
+    {
+      try
+      {
+        MBeanInfo info = _server.getMBeanInfo(beanName);
+        MBeanAttributeInfo[] infos = info.getAttributes();
+        _beanValueMap.put(beanName.toString(), new HashMap<String, Object>());
+        for(MBeanAttributeInfo infoItem : infos)
+        {
+          Object val = _server.getAttribute(beanName, infoItem.getName());
+          // System.out.println("         " + infoItem.getName() + " : " + _server.getAttribute(beanName, infoItem.getName()) + " type : " + infoItem.getType());
+          _beanValueMap.get(beanName.toString()).put(infoItem.getName(), val);
+        }
+      }
+      catch (Exception e)
+      {
+        _logger.error("Error getting bean info, domain="+_domain, e);
+      }
+    }
+
+    @Override
+    public void onMBeanUnRegistered(MBeanServerConnection server,
+        MBeanServerNotification mbsNotification)
+    {
+
+    }
+  }
+  @Test(groups={ "unitTest" })
+  public void TestReportData() throws InstanceNotFoundException, MalformedObjectNameException, NullPointerException, IOException, InterruptedException
+  {
+  	System.out.println("START TestParticipantMonitor");
+    ParticipantMonitor monitor = new ParticipantMonitor();
+
+    int monitorNum = 0;
+
+    StateTransitionContext cxt = new StateTransitionContext("cluster", "instance", "db_1","a-b");
+    StateTransitionDataPoint data = new StateTransitionDataPoint(1000,1000,true);
+    monitor.reportTransitionStat(cxt, data);
+
+    data = new StateTransitionDataPoint(1000,1200,true);
+    monitor.reportTransitionStat(cxt, data);
+
+    ParticipantMonitorListener monitorListener = new ParticipantMonitorListener("CLMParticipantReport");
+    Thread.sleep(1000);
+    AssertJUnit.assertTrue(monitorListener._beanValueMap.size() == monitorNum + 1);
+
+    data = new StateTransitionDataPoint(1000,500,true);
+    monitor.reportTransitionStat(cxt, data);
+    Thread.sleep(1000);
+    AssertJUnit.assertTrue(monitorListener._beanValueMap.size() == monitorNum + 1);
+
+    data = new StateTransitionDataPoint(1000,500,true);
+    StateTransitionContext cxt2 = new StateTransitionContext("cluster", "instance", "db_2","a-b");
+    monitor.reportTransitionStat(cxt2, data);
+    monitor.reportTransitionStat(cxt2, data);
+    Thread.sleep(1000);
+    AssertJUnit.assertTrue(monitorListener._beanValueMap.size() == monitorNum + 2);
+
+    AssertJUnit.assertFalse(cxt.equals(cxt2));
+    AssertJUnit.assertFalse(cxt.equals(new Object()));
+    AssertJUnit.assertTrue(cxt.equals(new StateTransitionContext("cluster", "instance", "db_1","a-b")));
+
+    cxt2.getInstanceName();
+
+    ParticipantMonitorListener monitorListener2 = new ParticipantMonitorListener("CLMParticipantReport");
+
+    Thread.sleep(1000);
+    AssertJUnit.assertEquals(monitorListener2._beanValueMap.size() , monitorNum + 2);
+
+    monitorListener2.disconnect();
+    monitorListener.disconnect();
+    System.out.println("END TestParticipantMonitor");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/monitoring/TestStatCollector.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/TestStatCollector.java b/helix-core/src/test/java/org/apache/helix/monitoring/TestStatCollector.java
new file mode 100644
index 0000000..470baee
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/TestStatCollector.java
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.monitoring;
+
+import org.apache.helix.monitoring.StatCollector;
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TestStatCollector
+{
+  @Test(groups={ "unitTest" })
+  public void TestCollectData()
+  {
+    StatCollector collector = new StatCollector();
+    
+    int nPoints = 100;
+    for (int i = 0; i< nPoints; i++)
+    {
+      collector.addData(i*1000);
+    }
+    AssertJUnit.assertEquals(collector.getNumDataPoints(), nPoints);
+    AssertJUnit.assertEquals((long)collector.getMax(), 99000);
+    AssertJUnit.assertEquals((long)collector.getTotalSum(), 4950000);
+    AssertJUnit.assertEquals((long)collector.getPercentile(40), 39400);
+    AssertJUnit.assertEquals((long)collector.getMean(), 49500);
+    AssertJUnit.assertEquals((long)collector.getMin(), 0);
+    
+    collector.reset();
+    
+    AssertJUnit.assertEquals(collector.getNumDataPoints(), 0);
+    AssertJUnit.assertEquals((long)collector.getMax(), 0);
+    AssertJUnit.assertEquals((long)collector.getTotalSum(), 0);
+    AssertJUnit.assertEquals((long)collector.getPercentile(40), 0);
+    AssertJUnit.assertEquals((long)collector.getMean(), 0);
+    AssertJUnit.assertEquals((long)collector.getMin(), 0);
+    
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterAlertItemMBeanCollection.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterAlertItemMBeanCollection.java b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterAlertItemMBeanCollection.java
new file mode 100644
index 0000000..d9db707
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterAlertItemMBeanCollection.java
@@ -0,0 +1,255 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.monitoring.mbeans;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.AttributeNotFoundException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.MBeanException;
+import javax.management.MalformedObjectNameException;
+import javax.management.ReflectionException;
+
+import org.apache.helix.ZNRecord;
+import org.apache.helix.alerts.AlertValueAndStatus;
+import org.apache.helix.alerts.Tuple;
+import org.apache.helix.healthcheck.TestWildcardAlert.TestClusterMBeanObserver;
+import org.apache.helix.monitoring.mbeans.ClusterAlertMBeanCollection;
+import org.apache.log4j.Logger;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TestClusterAlertItemMBeanCollection
+{
+  private static final Logger _logger = Logger.getLogger(TestClusterAlertItemMBeanCollection.class);
+
+  @Test
+  public void TestAlertReportingHistory() throws InstanceNotFoundException, MalformedObjectNameException, NullPointerException, IOException, IntrospectionException, AttributeNotFoundException, ReflectionException, MBeanException
+  {
+    ClusterAlertMBeanCollection beanCollection = new ClusterAlertMBeanCollection();
+    
+    String clusterName = "TestCluster";
+    String originAlert1 = "EXP(decay(1.0)(esv4-app7*.RestQueryStats@DBName=BizProfile.MinServerLatency))CMP(GREATER)CON(10)";
+    Map<String, AlertValueAndStatus> alertResultMap1 = new HashMap<String, AlertValueAndStatus>();
+    int nAlerts1 = 5;
+    
+    String originAlert2 = "EXP(decay(1.0)(esv4-app9*.RestQueryStats@DBName=BizProfile.MaxServerLatency))CMP(GREATER)CON(10)";
+    Map<String, AlertValueAndStatus> alertResultMap2 = new HashMap<String, AlertValueAndStatus>();
+    int nAlerts2 = 3;
+    
+    TestClusterMBeanObserver jmxMBeanObserver = new TestClusterMBeanObserver(ClusterAlertMBeanCollection.DOMAIN_ALERT);
+    
+    for(int i = 0; i < nAlerts1; i++)
+    {
+      String alertName = "esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MinServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 0; i < nAlerts2; i++)
+    {
+      String alertName = "esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MaxServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    beanCollection.setAlerts(originAlert1, alertResultMap1, clusterName);
+    beanCollection.setAlerts(originAlert2, alertResultMap2, clusterName);
+    
+    beanCollection.refreshAlertDelta(clusterName);
+    String summaryKey = ClusterAlertMBeanCollection.ALERT_SUMMARY + "_" + clusterName;
+    jmxMBeanObserver.refresh();
+    
+    // Get the history list
+    String beanName = "HelixAlerts:alert=" + summaryKey;
+    Map<String, Object> beanValueMap = jmxMBeanObserver._beanValueMap.get(beanName);
+    String history1 = (String) (beanValueMap.get("AlertFiredHistory"));
+    
+    StringReader sr = new StringReader(history1);
+    ObjectMapper mapper = new ObjectMapper();
+
+    // check the history
+   
+    Map<String, String> delta = beanCollection.getRecentAlertDelta();
+    Assert.assertEquals(delta.size(), nAlerts1 + nAlerts2);
+    for(int i = 0; i < nAlerts1; i++)
+    {
+      String alertBeanName = "(esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MinServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("ON"));
+    }
+    
+    for(int i = 0; i < nAlerts2; i++)
+    {
+      String alertBeanName = "(esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MaxServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("ON"));
+    }
+    
+    alertResultMap1 = new HashMap<String, AlertValueAndStatus>();
+    for(int i = 0; i < 3; i++)
+    {
+      String alertName = "esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MinServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 3; i < 5; i++)
+    {
+      String alertName = "esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MinServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , false);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 7; i < 9; i++)
+    {
+      String alertName = "esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MinServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 0; i < 2; i++)
+    {
+      String alertName = "esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MaxServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , false);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 2; i < 3; i++)
+    {
+      String alertName = "esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MaxServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    for(int i = 7; i < 9; i++)
+    {
+      String alertName = "esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MaxServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    beanCollection.setAlerts(originAlert1, alertResultMap1, clusterName);
+    beanCollection.refreshAlertDelta(clusterName);
+    jmxMBeanObserver.refresh();
+
+    beanValueMap = jmxMBeanObserver._beanValueMap.get(beanName);
+    history1 = (String) (beanValueMap.get("AlertFiredHistory"));
+    
+    sr = new StringReader(history1);
+    mapper = new ObjectMapper();
+
+    // check the history
+    delta = beanCollection.getRecentAlertDelta();
+    Assert.assertEquals(delta.size(),  8);
+    for(int i = 3; i < 5; i++)
+    {
+      String alertBeanName = "(esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MinServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("OFF"));
+    }
+    for(int i = 7; i < 9; i++)
+    {
+      String alertBeanName = "(esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MinServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("ON"));
+    }
+    
+    for(int i = 0; i < 2; i++)
+    {
+      String alertBeanName = "(esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MaxServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("OFF"));
+    }
+    for(int i = 7; i < 9; i++)
+    {
+      String alertBeanName = "(esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName#BizProfile.MaxServerLatency)GREATER(10)";
+      Assert.assertTrue(delta.get(alertBeanName).equals("ON"));
+    }
+  }
+  @Test
+  public void TestAlertRefresh() throws InstanceNotFoundException, MalformedObjectNameException, NullPointerException, IOException, IntrospectionException, AttributeNotFoundException, ReflectionException, MBeanException, InterruptedException
+  {
+    ClusterAlertMBeanCollection beanCollection = new ClusterAlertMBeanCollection();
+    
+    String clusterName = "TestCluster";
+    String originAlert1 = "EXP(decay(1.0)(esv4-app7*.RestQueryStats@DBName=BizProfile.MinServerLatency))CMP(GREATER)CON(10)";
+    Map<String, AlertValueAndStatus> alertResultMap1 = new HashMap<String, AlertValueAndStatus>();
+    int nAlerts1 = 5;
+    
+    String originAlert2 = "EXP(decay(1.0)(esv4-app9*.RestQueryStats@DBName=BizProfile.MaxServerLatency))CMP(GREATER)CON(10)";
+    Map<String, AlertValueAndStatus> alertResultMap2 = new HashMap<String, AlertValueAndStatus>();
+    int nAlerts2 = 3;
+    
+    TestClusterMBeanObserver jmxMBeanObserver = new TestClusterMBeanObserver(ClusterAlertMBeanCollection.DOMAIN_ALERT);
+    
+    for(int i = 0; i < nAlerts1; i++)
+    {
+      String alertName = "esv4-app7" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MinServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap1.put(alertName, valueAndStatus);
+    }
+    
+    for(int i = 0; i < nAlerts2; i++)
+    {
+      String alertName = "esv4-app9" + i + ".stg.linkedin.com_12918.RestQueryStats@DBName=BizProfile.MaxServerLatency";
+      Tuple<String> value = new Tuple<String>();
+      value.add("22" + i);
+      AlertValueAndStatus valueAndStatus = new AlertValueAndStatus(value , true);
+      alertResultMap2.put(alertName, valueAndStatus);
+    }
+    
+    beanCollection.setAlerts(originAlert1, alertResultMap1, clusterName);
+    beanCollection.setAlerts(originAlert2, alertResultMap2, clusterName);
+    
+    beanCollection.refreshAlertDelta(clusterName);
+    String summaryKey = ClusterAlertMBeanCollection.ALERT_SUMMARY + "_" + clusterName;
+    jmxMBeanObserver.refresh();
+    
+    Assert.assertEquals(jmxMBeanObserver._beanValueMap.size(), nAlerts2 + nAlerts1 + 1);
+    
+    Thread.sleep(300);
+    
+    beanCollection.setAlerts(originAlert1, alertResultMap1, clusterName);
+    beanCollection.checkMBeanFreshness(200);
+    
+    Thread.sleep(500);
+    
+    jmxMBeanObserver.refresh();
+    
+    Assert.assertEquals(jmxMBeanObserver._beanValueMap.size(), nAlerts1 + 1);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterStatusMonitor.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterStatusMonitor.java b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterStatusMonitor.java
new file mode 100644
index 0000000..80c51c6
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestClusterStatusMonitor.java
@@ -0,0 +1,128 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.monitoring.mbeans;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.helix.DataAccessor;
+import org.apache.helix.HelixDataAccessor;
+import org.apache.helix.HelixProperty;
+import org.apache.helix.Mocks;
+import org.apache.helix.NotificationContext;
+import org.apache.helix.PropertyType;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.model.ExternalView;
+import org.apache.helix.model.LiveInstance;
+import org.apache.helix.model.LiveInstance.LiveInstanceProperty;
+import org.apache.helix.monitoring.mbeans.ClusterStatusMonitor;
+import org.apache.helix.tools.IdealStateCalculatorForStorageNode;
+import org.testng.annotations.Test;
+
+
+
+public class TestClusterStatusMonitor
+{
+  List<String> _instances;
+  List<ZNRecord> _liveInstances;
+  String _db = "DB";
+  String _db2 = "TestDB";
+  int _replicas = 3;
+  int _partitions = 50;
+  ZNRecord _externalView, _externalView2;
+
+  class MockDataAccessor extends Mocks.MockAccessor
+  {
+    public MockDataAccessor()
+    {
+      _instances = new ArrayList<String>();
+      for(int i = 0;i < 5; i++)
+      {
+        String instance = "localhost_"+(12918+i);
+        _instances.add(instance);
+      }
+      ZNRecord externalView = IdealStateCalculatorForStorageNode.calculateIdealState(
+          _instances, _partitions, _replicas, _db, "MASTER", "SLAVE");
+
+      ZNRecord externalView2 = IdealStateCalculatorForStorageNode.calculateIdealState(
+          _instances, 80, 2, _db2, "MASTER", "SLAVE");
+
+    }
+    public ZNRecord getProperty(PropertyType type, String resource)
+    {
+      if(type == PropertyType.IDEALSTATES || type == PropertyType.EXTERNALVIEW)
+      {
+        if(resource.equals(_db))
+        {
+          return _externalView;
+        }
+        else if(resource.equals(_db2))
+        {
+          return _externalView2;
+        }
+      }
+      return null;
+    }
+  }
+  class MockHelixManager extends Mocks.MockManager
+  {
+    MockDataAccessor _accessor = new MockDataAccessor();
+
+    @Override
+		public HelixDataAccessor getHelixDataAccessor()
+    {
+      return _accessor;
+    }
+
+  }
+  @Test()
+  public void TestReportData()
+  {
+  	System.out.println("START TestClusterStatusMonitor at" + new Date(System.currentTimeMillis()));
+    List<String> _instances;
+    List<ZNRecord> _liveInstances = new ArrayList<ZNRecord>();
+    String _db = "DB";
+    int _replicas = 3;
+    int _partitions = 50;
+
+    _instances = new ArrayList<String>();
+    for(int i = 0;i < 5; i++)
+    {
+      String instance = "localhost_"+(12918+i);
+      _instances.add(instance);
+      ZNRecord metaData = new ZNRecord(instance);
+      metaData.setSimpleField(LiveInstanceProperty.SESSION_ID.toString(),
+          UUID.randomUUID().toString());
+      _liveInstances.add(metaData);
+    }
+    ZNRecord externalView = IdealStateCalculatorForStorageNode.calculateIdealState(
+        _instances, _partitions, _replicas, _db, "MASTER", "SLAVE");
+
+    ZNRecord externalView2 = IdealStateCalculatorForStorageNode.calculateIdealState(
+        _instances, 80, 2, "TestDB", "MASTER", "SLAVE");
+
+    List<ZNRecord> externalViews = new ArrayList<ZNRecord>();
+    externalViews.add(externalView);
+    externalViews.add(externalView2);
+
+    ClusterStatusMonitor monitor = new ClusterStatusMonitor("cluster1");
+    MockHelixManager manager = new MockHelixManager();
+    NotificationContext context = new NotificationContext(manager);
+    System.out.println("END TestClusterStatusMonitor at" + new Date(System.currentTimeMillis()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestResourceMonitor.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestResourceMonitor.java b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestResourceMonitor.java
new file mode 100644
index 0000000..c044b12
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/monitoring/mbeans/TestResourceMonitor.java
@@ -0,0 +1,172 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.monitoring.mbeans;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.helix.DataAccessor;
+import org.apache.helix.HelixDataAccessor;
+import org.apache.helix.HelixProperty;
+import org.apache.helix.Mocks;
+import org.apache.helix.PropertyKey;
+import org.apache.helix.PropertyType;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.PropertyKey.Builder;
+import org.apache.helix.model.ExternalView;
+import org.apache.helix.model.IdealState;
+import org.apache.helix.model.LiveInstance.LiveInstanceProperty;
+import org.apache.helix.monitoring.mbeans.ResourceMonitor;
+import org.apache.helix.tools.IdealStateCalculatorForStorageNode;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestResourceMonitor
+{
+  String _clusterName = "Test-cluster";
+  String _dbName = "TestDB";
+  int _replicas = 3;
+  int _partitions = 50;
+
+  class MockHelixManager extends Mocks.MockManager
+  {
+    class MockDataAccessor extends Mocks.MockAccessor
+    {
+      @Override
+      public <T extends HelixProperty> List<T>  getChildValues(PropertyKey key)
+      {
+        List<T> result = new ArrayList<T>();
+        PropertyType type = key.getType();
+        Class<? extends HelixProperty> clazz = key.getTypeClass();
+        if (type == PropertyType.EXTERNALVIEW)
+        {
+          HelixProperty typedInstance = HelixProperty.convertToTypedInstance(clazz, _externalView);
+          result.add((T) typedInstance);
+          return result;
+        }
+        else if (type == PropertyType.LIVEINSTANCES)
+        {
+          return (List<T>) HelixProperty.convertToTypedList(clazz, _liveInstances);
+        }
+
+        return result;
+      }
+
+      @Override
+      public  <T extends HelixProperty> T  getProperty(PropertyKey key)
+      {
+        PropertyType type = key.getType();
+        if (type == PropertyType.EXTERNALVIEW)
+        {
+          return (T) new ExternalView(_externalView);
+        }
+        else if (type == PropertyType.IDEALSTATES)
+        {
+          return (T) new IdealState(_idealState);
+        }
+        return null;
+      }
+    }
+
+    HelixDataAccessor _accessor = new MockDataAccessor();
+    ZNRecord _idealState;
+    ZNRecord _externalView;
+    List<String> _instances;
+    List<ZNRecord> _liveInstances;
+    String _db = "DB";
+
+    public MockHelixManager()
+    {
+      _liveInstances = new ArrayList<ZNRecord>();
+      _instances = new ArrayList<String>();
+      for(int i = 0;i<5; i++)
+      {
+        String instance = "localhost_"+(12918+i);
+        _instances.add(instance);
+        ZNRecord metaData = new ZNRecord(instance);
+        metaData.setSimpleField(LiveInstanceProperty.SESSION_ID.toString(),
+            UUID.randomUUID().toString());
+
+      }
+      _idealState= IdealStateCalculatorForStorageNode.calculateIdealState(_instances,
+                                                                          _partitions,
+                                                                          _replicas,
+                                                                          _dbName,
+                                                                          "MASTER",
+                                                                          "SLAVE");
+      _externalView = new ZNRecord(_idealState);
+    }
+
+    @Override
+    public HelixDataAccessor getHelixDataAccessor()
+    {
+      return _accessor;
+    }
+
+  }
+
+  @Test()
+  public void TestReportData()
+  {
+    MockHelixManager manager = new MockHelixManager();
+    ResourceMonitor monitor = new ResourceMonitor(_clusterName, _dbName);
+
+    HelixDataAccessor helixDataAccessor = manager.getHelixDataAccessor();
+    Builder keyBuilder = helixDataAccessor.keyBuilder();
+    ExternalView externalView = 
+        helixDataAccessor.getProperty(keyBuilder.externalView(_dbName));
+    IdealState idealState = helixDataAccessor.getProperty(keyBuilder.idealStates(_dbName));
+
+    monitor.updateExternalView(externalView, idealState);
+
+    AssertJUnit.assertEquals(monitor.getDifferenceWithIdealStateGauge(), 0);
+    AssertJUnit.assertEquals(monitor.getErrorPartitionGauge(), 0);
+    AssertJUnit.assertEquals(monitor.getExternalViewPartitionGauge(), _partitions);
+    AssertJUnit.assertEquals(monitor.getPartitionGauge(), _partitions);
+    monitor.getBeanName();
+
+    int n = 4;
+    for (int i = 0; i < n; i++)
+    {
+      Map<String, String> map = externalView.getStateMap(_dbName + "_" + 3 * i);
+      String key = map.keySet().toArray()[0].toString();
+      map.put(key, "ERROR");
+      externalView.setStateMap(_dbName + "_" + 3 * i, map);
+    }
+
+    monitor.updateExternalView(externalView, idealState);
+    AssertJUnit.assertEquals(monitor.getDifferenceWithIdealStateGauge(), 0);
+    AssertJUnit.assertEquals(monitor.getErrorPartitionGauge(), n);
+    AssertJUnit.assertEquals(monitor.getExternalViewPartitionGauge(), _partitions);
+    AssertJUnit.assertEquals(monitor.getPartitionGauge(), _partitions);
+
+    n = 5;
+    for (int i = 0; i < n; i++)
+    {
+      externalView.getRecord().getMapFields().remove(_dbName + "_" + 4 * i);
+    }
+
+    monitor.updateExternalView(externalView, idealState);
+    AssertJUnit.assertEquals(monitor.getDifferenceWithIdealStateGauge(), n
+        * (_replicas + 1));
+    AssertJUnit.assertEquals(monitor.getErrorPartitionGauge(), 3);
+    AssertJUnit.assertEquals(monitor.getExternalViewPartitionGauge(), _partitions - n);
+    AssertJUnit.assertEquals(monitor.getPartitionGauge(), _partitions);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/participant/MockZKHelixManager.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/MockZKHelixManager.java b/helix-core/src/test/java/org/apache/helix/participant/MockZKHelixManager.java
new file mode 100644
index 0000000..04c41d3
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/MockZKHelixManager.java
@@ -0,0 +1,280 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.participant;
+
+import java.util.UUID;
+
+import org.apache.helix.ClusterMessagingService;
+import org.apache.helix.ConfigAccessor;
+import org.apache.helix.ConfigChangeListener;
+import org.apache.helix.ControllerChangeListener;
+import org.apache.helix.CurrentStateChangeListener;
+import org.apache.helix.DataAccessor;
+import org.apache.helix.ExternalViewChangeListener;
+import org.apache.helix.HealthStateChangeListener;
+import org.apache.helix.HelixAdmin;
+import org.apache.helix.HelixDataAccessor;
+import org.apache.helix.HelixManager;
+import org.apache.helix.IdealStateChangeListener;
+import org.apache.helix.InstanceType;
+import org.apache.helix.LiveInstanceChangeListener;
+import org.apache.helix.MessageListener;
+import org.apache.helix.PreConnectCallback;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.healthcheck.ParticipantHealthReportCollector;
+import org.apache.helix.manager.zk.ZKHelixDataAccessor;
+import org.apache.helix.manager.zk.ZkBaseDataAccessor;
+import org.apache.helix.manager.zk.ZkClient;
+import org.apache.helix.participant.StateMachineEngine;
+import org.apache.helix.store.PropertyStore;
+import org.apache.helix.store.zk.ZkHelixPropertyStore;
+
+
+public class MockZKHelixManager implements HelixManager
+{
+  private final ZKHelixDataAccessor _accessor;
+  private final String              _instanceName;
+  private final String              _clusterName;
+  private final InstanceType        _type;
+
+  public MockZKHelixManager(String clusterName,
+                            String instanceName,
+                            InstanceType type,
+                            ZkClient zkClient)
+  {
+    _instanceName = instanceName;
+    _clusterName = clusterName;
+    _type = type;
+    _accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(zkClient));
+  }
+
+  @Override
+  public void connect() throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public boolean isConnected()
+  {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  @Override
+  public void disconnect()
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addIdealStateChangeListener(IdealStateChangeListener listener) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addLiveInstanceChangeListener(LiveInstanceChangeListener listener) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addConfigChangeListener(ConfigChangeListener listener) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addMessageListener(MessageListener listener, String instanceName) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addCurrentStateChangeListener(CurrentStateChangeListener listener,
+                                            String instanceName,
+                                            String sessionId) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void addExternalViewChangeListener(ExternalViewChangeListener listener) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public boolean removeListener(Object listener)
+  {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  @Override
+  public HelixDataAccessor getHelixDataAccessor()
+  {
+    return _accessor;
+  }
+
+  @Override
+  public String getClusterName()
+  {
+    return _clusterName;
+  }
+
+  @Override
+  public String getInstanceName()
+  {
+    return _instanceName;
+  }
+
+  @Override
+  public String getSessionId()
+  {
+    // TODO Auto-generated method stub
+    return UUID.randomUUID().toString();
+  }
+
+  @Override
+  public long getLastNotificationTime()
+  {
+    // TODO Auto-generated method stub
+    return 0;
+  }
+
+  @Override
+  public void addControllerListener(ControllerChangeListener listener)
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public HelixAdmin getClusterManagmentTool()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public PropertyStore<ZNRecord> getPropertyStore()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public ClusterMessagingService getMessagingService()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public ParticipantHealthReportCollector getHealthReportCollector()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public InstanceType getInstanceType()
+  {
+    return _type;
+  }
+
+  @Override
+  public void addHealthStateChangeListener(HealthStateChangeListener listener,
+                                           String instanceName) throws Exception
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public String getVersion()
+  {
+    // TODO Auto-generated method stub
+    return UUID.randomUUID().toString();
+  }
+
+  @Override
+  public StateMachineEngine getStateMachineEngine()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public boolean isLeader()
+  {
+    // TODO Auto-generated method stub
+    return false;
+  }
+
+  @Override
+  public ConfigAccessor getConfigAccessor()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void startTimerTasks()
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void stopTimerTasks()
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public DataAccessor getDataAccessor()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public void addPreConnectCallback(PreConnectCallback callback)
+  {
+    // TODO Auto-generated method stub
+    
+  }
+
+  @Override
+  public ZkHelixPropertyStore<ZNRecord> getHelixPropertyStore()
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerElection.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerElection.java b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerElection.java
new file mode 100644
index 0000000..9b0f166
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerElection.java
@@ -0,0 +1,181 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.participant;
+
+import java.util.Date;
+
+import org.apache.helix.HelixManager;
+import org.apache.helix.InstanceType;
+import org.apache.helix.NotificationContext;
+import org.apache.helix.PropertyPathConfig;
+import org.apache.helix.PropertyType;
+import org.apache.helix.TestHelper;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.PropertyKey.Builder;
+import org.apache.helix.manager.zk.ZKHelixDataAccessor;
+import org.apache.helix.manager.zk.ZkBaseDataAccessor;
+import org.apache.helix.model.LiveInstance;
+import org.apache.helix.participant.DistClusterControllerElection;
+import org.apache.log4j.Logger;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestDistControllerElection extends ZkUnitTestBase
+{
+  private static Logger LOG = Logger.getLogger(TestDistControllerElection.class);
+
+  @Test()
+  public void testController() throws Exception
+  {
+    System.out.println("START TestDistControllerElection at "
+        + new Date(System.currentTimeMillis()));
+    String className = getShortClassName();
+
+    final String clusterName = CLUSTER_PREFIX + "_" + className + "_" + "testController";
+    String path = "/" + clusterName;
+    if (_gZkClient.exists(path))
+    {
+      _gZkClient.deleteRecursive(path);
+    }
+   
+    ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient));
+    Builder keyBuilder = accessor.keyBuilder();
+
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+
+    final String controllerName = "controller_0";
+    HelixManager manager = new MockZKHelixManager(clusterName, controllerName,
+                               InstanceType.CONTROLLER,
+                               _gZkClient);
+
+    DistClusterControllerElection election = new DistClusterControllerElection(ZK_ADDR);
+    NotificationContext context = new NotificationContext(manager);
+    context.setType(NotificationContext.Type.INIT);
+    election.onControllerChange(context);
+
+//    path = PropertyPathConfig.getPath(PropertyType.LEADER, clusterName);
+//    ZNRecord leaderRecord = _gZkClient.<ZNRecord> readData(path);
+    LiveInstance liveInstance = accessor.getProperty(keyBuilder.controllerLeader());
+    AssertJUnit.assertEquals(controllerName, liveInstance.getInstanceName());
+    // AssertJUnit.assertNotNull(election.getController());
+    // AssertJUnit.assertNull(election.getLeader());
+
+    manager = new MockZKHelixManager(clusterName, "controller_1", InstanceType.CONTROLLER,
+                               _gZkClient);
+    election = new DistClusterControllerElection(ZK_ADDR);
+    context = new NotificationContext(manager);
+    context.setType(NotificationContext.Type.INIT);
+    election.onControllerChange(context);
+//    leaderRecord = _gZkClient.<ZNRecord> readData(path);
+    liveInstance = accessor.getProperty(keyBuilder.controllerLeader());
+    AssertJUnit.assertEquals(controllerName, liveInstance.getInstanceName());
+    // AssertJUnit.assertNull(election.getController());
+    // AssertJUnit.assertNull(election.getLeader());
+
+    System.out.println("END TestDistControllerElection at " + new Date(System.currentTimeMillis()));
+  }
+
+  @Test()
+  public void testControllerParticipant() throws Exception
+  {
+    String className = getShortClassName();
+    LOG.info("RUN " + className + " at " + new Date(System.currentTimeMillis()));
+
+    final String clusterName = CONTROLLER_CLUSTER_PREFIX + "_" + className + "_"
+        + "testControllerParticipant";
+    String path = "/" + clusterName;
+    if (_gZkClient.exists(path))
+    {
+      _gZkClient.deleteRecursive(path);
+    }
+    
+    ZKHelixDataAccessor accessor = new ZKHelixDataAccessor(clusterName, new ZkBaseDataAccessor(_gZkClient));
+    Builder keyBuilder = accessor.keyBuilder();
+
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+
+    final String controllerName = "controller_0";
+    HelixManager manager = new MockZKHelixManager(clusterName, controllerName,
+                               InstanceType.CONTROLLER_PARTICIPANT,
+                               _gZkClient);
+
+    DistClusterControllerElection election = new DistClusterControllerElection(ZK_ADDR);
+    NotificationContext context = new NotificationContext(manager);
+    context.setType(NotificationContext.Type.CALLBACK);
+    election.onControllerChange(context);
+
+    LiveInstance liveInstance = accessor.getProperty(keyBuilder.controllerLeader());
+    AssertJUnit.assertEquals(controllerName, liveInstance.getInstanceName());
+
+//    path = PropertyPathConfig.getPath(PropertyType.LEADER, clusterName);
+//    ZNRecord leaderRecord = _gZkClient.<ZNRecord> readData(path);
+//    AssertJUnit.assertEquals(controllerName, leaderRecord.getSimpleField("LEADER"));
+    // AssertJUnit.assertNotNull(election.getController());
+    // AssertJUnit.assertNotNull(election.getLeader());
+
+    manager = new MockZKHelixManager(clusterName, "controller_1",
+                               InstanceType.CONTROLLER_PARTICIPANT,
+                               _gZkClient);
+    election = new DistClusterControllerElection(ZK_ADDR);
+    context = new NotificationContext(manager);
+    context.setType(NotificationContext.Type.CALLBACK);
+    election.onControllerChange(context);
+
+    liveInstance = accessor.getProperty(keyBuilder.controllerLeader());
+    AssertJUnit.assertEquals(controllerName, liveInstance.getInstanceName());
+
+//    leaderRecord = _gZkClient.<ZNRecord> readData(path);
+//    AssertJUnit.assertEquals(controllerName, leaderRecord.getSimpleField("LEADER"));
+    // AssertJUnit.assertNull(election.getController());
+    // AssertJUnit.assertNull(election.getLeader());
+
+    LOG.info("END " + getShortClassName() + " at " + new Date(System.currentTimeMillis()));
+  }
+
+  @Test()
+  public void testParticipant() throws Exception
+  {
+    String className = getShortClassName();
+    LOG.info("RUN " + className + " at " + new Date(System.currentTimeMillis()));
+
+    final String clusterName = CLUSTER_PREFIX + "_" + className + "_" + "testParticipant";
+    String path = "/" + clusterName;
+    if (_gZkClient.exists(path))
+    {
+      _gZkClient.deleteRecursive(path);
+    }
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+
+    final String controllerName = "participant_0";
+    HelixManager manager = new MockZKHelixManager(clusterName, controllerName,
+                               InstanceType.PARTICIPANT,
+                               _gZkClient);
+
+    DistClusterControllerElection election = new DistClusterControllerElection(ZK_ADDR);
+    NotificationContext context = new NotificationContext(manager);
+    context.setType(NotificationContext.Type.INIT);
+    election.onControllerChange(context);
+
+    path = PropertyPathConfig.getPath(PropertyType.LEADER, clusterName);
+    ZNRecord leaderRecord = _gZkClient.<ZNRecord> readData(path, true);
+    AssertJUnit.assertNull(leaderRecord);
+    // AssertJUnit.assertNull(election.getController());
+    // AssertJUnit.assertNull(election.getLeader());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
new file mode 100644
index 0000000..3f57bbf
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModel.java
@@ -0,0 +1,135 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.participant;
+
+import org.apache.helix.NotificationContext;
+import org.apache.helix.TestHelper;
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.model.Message;
+import org.apache.helix.model.Message.MessageType;
+import org.apache.helix.participant.DistClusterControllerStateModel;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+public class TestDistControllerStateModel extends ZkUnitTestBase
+{
+  final String clusterName = CLUSTER_PREFIX + "_" + getShortClassName();
+  DistClusterControllerStateModel stateModel = null;
+
+  @BeforeMethod()
+  public void beforeMethod()
+  {
+    stateModel = new DistClusterControllerStateModel(ZK_ADDR);
+    if (_gZkClient.exists("/" + clusterName))
+    {
+      _gZkClient.deleteRecursive("/" + clusterName);
+    }
+    TestHelper.setupEmptyCluster(_gZkClient, clusterName);
+  }
+
+  @Test()
+  public void testOnBecomeStandbyFromOffline()
+  {
+    stateModel.onBecomeStandbyFromOffline(null, null);
+  }
+
+  @Test()
+  public void testOnBecomeLeaderFromStandby()
+  {
+    Message message = new Message(MessageType.STATE_TRANSITION, "0");
+    message.setPartitionName(clusterName);
+    message.setTgtName("controller_0");
+    try
+    {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    }
+    catch (Exception e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
+  }
+
+  @Test()
+  public void testOnBecomeStandbyFromLeader()
+  {
+    Message message = new Message(MessageType.STATE_TRANSITION, "0");
+    message.setPartitionName(clusterName);
+    message.setTgtName("controller_0");
+    stateModel.onBecomeStandbyFromLeader(message, new NotificationContext(null));
+  }
+
+  @Test()
+  public void testOnBecomeOfflineFromStandby()
+  {
+    Message message = new Message(MessageType.STATE_TRANSITION, "0");
+    message.setPartitionName(clusterName);
+    message.setTgtName("controller_0");
+
+    stateModel.onBecomeOfflineFromStandby(message, null);
+  }
+
+  @Test()
+  public void testOnBecomeDroppedFromOffline()
+  {
+    stateModel.onBecomeDroppedFromOffline(null, null);
+  }
+
+  @Test()
+  public void testOnBecomeOfflineFromDropped()
+  {
+    stateModel.onBecomeOfflineFromDropped(null, null);
+  }
+
+  @Test()
+  public void testRollbackOnError()
+  {
+    Message message = new Message(MessageType.STATE_TRANSITION, "0");
+    message.setPartitionName(clusterName);
+    message.setTgtName("controller_0");
+    try
+    {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    }
+    catch (Exception e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    stateModel.rollbackOnError(message, new NotificationContext(null), null);
+  }
+
+  @Test()
+  public void testReset()
+  {
+    Message message = new Message(MessageType.STATE_TRANSITION, "0");
+    message.setPartitionName(clusterName);
+    message.setTgtName("controller_0");
+    try
+    {
+      stateModel.onBecomeLeaderFromStandby(message, new NotificationContext(null));
+    }
+    catch (Exception e)
+    {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    stateModel.reset();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
new file mode 100644
index 0000000..554dca4
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/participant/TestDistControllerStateModelFactory.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.participant;
+
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.participant.DistClusterControllerStateModel;
+import org.apache.helix.participant.DistClusterControllerStateModelFactory;
+import org.testng.annotations.Test;
+import org.testng.annotations.Test;
+
+
+public class TestDistControllerStateModelFactory
+{
+  final String zkAddr = ZkUnitTestBase.ZK_ADDR;
+      
+  @Test(groups = { "unitTest" })
+  public void testDistControllerStateModelFactory()
+  {
+    DistClusterControllerStateModelFactory factory = new DistClusterControllerStateModelFactory(zkAddr);
+    DistClusterControllerStateModel stateModel = factory.createNewStateModel("key");
+    stateModel.onBecomeStandbyFromOffline(null, null);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/TestJsonComparator.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/TestJsonComparator.java b/helix-core/src/test/java/org/apache/helix/store/TestJsonComparator.java
new file mode 100644
index 0000000..bd7a66f
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/TestJsonComparator.java
@@ -0,0 +1,40 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store;
+
+import java.util.Date;
+
+import org.apache.helix.ZNRecord;
+import org.apache.helix.store.PropertyJsonComparator;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestJsonComparator
+{
+  @Test (groups = {"unitTest"})
+  public void testJsonComparator()
+  {
+    System.out.println("START TestJsonComparator at " + new Date(System.currentTimeMillis()));
+
+    ZNRecord record = new ZNRecord("id1");
+    PropertyJsonComparator<ZNRecord> comparator = new PropertyJsonComparator<ZNRecord>(ZNRecord.class);
+    AssertJUnit.assertTrue(comparator.compare(null, null) == 0);
+    AssertJUnit.assertTrue(comparator.compare(null, record) == -1);
+    AssertJUnit.assertTrue(comparator.compare(record, null) == 1);
+    System.out.println("END TestJsonComparator at " + new Date(System.currentTimeMillis()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/TestPropertyStat.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/TestPropertyStat.java b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStat.java
new file mode 100644
index 0000000..bfeb212
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStat.java
@@ -0,0 +1,35 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store;
+
+import org.apache.helix.store.PropertyStat;
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestPropertyStat
+{
+  @Test (groups = {"unitTest"})
+  public void testPropertyStat()
+  {
+    PropertyStat stat = new PropertyStat(0, 0);
+    AssertJUnit.assertEquals(0, stat.getLastModifiedTime());
+    AssertJUnit.assertEquals(0, stat.getVersion());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreException.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreException.java b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreException.java
new file mode 100644
index 0000000..813c96d
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreException.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store;
+
+import org.apache.helix.store.PropertyStoreException;
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestPropertyStoreException
+{
+  @Test (groups = {"unitTest"})
+  public void testPropertyStoreException()
+  {
+    PropertyStoreException exception = new PropertyStoreException("msg");
+    AssertJUnit.assertEquals(exception.getMessage(), "msg");
+    
+    exception = new PropertyStoreException();
+    AssertJUnit.assertNull(exception.getMessage());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreFactory.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreFactory.java b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreFactory.java
new file mode 100644
index 0000000..c2fd8c1
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/TestPropertyStoreFactory.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store;
+
+import org.apache.helix.ZNRecord;
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.store.PropertyJsonComparator;
+import org.apache.helix.store.PropertyJsonSerializer;
+import org.apache.helix.store.PropertyStore;
+import org.apache.helix.store.PropertyStoreFactory;
+import org.testng.Assert;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestPropertyStoreFactory extends ZkUnitTestBase
+{
+  @Test()
+  public void testZkPropertyStoreFactory()
+  {
+
+    try
+    {
+      PropertyStoreFactory.<ZNRecord> getZKPropertyStore(null, null, null);
+      Assert.fail("Should fail since zkAddr|serializer|root can't be null");
+    }
+    catch (IllegalArgumentException e)
+    {
+      // OK
+    }
+    
+    final String rootNamespace = "TestPropertyStoreFactory";
+    PropertyJsonSerializer<ZNRecord> serializer =
+        new PropertyJsonSerializer<ZNRecord>(ZNRecord.class);
+    try
+    {
+      PropertyStoreFactory.<ZNRecord> getZKPropertyStore("localhost:1812", serializer, rootNamespace);
+      Assert.fail("Should fail since zkAddr is not connectable");
+    }
+    catch (Exception e)
+    {
+      // OK
+    }
+
+    PropertyStore<ZNRecord> store =
+        PropertyStoreFactory.<ZNRecord> getZKPropertyStore(ZK_ADDR,
+                                                           serializer,
+                                                           rootNamespace);
+    Assert.assertNotNull(store);
+  }
+
+  @Test()
+  public void testFilePropertyStoreFactory()
+  {
+    final String rootNamespace = "/tmp/TestPropertyStoreFactory";
+    PropertyJsonSerializer<ZNRecord> serializer =
+        new PropertyJsonSerializer<ZNRecord>(ZNRecord.class);
+    PropertyJsonComparator<ZNRecord> comparator =
+        new PropertyJsonComparator<ZNRecord>(ZNRecord.class);
+    PropertyStore<ZNRecord> store;
+
+    boolean exceptionCaught = false;
+    try
+    {
+      store = PropertyStoreFactory.<ZNRecord> getFilePropertyStore(null, null, null);
+    }
+    catch (IllegalArgumentException e)
+    {
+      exceptionCaught = true;
+    }
+    AssertJUnit.assertTrue(exceptionCaught);
+
+    store =
+        PropertyStoreFactory.<ZNRecord> getFilePropertyStore(serializer,
+                                                             rootNamespace,
+                                                             comparator);
+    Assert.assertNotNull(store);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/TestZNRecordJsonSerializer.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/TestZNRecordJsonSerializer.java b/helix-core/src/test/java/org/apache/helix/store/TestZNRecordJsonSerializer.java
new file mode 100644
index 0000000..56ffce3
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/TestZNRecordJsonSerializer.java
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.helix.ZNRecord;
+import org.apache.helix.ZkUnitTestBase;
+import org.apache.helix.manager.zk.ZkClient;
+import org.apache.helix.store.ZNRecordJsonSerializer;
+import org.apache.helix.store.zk.ZKPropertyStore;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TestZNRecordJsonSerializer extends ZkUnitTestBase
+{
+
+  @Test
+  public void testZNRecordJsonSerializer() throws Exception
+  {
+    final String testRoot = getShortClassName();
+
+    System.out.println("START " + testRoot + " at " + new Date(System.currentTimeMillis()));
+
+    ZNRecord record = new ZNRecord("node1");
+    record.setSimpleField(ZNRecord.LIST_FIELD_BOUND, "" + 3);
+    List<String> list1 = Arrays.asList("one", "two", "three", "four");
+    List<String> list2 = Arrays.asList("a", "b", "c", "d");
+    List<String> list3 = Arrays.asList("x", "y");
+    record.setListField("list1", list1);
+    record.setListField("list2", list2);
+    record.setListField("list3", list3);
+
+    ZKPropertyStore<ZNRecord> store = new ZKPropertyStore<ZNRecord>(new ZkClient(ZK_ADDR),
+        new ZNRecordJsonSerializer(), "/" + testRoot);
+
+    store.setProperty("node1", record);
+    ZNRecord newRecord = store.getProperty("node1");
+    list1 = newRecord.getListField("list1");
+    Assert.assertTrue(list1.size() == 3);
+    Assert.assertTrue(list1.contains("one"));
+    Assert.assertTrue(list1.contains("two"));
+    Assert.assertTrue(list1.contains("three"));
+
+    list2 = newRecord.getListField("list2");
+    Assert.assertTrue(list2.size() == 3);
+    Assert.assertTrue(list2.contains("a"));
+    Assert.assertTrue(list2.contains("b"));
+    Assert.assertTrue(list2.contains("c"));
+
+    list3 = newRecord.getListField("list3");
+    Assert.assertTrue(list3.size() == 2);
+    Assert.assertTrue(list3.contains("x"));
+    Assert.assertTrue(list3.contains("y"));
+
+    System.out.println("END " + testRoot + " at " + new Date(System.currentTimeMillis()));
+
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-helix/blob/437eb42e/helix-core/src/test/java/org/apache/helix/store/file/TestFilePropertyStore.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/store/file/TestFilePropertyStore.java b/helix-core/src/test/java/org/apache/helix/store/file/TestFilePropertyStore.java
new file mode 100644
index 0000000..b665621
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/store/file/TestFilePropertyStore.java
@@ -0,0 +1,156 @@
+/**
+ * Copyright (C) 2012 LinkedIn Inc <op...@linkedin.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.helix.store.file;
+
+import java.util.Date;
+import java.util.List;
+
+import org.I0Itec.zkclient.DataUpdater;
+import org.apache.helix.store.PropertyChangeListener;
+import org.apache.helix.store.PropertyJsonComparator;
+import org.apache.helix.store.PropertyJsonSerializer;
+import org.apache.helix.store.file.FilePropertyStore;
+import org.apache.log4j.Logger;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+
+public class TestFilePropertyStore
+{
+  private static Logger logger = Logger.getLogger(TestFilePropertyStore.class);
+  private static final String rootNamespace = "/tmp/TestFilePropertyStore";
+
+  public class TestPropertyChangeListener implements PropertyChangeListener<String>
+  {
+    public boolean _propertyChangeReceived = false;
+
+    @Override
+    public void onPropertyChange(String key)
+    {
+      logger.info("property changed at " + key);
+      _propertyChangeReceived = true;
+    }
+
+  }
+
+  public class TestUpdater implements DataUpdater<String>
+  {
+
+    @Override
+    public String update(String currentData)
+    {
+      return "new " + currentData;
+    }
+
+  }
+
+  @Test (groups = {"unitTest"})
+  public void testFilePropertyStore() throws Exception
+  {
+    System.out.println("START TestFilePropertyStore at " + new Date(System.currentTimeMillis()));
+
+    final int SLEEP_TIME = 2000;
+    PropertyJsonSerializer<String> serializer = new PropertyJsonSerializer<String>(String.class);
+    PropertyJsonComparator<String> comparator = new PropertyJsonComparator<String>(String.class);
+
+    FilePropertyStore<String> store = new FilePropertyStore<String>(serializer, rootNamespace,
+        comparator);
+    // store.removeRootNamespace();
+    // store.createRootNamespace();
+    store.start();
+
+    // test set
+    store.createPropertyNamespace("/child1");
+    store.setProperty("/child1/grandchild1", "grandchild1\n");
+    store.setProperty("/child1/grandchild2", "grandchild2\n");
+    store.createPropertyNamespace("/child1/grandchild3");
+    store.setProperty("/child1/grandchild3/grandgrandchild1", "grandgrandchild1\n");
+
+    // test get-names
+    List<String> names = store.getPropertyNames("/child1");
+    AssertJUnit.assertEquals(names.size(), 3);
+    AssertJUnit.assertTrue(names.contains("/child1/grandchild1"));
+    AssertJUnit.assertTrue(names.contains("/child1/grandchild2"));
+    AssertJUnit.assertTrue(names.contains("/child1/grandchild3/grandgrandchild1"));
+
+    // test get
+    String value = store.getProperty("nonExist");
+    AssertJUnit.assertEquals(value, null);
+    value = store.getProperty("/child1/grandchild2");
+    AssertJUnit.assertEquals(value, "grandchild2\n");
+    Thread.sleep(SLEEP_TIME);
+
+    // test subscribe
+    TestPropertyChangeListener listener1 = new TestPropertyChangeListener();
+    TestPropertyChangeListener listener2 = new TestPropertyChangeListener();
+
+    store.subscribeForPropertyChange("/child1", listener1);
+    store.subscribeForPropertyChange("/child1", listener1);
+    store.subscribeForPropertyChange("/child1", listener2);
+
+    store.setProperty("/child1/grandchild2", "grandchild2-new\n");
+    Thread.sleep(SLEEP_TIME);
+    AssertJUnit.assertEquals(listener1._propertyChangeReceived, true);
+    AssertJUnit.assertEquals(listener2._propertyChangeReceived, true);
+
+    listener1._propertyChangeReceived = false;
+    listener2._propertyChangeReceived = false;
+
+    // test unsubscribe
+    store.unsubscribeForPropertyChange("/child1", listener1);
+    store.setProperty("/child1/grandchild3/grandgrandchild1", "grandgrandchild1-new\n");
+    Thread.sleep(SLEEP_TIME);
+
+    AssertJUnit.assertEquals(listener1._propertyChangeReceived, false);
+    AssertJUnit.assertEquals(listener2._propertyChangeReceived, true);
+
+    listener2._propertyChangeReceived = false;
+
+    // test update property
+    store.updatePropertyUntilSucceed("child1/grandchild2", new TestUpdater());
+    value = store.getProperty("child1/grandchild2");
+    AssertJUnit.assertEquals("new grandchild2-new\n", value);
+
+    // test remove
+    store.removeProperty("/child1/grandchild2");
+    value = store.getProperty("/child1/grandchild2");
+    AssertJUnit.assertEquals(value, null);
+    Thread.sleep(SLEEP_TIME);
+    AssertJUnit.assertEquals(listener2._propertyChangeReceived, true);
+    listener2._propertyChangeReceived = false;
+
+    // test compare and set
+    boolean success = store.compareAndSet("/child1/grandchild1", "grandchild1-old\n",
+                                          "grandchild1-new\n", comparator);
+    AssertJUnit.assertEquals(success, false);
+
+    success = store.compareAndSet("/child1/grandchild1", "grandchild1\n",
+                                  "grandchild1-new\n", comparator);
+    AssertJUnit.assertEquals(success, true);
+
+    store.stop();
+
+    // test stop
+    listener2._propertyChangeReceived = false;
+    store.setProperty("/child1/grandchild3/grandgrandchild1", "grandgrandchild1-new-new\n");
+    Thread.sleep(SLEEP_TIME);
+    AssertJUnit.assertEquals(listener2._propertyChangeReceived, false);
+
+    store.unsubscribeForPropertyChange("/child1", listener2);
+    // store.stop();
+    System.out.println("END TestFilePropertyStore at " + new Date(System.currentTimeMillis()));
+  }
+}