package org.apache.helix;

/*
 * 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.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.helix.model.IdealState;
import org.apache.helix.tools.IdealStateCalculatorForEspressoRelay;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestRelayIdealStateCalculator {
  @Test()
  public void testEspressoStorageClusterIdealState() throws Exception {
    testEspressoStorageClusterIdealState(15, 9, 3);
    testEspressoStorageClusterIdealState(15, 6, 3);
    testEspressoStorageClusterIdealState(15, 6, 2);
    testEspressoStorageClusterIdealState(6, 4, 2);
  }

  public void testEspressoStorageClusterIdealState(int partitions, int nodes, int replica)
      throws Exception {
    List<String> storageNodes = new ArrayList<String>();
    for (int i = 0; i < partitions; i++) {
      storageNodes.add("localhost:123" + i);
    }

    List<String> relays = new ArrayList<String>();
    for (int i = 0; i < nodes; i++) {
      relays.add("relay:123" + i);
    }

    IdealState idealstate =
        IdealStateCalculatorForEspressoRelay.calculateRelayIdealState(storageNodes, relays, "TEST",
            replica, "Leader", "Standby", "LeaderStandby");

    Assert.assertEquals(idealstate.getRecord().getListFields().size(), idealstate.getRecord()
        .getMapFields().size());

    Map<String, Integer> countMap = new TreeMap<String, Integer>();
    for (String key : idealstate.getRecord().getListFields().keySet()) {
      Assert.assertEquals(idealstate.getRecord().getListFields().get(key).size(), idealstate
          .getRecord().getMapFields().get(key).size());
      List<String> list = idealstate.getRecord().getListFields().get(key);
      Map<String, String> map = idealstate.getRecord().getMapFields().get(key);
      Assert.assertEquals(list.size(), replica);
      for (String val : list) {
        if (!countMap.containsKey(val)) {
          countMap.put(val, 1);
        } else {
          countMap.put(val, countMap.get(val) + 1);
        }
        Assert.assertTrue(map.containsKey(val));
      }
    }
    for (String nodeName : countMap.keySet()) {
      Assert.assertTrue(countMap.get(nodeName) <= partitions * replica / nodes + 1);
      // System.out.println(nodeName + " " + countMap.get(nodeName));
    }
    System.out.println();
  }
}
