You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@helix.apache.org by ka...@apache.org on 2015/11/02 00:01:29 UTC

[2/5] helix git commit: Added unit tests for CriteriaEvaluator

Added unit tests for CriteriaEvaluator

Signed-off-by: Yinan Li <li...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/helix/repo
Commit: http://git-wip-us.apache.org/repos/asf/helix/commit/2a2908ac
Tree: http://git-wip-us.apache.org/repos/asf/helix/tree/2a2908ac
Diff: http://git-wip-us.apache.org/repos/asf/helix/diff/2a2908ac

Branch: refs/heads/master
Commit: 2a2908ac3d536cf3595bb2eb23d49c8153c51d5e
Parents: 70962a0
Author: Yinan Li <li...@gmail.com>
Authored: Tue Sep 8 14:38:07 2015 -0700
Committer: Yinan Li <li...@gmail.com>
Committed: Tue Sep 8 14:38:07 2015 -0700

----------------------------------------------------------------------
 .../helix/messaging/CriteriaEvaluator.java      |  19 +-
 .../helix/messaging/CriteriaEvaluatorTest.java  | 184 +++++++++++++++++++
 2 files changed, 196 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/helix/blob/2a2908ac/helix-core/src/main/java/org/apache/helix/messaging/CriteriaEvaluator.java
----------------------------------------------------------------------
diff --git a/helix-core/src/main/java/org/apache/helix/messaging/CriteriaEvaluator.java b/helix-core/src/main/java/org/apache/helix/messaging/CriteriaEvaluator.java
index c57992f..11f4b82 100644
--- a/helix-core/src/main/java/org/apache/helix/messaging/CriteriaEvaluator.java
+++ b/helix-core/src/main/java/org/apache/helix/messaging/CriteriaEvaluator.java
@@ -33,6 +33,7 @@ import org.apache.helix.HelixProperty;
 import org.apache.helix.PropertyKey;
 import org.apache.log4j.Logger;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
@@ -71,7 +72,9 @@ public class CriteriaEvaluator {
     Set<String> liveParticipants = accessor.getChildValuesMap(keyBuilder.liveInstances()).keySet();
     List<ZNRecordRow> result = Lists.newArrayList();
     for (ZNRecordRow row : allRows) {
-      if (rowMatches(recipientCriteria, row) && liveParticipants.contains(row.getMapSubKey())) {
+      // The participant instance name is stored in the return value of either getRecordId() or getMapSubKey()
+      if (rowMatches(recipientCriteria, row) &&
+          (liveParticipants.contains(row.getRecordId()) || liveParticipants.contains(row.getMapSubKey()))) {
         result.add(row);
       }
     }
@@ -81,8 +84,9 @@ public class CriteriaEvaluator {
     // deduplicate and convert the matches into the required format
     for (ZNRecordRow row : result) {
       Map<String, String> resultRow = new HashMap<String, String>();
-      resultRow.put("instanceName",
-          !recipientCriteria.getInstanceName().equals("") ? row.getMapSubKey() : "");
+      resultRow.put("instanceName", !recipientCriteria.getInstanceName().equals("") ?
+          (!Strings.isNullOrEmpty(row.getMapSubKey()) ? row.getMapSubKey() : row.getRecordId()) :
+          "");
       resultRow.put("resourceName", !recipientCriteria.getResource().equals("") ? row.getRecordId()
           : "");
       resultRow.put("partitionName", !recipientCriteria.getPartition().equals("") ? row.getMapKey()
@@ -106,10 +110,11 @@ public class CriteriaEvaluator {
     String resourceName = normalizePattern(criteria.getResource());
     String partitionName = normalizePattern(criteria.getPartition());
     String partitionState = normalizePattern(criteria.getPartitionState());
-    return stringMatches(instanceName, row.getMapSubKey())
-        && stringMatches(resourceName, row.getRecordId())
-        && stringMatches(partitionName, row.getMapKey())
-        && stringMatches(partitionState, row.getMapValue());
+    return (stringMatches(instanceName, Strings.nullToEmpty(row.getMapSubKey())) ||
+            stringMatches(instanceName, Strings.nullToEmpty(row.getRecordId())))
+        && stringMatches(resourceName, Strings.nullToEmpty(row.getRecordId()))
+        && stringMatches(partitionName, Strings.nullToEmpty(row.getMapKey()))
+        && stringMatches(partitionState, Strings.nullToEmpty(row.getMapValue()));
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/helix/blob/2a2908ac/helix-core/src/test/java/org/apache/helix/messaging/CriteriaEvaluatorTest.java
----------------------------------------------------------------------
diff --git a/helix-core/src/test/java/org/apache/helix/messaging/CriteriaEvaluatorTest.java b/helix-core/src/test/java/org/apache/helix/messaging/CriteriaEvaluatorTest.java
new file mode 100644
index 0000000..d1b307c
--- /dev/null
+++ b/helix-core/src/test/java/org/apache/helix/messaging/CriteriaEvaluatorTest.java
@@ -0,0 +1,184 @@
+package org.apache.helix.messaging;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import java.util.List;
+import java.util.Map;
+
+import java.util.Set;
+import java.util.UUID;
+import org.apache.helix.Criteria;
+import org.apache.helix.HelixDataAccessor;
+import org.apache.helix.HelixManager;
+import org.apache.helix.HelixProperty;
+import org.apache.helix.InstanceType;
+import org.apache.helix.Mocks;
+import org.apache.helix.PropertyKey;
+import org.apache.helix.PropertyType;
+import org.apache.helix.ZNRecord;
+import org.apache.helix.controller.strategy.DefaultTwoStateStrategy;
+import org.apache.helix.model.IdealState;
+import org.apache.helix.model.LiveInstance;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Unit tests for {@link CriteriaEvaluator}.
+ *
+ * @author liyinan926
+ */
+@Test(groups = { "org.apache.helix.messaging" })
+public class CriteriaEvaluatorTest {
+
+  private static final String RESOURCE_NAME = "DB";
+  private static final int REPLICAS = 1;
+  private static final int PARTITIONS = 20;
+  private static final int PARTICIPANTS = 5;
+  private static final String INSTANCE_NAME_PREFIX = "localhost_";
+
+  private HelixManager _helixManager;
+
+  @BeforeClass
+  public void setUp() throws Exception {
+    _helixManager = new MockHelixManager();
+    _helixManager.connect();
+  }
+
+  @Test
+  public void testEvaluateCriteria() {
+    CriteriaEvaluator criteriaEvaluator = new CriteriaEvaluator();
+
+    Criteria recipientCriteria = new Criteria();
+    recipientCriteria.setInstanceName("%");
+    recipientCriteria.setResource("%");
+    recipientCriteria.setPartition("%");
+    recipientCriteria.setRecipientInstanceType(InstanceType.PARTICIPANT);
+    recipientCriteria.setDataSource(Criteria.DataSource.LIVEINSTANCES);
+
+    List<Map<String, String>> result = criteriaEvaluator.evaluateCriteria(recipientCriteria, _helixManager);
+    Assert.assertEquals(result.size(), 5);
+
+    Set<String> expectedInstances = Sets.newHashSet();
+    for (int i = 0; i < PARTICIPANTS; i++) {
+      expectedInstances.add(INSTANCE_NAME_PREFIX + i);
+    }
+
+    Set<String> actualInstances = Sets.newHashSet();
+    for (Map<String, String> row : result) {
+      actualInstances.add(row.get("instanceName"));
+    }
+
+    Assert.assertEquals(actualInstances, expectedInstances);
+
+    recipientCriteria.setInstanceName(INSTANCE_NAME_PREFIX + 2);
+    result = criteriaEvaluator.evaluateCriteria(recipientCriteria, _helixManager);
+    Assert.assertEquals(result.size(), 1);
+    Assert.assertEquals(result.get(0).get("instanceName"), INSTANCE_NAME_PREFIX + 2);
+
+    recipientCriteria.setInstanceName("%");
+    recipientCriteria.setDataSource(Criteria.DataSource.IDEALSTATES);
+    result = criteriaEvaluator.evaluateCriteria(recipientCriteria, _helixManager);
+    Assert.assertEquals(result.size(), 40);
+
+    recipientCriteria.setInstanceName(INSTANCE_NAME_PREFIX + 4);
+    result = criteriaEvaluator.evaluateCriteria(recipientCriteria, _helixManager);
+    Assert.assertEquals(result.size(), 8);
+  }
+
+  @AfterClass
+  public void tearDown() {
+    this._helixManager.disconnect();
+  }
+
+  private static class MockHelixManager extends Mocks.MockManager {
+
+    @SuppressWarnings("unchecked")
+    private class MockDataAccessor extends Mocks.MockAccessor {
+
+      @Override
+      public <T extends HelixProperty> T getProperty(PropertyKey key) {
+        PropertyType type = key.getType();
+
+        if (type == PropertyType.EXTERNALVIEW || type == PropertyType.IDEALSTATES) {
+          return (T) new IdealState(_idealState);
+        }
+
+        return null;
+      }
+
+      @Override
+      public <T extends HelixProperty> List<T> getChildValues(PropertyKey key) {
+        PropertyType type = key.getType();
+        Class<? extends HelixProperty> clazz = key.getTypeClass();
+        if (type == PropertyType.EXTERNALVIEW || type == PropertyType.IDEALSTATES) {
+          HelixProperty typedInstance = HelixProperty.convertToTypedInstance(clazz, _idealState);
+          return Lists.newArrayList((T) typedInstance);
+        } else if (type == PropertyType.INSTANCES || type == PropertyType.LIVEINSTANCES) {
+          return (List<T>) HelixProperty.convertToTypedList(clazz, _liveInstances);
+        }
+
+        return Lists.newArrayList();
+      }
+    }
+
+    private final HelixDataAccessor _accessor = new MockDataAccessor();
+    private final ZNRecord _idealState;
+    private final List<String> _instances = Lists.newArrayList();
+    private final List<ZNRecord> _liveInstances = Lists.newArrayList();
+
+    public MockHelixManager() {
+      for (int i = 0; i < PARTICIPANTS; i++) {
+        String instance = INSTANCE_NAME_PREFIX + i;
+        _instances.add(instance);
+        ZNRecord metaData = new ZNRecord(instance);
+        metaData.setSimpleField(LiveInstance.LiveInstanceProperty.SESSION_ID.toString(), UUID.randomUUID().toString());
+        _liveInstances.add(metaData);
+      }
+
+      _idealState = DefaultTwoStateStrategy.calculateIdealState(_instances, PARTITIONS, REPLICAS, RESOURCE_NAME,
+          "MASTER", "SLAVE");
+    }
+
+    @Override
+    public boolean isConnected() {
+      return true;
+    }
+
+    @Override
+    public HelixDataAccessor getHelixDataAccessor() {
+      return _accessor;
+    }
+
+    @Override
+    public String getInstanceName() {
+      return "localhost_0";
+    }
+
+    @Override
+    public InstanceType getInstanceType() {
+      return InstanceType.CONTROLLER;
+    }
+  }
+}