text:
package org.apache.cassandra.service;

import java.net.UnknownHostException;
import java.util.*;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import org.apache.cassandra.locator.EndpointsForRange;
import org.apache.cassandra.locator.EndpointsForToken;
import org.apache.cassandra.locator.RangesAtEndpoint;
import org.apache.cassandra.locator.RangesByEndpoint;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.cassandra.locator.InetAddressAndPort;
import org.apache.cassandra.locator.Replica;
import org.apache.cassandra.locator.ReplicaCollection;
import org.apache.cassandra.schema.MigrationManager;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.marshal.BytesType;
import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.Util;
import org.apache.cassandra.schema.Schema;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.RandomPartitioner;
import org.apache.cassandra.dht.RandomPartitioner.BigIntegerToken;
import org.apache.cassandra.dht.Range;
import org.apache.cassandra.dht.Token;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.gms.ApplicationState;
import org.apache.cassandra.gms.Gossiper;
import org.apache.cassandra.locator.AbstractNetworkTopologySnitch;
import org.apache.cassandra.locator.NetworkTopologyStrategy;
import org.apache.cassandra.locator.PendingRangeMaps;
import org.apache.cassandra.gms.VersionedValue;
import org.apache.cassandra.locator.AbstractReplicationStrategy;
import org.apache.cassandra.locator.SimpleSnitch;
import org.apache.cassandra.locator.TokenMetadata;
import org.apache.cassandra.schema.KeyspaceMetadata;
import org.apache.cassandra.schema.KeyspaceParams;
import org.apache.cassandra.schema.Tables;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertNotNull;

public class MoveTest
{
    private static final IPartitioner partitioner = RandomPartitioner.instance;
    private static IPartitioner oldPartitioner;
    //Simple Strategy Keyspaces
    private static final String Simple_RF1_KeyspaceName = "MoveTestKeyspace1";
    private static final String Simple_RF2_KeyspaceName = "MoveTestKeyspace5";
    private static final String Simple_RF3_KeyspaceName = "MoveTestKeyspace4";
    private static final String KEYSPACE2 = "MoveTestKeyspace2";
    private static final String KEYSPACE3 = "MoveTestKeyspace3";

    //Network Strategy Keyspace with RF DC1=1 and DC2=1 and so on.
    private static final String Network_11_KeyspaceName = "MoveTestNetwork11";
    private static final String Network_22_KeyspaceName = "MoveTestNetwork22";
    private static final String Network_33_KeyspaceName = "MoveTestNetwork33";

    /*
     * NOTE: the tests above uses RandomPartitioner, which is not the default
     * test partitioner. Changing the partitioner should be done before
     * loading the schema as loading the schema trigger the write of sstables.
     * So instead of extending SchemaLoader, we call it's method below.
     */
    @BeforeClass
    public static void setup() throws Exception
    {
        DatabaseDescriptor.daemonInitialization();
        oldPartitioner = StorageService.instance.setPartitionerUnsafe(partitioner);
        SchemaLoader.loadSchema();
        SchemaLoader.schemaDefinition("MoveTest");
        addNetworkTopologyKeyspace(Network_11_KeyspaceName, 1, 1);
        addNetworkTopologyKeyspace(Network_22_KeyspaceName, 2, 2);
        addNetworkTopologyKeyspace(Network_33_KeyspaceName, 3, 3);
    }

    @AfterClass
    public static void tearDown()
    {
        StorageService.instance.setPartitionerUnsafe(oldPartitioner);
    }

    @Before
    public void clearTokenMetadata()
    {
        PendingRangeCalculatorService.instance.blockUntilFinished();
        StorageService.instance.getTokenMetadata().clearUnsafe();
    }

    private static void addNetworkTopologyKeyspace(String keyspaceName, Integer... replicas) throws Exception
    {

        DatabaseDescriptor.setEndpointSnitch(new AbstractNetworkTopologySnitch()
        {
            //Odd IPs are in DC1 and Even are in DC2. Endpoints upto .14 will have unique racks and
            // then will be same for a set of three.
            @Override
            public String getRack(InetAddressAndPort endpoint)
            {
                int ipLastPart = getIPLastPart(endpoint);
                if (ipLastPart <= 14)
                    return UUID.randomUUID().toString();
                else
                    return "RAC" + (ipLastPart % 3);
            }

            @Override
            public String getDatacenter(InetAddressAndPort endpoint)
            {
                if (getIPLastPart(endpoint) % 2 == 0)
                    return "DC2";
                else
                    return "DC1";
            }

            private int getIPLastPart(InetAddressAndPort endpoint)
            {
                String str = endpoint.toString();
                int index = str.lastIndexOf(".");
                return Integer.parseInt(str.substring(index + 1).trim().split(":")[0]);
            }
        });

        final TokenMetadata tmd = StorageService.instance.getTokenMetadata();

        tmd.clearUnsafe();
        tmd.updateHostId(UUID.randomUUID(), InetAddressAndPort.getByName("127.0.0.1"));
        tmd.updateHostId(UUID.randomUUID(), InetAddressAndPort.getByName("127.0.0.2"));

        KeyspaceMetadata keyspace =  KeyspaceMetadata.create(keyspaceName,
                                                             KeyspaceParams.nts(configOptions(replicas)),
                                                             Tables.of(TableMetadata.builder(keyspaceName, "CF1")
                                                                                .addPartitionKeyColumn("key", BytesType.instance)
                                                                                .build()));

        MigrationManager.announceNewKeyspace(keyspace);
    }

    private static Object[] configOptions(Integer[] replicas)
    {
        Object[] configOptions = new Object[(replicas.length * 2)];
        int i = 1, j=0;
        for(Integer replica : replicas)
        {
            if(replica == null)
                continue;
            configOptions[j++] = "DC" + i++;
            configOptions[j++] = replica;
        }
        return configOptions;
    }

    @Test
    public void testMoveWithPendingRangesNetworkStrategyRackAwareThirtyNodes() throws Exception
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 60;

        TokenMetadata tmd = ss.getTokenMetadata();
        tmd.clearUnsafe();
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
        ArrayList<Token> endpointTokens = new ArrayList<>();
        ArrayList<Token> keyTokens = new ArrayList<>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<>();

        for(int i=0; i < RING_SIZE/2; i++)
        {
            endpointTokens.add(new BigIntegerToken(String.valueOf(10 * i)));
            endpointTokens.add(new BigIntegerToken(String.valueOf((10 * i) + 1)));
        }
        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);
        PendingRangeCalculatorService.instance.blockUntilFinished();

        //Moving Endpoint 127.0.0.37 in RAC1 with current token 180
        int MOVING_NODE = 36;
        moveHost(hosts.get(MOVING_NODE), 215, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(150, 151, "127.0.0.43"),
                generatePendingMapEntry(151, 160, "127.0.0.43"),generatePendingMapEntry(160, 161, "127.0.0.43"),
                generatePendingMapEntry(161, 170, "127.0.0.43"), generatePendingMapEntry(170, 171, "127.0.0.43"),
                generatePendingMapEntry(171, 180, "127.0.0.43"), generatePendingMapEntry(210, 211, "127.0.0.37"),
                generatePendingMapEntry(211, 215, "127.0.0.37")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 215, tmd);

        //Moving it back to original spot
        moveHost(hosts.get(MOVING_NODE), 180, tmd, valueFactory);
        finishMove(hosts.get(MOVING_NODE), 180, tmd);

    }

    @Test
    public void testMoveWithPendingRangesNetworkStrategyTenNode() throws Exception
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 14;

        TokenMetadata tmd = ss.getTokenMetadata();
        tmd.clearUnsafe();
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
        ArrayList<Token> endpointTokens = new ArrayList<>();
        ArrayList<Token> keyTokens = new ArrayList<>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<>();

        for(int i=0; i < RING_SIZE/2; i++)
        {
            endpointTokens.add(new BigIntegerToken(String.valueOf(10 * i)));
            endpointTokens.add(new BigIntegerToken(String.valueOf((10 * i) + 1)));
        }

        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);
        PendingRangeCalculatorService.instance.blockUntilFinished();

        int MOVING_NODE = 0;
        moveHost(hosts.get(MOVING_NODE), 5, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.1"),
                generatePendingMapEntry(1, 5, "127.0.0.1")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.1"),
                generatePendingMapEntry(1, 5, "127.0.0.1")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.1"),
                generatePendingMapEntry(1, 5, "127.0.0.1")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 5, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.3"),
                generatePendingMapEntry(1, 5, "127.0.0.3")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.5"),
                generatePendingMapEntry(1, 5, "127.0.0.5")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 1, "127.0.0.7"),
                generatePendingMapEntry(1, 5, "127.0.0.7")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        MOVING_NODE = 1;
        moveHost(hosts.get(MOVING_NODE), 5, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.2")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.2")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.2")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 5, tmd);

        moveHost(hosts.get(MOVING_NODE), 1, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.4")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.6")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 5, "127.0.0.8")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 1, tmd);

        MOVING_NODE = 3;
        moveHost(hosts.get(MOVING_NODE), 25, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 10, "127.0.0.6"),
                generatePendingMapEntry(10, 11, "127.0.0.6"), generatePendingMapEntry(21, 25, "127.0.0.4")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(61, 0, "127.0.0.6"),
                generatePendingMapEntry(0, 1, "127.0.0.6"), generatePendingMapEntry(21, 25, "127.0.0.4"),
                generatePendingMapEntry(11, 20, "127.0.0.4"),generatePendingMapEntry(20, 21, "127.0.0.4")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(51, 60, "127.0.0.6"),
                generatePendingMapEntry(60, 61, "127.0.0.6"), generatePendingMapEntry(21, 25, "127.0.0.4"),
                generatePendingMapEntry(11, 20, "127.0.0.4"), generatePendingMapEntry(20, 21, "127.0.0.4")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 25, tmd);

        moveHost(hosts.get(MOVING_NODE), 11, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1, 10, "127.0.0.4"),
                generatePendingMapEntry(10, 11, "127.0.0.4"), generatePendingMapEntry(21, 25, "127.0.0.8")), Network_11_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(61, 0, "127.0.0.4"),
                generatePendingMapEntry(0, 1, "127.0.0.4"), generatePendingMapEntry(11, 20, "127.0.0.8"),
                generatePendingMapEntry(20, 21, "127.0.0.8"), generatePendingMapEntry(21, 25, "127.0.0.10")), Network_22_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(51, 60, "127.0.0.4"),
                generatePendingMapEntry(60, 61, "127.0.0.4"), generatePendingMapEntry(21, 25, "127.0.0.12"),
                generatePendingMapEntry(11, 20, "127.0.0.10"), generatePendingMapEntry(20, 21, "127.0.0.10")), Network_33_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 11, tmd);
    }

    @Test
    public void testMoveWithPendingRangesSimpleStrategyTenNode() throws Exception
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 10;

        TokenMetadata tmd = ss.getTokenMetadata();
        tmd.clearUnsafe();
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
        ArrayList<Token> endpointTokens = new ArrayList<>();
        ArrayList<Token> keyTokens = new ArrayList<>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<>();

        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);
        PendingRangeCalculatorService.instance.blockUntilFinished();

        final int MOVING_NODE = 0; // index of the moving node
        moveHost(hosts.get(MOVING_NODE), 2, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 2, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        moveHost(hosts.get(MOVING_NODE), 1000, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 1000, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1000, 0, "127.0.0.1")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        moveHost(hosts.get(MOVING_NODE), 35, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 35, "127.0.0.1"), generatePendingMapEntry(90, 0, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 35, "127.0.0.1"), generatePendingMapEntry(20, 30, "127.0.0.1"),
                generatePendingMapEntry(80, 90, "127.0.0.2"), generatePendingMapEntry(90, 0, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 35, "127.0.0.1"), generatePendingMapEntry(20, 30, "127.0.0.1"),
                generatePendingMapEntry(80, 90, "127.0.0.3"), generatePendingMapEntry(90, 0, "127.0.0.4"),
                generatePendingMapEntry(10, 20, "127.0.0.1"), generatePendingMapEntry(70, 80, "127.0.0.2")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 35, tmd);

    }

    @Test
    public void testMoveWithPendingRangesForSimpleStrategyFourNode() throws Exception
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 4;

        TokenMetadata tmd = ss.getTokenMetadata();
        tmd.clearUnsafe();
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);
        ArrayList<Token> endpointTokens = new ArrayList<>();
        ArrayList<Token> keyTokens = new ArrayList<>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<>();

        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);
        PendingRangeCalculatorService.instance.blockUntilFinished();

        int MOVING_NODE = 0; // index of the moving node
        moveHost(hosts.get(MOVING_NODE), 2, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.1")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 2, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 2, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        moveHost(hosts.get(MOVING_NODE), 1500, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 1500, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(1500, 0, "127.0.0.1")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        moveHost(hosts.get(MOVING_NODE), 15, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(10, 15, "127.0.0.1"), generatePendingMapEntry(30, 0, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(20, 30, "127.0.0.2"), generatePendingMapEntry(10, 15, "127.0.0.1"),
                generatePendingMapEntry(0, 10, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(15, 20, "127.0.0.2"),
                generatePendingMapEntry(0, 10, "127.0.0.1")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 15, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 0, "127.0.0.1"),
                generatePendingMapEntry(10, 15, "127.0.0.3")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(20, 30, "127.0.0.1"),
                generatePendingMapEntry(10, 15, "127.0.0.4"), generatePendingMapEntry(0, 10, "127.0.0.3")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(15, 20, "127.0.0.1"),
                generatePendingMapEntry(0, 10, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        moveHost(hosts.get(MOVING_NODE), 26, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(20, 26, "127.0.0.1"),
                generatePendingMapEntry(30, 0, "127.0.0.2")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(26, 30, "127.0.0.2"),
                generatePendingMapEntry(30, 0, "127.0.0.3"), generatePendingMapEntry(10, 20, "127.0.0.1")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(0, 10, "127.0.0.1"),
                generatePendingMapEntry(26, 30, "127.0.0.3")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 26, tmd);

        moveHost(hosts.get(MOVING_NODE), 0, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(20, 26, "127.0.0.4"),
                generatePendingMapEntry(30, 0, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 0, "127.0.0.1"),
                generatePendingMapEntry(26, 30, "127.0.0.1"), generatePendingMapEntry(10, 20, "127.0.0.4")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(26, 30, "127.0.0.1"),
                generatePendingMapEntry(0, 10, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 0, tmd);

        MOVING_NODE = 3;

        moveHost(hosts.get(MOVING_NODE), 33, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.4")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.4")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.4")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 33, tmd);

        moveHost(hosts.get(MOVING_NODE), 30, tmd, valueFactory);

        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.1")), Simple_RF1_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.2")), Simple_RF2_KeyspaceName);
        assertPendingRanges(tmd, generatePendingRanges(generatePendingMapEntry(30, 33, "127.0.0.3")), Simple_RF3_KeyspaceName);

        finishMove(hosts.get(MOVING_NODE), 30, tmd);
    }

    private void moveHost(InetAddressAndPort host, int token, TokenMetadata tmd, VersionedValue.VersionedValueFactory valueFactory )
    {
        StorageService.instance.onChange(host, ApplicationState.STATUS, valueFactory.moving(new BigIntegerToken(String.valueOf(token))));
        PendingRangeCalculatorService.instance.blockUntilFinished();
        assertTrue(tmd.isMoving(host));
    }

    private void finishMove(InetAddressAndPort host, int token, TokenMetadata tmd)
    {
        tmd.removeFromMoving(host);
        assertTrue(!tmd.isMoving(host));
        Token newToken = new BigIntegerToken(String.valueOf(token));
        tmd.updateNormalToken(newToken, host);
        // As well as upating TMD, update the host's tokens in gossip. Since CASSANDRA-15120, status changing to MOVING
        // ensures that TMD is up to date with token assignments according to gossip. So we need to make sure gossip has
        // the correct new token, as the moving node itself would do upon successful completion of the move operation.
        // Without this, the next movement for that host will set the token in TMD's back to the old value from gossip
        // and incorrect range movements will follow
        Gossiper.instance.injectApplicationState(host,
                                                 ApplicationState.TOKENS,
                                                 new VersionedValue.VersionedValueFactory(partitioner).tokens(Collections.singleton(newToken)));
    }

    private Map.Entry<Range<Token>, EndpointsForRange> generatePendingMapEntry(int start, int end, String... endpoints) throws UnknownHostException
    {
        Map<Range<Token>, EndpointsForRange> pendingRanges = new HashMap<>();
        Range<Token> range = generateRange(start, end);
        pendingRanges.put(range, makeReplicas(range, endpoints));
        return pendingRanges.entrySet().iterator().next();
    }

    private Map<Range<Token>, EndpointsForRange> generatePendingRanges(Map.Entry<Range<Token>, EndpointsForRange>... entries)
    {
        Map<Range<Token>, EndpointsForRange> pendingRanges = new HashMap<>();
        for(Map.Entry<Range<Token>, EndpointsForRange> entry : entries)
        {
            pendingRanges.put(entry.getKey(), entry.getValue());
        }
        return pendingRanges;
    }

    private void assertPendingRanges(TokenMetadata tmd, Map<Range<Token>, EndpointsForRange> pendingRanges, String keyspaceName) throws ConfigurationException
    {
        boolean keyspaceFound = false;
        for (String nonSystemKeyspaceName : Schema.instance.getNonLocalStrategyKeyspaces())
        {
            if(!keyspaceName.equals(nonSystemKeyspaceName))
                continue;
            assertMaps(pendingRanges, tmd.getPendingRanges(keyspaceName));
            keyspaceFound = true;
        }

        assert keyspaceFound;
    }

    private void assertMaps(Map<Range<Token>, EndpointsForRange> expected, PendingRangeMaps actual)
    {
        int sizeOfActual = 0;
        Iterator<Map.Entry<Range<Token>, EndpointsForRange.Builder>> iterator = actual.iterator();
        while(iterator.hasNext())
        {
            Map.Entry<Range<Token>, EndpointsForRange.Builder> actualEntry = iterator.next();
            assertNotNull(expected.get(actualEntry.getKey()));
            assertEquals(ImmutableSet.copyOf(expected.get(actualEntry.getKey())), ImmutableSet.copyOf(actualEntry.getValue()));
            sizeOfActual++;
        }

        assertEquals(expected.size(), sizeOfActual);
    }

    /*
     * Test whether write endpoints is correct when the node is moving. Uses
     * StorageService.onChange and does not manipulate token metadata directly.
     */
    @Test
    public void newTestWriteEndpointsDuringMove() throws Exception
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 10;
        final int MOVING_NODE = 3; // index of the moving node

        TokenMetadata tmd = ss.getTokenMetadata();
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);

        ArrayList<Token> endpointTokens = new ArrayList<Token>();
        ArrayList<Token> keyTokens = new ArrayList<Token>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<UUID>();

        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);

        Map<Token, List<InetAddressAndPort>> expectedEndpoints = new HashMap<>();
        for (Token token : keyTokens)
        {
            List<InetAddressAndPort> endpoints = new ArrayList<>();
            Iterator<Token> tokenIter = TokenMetadata.ringIterator(tmd.sortedTokens(), token, false);
            while (tokenIter.hasNext())
            {
                endpoints.add(tmd.getEndpoint(tokenIter.next()));
            }
            expectedEndpoints.put(token, endpoints);
        }

        // node LEAVING_NODE should move to this token
        Token newToken = positionToken(MOVING_NODE);

        // Third node leaves
        ss.onChange(hosts.get(MOVING_NODE), ApplicationState.STATUS, valueFactory.moving(newToken));
        PendingRangeCalculatorService.instance.blockUntilFinished();

        assertTrue(tmd.isMoving(hosts.get(MOVING_NODE)));

        AbstractReplicationStrategy strategy;
        for (String keyspaceName : Schema.instance.getNonLocalStrategyKeyspaces())
        {
            strategy = getStrategy(keyspaceName, tmd);
            if(strategy instanceof NetworkTopologyStrategy)
                continue;
            int numMoved = 0;
            for (Token token : keyTokens)
            {
                int replicationFactor = strategy.getReplicationFactor().allReplicas;

                EndpointsForToken actual = tmd.getWriteEndpoints(token, keyspaceName, strategy.calculateNaturalReplicas(token, tmd.cloneOnlyTokenMap()).forToken(token));
                HashSet<InetAddressAndPort> expected = new HashSet<>();

                for (int i = 0; i < replicationFactor; i++)
                {
                    expected.add(expectedEndpoints.get(token).get(i));
                }

                if (expected.size() == actual.size()) {
                	assertEquals("mismatched endpoint sets", expected, actual.endpoints());
                } else {
                	expected.add(hosts.get(MOVING_NODE));
                	assertEquals("mismatched endpoint sets", expected, actual.endpoints());
                	numMoved++;
                }
            }
            assertEquals("mismatched number of moved token", 1, numMoved);
        }

        // moving endpoint back to the normal state
        ss.onChange(hosts.get(MOVING_NODE), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(newToken)));
    }

    /*
     * Test ranges and write endpoints when multiple nodes are on the move simultaneously
     */
    @Test
    public void testSimultaneousMove() throws UnknownHostException
    {
        StorageService ss = StorageService.instance;
        final int RING_SIZE = 10;
        TokenMetadata tmd = ss.getTokenMetadata();
        IPartitioner partitioner = RandomPartitioner.instance;
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);

        ArrayList<Token> endpointTokens = new ArrayList<Token>();
        ArrayList<Token> keyTokens = new ArrayList<Token>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<UUID>();

        // create a ring or 10 nodes
        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, RING_SIZE);

        // nodes 6, 8 and 9 leave
        final int[] MOVING = new int[] {6, 8, 9};

        Map<Integer, Token> newTokens = new HashMap<Integer, Token>();

        for (int movingIndex : MOVING)
        {
            Token newToken = positionToken(movingIndex);
            ss.onChange(hosts.get(movingIndex), ApplicationState.STATUS, valueFactory.moving(newToken));

            // storing token associated with a node index
            newTokens.put(movingIndex, newToken);
        }

        tmd = tmd.cloneAfterAllSettled();
        ss.setTokenMetadataUnsafe(tmd);

        // boot two new nodes with keyTokens.get(5) and keyTokens.get(7)
        InetAddressAndPort boot1 = InetAddressAndPort.getByName("127.0.1.1");
        Gossiper.instance.initializeNodeUnsafe(boot1, UUID.randomUUID(), 1);
        Gossiper.instance.injectApplicationState(boot1, ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(5))));
        ss.onChange(boot1,
                    ApplicationState.STATUS,
                    valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(5))));
        PendingRangeCalculatorService.instance.blockUntilFinished();

        InetAddressAndPort boot2 = InetAddressAndPort.getByName("127.0.1.2");
        Gossiper.instance.initializeNodeUnsafe(boot2, UUID.randomUUID(), 1);
        Gossiper.instance.injectApplicationState(boot2, ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(keyTokens.get(7))));
        ss.onChange(boot2,
                    ApplicationState.STATUS,
                    valueFactory.bootstrapping(Collections.<Token>singleton(keyTokens.get(7))));
        PendingRangeCalculatorService.instance.blockUntilFinished();

        // don't require test update every time a new keyspace is added to test/conf/cassandra.yaml
        Map<String, AbstractReplicationStrategy> keyspaceStrategyMap = new HashMap<String, AbstractReplicationStrategy>();
        for (int i = 1; i <= 4; i++)
        {
            keyspaceStrategyMap.put("MoveTestKeyspace" + i, getStrategy("MoveTestKeyspace" + i, tmd));
        }

       /**
        *  Keyspace1 & Keyspace2 RF=1
        *  {
        *      /127.0.0.1=[(97,0]],
        *      /127.0.0.2=[(0,10]],
        *      /127.0.0.3=[(10,20]],
        *      /127.0.0.4=[(20,30]],
        *      /127.0.0.5=[(30,40]],
        *      /127.0.0.6=[(40,50]],
        *      /127.0.0.7=[(50,67]],
        *      /127.0.0.8=[(67,70]],
        *      /127.0.0.9=[(70,87]],
        *      /127.0.0.10=[(87,97]]
        *  }
        */

        RangesByEndpoint keyspace1ranges = keyspaceStrategyMap.get(Simple_RF1_KeyspaceName).getAddressReplicas();

        assertRanges(keyspace1ranges, "127.0.0.1", 97, 0);
        assertRanges(keyspace1ranges, "127.0.0.2", 0, 10);
        assertRanges(keyspace1ranges, "127.0.0.3", 10, 20);
        assertRanges(keyspace1ranges, "127.0.0.4", 20, 30);
        assertRanges(keyspace1ranges, "127.0.0.5", 30, 40);
        assertRanges(keyspace1ranges, "127.0.0.6", 40, 50);
        assertRanges(keyspace1ranges, "127.0.0.7", 50, 67);
        assertRanges(keyspace1ranges, "127.0.0.8", 67, 70);
        assertRanges(keyspace1ranges, "127.0.0.9", 70, 87);
        assertRanges(keyspace1ranges, "127.0.0.10", 87, 97);

        /**
        * Keyspace3 RF=5
        * {
        *      /127.0.0.1=[(97,0], (70,87], (50,67], (87,97], (67,70]],
        *      /127.0.0.2=[(97,0], (70,87], (87,97], (0,10], (67,70]],
        *      /127.0.0.3=[(97,0], (70,87], (87,97], (0,10], (10,20]],
        *      /127.0.0.4=[(97,0], (20,30], (87,97], (0,10], (10,20]],
        *      /127.0.0.5=[(97,0], (30,40], (20,30], (0,10], (10,20]],
        *      /127.0.0.6=[(40,50], (30,40], (20,30], (0,10], (10,20]],
        *      /127.0.0.7=[(40,50], (30,40], (50,67], (20,30], (10,20]],
        *      /127.0.0.8=[(40,50], (30,40], (50,67], (20,30], (67,70]],
        *      /127.0.0.9=[(40,50], (70,87], (30,40], (50,67], (67,70]],
        *      /127.0.0.10=[(40,50], (70,87], (50,67], (87,97], (67,70]]
        * }
        */

        RangesByEndpoint keyspace3ranges = keyspaceStrategyMap.get(KEYSPACE3).getAddressReplicas();
        assertRanges(keyspace3ranges, "127.0.0.1", 97, 0, 70, 87, 50, 67, 87, 97, 67, 70);
        assertRanges(keyspace3ranges, "127.0.0.2", 97, 0, 70, 87, 87, 97, 0, 10, 67, 70);
        assertRanges(keyspace3ranges, "127.0.0.3", 97, 0, 70, 87, 87, 97, 0, 10, 10, 20);
        assertRanges(keyspace3ranges, "127.0.0.4", 97, 0, 20, 30, 87, 97, 0, 10, 10, 20);
        assertRanges(keyspace3ranges, "127.0.0.5", 97, 0, 30, 40, 20, 30, 0, 10, 10, 20);
        assertRanges(keyspace3ranges, "127.0.0.6", 40, 50, 30, 40, 20, 30, 0, 10, 10, 20);
        assertRanges(keyspace3ranges, "127.0.0.7", 40, 50, 30, 40, 50, 67, 20, 30, 10, 20);
        assertRanges(keyspace3ranges, "127.0.0.8", 40, 50, 30, 40, 50, 67, 20, 30, 67, 70);
        assertRanges(keyspace3ranges, "127.0.0.9", 40, 50, 70, 87, 30, 40, 50, 67, 67, 70);
        assertRanges(keyspace3ranges, "127.0.0.10", 40, 50, 70, 87, 50, 67, 87, 97, 67, 70);

        /**
         * Keyspace4 RF=3
         * {
         *      /127.0.0.1=[(97,0], (70,87], (87,97]],
         *      /127.0.0.2=[(97,0], (87,97], (0,10]],
         *      /127.0.0.3=[(97,0], (0,10], (10,20]],
         *      /127.0.0.4=[(20,30], (0,10], (10,20]],
         *      /127.0.0.5=[(30,40], (20,30], (10,20]],
         *      /127.0.0.6=[(40,50], (30,40], (20,30]],
         *      /127.0.0.7=[(40,50], (30,40], (50,67]],
         *      /127.0.0.8=[(40,50], (50,67], (67,70]],
         *      /127.0.0.9=[(70,87], (50,67], (67,70]],
         *      /127.0.0.10=[(70,87], (87,97], (67,70]]
         *  }
         */
        RangesByEndpoint keyspace4ranges = keyspaceStrategyMap.get(Simple_RF3_KeyspaceName).getAddressReplicas();

        assertRanges(keyspace4ranges, "127.0.0.1", 97, 0, 70, 87, 87, 97);
        assertRanges(keyspace4ranges, "127.0.0.2", 97, 0, 87, 97, 0, 10);
        assertRanges(keyspace4ranges, "127.0.0.3", 97, 0, 0, 10, 10, 20);
        assertRanges(keyspace4ranges, "127.0.0.4", 20, 30, 0, 10, 10, 20);
        assertRanges(keyspace4ranges, "127.0.0.5", 30, 40, 20, 30, 10, 20);
        assertRanges(keyspace4ranges, "127.0.0.6", 40, 50, 30, 40, 20, 30);
        assertRanges(keyspace4ranges, "127.0.0.7", 40, 50, 30, 40, 50, 67);
        assertRanges(keyspace4ranges, "127.0.0.8", 40, 50, 50, 67, 67, 70);
        assertRanges(keyspace4ranges, "127.0.0.9", 70, 87, 50, 67, 67, 70);
        assertRanges(keyspace4ranges, "127.0.0.10", 70, 87, 87, 97, 67, 70);

        // pre-calculate the results.
        Map<String, Multimap<Token, InetAddressAndPort>> expectedEndpoints = new HashMap<>();
        expectedEndpoints.put(Simple_RF1_KeyspaceName, HashMultimap.<Token, InetAddressAndPort>create());
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.1.1"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.7"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.1.2"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.9"));
        expectedEndpoints.get(Simple_RF1_KeyspaceName).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.10"));
        expectedEndpoints.put(KEYSPACE2, HashMultimap.<Token, InetAddressAndPort>create());
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.1.1"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.7"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.9"));
        expectedEndpoints.get(KEYSPACE2).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.10"));
        expectedEndpoints.put(KEYSPACE3, HashMultimap.<Token, InetAddressAndPort>create());
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2", "127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3", "127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.1.1"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4", "127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.1.1"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.1.1", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.1.1", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.1.1", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.1.2"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3"));
        expectedEndpoints.get(KEYSPACE3).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.10", "127.0.0.1", "127.0.0.2", "127.0.0.3", "127.0.0.4"));
        expectedEndpoints.put(Simple_RF3_KeyspaceName, HashMultimap.<Token, InetAddressAndPort>create());
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("5"), makeAddrs("127.0.0.2", "127.0.0.3", "127.0.0.4"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("15"), makeAddrs("127.0.0.3", "127.0.0.4", "127.0.0.5"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("25"), makeAddrs("127.0.0.4", "127.0.0.5", "127.0.0.6"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("35"), makeAddrs("127.0.0.5", "127.0.0.6", "127.0.0.7", "127.0.1.1"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("45"), makeAddrs("127.0.0.6", "127.0.0.7", "127.0.0.8", "127.0.1.1"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("55"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.1.1", "127.0.1.2"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("65"), makeAddrs("127.0.0.7", "127.0.0.8", "127.0.0.9", "127.0.1.2"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("75"), makeAddrs("127.0.0.9", "127.0.0.10", "127.0.0.1", "127.0.1.2"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("85"), makeAddrs("127.0.0.9", "127.0.0.10", "127.0.0.1"));
        expectedEndpoints.get(Simple_RF3_KeyspaceName).putAll(new BigIntegerToken("95"), makeAddrs("127.0.0.10", "127.0.0.1", "127.0.0.2"));

        for (Map.Entry<String, AbstractReplicationStrategy> keyspaceStrategy : keyspaceStrategyMap.entrySet())
        {
            String keyspaceName = keyspaceStrategy.getKey();
            AbstractReplicationStrategy strategy = keyspaceStrategy.getValue();

            for (Token token : keyTokens)
            {
                Collection<InetAddressAndPort> endpoints = tmd.getWriteEndpoints(token, keyspaceName, strategy.getNaturalReplicasForToken(token)).endpoints();
                assertEquals(expectedEndpoints.get(keyspaceName).get(token).size(), endpoints.size());
                assertTrue(expectedEndpoints.get(keyspaceName).get(token).containsAll(endpoints));
            }

            // just to be sure that things still work according to the old tests, run them:
            if (strategy.getReplicationFactor().allReplicas != 3)
                continue;

            ReplicaCollection<?> replicas = null;
            // tokens 5, 15 and 25 should go three nodes
            for (int i = 0; i < 3; i++)
            {
                replicas = tmd.getWriteEndpoints(keyTokens.get(i), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(i)));
                assertEquals(3, replicas.size());
                assertTrue(replicas.endpoints().contains(hosts.get(i + 1)));
                assertTrue(replicas.endpoints().contains(hosts.get(i + 2)));
                assertTrue(replicas.endpoints().contains(hosts.get(i + 3)));
            }

            // token 35 should go to nodes 4, 5, 6 and boot1
            replicas = tmd.getWriteEndpoints(keyTokens.get(3), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(3)));
            assertEquals(4, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(4)));
            assertTrue(replicas.endpoints().contains(hosts.get(5)));
            assertTrue(replicas.endpoints().contains(hosts.get(6)));
            assertTrue(replicas.endpoints().contains(boot1));

            // token 45 should go to nodes 5, 6, 7 boot1
            replicas = tmd.getWriteEndpoints(keyTokens.get(4), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(4)));
            assertEquals(4, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(5)));
            assertTrue(replicas.endpoints().contains(hosts.get(6)));
            assertTrue(replicas.endpoints().contains(hosts.get(7)));
            assertTrue(replicas.endpoints().contains(boot1));

            // token 55 should go to nodes 6, 7, 8 boot1 and boot2
            replicas = tmd.getWriteEndpoints(keyTokens.get(5), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(5)));
            assertEquals(5, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(6)));
            assertTrue(replicas.endpoints().contains(hosts.get(7)));
            assertTrue(replicas.endpoints().contains(hosts.get(8)));
            assertTrue(replicas.endpoints().contains(boot1));
            assertTrue(replicas.endpoints().contains(boot2));

            // token 65 should go to nodes 6, 7, 8 and boot2
            replicas = tmd.getWriteEndpoints(keyTokens.get(6), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(6)));
            assertEquals(4, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(6)));
            assertTrue(replicas.endpoints().contains(hosts.get(7)));
            assertTrue(replicas.endpoints().contains(hosts.get(8)));
            assertTrue(replicas.endpoints().contains(boot2));

            // token 75 should to go nodes 8, 9, 0 and boot2
            replicas = tmd.getWriteEndpoints(keyTokens.get(7), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(7)));
            assertEquals(4, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(8)));
            assertTrue(replicas.endpoints().contains(hosts.get(9)));
            assertTrue(replicas.endpoints().contains(hosts.get(0)));
            assertTrue(replicas.endpoints().contains(boot2));

            // token 85 should go to nodes 8, 9 and 0
            replicas = tmd.getWriteEndpoints(keyTokens.get(8), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(8)));
            assertEquals(3, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(8)));
            assertTrue(replicas.endpoints().contains(hosts.get(9)));
            assertTrue(replicas.endpoints().contains(hosts.get(0)));

            // token 95 should go to nodes 9, 0 and 1
            replicas = tmd.getWriteEndpoints(keyTokens.get(9), keyspaceName, strategy.getNaturalReplicasForToken(keyTokens.get(9)));
            assertEquals(3, replicas.size());
            assertTrue(replicas.endpoints().contains(hosts.get(9)));
            assertTrue(replicas.endpoints().contains(hosts.get(0)));
            assertTrue(replicas.endpoints().contains(hosts.get(1)));
        }

        // all moving nodes are back to the normal state
        for (Integer movingIndex : MOVING)
        {
            ss.onChange(hosts.get(movingIndex),
                        ApplicationState.STATUS,
                        valueFactory.normal(Collections.singleton(newTokens.get(movingIndex))));
        }
    }

    @Test
    public void testStateJumpToNormal() throws UnknownHostException
    {
        StorageService ss = StorageService.instance;
        TokenMetadata tmd = ss.getTokenMetadata();
        IPartitioner partitioner = RandomPartitioner.instance;
        VersionedValue.VersionedValueFactory valueFactory = new VersionedValue.VersionedValueFactory(partitioner);

        ArrayList<Token> endpointTokens = new ArrayList<Token>();
        ArrayList<Token> keyTokens = new ArrayList<Token>();
        List<InetAddressAndPort> hosts = new ArrayList<>();
        List<UUID> hostIds = new ArrayList<UUID>();

        // create a ring or 6 nodes
        Util.createInitialRing(ss, partitioner, endpointTokens, keyTokens, hosts, hostIds, 6);

        // node 2 leaves
        Token newToken = positionToken(7);
        ss.onChange(hosts.get(2), ApplicationState.STATUS, valueFactory.moving(newToken));

        assertTrue(tmd.isMoving(hosts.get(2)));
        assertEquals(endpointTokens.get(2), tmd.getToken(hosts.get(2)));

        // back to normal
        Gossiper.instance.injectApplicationState(hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(newToken)));
        ss.onChange(hosts.get(2), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(newToken)));

        assertTrue(tmd.getSizeOfMovingEndpoints() == 0);
        assertEquals(newToken, tmd.getToken(hosts.get(2)));

        newToken = positionToken(8);
        // node 2 goes through leave and left and then jumps to normal at its new token
        ss.onChange(hosts.get(2), ApplicationState.STATUS, valueFactory.moving(newToken));
        Gossiper.instance.injectApplicationState(hosts.get(2), ApplicationState.TOKENS, valueFactory.tokens(Collections.singleton(newToken)));
        ss.onChange(hosts.get(2), ApplicationState.STATUS, valueFactory.normal(Collections.singleton(newToken)));

        assertTrue(tmd.getBootstrapTokens().isEmpty());
        assertTrue(tmd.getSizeOfMovingEndpoints() == 0);
        assertEquals(newToken, tmd.getToken(hosts.get(2)));
    }

    private static Collection<InetAddressAndPort> makeAddrs(String... hosts) throws UnknownHostException
    {
        ArrayList<InetAddressAndPort> addrs = new ArrayList<>(hosts.length);
        for (String host : hosts)
            addrs.add(InetAddressAndPort.getByName(host));
        return addrs;
    }

    private static EndpointsForRange makeReplicas(Range<Token> range, String... hosts) throws UnknownHostException
    {
        EndpointsForRange.Builder replicas = EndpointsForRange.builder(range, hosts.length);
        for (String host : hosts)
            replicas.add(Replica.fullReplica(InetAddressAndPort.getByName(host), range));
        return replicas.build();
    }

    private AbstractReplicationStrategy getStrategy(String keyspaceName, TokenMetadata tmd)
    {
        KeyspaceMetadata ksmd = Schema.instance.getKeyspaceMetadata(keyspaceName);
        return AbstractReplicationStrategy.createReplicationStrategy(
                keyspaceName,
                ksmd.params.replication.klass,
                tmd,
                new SimpleSnitch(),
                ksmd.params.replication.options);
    }

    private Token positionToken(int position)
    {
        return new BigIntegerToken(String.valueOf(10 * position + 7));
    }

    private static int collectionSize(Collection<?> collection)
    {
        if (collection.isEmpty())
            return 0;

        Iterator<?> iterator = collection.iterator();

        int count = 0;
        while (iterator.hasNext())
        {
            iterator.next();
            count++;
        }

        return count;
    }

    private Collection<Range<Token>> generateRanges(int... rangePairs)
    {
        if (rangePairs.length % 2 == 1)
            throw new RuntimeException("generateRanges argument count should be even");

        Set<Range<Token>> ranges = new HashSet<Range<Token>>();

        for (int i = 0; i < rangePairs.length; i+=2)
        {
            ranges.add(generateRange(rangePairs[i], rangePairs[i+1]));
        }

        return ranges;
    }

    private static Token tk(int v)
    {
        return new BigIntegerToken(String.valueOf(v));
    }

    private static Range<Token> generateRange(int left, int right)
    {
        return new Range<Token>(tk(left), tk(right));
    }

    private static Replica replica(InetAddressAndPort endpoint, int left, int right, boolean full)
    {
        return new Replica(endpoint, tk(left), tk(right), full);
    }

    private static InetAddressAndPort inet(String name)
    {
        try
        {
            return InetAddressAndPort.getByName(name);
        }
        catch (UnknownHostException e)
        {
            throw new AssertionError(e);
        }
    }

    private static Replica replica(InetAddressAndPort endpoint, int left, int right)
    {
        return replica(endpoint, left, right, true);
    }

    private static void assertRanges(RangesByEndpoint epReplicas, String endpoint, int... rangePairs)
    {
        if (rangePairs.length % 2 == 1)
            throw new RuntimeException("assertRanges argument count should be even");

        InetAddressAndPort ep = inet(endpoint);
        List<Replica> expected = new ArrayList<>(rangePairs.length/2);
        for (int i=0; i<rangePairs.length; i+=2)
            expected.add(replica(ep, rangePairs[i], rangePairs[i+1]));

        RangesAtEndpoint actual = epReplicas.get(ep);
        assertEquals(expected.size(), actual.size());
        for (Replica replica : expected)
            if (!actual.contains(replica))
                assertEquals(RangesAtEndpoint.copyOf(expected), actual);
    }
}


text:
Ruby command-line helpers

# Installation

```bash
gem install rclopts
```

# API usage

## `RequiredArgOptionParser` class

This is an enhancement of the standard Ruby `OptionParser` class which handles
required arguments in a consistent manner. It also passes an instance of
`OpenStruct` into each code block to allow code to accumulate command-line
arguments in a more natural manner than the original class allows.

```ruby
require 'rclopts'

option_parser = Rclopts::RequiredArgOptionParser.new do |p|
  p.banner = "Usage: my-command-line-tool [options]"

  p.on_required '-r VALUE', '--something-required VALUE', 'A required argument' do |o, value|
    o.something_required = value
  end

  p.on '-n VALUE', '--not-required VALUE', 'A not-required argument' do |o, value|
    o.not_required = value
  end

  p.on_tail '-h', '--help', 'Show help' do
    puts p
    exit
  end
end

begin
  options, free_args = option_parser.process_args(ARGV)
rescue Rclopts::RequiredArgOptionParser::RequiredArgOptionParserError => e
  $stderr.puts e.message
  exit 1
end

# Go about your usual business...
```

This returns an `OpenStruct` instance `options` populated with values obtained
from the command line and an array `free_args` of the free arguments passed on
the command line.

## `CliHelper` module

This class encapsulates the standard behaviour of handling parser errors,
displaying them via standard error and exiting with a nonzero return code.

You can replace

```ruby
begin
  options, free_args = option_parser.process_args(ARGV)
rescue Rclopts::RequiredArgOptionParser::RequiredArgOptionParserError => e
  $stderr.puts e.message
  exit 1
end
```

with

```ruby
options, free_args = Rclopts::CliHelper.process_args(option_parser, ARGV)
```

Easy!

# Licence

_rclopts_ is released under the MIT licence.

redpajama_set_name: RedPajamaGithub


text:
title: Composant React Button
components: Button, Fab, IconButton, ButtonBase, Zoom
---

# Buttons (Boutons)

Les boutons permettent aux utilisateurs d'effectuer une action et de faire des choix en un seul clic.

[Buttons](https://material.io/design/components/buttons.html) communiquent les actions que les utilisateurs peuvent effectuer. Ils sont généralement placés dans votre interface utilisateur, dans des endroits tels que:

- Dialogues
- Fenêtres modales
- Formulaires
- Cartes
- Barres d'outils

## Contained Buttons (boutons contenus)

[Les boutons contenus](https://material.io/design/components/buttons.html#contained-button) sont très accentués, ils se distinguent par leur utilisation de l'élévation et du remplissage. Ils contiennent des actions qui sont essentielles à votre application.

Le dernier exemple de cette démo montre comment utiliser un bouton de téléchargement.

{{"demo": "pages/components/buttons/ContainedButtons.js"}}

## Boutons de texte

[Les boutons de texte](https://material.io/design/components/buttons.html#text-button) sont généralement utilisés pour les actions moins prononcées, y compris celles situées:

- Dans les dialogues
- Dans les cartes

Dans les cartes, les boutons de texte aident à maintenir l'accent sur le contenu des cartes.

{{"demo": "pages/components/buttons/TextButtons.js"}}

## Boutons en surbrillance

[boutons en surbrillance](https://material.io/design/components/buttons.html#outlined-button) sont des boutons à accent moyen. Ils contiennent des actions importantes mais qui ne sont pas l'action principale d'une application.

### Alternatives

Les boutons surbrillance sont également une alternative moins importante que les boutons contenus, ou une alternative plus importante aux boutons de texte.

{{"demo": "pages/components/buttons/OutlinedButtons.js"}}

## Boutons d'action flottant

A [bouton d'action flottante](https://material.io/design/components/buttons-floating-action-button.html) (FAB) effectue la première, ou la plus courante, l' action sur un écran. Il apparaît devant tout le contenu de l'écran, généralement sous la forme d'une forme circulaire avec une icône en son centre. Il existe deux types de FAB: régulier et étendu.

Utilisez un FAB uniquement si c'est le moyen le plus approprié pour présenter l'action principale d'un écran.

Un seul bouton d'action flottante est recommandé par écran pour représenter l'action la plus courante.

{{"demo": "pages/components/buttons/FloatingActionButtons.js"}}

Le bouton d'action flottante s'anime sur l'écran en tant que matériau en expansion, par défaut.

Un bouton d'action flottant qui s'étend sur plusieurs écrans latéraux (tels que des écrans à onglets) devrait disparaître brièvement, puis sur si son action change.

La transition Zoom peut être utilisée pour y parvenir. Notez que, comme les animations sortantes et entrantes sont déclenchées simultanément, nous utilisons `enterDelay` pour permettre à l'animation du bouton d'action flottant sortant de se terminer avant l'entrée de la nouvelle.

{{"demo": "pages/components/buttons/FloatingActionButtonZoom.js"}}

## Tailles

Envie de boutons plus grands ou plus petits? Utilisez la propriété `size`.

{{"demo": "pages/components/buttons/ButtonSizes.js"}}

## Boutons avec des icônes et une étiquette

Parfois, vous voudrez peut-être avoir des icônes pour certains boutons afin d'améliorer l'UX de l'application, car nous reconnaissons plus facilement les logos que le texte brut. Par exemple, si vous avez un bouton de suppression, vous pouvez lui attribuer une icône représentant une poubelle.

{{"demo": "pages/components/buttons/IconLabelButtons.js"}}

## Boutons avec icône

Les boutons d'icône se trouvent généralement dans les barres d'applications et les barres d'outils.

Les icônes sont également appropriés pour les boutons à bascule qui permettent à un seul choix à choisir ou décochée, comme l' ajout ou la suppression d' une étoile à un élément.

{{"demo": "pages/components/buttons/IconButtons.js"}}

## Boutons personnalisés

Voici quelques exemples de personnalisation du composant. Vous pouvez en apprendre plus sur [la page de documentation de personnalisation](/customization/components/).

{{"demo": "pages/components/buttons/CustomizedButtons.js"}}

## Boutons complexes

Les boutons texte, les boutons contained, les bouton d'action flottante et les boutons icône sont tous basés sur le composant `ButtonBase`. Vous pouvez tirer parti de ce composant de niveau inférieur pour créer des interactions personnalisées.

{{"demo": "pages/components/buttons/ButtonBases.js"}}

## Bibliothèque de routage tierce

Un cas d'utilisation courant consiste à utiliser le bouton pour déclencher une navigation vers une nouvelle page. Le composant `ButtonBase` fournit une propriété pour traiter ce cas d'utilisation: `composant`. Cependant, pour certains focus polyfills `ButtonBase` requiert le nœud DOM du composant fourni. Pour ce faire, associez une référence au composant et attendez-vous à ce que le composant transmette cette référence au noeud DOM sous-jacent. Étant donné que beaucoup de nos composants interactifs comptent sur `ButtonBase`, vous devriez être en mesure d'en tirer profit partout:

{{"demo": "pages/components/buttons/ButtonRouter.js", "defaultCodeOpen": true}}

*Note : La création de composants Button est nécessaire pour éviter une erreur inattendu. Vous pouvez en lire plus dans notre [guide de propriété de composant](/guides/composition/#component-property).*


text:
layout: page
title: Shadow Charm Company Seminar
date: 2016-05-24
author: Helen Martin
tags: weekly links, java
status: published
summary: Sed laoreet ligula vitae mauris.
banner: images/banner/office-01.jpg
booking:
  startDate: 06/24/2019
  endDate: 06/25/2019
  ctyhocn: WAWAPHX
  groupCode: SCCS
published: true
---
Etiam eget massa nec ligula porttitor elementum. In non nunc fermentum, ultrices felis quis, mattis est. Cras gravida velit sit amet pretium efficitur. Cras sodales pretium convallis. Aenean non sollicitudin dolor. Ut faucibus mauris ac interdum pharetra. Quisque aliquet mauris elit. Praesent volutpat at enim eget sollicitudin. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed ligula felis, lacinia in suscipit ac, elementum vitae nunc.

* Morbi imperdiet ante vitae massa sodales, quis euismod nulla accumsan
* Suspendisse in odio eu dui maximus blandit id id mi
* Suspendisse vel odio a massa viverra semper consequat eu lorem.

Nulla venenatis scelerisque vehicula. Aliquam eleifend fermentum sem, at semper purus vestibulum vel. Phasellus ullamcorper justo nibh, eu dictum arcu varius non. Morbi pulvinar vestibulum congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Quisque convallis lacinia commodo. Ut vitae malesuada nisi, ac vehicula lorem. Maecenas eu consequat elit.


text:
#undef I3__FILE__
#define I3__FILE__ "regex.c"
/*
 * vim:ts=4:sw=4:expandtab
 *
 * i3 - an improved dynamic tiling window manager
 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
 *
 * regex.c: Interface to libPCRE (perl compatible regular expressions).
 *
 */
#include "all.h"

/*
 * Creates a new 'regex' struct containing the given pattern and a PCRE
 * compiled regular expression. Also, calls pcre_study because this regex will
 * most likely be used often (like for every new window and on every relevant
 * property change of existing windows).
 *
 * Returns NULL if the pattern could not be compiled into a regular expression
 * (and ELOGs an appropriate error message).
 *
 */
struct regex *regex_new(const char *pattern) {
    const char *error;
    int errorcode, offset;

    struct regex *re = scalloc(sizeof(struct regex));
    re->pattern = sstrdup(pattern);
    int options = PCRE_UTF8;
#ifdef PCRE_HAS_UCP
    /* We use PCRE_UCP so that \B, \b, \D, \d, \S, \s, \W, \w and some POSIX
     * character classes play nicely with Unicode */
    options |= PCRE_UCP;
#endif
    while (!(re->regex = pcre_compile2(pattern, options, &errorcode, &error, &offset, NULL))) {
        /* If the error is that PCRE was not compiled with UTF-8 support we
         * disable it and try again */
        if (errorcode == 32) {
            options &= ~PCRE_UTF8;
            continue;
        }
        ELOG("PCRE regular expression compilation failed at %d: %s\n",
             offset, error);
        return NULL;
    }
    re->extra = pcre_study(re->regex, 0, &error);
    /* If an error happened, we print the error message, but continue.
     * Studying the regular expression leads to faster matching, but it's not
     * absolutely necessary. */
    if (error) {
        ELOG("PCRE regular expression studying failed: %s\n", error);
    }
    return re;
}

/*
 * Frees the given regular expression. It must not be used afterwards!
 *
 */
void regex_free(struct regex *regex) {
    if (!regex)
        return;
    FREE(regex->pattern);
    FREE(regex->regex);
    FREE(regex->extra);
}

/*
 * Checks if the given regular expression matches the given input and returns
 * true if it does. In either case, it logs the outcome using LOG(), so it will
 * be visible without debug logging.
 *
 */
bool regex_matches(struct regex *regex, const char *input) {
    int rc;

    /* We use strlen() because pcre_exec() expects the length of the input
     * string in bytes */
    if ((rc = pcre_exec(regex->regex, regex->extra, input, strlen(input), 0, 0, NULL, 0)) == 0) {
        LOG("Regular expression \"%s\" matches \"%s\"\n",
            regex->pattern, input);
        return true;
    }

    if (rc == PCRE_ERROR_NOMATCH) {
        LOG("Regular expression \"%s\" does not match \"%s\"\n",
            regex->pattern, input);
        return false;
    }

    ELOG("PCRE error %d while trying to use regular expression \"%s\" on input \"%s\", see pcreapi(3)\n",
         rc, regex->pattern, input);
    return false;
}


text:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Dotnet.Script.DependencyModel.Environment;
using Dotnet.Script.DependencyModel.Logging;
using Dotnet.Script.DependencyModel.Process;

namespace Dotnet.Script.DependencyModel.ProjectSystem
{
    public class ScriptProjectProvider
    {
        private readonly ScriptParser _scriptParser;
        private readonly ScriptFilesResolver _scriptFilesResolver;
        private readonly ScriptEnvironment _scriptEnvironment;
        private readonly Logger _logger;

        private ScriptProjectProvider(ScriptParser scriptParser, ScriptFilesResolver scriptFilesResolver, LogFactory logFactory, ScriptEnvironment scriptEnvironment)
        {
            _logger = logFactory.CreateLogger<ScriptProjectProvider>();
            _scriptParser = scriptParser;
            _scriptFilesResolver = scriptFilesResolver;
            _scriptEnvironment = scriptEnvironment;
        }

        public ScriptProjectProvider(LogFactory logFactory) : this(new ScriptParser(logFactory), new ScriptFilesResolver(), logFactory, ScriptEnvironment.Default)
        {
        }

        public ProjectFileInfo CreateProjectForRepl(string code, string targetDirectory, string defaultTargetFramework = "net46")
        {
            var scriptFiles = _scriptFilesResolver.GetScriptFilesFromCode(code);
            targetDirectory = Path.Combine(targetDirectory, "interactive");

            var parseResultFromCode = _scriptParser.ParseFromCode(code);
            var parseResultFromLoadedFiles = _scriptParser.ParseFromFiles(scriptFiles);
            var allPackageReferences = new HashSet<PackageReference>();

            foreach (var packageReference in parseResultFromCode.PackageReferences)
            {
                allPackageReferences.Add(packageReference);
            }

            foreach (var packageReference in parseResultFromLoadedFiles.PackageReferences)
            {
                allPackageReferences.Add(packageReference);
            }

            targetDirectory = Path.Combine(targetDirectory, "interactive");
            var pathToProjectFile = GetPathToProjectFile(targetDirectory, defaultTargetFramework);
            var projectFile = new ProjectFile();

            foreach (var packageReference in allPackageReferences)
            {
                projectFile.PackageReferences.Add(packageReference);
            }

            projectFile.TargetFramework = defaultTargetFramework;

            projectFile.Save(pathToProjectFile);

            LogProjectFileInfo(pathToProjectFile);

            return new ProjectFileInfo(pathToProjectFile, NuGetUtilities.GetNearestConfigPath(targetDirectory));
        }

        private void LogProjectFileInfo(string pathToProjectFile)
        {
            _logger.Debug($"Project file saved to {pathToProjectFile}");
            var content = File.ReadAllText(pathToProjectFile);
            _logger.Debug(content);
        }

        public ProjectFileInfo CreateProject(string targetDirectory, string defaultTargetFramework = "net46", bool enableNuGetScriptReferences = false)
        {
            return CreateProject(targetDirectory, Directory.GetFiles(targetDirectory, "*.csx", SearchOption.AllDirectories), defaultTargetFramework, enableNuGetScriptReferences);
        }

        public ProjectFileInfo CreateProject(string targetDirectory, IEnumerable<string> scriptFiles, string defaultTargetFramework = "net46", bool enableNuGetScriptReferences = false)
        {
            if (scriptFiles == null || !scriptFiles.Any())
            {
                return null;
            }

            var pathToProjectFile = Directory.GetFiles(targetDirectory, "*.csproj").FirstOrDefault();
            if (pathToProjectFile == null && !enableNuGetScriptReferences)
            {
                return null;
            }

            _logger.Debug($"Creating project file for *.csx files found in {targetDirectory} using {defaultTargetFramework} as the default framework.");

            return SaveProjectFileFromScriptFiles(targetDirectory, defaultTargetFramework, scriptFiles.ToArray());
        }

        public ProjectFileInfo CreateProjectForScriptFile(string scriptFile)
        {
            _logger.Debug($"Creating project file for {scriptFile}");
            var scriptFiles = _scriptFilesResolver.GetScriptFiles(scriptFile);
            return SaveProjectFileFromScriptFiles(Path.GetDirectoryName(scriptFile), _scriptEnvironment.TargetFramework, scriptFiles.ToArray());
        }

        private ProjectFileInfo SaveProjectFileFromScriptFiles(string targetDirectory, string defaultTargetFramework, string[] csxFiles)
        {
            ProjectFile projectFile = CreateProjectFileFromScriptFiles(defaultTargetFramework, csxFiles);

            var pathToProjectFile = GetPathToProjectFile(targetDirectory, defaultTargetFramework);
            projectFile.Save(pathToProjectFile);

            LogProjectFileInfo(pathToProjectFile);

            return new ProjectFileInfo(pathToProjectFile, NuGetUtilities.GetNearestConfigPath(targetDirectory));
        }

        public ProjectFile CreateProjectFileFromScriptFiles(string defaultTargetFramework, string[] csxFiles)
        {
            var parseresult = _scriptParser.ParseFromFiles(csxFiles);

            var projectFile = new ProjectFile();

            foreach (var packageReference in parseresult.PackageReferences)
            {
                projectFile.PackageReferences.Add(packageReference);
            }

            projectFile.TargetFramework = defaultTargetFramework;
            return projectFile;
        }

        public static string GetPathToProjectFile(string targetDirectory, string targetFramework, string projectName = null)
        {
            projectName ??= "script";
            var projectFileName = projectName + ".csproj";
            var pathToProjectDirectory = FileUtils.CreateTempFolder(targetDirectory, targetFramework);
            var pathToProjectFile = Path.Combine(pathToProjectDirectory, projectFileName);
            return pathToProjectFile;
        }
    }
}


text:
import requests

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/plain')])
    assert requests.__version__ == '2.17.0'
    return [b"Hello from gunicorn WSGI application!"]


text:
/* jshint -W030 */
/* jshint -W003 */
/* jshint -W098 */
var expect = chai.expect;
describe('genie', function() {
  'use strict';
  beforeEach(prepForTest);

  describe('#', function() {
    beforeEach(prepForTest);
    it('should register with an object', function() {
      var minimalObject = genie({
        magicWords: 'magicWord',
        action: function() {}
      });
      var wishData = {
        name: 'value'
      };
      var maximalObject = genie({
        id: 'coolId',
        context: ['gandpa', 'child', 'grandchild'],
        data: wishData,
        magicWords: ['magic', 'word'],
        action: function() {}
      });
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(2);
      expect(maximalObject).to.have.property('id').to.equal('coolId');
      expect(maximalObject).to.have.property('context').to.have.property('any').with.length(3);
      expect(maximalObject).to.have.property('data').to.equal(wishData);
      expect(maximalObject).to.have.property('magicWords').with.length(2);
    });

    it('should register with an array', function() {
      var wishes = genie([
        {
          magicWords: 'wish1',
          action: function(){}
        },
        {
          magicWords: 'wish2',
          action: function(){}
        },
        {
          magicWords: 'wish3',
          action: function(){}
        }
      ]);

      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(3);
    });

    it('should overwrite wish with duplicateId', function() {
      var wishOne = genie(fillInWish({
        id: 'id'
      }));
      var wishTwo = genie(fillInWish({
        id: 'id'
      }));
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(1);
      expect(wishTwo).to.equal(allWishes[0]);
      expect(wishOne).to.not.equal(allWishes[0]);
    });

    it('should not have any wishes registered prior to registration', function() {
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(0);
    });

    it('should have one wish registered upon registration and zero upon deregistration', function() {
      var wish = genie(fillInWish());
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(1);
      genie.deregisterWish(wish);
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(0);
    });

    it('should make the last wish registered without giving magic words', function() {
      genie(fillInWish());
      var wishToBeMade = genie(fillInWish());
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(2);
      var madeWish = genie.makeWish();
      expect(wishToBeMade.data.timesMade.total).to.equal(1);
      expect(madeWish).to.equal(wishToBeMade);
    });

    it('should return empty object and not register a wish when genie is disabled', function() {
      genie.enabled(false);
      var emptyObject = genie(fillInWish());
      expect(emptyObject).to.be.empty;
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(0);

      genie.enabled(true);
      genie.returnOnDisabled(false);
      genie.enabled(false);
      var nullObject = genie(fillInWish());

      expect(nullObject).to.be.null;
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.be.null;
    });

    describe('special wish types', function() {
      describe('navigation wish type', function() {
        it('should navigate when a wish is made whose action is a string', function() {
          var destination = window.location.href + '#success';
          var moveToSuccess = genie({
            magicWords: 'Add success hash',
            action: destination
          });
          genie.makeWish(moveToSuccess);
          expect(window.location.href).to.equal(destination);
          // Cannot really test the new tab action, but if I could, it would look like this:
          // wish = genie({
          //   magicWords: 'Open GenieJS repo',
          //   action: {
          //     destination: 'http://www.github.com/kentcdodds/genie',
          //     openNewTab: true
          //   }
          // });
          // genie.makeWish(wish);
        });
      });
    });
  });

  describe('#reset', function() {
    beforeEach(prepForTest);
    it('should reset all options', function() {
      var originalOptions = genie.options();

      var wish = genie(fillInWish());
      genie.makeWish(wish);

      expect(genie.options()).to.not.equal(originalOptions);
      genie.reset();
//      expect(genie.options()).to.equal(originalOptions);
    });
  });

  // End registration

  describe('#deregisterWish #deregisterWishesWithContex', function() {
    beforeEach(prepForTest);
    var allWishCount = 5;
    var wish1;
    var allWishes;
    beforeEach(function(done) {
      wish1 = genie(fillInWish());
      genie(fillInWish({
        context: 'context1'
      }));
      genie(fillInWish({
        context: 'context1'
      }));
      genie(fillInWish({
        context: 'context2'
      }));
      genie(fillInWish({
        context: 'context2'
      }));
      done();
    });
    it('should have one less wish when a wish is deregistered', function() {
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(allWishCount);
      genie.deregisterWish(wish1);

      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(allWishCount - 1);
    });

    it('should remove only wishes in a given context (excluding the default context) when deregisterWishesWithContext is called', function() {
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(allWishCount);
      genie.deregisterWishesWithContext('context1');

      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(allWishCount - 2);
    });
  });
  // End #deregisterWish #deregisterWishesWithContex

  describe('#context #addContext #removeContext', function() {
    beforeEach(prepForTest);
    var defaultContextWish;
    var complexContextNone;
    var allWishes;
    beforeEach(function(done) {
      defaultContextWish = genie(fillInWish());
      var newContextWish1 = genie(fillInWish({
        context: 'context1'
      }));
      var newContextWish2 = genie(fillInWish({
        context: 'context2'
      }));
      var newContextWish3 = genie(fillInWish({
        context: ['context3']
      }));
      var multiContextWish = genie(fillInWish({
        context: ['context1', 'context2', 'context3']
      }));
      var complexContextAll = genie(fillInWish({
        context: {
          all: ['context1', 'context2', 'context3']
        }
      }));
      var complexContextAny = genie(fillInWish({
        context: {
          any: ['context1', 'context3', 'context5']
        }
      }));
      complexContextNone = genie(fillInWish({
        context: {
          none: ['context1', 'context2']
        }
      }));
      var veryComplexContext = genie(fillInWish({
        context: {
          all: ['context1', 'context3'],
          any: ['context4', 'context5'],
          none: ['context2']
        }
      }));
      done();
    });
    it('should have all wishes when genie.context is default', function() {
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(9);
    });

    it('should have only wishes with default context when genie.context is not default', function() {
      genie.context('different-context');
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(2);
      expect(allWishes[0]).to.equal(complexContextNone);
      expect(allWishes[1]).to.equal(defaultContextWish);
    });

    it('should have only in context wishes (including default context wishes) when genie.context is not default', function() {
      genie.context('context1');
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(4);
    });

    it('should be able to have multiple contexts', function() {
      genie.context(['context1', 'context2']);
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(5);
    });

    it('should be able to add a string context', function() {
      genie.context('context1');
      genie.addContext('context2');
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(5);
    });

    it('should be able to add an array of contexts', function() {
      genie.context('context1');
      genie.addContext(['context2', 'context3']);
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(7);
    });

    it('should be able to remove string context', function() {
      genie.context(['context1', 'context2']);
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(5);

      genie.removeContext('context1');
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(3);
    });

    it('should be able to remove an array of contexts', function() {
      genie.context(['context1', 'context2', 'context3']);
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(7);

      genie.removeContext(['context1', 'context2']);
      allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(5);
    });

    it('should be able to manage complex contexts', function() {
      genie.context(['context1', 'context3', 'context5']);
      var allWishes = genie.getMatchingWishes();
      expect(allWishes).to.have.length(6);
    });
  }); // end #context #addContext #removeContext

  describe('#getMatchingWishes', function() {
    beforeEach(prepForTest);
    var wishes;
    var wishesArray;
    beforeEach(function(done) {
      wishes = {};
      wishesArray = [];
      wishes.equal = genie(fillInWish({
        magicWords: 'tTOtc' // equal
      }));
      wishesArray.push(wishes.equal);

      wishes.equal2 = genie(fillInWish({
        magicWords: ['First Magic Word', 'tTOtc'] // equal 2nd magic word
      }));
      wishesArray.push(wishes.equal2);

      wishes.contains = genie(fillInWish({
        magicWords: 'The ttotc container' // contains
      }));
      wishesArray.push(wishes.contains);

      wishes.contains2 = genie(fillInWish({
        magicWords: ['First Magic Word', 'The ttotc container'] // contains 2nd magic word
      }));
      wishesArray.push(wishes.contains2);

      wishes.acronym = genie(fillInWish({
        magicWords: 'The Tail of Two Cities' // acronym
      }));
      wishesArray.push(wishes.acronym);

      wishes.acronym2 = genie(fillInWish({
        magicWords: ['First Magic Word', 'The Tail of Two Cities'] // acronym 2nd magic word
      }));
      wishesArray.push(wishes.acronym2);

      wishes.match = genie(fillInWish({
        magicWords: 'The Tail of Forty Cities' // match
      }));
      wishesArray.push(wishes.match);

      wishes.match2 = genie(fillInWish({
        magicWords: ['First Magic Word', 'The Tail of Forty Cities'] // match 2nd magic word
      }));
      wishesArray.push(wishes.match2);

      wishes.noMatch = genie(fillInWish({
        magicWords: 'no match'
      }));
      wishesArray.push(wishes.noMatch);

      done();
    });

    it('should return wishes in order of most recently registered when not given any params', function() {
      var allWishes = genie.getMatchingWishes();
      var j = wishesArray.length - 1;
      for (var i = 0; i < allWishes.length && j >= 0; i++, j--) {
        expect(allWishes[i]).to.equal(wishesArray[j]);
      }
    });

    it('should match equal, contains, acronym, and then match with the second magic word match coming after the first', function() {
      var ttotcAcronym = 'ttotc';

      // Even though they were registered in reverse order, the matching should follow this pattern
      var matchingWishes = genie.getMatchingWishes(ttotcAcronym);
      expect(matchingWishes).to.have.length(wishesArray.length - 1);
      expect(matchingWishes[0]).to.equal(wishes.equal);
      expect(matchingWishes[1]).to.equal(wishes.equal2);
      expect(matchingWishes[2]).to.equal(wishes.contains);
      expect(matchingWishes[3]).to.equal(wishes.contains2);
      expect(matchingWishes[4]).to.equal(wishes.acronym);
      expect(matchingWishes[5]).to.equal(wishes.acronym2);
      expect(matchingWishes[6]).to.equal(wishes.match);
      expect(matchingWishes[7]).to.equal(wishes.match2);
    });

    it('should match entered magic words before anything else', function() {
      genie.makeWish(wishes.contains, 'tt');
      // This shouldn't affect the results of a search with more text

      genie.makeWish(wishes.match, 'ttot');
      var matchingWishes = genie.getMatchingWishes('ttot');
      expect(matchingWishes).to.have.length(wishesArray.length - 1);
      expect(matchingWishes[0]).to.equal(wishes.match);
      expect(matchingWishes[1]).to.equal(wishes.equal); // starts with (not equal) in this case
      expect(matchingWishes[2]).to.equal(wishes.equal2); // starts with 2 in this case
      expect(matchingWishes[3]).to.equal(wishes.contains);
      expect(matchingWishes[4]).to.equal(wishes.contains2);
      expect(matchingWishes[5]).to.equal(wishes.acronym);
      expect(matchingWishes[6]).to.equal(wishes.acronym2);
      expect(matchingWishes[7]).to.equal(wishes.match2);

      genie.makeWish(wishes.match2, 'ttotc');
      matchingWishes = genie.getMatchingWishes('ttot');
      expect(matchingWishes).to.have.length(wishesArray.length - 1);
      expect(matchingWishes[0]).to.equal(wishes.match);
      expect(matchingWishes[1]).to.equal(wishes.match2);
      expect(matchingWishes[2]).to.equal(wishes.equal); // starts with in this case
      expect(matchingWishes[3]).to.equal(wishes.equal2); // starts with 2 in this case
      expect(matchingWishes[4]).to.equal(wishes.contains);
      expect(matchingWishes[5]).to.equal(wishes.contains2);
      expect(matchingWishes[6]).to.equal(wishes.acronym);
      expect(matchingWishes[7]).to.equal(wishes.acronym2);

      matchingWishes = genie.getMatchingWishes('ttotc');
      expect(matchingWishes).to.have.length(wishesArray.length - 1);
      expect(matchingWishes[0]).to.equal(wishes.match2);
      expect(matchingWishes[1]).to.equal(wishes.equal);
      expect(matchingWishes[2]).to.equal(wishes.equal2);
      expect(matchingWishes[3]).to.equal(wishes.contains);
      expect(matchingWishes[4]).to.equal(wishes.contains2);
      expect(matchingWishes[5]).to.equal(wishes.acronym);
      expect(matchingWishes[6]).to.equal(wishes.acronym2);
      expect(matchingWishes[7]).to.equal(wishes.match);
    });

    it('should follow the rules with "on deck" and "king of the hill"', function() {
      var fred = wishes.contains2;
      var ethel = wishes.acronym2;
      var lucy = wishes.match2;

      var wordToGet = 'magic';

      // In opposite order of their registration
      var mertzMatch = genie.getMatchingWishes(wordToGet);
      expect(mertzMatch[0]).to.equal(lucy);
      expect(mertzMatch[1]).to.equal(ethel);
      expect(mertzMatch[2]).to.equal(fred);

      // In order of called then opposite registration
      genie.makeWish(ethel, wordToGet);
      mertzMatch = genie.getMatchingWishes(wordToGet);
      expect(mertzMatch[0]).to.equal(ethel);
      expect(mertzMatch[1]).to.equal(lucy);
      expect(mertzMatch[2]).to.equal(fred);

      /*
       * More complicated here. A specific wish must be called
       * twice in a row for a specific magic word for it to
       * be lucy if that magic word already has a wish
       * associated with it. So lucy must be called with
       * 'mertz' twice in a row before she can take the
       * top spot.
       */
      genie.makeWish(lucy, wordToGet);
      mertzMatch = genie.getMatchingWishes(wordToGet);
      expect(mertzMatch[0]).to.equal(ethel);
      expect(mertzMatch[1]).to.equal(lucy);
      expect(mertzMatch[2]).to.equal(fred);

      /*
       * Lucy is now king of the hill.
       * Ethel is second, and fred isn't
       * even on the hill at all...
       */
      genie.makeWish(lucy, wordToGet);
      mertzMatch = genie.getMatchingWishes(wordToGet);
      expect(mertzMatch[0]).to.equal(lucy);
      expect(mertzMatch[1]).to.equal(ethel);
      expect(mertzMatch[2]).to.equal(fred);

      /*
       * De-registering lucy and making a
       * wish with fred will place ethel as
       * king of the hill and fred as second
       */
      genie.deregisterWish(lucy);
      genie.makeWish(fred, wordToGet);
      mertzMatch = genie.getMatchingWishes(wordToGet);
      expect(mertzMatch.length).to.equal(3);
      expect(mertzMatch[0]).to.equal(ethel);
      expect(mertzMatch[1]).to.equal(fred);
    });
  });

  describe('#enabled', function() {
    describe('returnOnDisabled behavior when disabled', function() {
      beforeEach(prepForTest);
      it('should cause functions to return a reasonable empty return when enabled', function() {
        genie.enabled(false);
        expect(genie()).to.be.empty;
        expect(genie.getMatchingWishes()).to.be.empty;
        expect(genie.makeWish()).to.be.empty;
        expect(genie.options()).to.be.empty;
        expect(genie.deregisterWish()).to.be.empty;
        expect(genie.reset()).to.be.empty;
        expect(genie.context()).to.be.empty;
        expect(genie.revertContext()).to.be.empty;
        expect(genie.restoreContext()).to.be.empty;
        expect(genie.enabled()).to.be.false;
        expect(genie.returnOnDisabled()).to.be.true;
      });
      it('should cause functions to return a reasonable empty return when disabled', function() {
        genie.returnOnDisabled(false);
        genie.enabled(false);

        expect(genie()).to.be.null;
        expect(genie.getMatchingWishes()).to.be.null;
        expect(genie.makeWish()).to.be.null;
        expect(genie.options()).to.be.null;
        expect(genie.deregisterWish()).to.be.null;
        expect(genie.reset()).to.be.null;
        expect(genie.context()).to.be.null;
        expect(genie.revertContext()).to.be.null;
        expect(genie.restoreContext()).to.be.null;
        expect(genie.enabled()).to.equal(false); // Special case. Enabled always runs.
        expect(genie.returnOnDisabled()).to.be.null;
      });
    });
  });

  // UTIL FUNCTIONS

  function fillInWish(defaults) {
    defaults = defaults || {};
    if (typeof defaults === 'string') {
      defaults = {
        magicWords: defaults
      };
    }
    return createWishWithDefaults(defaults);
  }

  function createWishWithDefaults(defaults) {
    return {
      id: defaults.id,
      context: defaults.context,
      data: defaults.data,
      magicWords: defaults.magicWords || 'magicWords',
      action: defaults.action || function() {}
    };
  }

  function prepForTest(done) {
    genie.reset();
    genie.restoreContext();
    genie.enabled(true);
    genie.returnOnDisabled(true);
    done && done();
  }
});


text:
var path = require('path');
var webpack = require('webpack');
var postcssAssets = require('postcss-assets');
var postcssNext = require('postcss-cssnext');
var appConfig = require('../main');

module.exports = function (config) {
  const conf = {
    frameworks: ['mocha', 'chai', 'es6-shim'],

    browsers: ['PhantomJS'],

    files: ['../webpack/test.js'],

    preprocessors: {
      '../src/**/*.ts': ['coverage'],
      '../src/**/*.tsx': ['coverage'],
      '../webpack/test.js': ['webpack']
    },

    plugins: ['karma-*'],

    reporters: ['mocha', 'coverage'],

    coverageReporter: {
      dir: '../../coverage',
      reporters: []
    },

    hostname: appConfig.host,

    port: appConfig.karmaPort,

    colors: true,

    logLevel: config.LOG_INFO,

    autoWatch: true,

    singleRun: false,

    concurrency: Infinity,

    webpack: {
      devtool: 'inline-source-map',

      resolve: {
        root: path.resolve(__dirname),
        modulesDirectories: [
          '../../src',
          'node_modules'
        ],
        extensions: ['', '.json', '.js', '.ts', '.tsx', '.jsx']
      },

      module: {
        loaders: [
          {
            test: /\.tsx?$/,
            loader: 'ts'
          },
          {
            test: /\.(jpe?g|png|gif)$/i,
            loader: 'url?limit=1000&name=images/[hash].[ext]'
          },
          {
            test: /\.json$/,
            loader: 'json-loader'
          },
          {
            test: /\.css$/,
            include: path.resolve('./src/app'),
            loaders: [
              'style',
              'css?modules&importLoaders=2&sourceMap&localIdentName=[local]___[hash:base64:5]',
              'postcss'
            ]
          },
          {
            test: /\.css$/,
            exclude: path.resolve('./src/app'),
            loader: 'style!css'
          }
        ],
        postLoaders: [
          {
            test: /\.tsx?$/,
            loader: 'istanbul-instrumenter-loader',
            include: path.resolve('./src/app')
          }
        ]
      },

      postcss: function () {
        return [
          postcssNext(),
          postcssAssets({ relative: true })
        ];
      },

      externals: {
        'react/lib/ExecutionEnvironment': true,
        'react/lib/ReactContext': 'window'
      },

      plugins: [
        new webpack.IgnorePlugin(/^fs$/),
        new webpack.IgnorePlugin(/^react\/addons$/),
        new webpack.NoErrorsPlugin(),
        new webpack.DefinePlugin({
          'process.env': {
            BROWSER: JSON.stringify(true),
            NODE_ENV: JSON.stringify('development')
          }
        })
      ]
    },

    webpackServer: {
      noInfo: true
    }
  };

  if (process.env.NODE_ENV === 'ci') {
    conf.autoWatch = false;
    conf.singleRun = true;
    conf.browsers.push('Firefox');
    conf.coverageReporter.reporters.push({ type: 'lcov', subdir: '.' });
  } else {
    conf.coverageReporter.reporters.push({ type: 'html', subdir: 'html' });
  }

  config.set(conf);
};


text:
using System;
using System.Threading.Tasks;
using MatterHackers.Agg;
using MatterHackers.Agg.VertexSource;
using MatterHackers.DataConverters3D;
using MatterHackers.Localizations;
using MatterHackers.VectorMath;

namespace MatterHackers.MatterControl.DesignTools
{
	public class SphereObject3D : PrimitiveObject3D, IPropertyGridModifier
	{
		public SphereObject3D()
		{
			Name = "Sphere".Localize();
			Color = Operations.Object3DExtensions.PrimitiveColors["Sphere"];
		}

		public SphereObject3D(double diameter, int sides)
			: this()
		{
			Diameter = diameter;
			Sides = sides;

			Rebuild();
		}

		public static async Task<SphereObject3D> Create()
		{
			var item = new SphereObject3D();

			await item.Rebuild();
			return item;
		}

		public double Diameter { get; set; } = 20;
		public int Sides { get; set; } = 40;

		public bool Advanced { get; set; } = false;
		public double StartingAngle { get; set; } = 0;
		public double EndingAngle { get; set; } = 360;
		public int LatitudeSides { get; set; } = 30;

		public override async void OnInvalidate(InvalidateArgs invalidateType)
		{
			if (invalidateType.InvalidateType.HasFlag(InvalidateType.Properties)
				&& invalidateType.Source == this)
			{
				await Rebuild();
			}
			else
			{
				base.OnInvalidate(invalidateType);
			}
		}

		public override Task Rebuild()
		{
			this.DebugDepth("Rebuild");
			bool valuesChanged = false;
			using (RebuildLock())
			{
				Sides = agg_basics.Clamp(Sides, 3, 360, ref valuesChanged);
				LatitudeSides = agg_basics.Clamp(LatitudeSides, 3, 360, ref valuesChanged);

				using (new CenterAndHeightMaintainer(this))
				{
					var startingAngle = StartingAngle;
					var endingAngle = EndingAngle;
					var latitudeSides = LatitudeSides;
					if (!Advanced)
					{
						startingAngle = 0;
						endingAngle = 360;
						latitudeSides = Sides;
					}

					var path = new VertexStorage();
					var angleDelta = MathHelper.Tau / 2 / latitudeSides;
					var angle = -MathHelper.Tau / 4;
					var radius = Diameter / 2;
					path.MoveTo(new Vector2(radius * Math.Cos(angle), radius * Math.Sin(angle)));
					for (int i = 0; i < latitudeSides; i++)
					{
						angle += angleDelta;
						path.LineTo(new Vector2(radius * Math.Cos(angle), radius * Math.Sin(angle)));
					}

					var startAngle = MathHelper.Range0ToTau(MathHelper.DegreesToRadians(startingAngle));
					var endAngle = MathHelper.Range0ToTau(MathHelper.DegreesToRadians(endingAngle));
					var steps = Math.Max(1, (int)(Sides * MathHelper.Tau / Math.Abs(MathHelper.GetDeltaAngle(startAngle, endAngle)) + .5));
					Mesh = VertexSourceToMesh.Revolve(path,
						steps,
						startAngle,
						endAngle);
				}
			}

			if (valuesChanged)
			{
				Invalidate(InvalidateType.DisplayValues);
			}

			Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
			return Task.CompletedTask;
		}

		public void UpdateControls(PublicPropertyChange change)
		{
			change.SetRowVisible(nameof(StartingAngle), () => Advanced);
			change.SetRowVisible(nameof(EndingAngle), () => Advanced);
			change.SetRowVisible(nameof(LatitudeSides), () => Advanced);
		}
	}
}


text:
package org.globus.gatekeeper.jobmanager;

import org.globus.gatekeeper.ServiceException;

public class ShellJobManagerService extends JobManagerService {

    public ShellJobManagerService() {
        super( new ShellJobManager() );
    }

    public void setArguments(String [] args)
        throws ServiceException {

	ShellJobManager jobManager = (ShellJobManager)_jobManager;

	for (int i=0;i<args.length;i++) {

	    if (args[i].equalsIgnoreCase("-type")) {
		jobManager.setType( args[++i] );
	    } else if (args[i].equalsIgnoreCase("-libexec")) {
		jobManager.setLibExecDirectory( args[++i] );
	    }

	}
    }

}