@Test
public void testReplaceVariablesWithFunctions() throws AmbariException {

  Map<String, Map<String, String>> configurations = new HashMap<String, Map<String, String>>() {
    {
      put("", new HashMap<String, String>() {{
        put("delimited.data", "one,two,three,four");
        put("realm", "UNIT.TEST");
      }});
      put("kafka-broker", new HashMap<String, String>() {{
        put("listeners", "PLAINTEXT://localhost:6667");
      }});
      
      put("clusterHostInfo", new HashMap<String, String>() {{
        put("hive_metastore_host", "host1.unit.test, host2.unit.test , host3.unit.test"); // spaces are there on purpose.
      }});
      put("foobar-site", new HashMap<String, String>() {{
        put("data", "one, two, three,    four"); // spaces are there on purpose.
        put("hello", "hello");
        put("hello_there", "hello, there");
        put("hello_there_one", "hello, there, one");
      }});
    }
  };
  Assert.assertEquals("test=thrift://one:9083\\,thrift://two:9083\\,thrift://three:9083\\,thrift://four:9083",
      helper.replaceVariables("test=${delimited.data|each(thrift://%s:9083, \\\\,, \\s*\\,\\s*)}", configurations));
  Assert.assertEquals("hive.metastore.local=false,hive.metastore.uris=thrift://host1.unit.test:9083\\,thrift://host2.unit.test:9083\\,thrift://host3.unit.test:9083,hive.metastore.sasl.enabled=true,hive.metastore.execute.setugi=true,hive.metastore.warehouse.dir=/apps/hive/warehouse,hive.exec.mode.local.auto=false,hive.metastore.kerberos.principal=hive/_HOST@UNIT.TEST",
      helper.replaceVariables("hive.metastore.local=false,hive.metastore.uris=${clusterHostInfo/hive_metastore_host | each(thrift://%s:9083, \\\\,, \\s*\\,\\s*)},hive.metastore.sasl.enabled=true,hive.metastore.execute.setugi=true,hive.metastore.warehouse.dir=/apps/hive/warehouse,hive.exec.mode.local.auto=false,hive.metastore.kerberos.principal=hive/_HOST@${realm}", configurations));
  List<String> expected;
  List<String> actual;
  expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "three", "two"));
  actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello | append(foobar-site/data, \\,, true)}", configurations).split(",")));
  Collections.sort(expected);
  Collections.sort(actual);
  Assert.assertEquals(expected, actual);
  expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "there", "three", "two"));
  actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there | append(foobar-site/data, \\,, true)}", configurations).split(",")));
  Collections.sort(expected);
  Collections.sort(actual);
  Assert.assertEquals(expected, actual);
  expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "there", "three", "two"));
  actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,, true)}", configurations).split(",")));
  Collections.sort(expected);
  Collections.sort(actual);
  Assert.assertEquals(expected, actual);
  expected = new LinkedList<String>(Arrays.asList("four", "hello", "one", "one", "there", "three", "two"));
  actual = new LinkedList<String>(Arrays.asList(helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,, false)}", configurations).split(",")));
  Collections.sort(expected);
  Collections.sort(actual);
  Assert.assertEquals(expected, actual);
  // Test invalid number of arguments.
  try {
    helper.replaceVariables("${foobar-site/hello_there_one | append(foobar-site/data, \\,)}", configurations);
    Assert.fail("Expected IllegalArgumentException");
  }
  catch (IllegalArgumentException e) {
    // Ignore this is expected.
  }
  Assert.assertEquals("test=unit.test", helper.replaceVariables("test=${realm|toLower()}", configurations));

  Assert.assertEquals("PLAINTEXTSASL://localhost:6667", helper.replaceVariables("${kafka-broker/listeners|replace(\\bPLAINTEXT\\b,PLAINTEXTSASL)}", configurations)); 
}