/*
 * 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.cassandra.dht;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.junit.Before;
import org.junit.Test;

import org.apache.cassandra.service.StorageService;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public abstract class PartitionerTestCase
{
    protected IPartitioner partitioner;

    public abstract void initPartitioner();

    @Before
    public void clean()
    {
        initPartitioner();
    }

    public Token tok(byte[] key)
    {
        return partitioner.getToken(ByteBuffer.wrap(key));
    }

    public Token tok(String key)
    {
        return tok(key.getBytes());
    }

    /**
     * Recurses randomly to the given depth a few times.
     */
    public void assertMidpoint(Token left, Token right, int depth)
    {
        Random rand = new Random();
        for (int i = 0; i < 1000; i++)
        {
            assertMidpoint(left, right, rand, depth);
        }
    }

    private void assertMidpoint(Token left, Token right, Random rand, int depth)
    {
        Token mid = partitioner.midpoint(left, right);
        assert new Range<Token>(left, right).contains(mid)
                : "For " + left + "," + right + ": range did not contain mid:" + mid;
        if (depth < 1)
            return;

        if (rand.nextBoolean())
            assertMidpoint(left, mid, rand, depth-1);
        else
            assertMidpoint(mid, right, rand, depth-1);
    }

    @Test
    public void testMidpoint()
    {
        assertMidpoint(tok("a"), tok("b"), 16);
        assertMidpoint(tok("a"), tok("bbb"), 16);
    }

    @Test
    public void testMidpointMinimum()
    {
        midpointMinimumTestCase();
    }

    protected void midpointMinimumTestCase()
    {
        Token mintoken = partitioner.getMinimumToken();
        assert mintoken.compareTo(partitioner.midpoint(mintoken, mintoken)) != 0;
        assertMidpoint(mintoken, tok("a"), 16);
        assertMidpoint(mintoken, tok("aaa"), 16);
        assertMidpoint(mintoken, mintoken, 126);
        assertMidpoint(tok("a"), mintoken, 16);
    }

    @Test
    public void testMidpointWrapping()
    {
        assertMidpoint(tok("b"), tok("a"), 16);
        assertMidpoint(tok("bbb"), tok("a"), 16);
    }

    @Test
    public void testTokenFactoryBytes()
    {
        Token.TokenFactory factory = partitioner.getTokenFactory();
        assert tok("a").compareTo(factory.fromByteArray(factory.toByteArray(tok("a")))) == 0;
    }

    @Test
    public void testTokenFactoryStrings()
    {
        Token.TokenFactory factory = partitioner.getTokenFactory();
        assert tok("a").compareTo(factory.fromString(factory.toString(tok("a")))) == 0;
    }

    @Test
    public void testDescribeOwnership()
    {
        // This call initializes StorageService, needed to populate the keyspaces.
        // TODO: This points to potential problems in the initialization sequence. Should be solved by CASSANDRA-7837.
        StorageService.instance.getKeyspaces();

        try
        {
            testDescribeOwnershipWith(0);
            fail();
        }
        catch (RuntimeException e)
        {
            // success
        }
        testDescribeOwnershipWith(1);
        testDescribeOwnershipWith(2);
        testDescribeOwnershipWith(256);
    }

    private void testDescribeOwnershipWith(int numTokens)
    {
        List<Token> tokens = new ArrayList<Token>();
        while (tokens.size() < numTokens)
        {
            Token randomToken = partitioner.getRandomToken();
            if (!tokens.contains(randomToken))
                tokens.add(randomToken);
        }
        Collections.sort(tokens);
        Map<Token, Float> owns = partitioner.describeOwnership(tokens);

        float totalOwnership = 0;
        for (float ownership : owns.values())
            totalOwnership += ownership;
        assertEquals(1.0, totalOwnership, 0.001);
    }
}
