metron-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nickal...@apache.org
Subject [1/2] incubator-metron git commit: METRON-701 Triage Metrics Produced by the Profiler (nickwallen) closes apache/incubator-metron#449
Date Thu, 02 Mar 2017 22:02:12 GMT
Repository: incubator-metron
Updated Branches:
  refs/heads/master e66284993 -> 818b0b17b


http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileConfig.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileConfig.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileConfig.java
index d8f8acf..0ac1314 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileConfig.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileConfig.java
@@ -17,12 +17,18 @@
  */
 package org.apache.metron.common.configuration.profiler;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 import java.io.Serializable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 /**
- * The user defined configuration values required to generate a Profile.
+ * The definition of a single Profile.
  */
 public class ProfileConfig implements Serializable {
 
@@ -46,7 +52,7 @@ public class ProfileConfig implements Serializable {
    * is only applied to a profile if this condition is true. This allows a profile
    * to filter the messages that it receives.
    */
-  private String onlyif;
+  private String onlyif = "true";
 
   /**
    * A set of expressions that is executed at the start of a window period.  A map is
@@ -71,12 +77,11 @@ public class ProfileConfig implements Serializable {
   private List<String> groupBy = new ArrayList<>();
 
   /**
-   * A Stellar expression that is executed when the window period expires.  The
-   * expression is expected to in some way summarize the messages that were applied
-   * to the profile over the window period.  The expression must result in a numeric
-   * value such as a Double, Long, Float, Short, or Integer.
+   * Stellar expression(s) that are executed when the window period expires.  The
+   * expression(s) are expected to in some way summarize the messages that were applied
+   * to the profile over the window period.
    */
-  private String result;
+  private ProfileResult result;
 
   /**
    * How long the data created by this Profile will be retained.  After this period of time
the
@@ -84,6 +89,23 @@ public class ProfileConfig implements Serializable {
    */
   private Long expires;
 
+  /**
+   * A profile definition requires at the very least the profile name, the foreach, and result
+   * expressions.
+   * @param profile The name of the profile.
+   * @param foreach The foreach expression of the profile.
+   * @param result The result expression of the profile.
+   */
+  public ProfileConfig(
+          @JsonProperty(value = "profile", required = true) String profile,
+          @JsonProperty(value = "foreach", required = true) String foreach,
+          @JsonProperty(value = "result",  required = true) ProfileResult result) {
+
+    this.profile = profile;
+    this.foreach = foreach;
+    this.result = result;
+  }
+
   public String getProfile() {
     return profile;
   }
@@ -132,11 +154,11 @@ public class ProfileConfig implements Serializable {
     this.groupBy = groupBy;
   }
 
-  public String getResult() {
+  public ProfileResult getResult() {
     return result;
   }
 
-  public void setResult(String result) {
+  public void setResult(ProfileResult result) {
     this.result = result;
   }
 
@@ -149,20 +171,6 @@ public class ProfileConfig implements Serializable {
   }
 
   @Override
-  public String toString() {
-    return "ProfileConfig{" +
-            "profile='" + profile + '\'' +
-            ", foreach='" + foreach + '\'' +
-            ", onlyif='" + onlyif + '\'' +
-            ", init=" + init +
-            ", update=" + update +
-            ", groupBy=" + groupBy +
-            ", result='" + result + '\'' +
-            ", expires=" + expires +
-            '}';
-  }
-
-  @Override
   public boolean equals(Object o) {
     if (this == o) return true;
     if (o == null || getClass() != o.getClass()) return false;
@@ -177,7 +185,6 @@ public class ProfileConfig implements Serializable {
     if (groupBy != null ? !groupBy.equals(that.groupBy) : that.groupBy != null) return false;
     if (result != null ? !result.equals(that.result) : that.result != null) return false;
     return expires != null ? expires.equals(that.expires) : that.expires == null;
-
   }
 
   @Override
@@ -192,4 +199,18 @@ public class ProfileConfig implements Serializable {
     result1 = 31 * result1 + (expires != null ? expires.hashCode() : 0);
     return result1;
   }
+
+  @Override
+  public String toString() {
+    return "ProfileConfig{" +
+            "profile='" + profile + '\'' +
+            ", foreach='" + foreach + '\'' +
+            ", onlyif='" + onlyif + '\'' +
+            ", init=" + init +
+            ", update=" + update +
+            ", groupBy=" + groupBy +
+            ", result=" + result +
+            ", expires=" + expires +
+            '}';
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResult.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResult.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResult.java
new file mode 100644
index 0000000..9a42426
--- /dev/null
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResult.java
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+package org.apache.metron.common.configuration.profiler;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * Defines the 'result' field of a Profile definition.
+ */
+public class ProfileResult {
+
+  /**
+   * A Stellar expression that is executed to produce
+   * a measurement that is persisted in the profile store.
+   */
+  @JsonProperty("profile")
+  private ProfileResultExpressions profileExpressions;
+
+  /**
+   * A set of named Stellar expressions that are executed
+   * to produce a measurement that can be used for threat
+   * triage.
+   */
+  @JsonProperty("triage")
+  private ProfileTriageExpressions triageExpressions;
+
+  @JsonCreator
+  public ProfileResult(
+          @JsonProperty(value = "profile", required = true) ProfileResultExpressions profileExpressions,
+          @JsonProperty(value = "triage") ProfileTriageExpressions triageExpressions) {
+    this.profileExpressions = profileExpressions;
+    this.triageExpressions = triageExpressions != null ? triageExpressions : new ProfileTriageExpressions();
+  }
+
+  /**
+   * Allows a single result expression to be interpreted as a 'profile' expression.
+   *
+   * The profile definition
+   *    <pre>{@code {..., "result": "2 + 2" }}</pre>
+   * is equivalent to
+   *    <pre>{@code {..., "result": { "profile": "2 + 2" }}}</pre>
+   *
+   * @param expression The result expression.
+   */
+  public ProfileResult(String expression) {
+    this.profileExpressions = new ProfileResultExpressions(expression);
+    this.triageExpressions = new ProfileTriageExpressions();
+  }
+
+  public ProfileResultExpressions getProfileExpressions() {
+    return profileExpressions;
+  }
+
+  public void setProfileExpressions(ProfileResultExpressions profileExpressions) {
+    this.profileExpressions = profileExpressions;
+  }
+
+  public ProfileTriageExpressions getTriageExpressions() {
+    return triageExpressions;
+  }
+
+  public void setTriageExpressions(ProfileTriageExpressions triageExpressions) {
+    this.triageExpressions = triageExpressions;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+
+    ProfileResult that = (ProfileResult) o;
+    if (profileExpressions != null ? !profileExpressions.equals(that.profileExpressions)
: that.profileExpressions != null)
+      return false;
+    return triageExpressions != null ? triageExpressions.equals(that.triageExpressions) :
that.triageExpressions == null;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = profileExpressions != null ? profileExpressions.hashCode() : 0;
+    result = 31 * result + (triageExpressions != null ? triageExpressions.hashCode() : 0);
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResultExpressions.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResultExpressions.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResultExpressions.java
new file mode 100644
index 0000000..1bca716
--- /dev/null
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileResultExpressions.java
@@ -0,0 +1,57 @@
+/**
+ * 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.
+ */
+package org.apache.metron.common.configuration.profiler;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * A Stellar expression that is executed to produce a single
+ * measurement that is persisted within the profile store.
+ */
+public class ProfileResultExpressions {
+
+  @JsonIgnore
+  private String expression;
+
+  @JsonCreator
+  public ProfileResultExpressions(String expression) {
+    this.expression = expression;
+  }
+
+  public String getExpression() {
+    return expression;
+  }
+
+  public void setExpression(String expression) {
+    this.expression = expression;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    ProfileResultExpressions that = (ProfileResultExpressions) o;
+    return expression != null ? expression.equals(that.expression) : that.expression == null;
+  }
+
+  @Override
+  public int hashCode() {
+    return expression != null ? expression.hashCode() : 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileTriageExpressions.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileTriageExpressions.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileTriageExpressions.java
new file mode 100644
index 0000000..da74f64
--- /dev/null
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfileTriageExpressions.java
@@ -0,0 +1,67 @@
+/**
+ * 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.
+ */
+package org.apache.metron.common.configuration.profiler;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A set of Stellar expressions that are executed to produce a single
+ * measurement that can be interrogated by the threat triage process.
+ *
+ * The result of evaluating each expression are made available, keyed
+ * by the given name, to the threat triage process.
+ */
+public class ProfileTriageExpressions {
+
+  /**
+   * A set of named Stellar expressions.  The name of the expression
+   * serves as the key and the value is the expression itself.
+   *
+   * Evaluating the expression(s) must result in a basic data type
+   * or map of basic data types that can be serialized.
+   */
+  @JsonIgnore
+  private Map<String, String> expressions;
+
+  @JsonCreator
+  public ProfileTriageExpressions(Map<String, String> expressions) {
+    this.expressions = expressions;
+  }
+
+  @JsonCreator
+  public ProfileTriageExpressions() {
+    this.expressions = new HashMap<>();
+  }
+
+  /**
+   * Returns the expression associated with a given name.
+   * @param name The name of the expression.
+   * @return A Stellar expression.
+   */
+  public String getExpression(String name) {
+    return expressions.get(name);
+  }
+
+  public Map<String, String> getExpressions() {
+    return expressions;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfig.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfig.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfig.java
index fcc03fd..cd651bd 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfig.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfig.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- * The user defined configuration values required for the Profiler.
+ * The definition for entire Profiler, which may contain many Profile definitions.
  */
 public class ProfilerConfig implements Serializable {
 

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfigurations.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfigurations.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfigurations.java
index 19b6a5a..c098787 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfigurations.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/profiler/ProfilerConfigurations.java
@@ -26,7 +26,7 @@ import java.io.IOException;
 import java.io.InputStream;
 
 /**
- * Created by nallen on 7/28/16.
+ * Used to manage configurations for the Profiler.
  */
 public class ProfilerConfigurations extends Configurations {
 

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/main/java/org/apache/metron/common/utils/JSONUtils.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/main/java/org/apache/metron/common/utils/JSONUtils.java
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/utils/JSONUtils.java
index 856d18e..c61efc5 100644
--- a/metron-platform/metron-common/src/main/java/org/apache/metron/common/utils/JSONUtils.java
+++ b/metron-platform/metron-common/src/main/java/org/apache/metron/common/utils/JSONUtils.java
@@ -22,37 +22,20 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
 
 import java.io.*;
 
 public enum JSONUtils {
   INSTANCE;
-  private static ThreadLocal<ObjectMapper> _mapper = new ThreadLocal<ObjectMapper>()
{
-    /**
-     * Returns the current thread's "initial value" for this
-     * thread-local variable.  This method will be invoked the first
-     * time a thread accesses the variable with the {@link #get}
-     * method, unless the thread previously invoked the {@link #set}
-     * method, in which case the {@code initialValue} method will not
-     * be invoked for the thread.  Normally, this method is invoked at
-     * most once per thread, but it may be invoked again in case of
-     * subsequent invocations of {@link #remove} followed by {@link #get}.
-     * <p>
-     * <p>This implementation simply returns {@code null}; if the
-     * programmer desires thread-local variables to have an initial
-     * value other than {@code null}, {@code ThreadLocal} must be
-     * subclassed, and this method overridden.  Typically, an
-     * anonymous inner class will be used.
-     *
-     * @return the initial value for this thread-local
-     */
-    @Override
-    protected ObjectMapper initialValue() {
-      ObjectMapper ret = new ObjectMapper();
-      ret.setSerializationInclusion(JsonInclude.Include.NON_NULL);
-      return ret;
-    }
-  };
+
+  private static ThreadLocal<JSONParser> _parser = ThreadLocal.withInitial(() ->
+          new JSONParser());
+
+  private static ThreadLocal<ObjectMapper> _mapper = ThreadLocal.withInitial(() ->
+          new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL));
 
   public <T> T load(InputStream is, TypeReference<T> ref) throws IOException
{
     return _mapper.get().readValue(is, ref);
@@ -93,4 +76,11 @@ public enum JSONUtils {
   public byte[] toJSON(Object config) throws JsonProcessingException {
     return _mapper.get().writeValueAsBytes(config);
   }
+
+  /**
+   * Transforms a bean (aka POJO) to a JSONObject.
+   */
+  public JSONObject toJSONObject(Object o) throws JsonProcessingException, ParseException
{
+    return (JSONObject) _parser.get().parse(toJSON(o, false));
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-metron/blob/818b0b17/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/profiler/ProfileConfigTest.java
----------------------------------------------------------------------
diff --git a/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/profiler/ProfileConfigTest.java
b/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/profiler/ProfileConfigTest.java
new file mode 100644
index 0000000..a0e115d
--- /dev/null
+++ b/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/profiler/ProfileConfigTest.java
@@ -0,0 +1,207 @@
+/*
+ *
+ *  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.
+ *
+ */
+package org.apache.metron.common.configuration.profiler;
+
+import com.fasterxml.jackson.databind.JsonMappingException;
+import org.adrianwalker.multilinestring.Multiline;
+import org.apache.metron.common.utils.JSONUtils;
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+/**
+ * Ensures that Profile definitions have the expected defaults
+ * and can be (de)serialized to and from JSON.
+ */
+public class ProfileConfigTest {
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": "2 + 2"
+   * }
+   */
+  @Multiline
+  private String onlyIfDefault;
+
+  /**
+   * The 'onlyif' field should default to 'true' when it is not specified.
+   */
+  @Test
+  public void testOnlyIfDefault() throws IOException {
+    ProfileConfig profile = JSONUtils.INSTANCE.load(onlyIfDefault, ProfileConfig.class);
+    assertEquals("true", profile.getOnlyif());
+  }
+
+  /**
+   * {
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": "2 + 2"
+   * }
+   */
+  @Multiline
+  private String nameMissing;
+
+  /**
+   * The 'name' of the profile must be defined.
+   */
+  @Test(expected = JsonMappingException.class)
+  public void testNameMissing() throws IOException {
+    JSONUtils.INSTANCE.load(nameMissing, ProfileConfig.class);
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "update": {},
+   *    "result": "2 + 2"
+   * }
+   */
+  @Multiline
+  private String foreachMissing;
+
+  /**
+   * The 'foreach' field must be defined.
+   */
+  @Test(expected = JsonMappingException.class)
+  public void testForeachMissing() throws IOException {
+    JSONUtils.INSTANCE.load(foreachMissing, ProfileConfig.class);
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {}
+   * }
+   */
+  @Multiline
+  private String resultMissing;
+
+  /**
+   * The 'result' field must be defined.
+   */
+  @Test(expected = JsonMappingException.class)
+  public void testResultMissing() throws IOException {
+    JSONUtils.INSTANCE.load(resultMissing, ProfileConfig.class);
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": {}
+   * }
+   */
+  @Multiline
+  private String resultMissingProfileExpression;
+
+  /**
+   * The 'result' field must contain the 'profile' expression used to store the profile measurement.
+   */
+  @Test(expected = JsonMappingException.class)
+  public void testResultMissingProfileExpression() throws IOException {
+    JSONUtils.INSTANCE.load(resultMissingProfileExpression, ProfileConfig.class);
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": "2 + 2"
+   * }
+   */
+  @Multiline
+  private String resultWithExpression;
+
+  /**
+   * If the 'result' field has only a single expression, it should be treated as
+   * the 'profile' expression used to store the profile measurement.
+   */
+  @Test
+  public void testResultWithExpression() throws IOException {
+    ProfileConfig profile = JSONUtils.INSTANCE.load(resultWithExpression, ProfileConfig.class);
+    assertEquals("2 + 2", profile.getResult().getProfileExpressions().getExpression());
+
+    // no triage expressions expected
+    assertEquals(0, profile.getResult().getTriageExpressions().getExpressions().size());
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": {
+   *      "profile": "2 + 2"
+   *    }
+   * }
+   */
+  @Multiline
+  private String resultWithProfileOnly;
+
+  /**
+   * The result's 'triage' field is optional.
+   */
+  @Test
+  public void testResultWithProfileOnly() throws IOException {
+    ProfileConfig profile = JSONUtils.INSTANCE.load(resultWithProfileOnly, ProfileConfig.class);
+    assertEquals("2 + 2", profile.getResult().getProfileExpressions().getExpression());
+
+    // no triage expressions expected
+    assertEquals(0, profile.getResult().getTriageExpressions().getExpressions().size());
+  }
+
+  /**
+   * {
+   *    "profile": "test",
+   *    "foreach": "ip_src_addr",
+   *    "update": {},
+   *    "result": {
+   *      "profile": "2 + 2",
+   *      "triage": {
+   *        "eight": "4 + 4",
+   *        "sixteen": "8 + 8"
+   *      }
+   *    }
+   * }
+   */
+  @Multiline
+  private String resultWithTriage;
+
+  /**
+   * The result's 'triage' field can contain many named expressions.
+   */
+  @Test
+  public void testResultWithTriage() throws IOException {
+    ProfileConfig profile = JSONUtils.INSTANCE.load(resultWithTriage, ProfileConfig.class);
+
+    assertEquals("4 + 4", profile.getResult().getTriageExpressions().getExpression("eight"));
+    assertEquals("8 + 8", profile.getResult().getTriageExpressions().getExpression("sixteen"));
+  }
+}


Mime
View raw message