@Test
public void testMergeConfigurations() throws Exception {

  StackId stack211 = new StackId("HDP-2.1.1");
  StackId stack220 = new StackId("HDP-2.2.0");
  Map<String, Map<String, String>> stack211Configs = new HashMap<>();
  Map<String, String> stack211FooType = new HashMap<>();
  Map<String, String> stack211BarType = new HashMap<>();
  Map<String, String> stack211BazType = new HashMap<>();
  stack211Configs.put("foo-site", stack211FooType);
  stack211Configs.put("bar-site", stack211BarType);
  stack211Configs.put("baz-site", stack211BazType);
  stack211FooType.put("1", "one");
  stack211FooType.put("11", "one-one");
  stack211BarType.put("2", "two");
  stack211BazType.put("3", "three");
  Map<String, Map<String, String>> stack220Configs = new HashMap<>();
  Map<String, String> stack220FooType = new HashMap<>();
  Map<String, String> stack220BazType = new HashMap<>();
  Map<String, String> stack220FlumeEnvType = new HashMap<>();
  stack220Configs.put("foo-site", stack220FooType);
  stack220Configs.put("baz-site", stack220BazType);
  stack220Configs.put("flume-env", stack220FlumeEnvType);
  stack220FooType.put("1", "one-new");
  stack220FooType.put("111", "one-one-one");
  stack220BazType.put("3", "three-new");
  stack220FlumeEnvType.put("flume_env_key", "flume-env-value");
  Map<String, String> clusterFooType = new HashMap<>();
  Map<String, String> clusterBarType = new HashMap<>();
  Map<String, String> clusterBazType = new HashMap<>();
  Config fooConfig = EasyMock.createNiceMock(Config.class);
  Config barConfig = EasyMock.createNiceMock(Config.class);
  Config bazConfig = EasyMock.createNiceMock(Config.class);
  clusterFooType.put("1", "one");
  clusterFooType.put("11", "one-one");
  clusterBarType.put("2", "two");
  clusterBazType.put("3", "three-changed");
  expect(fooConfig.getProperties()).andReturn(clusterFooType);
  expect(barConfig.getProperties()).andReturn(clusterBarType);
  expect(bazConfig.getProperties()).andReturn(clusterBazType);
  Map<String, DesiredConfig> desiredConfigurations = new HashMap<>();
  desiredConfigurations.put("foo-site", null);
  desiredConfigurations.put("bar-site", null);
  desiredConfigurations.put("baz-site", null);
  Cluster cluster = EasyMock.createNiceMock(Cluster.class);
  expect(cluster.getCurrentStackVersion()).andReturn(stack211);
  expect(cluster.getDesiredStackVersion()).andReturn(stack220);
  expect(cluster.getDesiredConfigs()).andReturn(desiredConfigurations);
  expect(cluster.getDesiredConfigByType("foo-site")).andReturn(fooConfig);
  expect(cluster.getDesiredConfigByType("bar-site")).andReturn(barConfig);
  expect(cluster.getDesiredConfigByType("baz-site")).andReturn(bazConfig);
  // setup the config helper for placeholder resolution
  EasyMock.reset(configHelper);
  expect(
      configHelper.getDefaultProperties(EasyMock.eq(stack211), EasyMock.anyObject(Cluster.class), EasyMock.anyBoolean())).andReturn(
      stack211Configs).anyTimes();
  expect(
      configHelper.getDefaultProperties(EasyMock.eq(stack220), EasyMock.anyObject(Cluster.class), EasyMock.anyBoolean())).andReturn(
      stack220Configs).anyTimes();
  Capture<Map<String, Map<String, String>>> expectedConfigurationsCapture = EasyMock.newCapture();
  configHelper.createConfigTypes(EasyMock.anyObject(Cluster.class),
      EasyMock.anyObject(AmbariManagementController.class),
      EasyMock.capture(expectedConfigurationsCapture),
      EasyMock.anyObject(String.class), EasyMock.anyObject(String.class));
  EasyMock.expectLastCall().once();
  EasyMock.replay(configHelper, cluster, fooConfig, barConfig, bazConfig);
  UpgradeResourceProvider upgradeResourceProvider = createProvider(amc);
  Map<String, UpgradePack> upgradePacks = ambariMetaInfo.getUpgradePacks("HDP", "2.1.1");
  UpgradePack upgrade = upgradePacks.get("upgrade_to_new_stack");
  upgradeResourceProvider.applyStackAndProcessConfigurations(stack211.getStackName(), cluster, "2.2.0.0", Direction.UPGRADE, upgrade, "admin");
  Map<String, Map<String, String>> expectedConfigurations = expectedConfigurationsCapture.getValue();
  Map<String, String> expectedFooType = expectedConfigurations.get("foo-site");
  Map<String, String> expectedBarType = expectedConfigurations.get("bar-site");
  Map<String, String> expectedBazType = expectedConfigurations.get("baz-site");
  // As the upgrade pack did not have any Flume updates, its configs should not be updated.
  assertFalse(expectedConfigurations.containsKey("flume-env"));
  // the really important values are one-new and three-changed; one-new
  // indicates that the new stack value is changed since it was not customized
  // while three-changed represents that the customized value was preserved
  // even though the stack value changed
  assertEquals("one-new", expectedFooType.get("1"));
  assertEquals("one-one", expectedFooType.get("11"));
  assertEquals("two", expectedBarType.get("2"));
  assertEquals("three-changed", expectedBazType.get("3"));
}