content: /*
   * 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.ambari.server.api.services.parsers;
  
  import static org.junit.Assert.assertEquals;
  import static org.junit.Assert.assertNotNull;
  import static org.junit.Assert.assertNull;
  import static org.junit.Assert.assertTrue;
  import static org.junit.Assert.fail;
  
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Set;
  
  import org.apache.ambari.server.api.services.NamedPropertySet;
  import org.apache.ambari.server.api.services.RequestBody;
  import org.apache.ambari.server.controller.utilities.PropertyHelper;
  import org.junit.Test;
  
  import junit.framework.Assert;
  
  /**
   * Unit tests for JsonPropertyParser.
   */
  public class JsonRequestBodyParserTest {
  
    String serviceJson = "{\"Services\" : {" +
        "    \"display_name\" : \"HDFS\"," +
        "    \"description\" : \"Apache Hadoop Distributed File System\","+
        "    \"service_name\" : \"HDFS\"" +
        "  }," +
        "  \"ServiceInfo\" : {" +
        "    \"cluster_name\" : \"tbmetrictest\"," +
        "    \"state\" : \"STARTED\"" +
        "  }," +
        "\"OuterCategory\" : { \"propName\" : 100, \"nested1\" : { \"nested2\" : { \"innerPropName\" : \"innerPropValue\" } } }," +
        "\"topLevelProp\" : \"value\" }";
  
    String serviceJsonWithQuery = "{ \"RequestInfo\" : { \"query\" : \"foo=bar\" }, \"Body\":" + serviceJson + "}";
  
    String arrayJson = "[ {" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster1\"" +
        "} }," +
        "{" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster2\"," +
        "    \"property1\" : \"prop1Value\"" +
        "} }," +
        "{" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster3\"," +
        "    \"Category\" : { \"property2\" : null}" +
        "} } ]";
  
    String arrayJson2 = "{" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster1\"" +
        "} }," +
        "{" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster2\"," +
        "    \"property1\" : \"prop1Value\"" +
        "} }," +
        "{" +
        "\"Clusters\" : {\n" +
        "    \"cluster_name\" : \"unitTestCluster3\"," +
        "    \"Category\" : { \"property2\" : \"prop2Value\"}" +
        "} }";
  
    String multiBody = "[\n" +
        "  {\n" +
        "    \"RequestInfo\":{\n" +
        "      \"query\":\"Hosts/host_name=h1\"\n" +
        "    },\n" +
        "    \"Body\":\n" +
        "    {\n" +
        "      \"Hosts\": {\n" +
        "        \"desired_config\": {\n" +
        "          \"type\": \"global\",\n" +
        "          \"tag\": \"version20\",\n" +
        "          \"properties\": { \"a\": \"b\", \"x\": \"y\" }\n" +
        "        }\n" +
        "      }\n" +
        "    }\n" +
        "  },\n" +
        "  {\n" +
        "    \"RequestInfo\":{\n" +
        "      \"query\":\"Hosts/host_name=h2\"\n" +
        "    },\n" +
        "    \"Body\":\n" +
        "    {\n" +
        "      \"Hosts\": {\n" +
        "        \"desired_config\": {\n" +
        "          \"type\": \"global\",\n" +
        "          \"tag\": \"version21\",\n" +
        "          \"properties\": { \"a\": \"c\", \"x\": \"z\" }\n" +
        "        }\n" +
        "      }\n" +
        "    }\n" +
        "  }\n" +
        "]\n";
  
    String queryPostJson = "{ \"services\" : [ {" +
        "\"ServiceInfo\" : {\n" +
        "    \"service_name\" : \"unitTestService1\"" +
        "} }," +
        "{" +
        "\"ServiceInfo\" : {\n" +
        "    \"service_name\" : \"unitTestService2\"," +
        "    \"property1\" : \"prop1Value\"" +
        "} }," +
        "{" +
        "\"ServiceInfo\" : {\n" +
        "    \"service_name\" : \"unitTestService3\"," +
        "    \"Category\" : { \"property2\" : \"prop2Value\"}" +
        "} } ] }";
  
    String queryPostJsonWithQuery = "{ \"RequestInfo\" : { \"query\" : \"foo=bar\" }, \"Body\":" + queryPostJson + "}";
  
    String queryPostMultipleSubResourcesJson = "{ \"foo\" : [ {" +
        "\"ServiceInfo\" : {\n" +
        "    \"service_name\" : \"unitTestService1\"" +
        "} }" +
        "]," +
        " \"bar\" : [" +
        "{" +
        "\"ServiceInfo\" : {\n" +
        "    \"service_name\" : \"unitTestService2\"," +
        "    \"Category\" : { \"property2\" : \"prop2Value\"}" +
        "} } ] }";
  
    String bodyQueryOnly = "{ \"RequestInfo\" : { \"query\" : \"foo=bar\" }}";
  
    String malformedJson = "{ \"Category\" : { \"foo\" : \"bar\"}";
  
    String bodyWithRequestInfoProperties = "{ \"RequestInfo\" : { \"query\" : \"foo=bar\", \"prop1\" : \"val1\", \"prop2\" : \"val2\" }, \"Body\":" + serviceJson + "}";
  
    String bodyWithRequestBlobProperties = "{ \"RequestBodyInfo\" : { " +"\"RequestInfo\" : { \"query\" : \"foo=bar\", \"prop1\" : \"val1\", \"prop2\" : \"val2\" }, \"Body\":" + serviceJson + "} }";
  
    @Test
    public void testParse() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(serviceJson).iterator().next();
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
      assertEquals(1, setProps.size());
  
      Map<String, Object> mapExpected = new HashMap<>();
      mapExpected.put(PropertyHelper.getPropertyId("Services", "service_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "display_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "cluster_name"), "tbmetrictest");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "description"), "Apache Hadoop Distributed File System");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "state"), "STARTED");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory", "propName"), "100");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory/nested1/nested2", "innerPropName"), "innerPropValue");
      mapExpected.put(PropertyHelper.getPropertyId(null, "topLevelProp"), "value");
  
      assertEquals(mapExpected, setProps.iterator().next().getProperties());
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(mapExpected, setProps2.iterator().next().getProperties());
    }
  
    @Test
    public void testParse_NullBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(null).iterator().next();
  
      assertNotNull(body.getNamedPropertySets());
      assertEquals(0, body.getNamedPropertySets().size());
      assertNull(body.getQueryString());
      assertNull(body.getPartialResponseFields());
      assertNull(body.getBody());
    }
  
    @Test
    public void testParse_EmptyBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse("").iterator().next();
  
      assertNotNull(body.getNamedPropertySets());
      assertEquals(0, body.getNamedPropertySets().size());
      assertNull(body.getQueryString());
      assertNull(body.getPartialResponseFields());
      assertNull(body.getBody());
    }
  
    @Test
    public void testParse_MultiBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      Set<RequestBody> bodySet = parser.parse(multiBody);
  
      assertEquals(2, bodySet.size());
  
      for (RequestBody body : bodySet) {
        Set<NamedPropertySet> setProps = body.getNamedPropertySets();
        assertEquals(1, setProps.size());
  
        Map<String, Object> mapProps = setProps.iterator().next().getProperties();
  
        assertEquals(4, mapProps.size());
  
        assertEquals("global", mapProps.get("Hosts/desired_config/type"));
      }
    }
  
    @Test
    public void testParse_Array() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(arrayJson).iterator().next();
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
  
      assertEquals(3, setProps.size());
  
      boolean cluster1Matches = false;
      boolean cluster2Matches = false;
      boolean cluster3Matches = false;
  
      Map<String, String> mapCluster1 = new HashMap<>();
      mapCluster1.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster1");
  
      Map<String, String> mapCluster2 = new HashMap<>();
      mapCluster2.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster2");
      mapCluster2.put(PropertyHelper.getPropertyId("Clusters", "property1"), "prop1Value");
  
  
      Map<String, String> mapCluster3 = new HashMap<>();
      mapCluster3.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster3");
      mapCluster3.put(PropertyHelper.getPropertyId("Clusters/Category", "property2"), null);
  
  
      for (NamedPropertySet propertySet : setProps) {
        assertEquals("", propertySet.getName());
        Map<String, Object> mapProps = propertySet.getProperties();
        if (mapProps.equals(mapCluster1)) {
          cluster1Matches = true;
        } else if (mapProps.equals(mapCluster2)) {
          cluster2Matches = true;
        } else if (mapProps.equals(mapCluster3)) {
          cluster3Matches = true;
        }
      }
  
      assertTrue(cluster1Matches);
      assertTrue(cluster2Matches);
      assertTrue(cluster3Matches);
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
  
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(3, setProps2.size());
      assertEquals(setProps, setProps2);
    }
  
    @Test
    public void testParse___Array_NoArrayBrackets() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(arrayJson2).iterator().next();
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
  
      assertEquals(3, setProps.size());
  
      boolean cluster1Matches = false;
      boolean cluster2Matches = false;
      boolean cluster3Matches = false;
  
      Map<String, String> mapCluster1 = new HashMap<>();
      mapCluster1.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster1");
  
      Map<String, String> mapCluster2 = new HashMap<>();
      mapCluster2.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster2");
      mapCluster2.put(PropertyHelper.getPropertyId("Clusters", "property1"), "prop1Value");
  
  
      Map<String, String> mapCluster3 = new HashMap<>();
      mapCluster3.put(PropertyHelper.getPropertyId("Clusters", "cluster_name"), "unitTestCluster3");
      mapCluster3.put(PropertyHelper.getPropertyId("Clusters/Category", "property2"), "prop2Value");
  
  
      for (NamedPropertySet propertySet : setProps) {
        Map<String, Object> mapProps = propertySet.getProperties();
        if (mapProps.equals(mapCluster1)) {
          cluster1Matches = true;
        } else if (mapProps.equals(mapCluster2)) {
          cluster2Matches = true;
        } else if (mapProps.equals(mapCluster3)) {
          cluster3Matches = true;
        }
      }
  
      assertTrue(cluster1Matches);
      assertTrue(cluster2Matches);
      assertTrue(cluster3Matches);
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(3, setProps2.size());
      assertEquals(setProps, setProps2);
    }
  
    @Test
    public void testParse_QueryInBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(serviceJsonWithQuery).iterator().next();
  
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
      assertEquals(1, setProps.size());
  
      Map<String, Object> mapExpected = new HashMap<>();
      mapExpected.put(PropertyHelper.getPropertyId("Services", "service_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "display_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "cluster_name"), "tbmetrictest");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "description"), "Apache Hadoop Distributed File System");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "state"), "STARTED");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory", "propName"), "100");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory/nested1/nested2", "innerPropName"), "innerPropValue");
      mapExpected.put(PropertyHelper.getPropertyId(null, "topLevelProp"), "value");
  
      assertEquals(mapExpected, setProps.iterator().next().getProperties());
      assertEquals("foo=bar", body.getQueryString());
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(mapExpected, setProps2.iterator().next().getProperties());
    }
  
    @Test
    public void testParse_QueryPost() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(queryPostJson).iterator().next();
  
  
      Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
  
      assertEquals(1, setProperties.size());
      boolean contains1 = false;
      boolean contains2 = false;
      boolean contains3 = false;
  
      for (NamedPropertySet ps : setProperties) {
        Map<String, Object> mapProps = ps.getProperties();
        assertEquals(1, mapProps.size());
        Set<Map<String, Object>> set = (Set<Map<String, Object>>) mapProps.get("services");
  
        for (Map<String, Object> map : set) {
          String serviceName = (String) map.get("ServiceInfo/service_name");
          if (serviceName.equals("unitTestService1")) {
            assertEquals(1, map.size());
            contains1 = true;
          } else if (serviceName.equals("unitTestService2")) {
            assertEquals("prop1Value", map.get("ServiceInfo/property1"));
            assertEquals(2, map.size());
            contains2 = true;
          } else if (serviceName.equals("unitTestService3")) {
            assertEquals("prop2Value", map.get("ServiceInfo/Category/property2"));
            assertEquals(2, map.size());
            contains3 = true;
          } else {
            fail("Unexpected service name");
          }
        }
      }
      assertTrue(contains1);
      assertTrue(contains2);
      assertTrue(contains3);
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(1, setProps2.size());
      assertEquals(setProperties, setProps2);
      assertEquals("java.util.LinkedHashSet",
              body.getNamedPropertySets().iterator().next().getProperties().get("services").getClass().getName());
    }
  
    @Test
    public void testParse___QueryPost_multipleSubResTypes() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(queryPostMultipleSubResourcesJson).iterator().next();
  
  
      Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
  
      assertEquals(1, setProperties.size());
      boolean contains1 = false;
      boolean contains2 = false;
  
      for (NamedPropertySet ps : setProperties) {
  
        Map<String, Object> mapProps = ps.getProperties();
  
        for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
          Set<Map<String, Object>> set = (Set<Map<String, Object>>) entry.getValue();
  
          for (Map<String, Object> map : set) {
  
            String serviceName = (String) map.get("ServiceInfo/service_name");
            if (serviceName.equals("unitTestService1")) {
              assertEquals("foo", entry.getKey());
              assertEquals(1, map.size());
              contains1 = true;
            } else if (serviceName.equals("unitTestService2")) {
              assertEquals("bar", entry.getKey());
              assertEquals("prop2Value", map.get("ServiceInfo/Category/property2"));
              assertEquals(2, map.size());
              contains2 = true;
            } else {
              fail("Unexpected service name");
            }
  
          }
        }
      }
      assertTrue(contains1);
      assertTrue(contains2);
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(1, setProps2.size());
      assertEquals(setProperties, setProps2);
    }
  
    @Test
    public void testParse___QueryPost_QueryInBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
  
      RequestBody body = parser.parse(queryPostJsonWithQuery).iterator().next();
  
  
      Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
  
      assertEquals("foo=bar", body.getQueryString());
      assertEquals(1, setProperties.size());
      boolean contains1 = false;
      boolean contains2 = false;
      boolean contains3 = false;
  
      for (NamedPropertySet ps : setProperties) {
        assertEquals("", ps.getName());
        Map<String, Object> mapProps = ps.getProperties();
  
        for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
          Set<Map<String, Object>> set = (Set<Map<String, Object>>) entry.getValue();
  
          for (Map<String, Object> map : set) {
  
            String serviceName = (String) map.get("ServiceInfo/service_name");
            if (serviceName.equals("unitTestService1")) {
              assertEquals(1, map.size());
              contains1 = true;
            } else if (serviceName.equals("unitTestService2")) {
              assertEquals("prop1Value", map.get("ServiceInfo/property1"));
              assertEquals(2, map.size());
              contains2 = true;
            } else if (serviceName.equals("unitTestService3")) {
              assertEquals("prop2Value", map.get("ServiceInfo/Category/property2"));
              assertEquals(2, map.size());
              contains3 = true;
            } else {
              fail("Unexpected service name");
            }
          }
        }
      }
      assertTrue(contains1);
      assertTrue(contains2);
      assertTrue(contains3);
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      assertEquals(queryPostJsonWithQuery , b);
  
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(1, setProps2.size());
      assertEquals(setProperties, setProps2);
    }
  
    @Test
    public void testParse_QueryOnlyInBody() throws BodyParseException {
      RequestBodyParser parser = new JsonRequestBodyParser();
  
      RequestBody body = parser.parse(bodyQueryOnly).iterator().next();
  
      assertEquals("foo=bar", body.getQueryString());
      assertEquals(bodyQueryOnly, body.getBody());
    }
  
    @Test
    public void testParse_malformedBody() {
      RequestBodyParser parser = new JsonRequestBodyParser();
  
      try {
        parser.parse(malformedJson);
        fail("Expected exception due to malformed body");
      } catch (BodyParseException e) {
        // expected case
      }
    }
  
    @Test
    public void testRequestInfoProps() throws Exception {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(bodyWithRequestInfoProperties).iterator().next();
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
      assertEquals(1, setProps.size());
  
      Map<String, Object> mapExpected = new HashMap<>();
      mapExpected.put(PropertyHelper.getPropertyId("Services", "service_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "display_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "cluster_name"), "tbmetrictest");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "description"), "Apache Hadoop Distributed File System");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "state"), "STARTED");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory", "propName"), "100");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory/nested1/nested2", "innerPropName"), "innerPropValue");
      mapExpected.put(PropertyHelper.getPropertyId(null, "topLevelProp"), "value");
  
      assertEquals(mapExpected, setProps.iterator().next().getProperties());
      assertEquals("foo=bar", body.getQueryString());
  
      Map<String, String > mapRequestInfoProps = body.getRequestInfoProperties();
      assertEquals(4, mapRequestInfoProps.size());
      assertEquals("val1", mapRequestInfoProps.get("prop1"));
      assertEquals("val2", mapRequestInfoProps.get("prop2"));
      assertEquals("foo=bar", mapRequestInfoProps.get("query"));
      assertEquals(bodyWithRequestInfoProperties, mapRequestInfoProps.get("RAW_REQUEST_BODY"));
  
      //assert body is correct by checking that properties match
      String b = body.getBody();
      body = parser.parse(b).iterator().next();
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(mapExpected, setProps2.iterator().next().getProperties());
    }
  
    @Test
    public void testRequestBlobProperties() throws Exception {
      RequestBodyParser parser = new JsonRequestBodyParser();
      RequestBody body = parser.parse(bodyWithRequestBlobProperties).iterator().next();
  
      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
      assertEquals(1, setProps.size());
  
      String requestBlob = null;
  
      for (NamedPropertySet ps : setProps) {
        assertEquals("", ps.getName());
        Map<String, Object> mapProps = ps.getProperties();
  
        for (Map.Entry<String, Object> entry : mapProps.entrySet()) {
          if (entry.getKey().equals(JsonRequestBodyParser.REQUEST_BLOB_TITLE)) {
            requestBlob = (String) entry.getValue();
          }
        }
      }
  
      Assert.assertNotNull(requestBlob);
      body = parser.parse(requestBlob).iterator().next();
  
      Map<String, Object> mapExpected = new HashMap<>();
      mapExpected.put(PropertyHelper.getPropertyId("Services", "service_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "display_name"), "HDFS");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "cluster_name"), "tbmetrictest");
      mapExpected.put(PropertyHelper.getPropertyId("Services", "description"), "Apache Hadoop Distributed File System");
      mapExpected.put(PropertyHelper.getPropertyId("ServiceInfo", "state"), "STARTED");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory", "propName"), "100");
      mapExpected.put(PropertyHelper.getPropertyId("OuterCategory/nested1/nested2", "innerPropName"), "innerPropValue");
      mapExpected.put(PropertyHelper.getPropertyId(null, "topLevelProp"), "value");
  
      Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
      assertEquals(mapExpected, setProps2.iterator().next().getProperties());
    }
  }
  
  
  