package com.ctrip.framework.apollo.biz.service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import com.ctrip.framework.apollo.biz.AbstractIntegrationTest;
import com.ctrip.framework.apollo.biz.entity.GrayReleaseRule;
import com.ctrip.framework.apollo.biz.entity.Namespace;
import com.ctrip.framework.apollo.biz.entity.Release;
import com.ctrip.framework.apollo.biz.entity.ReleaseHistory;
import com.ctrip.framework.apollo.common.constants.ReleaseOperation;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.test.context.jdbc.Sql;

import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class ReleaseCreationTest extends AbstractIntegrationTest {

  private Gson gson = new Gson();
  private Type configurationTypeReference = new TypeToken<Map<String, String>>() {
  }.getType();

  @Autowired
  private ReleaseService releaseService;
  @Autowired
  private NamespaceBranchService namespaceBranchService;
  @Autowired
  private ReleaseHistoryService releaseHistoryService;

  private String testApp = "test";
  private String testNamespace = "application";
  private String operator = "apollo";
  private Pageable pageable = new PageRequest(0, 10);

  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testPublishNormalNamespace() {
    long namespaceId = 100;
    String clusterName = "only-master";
    Namespace namespace = instanceNamespace(namespaceId, clusterName);

    releaseService.publish(namespace, "", "", operator);

    Release latestRelease = releaseService.findLatestActiveRelease(namespace);

    Assert.assertNotNull(latestRelease);

    Map<String, String> configuration = parseConfiguration(latestRelease.getConfigurations());
    Assert.assertEquals(3, configuration.size());
    Assert.assertEquals("v1", configuration.get("k1"));
    Assert.assertEquals("v2", configuration.get("k2"));
    Assert.assertEquals("v3", configuration.get("k3"));

    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, clusterName, testNamespace, pageable);

    ReleaseHistory releaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(1, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.NORMAL_RELEASE, releaseHistory.getOperation());
    Assert.assertEquals(latestRelease.getId(), releaseHistory.getReleaseId());
    Assert.assertEquals(0, releaseHistory.getPreviousReleaseId());
  }


  /**
   *               Master     |      Branch
   *           ------------------------------                                      Master    |    Branch
   *     Items      k1=v1     |                                                 ----------------------------
   *                k2=v2     |                                                     k1=v1    |    k1=v1
   *                k3=v3                            publish master                 k2=v2    |    k2=v2
   *           ------------------------------        ===========>>      Result      k3=v3    |    k3=v3
   *    Release               |
   *                          |
   *                          |
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testPublishMasterNamespaceAndBranchHasNotItems() {
    long parentNamespaceId = 101;
    String parentClusterName = "default1";
    long childNamespaceId = 102;
    String childClusterName = "child-cluster1";
    Namespace parentNamespace = instanceNamespace(parentNamespaceId, parentClusterName);

    releaseService.publish(parentNamespace, "", "", operator);

    Release latestParentNamespaceRelease = releaseService.findLatestActiveRelease(parentNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestParentNamespaceRelease);

    Map<String, String> parentNamespaceConfiguration = parseConfiguration(latestParentNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", parentNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", parentNamespaceConfiguration.get("k3"));

    //assert child namespace
    Namespace childNamespace = instanceNamespace(childNamespaceId, childClusterName);
    Release latestChildNamespaceRelease = releaseService.findLatestActiveRelease(childNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestChildNamespaceRelease);

    Map<String, String> childNamespaceConfiguration = parseConfiguration(latestChildNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, childNamespaceConfiguration.size());
    Assert.assertEquals("v1", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", childNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", childNamespaceConfiguration.get("k3"));

    GrayReleaseRule rule= namespaceBranchService.findBranchGrayRules(testApp, parentClusterName,
                                                                     testNamespace, childClusterName);
    Assert.assertNotNull(rule);
    Assert.assertEquals(1, rule.getBranchStatus());
    Assert.assertEquals(Long.valueOf(latestChildNamespaceRelease.getId()), rule.getReleaseId());

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory masterReleaseHistory = releaseHistories.getContent().get(1);
    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(2, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.NORMAL_RELEASE, masterReleaseHistory.getOperation());
    Assert.assertEquals(latestParentNamespaceRelease.getId(), masterReleaseHistory.getReleaseId());
    Assert.assertEquals(0, masterReleaseHistory.getPreviousReleaseId());
    Assert.assertEquals(ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(latestChildNamespaceRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(String.format
        ("\"baseReleaseId\":%d", latestParentNamespaceRelease.getId())));
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(rule.getRules()));

  }


  /**
   *               Master     |      Branch
   *           ------------------------------                                      Master    |    Branch
   *     Items      k1=v1     |      k1=v1-2                                      -------------------------
   *                k2=v2     |                                                     k1=v1    |    k1=v1
   *                k3=v3                            publish master                 k2=v2    |    k2=v2
   *           ------------------------------        ===========>>      Result      k3=v3    |    k3=v3
   *    Release               |
   *                          |
   *                          |
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testPublishMasterNamespaceAndBranchHasItems() {
    long parentNamespaceId = 103;
    String parentClusterName = "default2";
    long childNamespaceId = 104;
    String childClusterName = "child-cluster2";
    Namespace parentNamespace = instanceNamespace(parentNamespaceId, parentClusterName);

    releaseService.publish(parentNamespace, "", "", operator);

    Release latestParentNamespaceRelease = releaseService.findLatestActiveRelease(parentNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestParentNamespaceRelease);

    Map<String, String> parentNamespaceConfiguration = parseConfiguration(latestParentNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", parentNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", parentNamespaceConfiguration.get("k3"));

    //assert child namespace
    Namespace childNamespace = instanceNamespace(childNamespaceId, childClusterName);
    Release latestChildNamespaceRelease = releaseService.findLatestActiveRelease(childNamespace);

    Assert.assertNotNull(latestChildNamespaceRelease);

    Map<String, String> childNamespaceConfiguration = parseConfiguration(latestChildNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, childNamespaceConfiguration.size());
    Assert.assertEquals("v1", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", childNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", childNamespaceConfiguration.get("k3"));

    GrayReleaseRule rule= namespaceBranchService.findBranchGrayRules(testApp, parentClusterName,
                                                                     testNamespace, childClusterName);
    Assert.assertNotNull(rule);
    Assert.assertEquals(1, rule.getBranchStatus());
    Assert.assertEquals(Long.valueOf(latestChildNamespaceRelease.getId()), rule.getReleaseId());

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory masterReleaseHistory = releaseHistories.getContent().get(1);
    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(2, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.NORMAL_RELEASE, masterReleaseHistory.getOperation());
    Assert.assertEquals(latestParentNamespaceRelease.getId(), masterReleaseHistory.getReleaseId());
    Assert.assertEquals(0, masterReleaseHistory.getPreviousReleaseId());
    Assert.assertEquals(ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(latestChildNamespaceRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(String.format
        ("\"baseReleaseId\":%d", latestParentNamespaceRelease.getId())));
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(rule.getRules()));
  }


  /**
   *               Master     |      Branch
   *           ------------------------------                                      Master    |    Branch
   *     Items      k1=v1     |      k1=v1-2                                    ----------------------------
   *               k2=v2-2    |                      publish master                 k1=v1    |    k1=v1-1
   *           ------------------------------        ===========>>      Result      k2=v2-2  |    k2=v2-2
   *    Release     k1=v1     |      k1=v1-1                                                 |
   *                k2=v2     |      k2=v3
   *                k3=v3     |      k3=v3
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testModifyMasterNamespaceItemsAndBranchAlsoModify() {
    long parentNamespaceId = 105;
    String parentClusterName = "default3";
    long childNamespaceId = 106;
    String childClusterName = "child-cluster3";
    Namespace parentNamespace = instanceNamespace(parentNamespaceId, parentClusterName);

    releaseService.publish(parentNamespace, "", "", operator);

    Release latestParentNamespaceRelease = releaseService.findLatestActiveRelease(parentNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestParentNamespaceRelease);

    Map<String, String> parentNamespaceConfiguration = parseConfiguration(latestParentNamespaceRelease.getConfigurations());
    Assert.assertEquals(2, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2-2", parentNamespaceConfiguration.get("k2"));

    //assert child namespace
    Namespace childNamespace = instanceNamespace(childNamespaceId, childClusterName);
    Release latestChildNamespaceRelease = releaseService.findLatestActiveRelease(childNamespace);

    Assert.assertNotNull(latestChildNamespaceRelease);

    Map<String, String> childNamespaceConfiguration = parseConfiguration(latestChildNamespaceRelease.getConfigurations());
    Assert.assertEquals(2, childNamespaceConfiguration.size());
    Assert.assertEquals("v1-1", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2-2", childNamespaceConfiguration.get("k2"));

    GrayReleaseRule rule= namespaceBranchService.findBranchGrayRules(testApp, parentClusterName,
                                                                     testNamespace, childClusterName);
    Assert.assertNotNull(rule);
    Assert.assertEquals(1, rule.getBranchStatus());
    Assert.assertEquals(Long.valueOf(latestChildNamespaceRelease.getId()), rule.getReleaseId());

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory masterReleaseHistory = releaseHistories.getContent().get(1);
    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(2, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.NORMAL_RELEASE, masterReleaseHistory.getOperation());
    Assert.assertEquals(latestParentNamespaceRelease.getId(), masterReleaseHistory.getReleaseId());
    Assert.assertEquals(1, masterReleaseHistory.getPreviousReleaseId());
    Assert.assertEquals(ReleaseOperation.MASTER_NORMAL_RELEASE_MERGE_TO_GRAY,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(latestChildNamespaceRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertEquals(2, branchReleaseHistory.getPreviousReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(String.format
        ("\"baseReleaseId\":%d", latestParentNamespaceRelease.getId())));
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(rule.getRules()));
  }

  /**
   *               Master     |      Branch
   *           ------------------------------                                      Master    |    Branch
   *     Items      k1=v1     |      k1=v1-2                                    ----------------------------
   *               k2=v2-2    |      k4=v4           publish branch                 k1=v1    |    k1=v1-2
   *           ------------------------------        ===========>>      Result      k2=v2    |    k2=v2
   *    Release     k1=v1     |                                                     k3=v3    |    k3=v3
   *                k2=v2     |                                                              |    k4=v4
   *                k3=v3     |
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testPublishBranchAtFirstTime() {
    long parentNamespaceId = 107;
    String parentClusterName = "default4";
    long childNamespaceId = 108;
    String childClusterName = "child-cluster4";
    //assert child namespace
    Namespace childNamespace = instanceNamespace(childNamespaceId, childClusterName);
    releaseService.publish(childNamespace, "", "", operator);

    Release latestChildNamespaceRelease = releaseService.findLatestActiveRelease(childNamespace);

    Assert.assertNotNull(latestChildNamespaceRelease);

    Map<String, String> childNamespaceConfiguration = parseConfiguration(latestChildNamespaceRelease.getConfigurations());
    Assert.assertEquals(4, childNamespaceConfiguration.size());
    Assert.assertEquals("v1-2", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", childNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", childNamespaceConfiguration.get("k3"));
    Assert.assertEquals("v4", childNamespaceConfiguration.get("k4"));

    Namespace parentNamespace = instanceNamespace(parentNamespaceId, parentClusterName);

    Release latestParentNamespaceRelease = releaseService.findLatestActiveRelease(parentNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestParentNamespaceRelease);

    Map<String, String> parentNamespaceConfiguration = parseConfiguration(latestParentNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", parentNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", parentNamespaceConfiguration.get("k3"));

    GrayReleaseRule rule= namespaceBranchService.findBranchGrayRules(testApp, parentClusterName,
                                                                     testNamespace, childClusterName);
    Assert.assertNotNull(rule);
    Assert.assertEquals(1, rule.getBranchStatus());
    Assert.assertEquals(Long.valueOf(latestChildNamespaceRelease.getId()), rule.getReleaseId());

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(1, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.GRAY_RELEASE,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(latestChildNamespaceRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertEquals(0, branchReleaseHistory.getPreviousReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains("\"baseReleaseId\":3"));
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(rule.getRules()));
  }


  /**
   *               Master     |      Branch
   *           ------------------------------                                      Master    |    Branch
   *     Items      k1=v1     |      k1=v1-2                                    ----------------------------
   *               k2=v2-2    |      k4=v4                                          k1=v1    |    k1=v1-2
   *                                 k6=v6           publish branch                 k2=v2    |    k2=v2
   *           ------------------------------        ===========>>      Result      k3=v3    |    k3=v3
   *    Release     k1=v1     |      k1=v1-1                                                 |    k4=v4
   *                k2=v2     |      k2=v2                                                   |    k6=v6
   *                k3=v3     |      k3=v3
   *                          |      k4=v4
   *                          |      k5=v5
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testPublishBranch() {
    long parentNamespaceId = 109;
    String parentClusterName = "default5";
    long childNamespaceId = 1010;
    String childClusterName = "child-cluster5";
    //assert child namespace
    Namespace childNamespace = instanceNamespace(childNamespaceId, childClusterName);
    releaseService.publish(childNamespace, "", "", operator);

    Release latestChildNamespaceRelease = releaseService.findLatestActiveRelease(childNamespace);

    Assert.assertNotNull(latestChildNamespaceRelease);

    Map<String, String> childNamespaceConfiguration = parseConfiguration(latestChildNamespaceRelease.getConfigurations());
    Assert.assertEquals(5, childNamespaceConfiguration.size());
    Assert.assertEquals("v1-2", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", childNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", childNamespaceConfiguration.get("k3"));
    Assert.assertEquals("v4", childNamespaceConfiguration.get("k4"));
    Assert.assertEquals("v6", childNamespaceConfiguration.get("k6"));

    Namespace parentNamespace = instanceNamespace(parentNamespaceId, parentClusterName);

    Release latestParentNamespaceRelease = releaseService.findLatestActiveRelease(parentNamespace);

    //assert parent namespace
    Assert.assertNotNull(latestParentNamespaceRelease);

    Map<String, String> parentNamespaceConfiguration = parseConfiguration(latestParentNamespaceRelease.getConfigurations());
    Assert.assertEquals(3, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2", parentNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", parentNamespaceConfiguration.get("k3"));

    GrayReleaseRule rule= namespaceBranchService.findBranchGrayRules(testApp, parentClusterName,
                                                                     testNamespace, childClusterName);
    Assert.assertNotNull(rule);
    Assert.assertEquals(1, rule.getBranchStatus());
    Assert.assertEquals(Long.valueOf(latestChildNamespaceRelease.getId()), rule.getReleaseId());

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(1, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.GRAY_RELEASE,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(latestChildNamespaceRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertEquals(5, branchReleaseHistory.getPreviousReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains("\"baseReleaseId\":4"));
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(rule.getRules()));
  }

  /**
   *                          Master     |      Branch
   *                       ------------------------------                                      Master   |    Branch
   *     Rollback Release      k1=v1     |      k1=v1-2                                    ----------------------------
   *                           k2=v2     |      k2=v2                                        k1=v1-1    |    k1=v1-2
   *                                     |      k3=v3                                        k2=v2-1    |    k2=v2-1
   *                                                            rollback                     k3=v3      |    k3=v3
   *                       ------------------------------     ===========>>   New Release
   *    New  Release           k1=v1-1   |
   *                           k2=v2-1   |
   *                           k3=v3     |
   *
   *
   */
  @Test
  @Sql(scripts = "/sql/release-creation-test.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/sql/clean.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
  public void testRollback() {

    String parentClusterName = "default6";
    String childClusterName = "child-cluster6";
    String operator = "apollo";

    Release parentNamespaceLatestRelease = releaseService.findLatestActiveRelease(testApp, parentClusterName, testNamespace);
    releaseService.rollback(parentNamespaceLatestRelease.getId(), operator);

    Release parentNamespaceNewLatestRelease = releaseService.findLatestActiveRelease(testApp, parentClusterName, testNamespace);
    Map<String, String> parentNamespaceConfiguration = parseConfiguration(parentNamespaceNewLatestRelease.getConfigurations());
    Assert.assertEquals(3, parentNamespaceConfiguration.size());
    Assert.assertEquals("v1-1", parentNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2-1", parentNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", parentNamespaceConfiguration.get("k3"));

    Release childNamespaceNewLatestRelease = releaseService.findLatestActiveRelease(testApp, childClusterName, testNamespace);
    Map<String, String> childNamespaceConfiguration = parseConfiguration(childNamespaceNewLatestRelease.getConfigurations());
    Assert.assertEquals(3, childNamespaceConfiguration.size());
    Assert.assertEquals("v1-2", childNamespaceConfiguration.get("k1"));
    Assert.assertEquals("v2-1", childNamespaceConfiguration.get("k2"));
    Assert.assertEquals("v3", childNamespaceConfiguration.get("k3"));

    //assert release history
    Page<ReleaseHistory> releaseHistories = releaseHistoryService.findReleaseHistoriesByNamespace
        (testApp, parentClusterName, testNamespace, pageable);

    ReleaseHistory masterReleaseHistory = releaseHistories.getContent().get(1);
    ReleaseHistory branchReleaseHistory = releaseHistories.getContent().get(0);

    Assert.assertEquals(2, releaseHistories.getTotalElements());
    Assert.assertEquals(ReleaseOperation.ROLLBACK, masterReleaseHistory.getOperation());
    Assert.assertEquals(6, masterReleaseHistory.getReleaseId());
    Assert.assertEquals(7, masterReleaseHistory.getPreviousReleaseId());
    Assert.assertEquals(ReleaseOperation.MATER_ROLLBACK_MERGE_TO_GRAY,
        branchReleaseHistory.getOperation());
    Assert.assertEquals(childNamespaceNewLatestRelease.getId(), branchReleaseHistory.getReleaseId());
    Assert.assertEquals(8, branchReleaseHistory.getPreviousReleaseId());
    Assert.assertTrue(branchReleaseHistory.getOperationContext().contains(String.format
        ("\"baseReleaseId\":%d", parentNamespaceNewLatestRelease.getId())));
  }


  private Namespace instanceNamespace(long id, String clusterName) {
    Namespace namespace = new Namespace();
    namespace.setAppId(testApp);
    namespace.setNamespaceName(testNamespace);
    namespace.setId(id);
    namespace.setClusterName(clusterName);
    return namespace;
  }

  private Map<String, String> parseConfiguration(String configuration) {
    return gson.fromJson(configuration, configurationTypeReference);
  }

}
