content: package redis.clients.jedis.tests.commands;
  
  import org.junit.After;
  import org.junit.AfterClass;
  import org.junit.Before;
  import org.junit.Test;
  import redis.clients.jedis.HostAndPort;
  import redis.clients.jedis.Jedis;
  import redis.clients.jedis.JedisCluster;
  import redis.clients.jedis.exceptions.JedisClusterException;
  import redis.clients.jedis.exceptions.JedisDataException;
  import redis.clients.jedis.tests.HostAndPortUtil;
  import redis.clients.jedis.tests.JedisTestBase;
  import redis.clients.util.JedisClusterCRC16;
  
  import java.util.ArrayList;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  public class ClusterScriptingCommandsTest extends JedisTestBase {
    private Jedis node1;
    private static Jedis node2;
    private static Jedis node3;
  
    private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);
    private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);
    private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2);
    private final Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
    JedisCluster jedisCluster;
  
    @Before
    public void setUp() throws InterruptedException {
      node1 = new Jedis(nodeInfo1.getHost(), nodeInfo1.getPort());
      node1.connect();
      node1.flushAll();
  
      node2 = new Jedis(nodeInfo2.getHost(), nodeInfo2.getPort());
      node2.connect();
      node2.flushAll();
  
      node3 = new Jedis(nodeInfo3.getHost(), nodeInfo3.getPort());
      node3.connect();
      node3.flushAll();
  
      // ---- configure cluster
  
      // add nodes to cluster
      node1.clusterMeet("127.0.0.1", nodeInfo2.getPort());
      node1.clusterMeet("127.0.0.1", nodeInfo3.getPort());
  
      // split available slots across the three nodes
      int slotsPerNode = JedisCluster.HASHSLOTS / 3;
      int[] node1Slots = new int[slotsPerNode];
      int[] node2Slots = new int[slotsPerNode + 1];
      int[] node3Slots = new int[slotsPerNode];
      for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0; i < JedisCluster.HASHSLOTS; i++) {
        if (i < slotsPerNode) {
          node1Slots[slot1++] = i;
        } else if (i > slotsPerNode * 2) {
          node3Slots[slot3++] = i;
        } else {
          node2Slots[slot2++] = i;
        }
      }
  
      node1.clusterAddSlots(node1Slots);
      node2.clusterAddSlots(node2Slots);
      node3.clusterAddSlots(node3Slots);
  
      waitForClusterReady();
  
      jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379));
      jedisCluster = new JedisCluster(jedisClusterNode);
  
    }
  
    @AfterClass
    public static void cleanUp() {
      int slotTest = JedisClusterCRC16.getSlot("test");
      int slot51 = JedisClusterCRC16.getSlot("51");
      String node3Id = getNodeId(node3.clusterNodes());
      node2.clusterSetSlotNode(slotTest, node3Id);
      node2.clusterSetSlotNode(slot51, node3Id);
      node2.clusterDelSlots(slotTest, slot51);
    }
  
    @After
    public void tearDown() {
      // clear all slots
      int[] slotsToDelete = new int[JedisCluster.HASHSLOTS];
      for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {
        slotsToDelete[i] = i;
      }
      node1.clusterDelSlots(slotsToDelete);
      node2.clusterDelSlots(slotsToDelete);
      node3.clusterDelSlots(slotsToDelete);
    }
  
    @SuppressWarnings("unchecked")
    @Test(expected = JedisClusterException.class)
    public void testJedisClusterException() {
      String script = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}";
      List<String> keys = new ArrayList<String>();
      keys.add("key1");
      keys.add("key2");
      List<String> args = new ArrayList<String>();
      args.add("first");
      args.add("second");
      args.add("third");
      jedisCluster.eval(script, keys, args);
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testEval2() {
      String script = "return redis.call('set',KEYS[1],'bar')";
      int numKeys = 1;
      String[] args = { "foo" };
      jedisCluster.eval(script, numKeys, args);
      assertEquals(jedisCluster.get("foo"), "bar");
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testScriptLoadAndScriptExists() {
      String sha1 = jedisCluster.scriptLoad("return redis.call('get','foo')", "key1");
      assertTrue(jedisCluster.scriptExists(sha1, "key1"));
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testEvalsha() {
      String sha1 = jedisCluster.scriptLoad("return 10", "key1");
      Object o = jedisCluster.evalsha(sha1, 1, "key1");
      assertEquals("10", o.toString());
    }
  
    @SuppressWarnings("unchecked")
    @Test(expected = JedisClusterException.class)
    public void testJedisClusterException2() {
      byte[] script = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2],ARGV[3]}".getBytes();
      List<byte[]> keys = new ArrayList<byte[]>();
      keys.add("key1".getBytes());
      keys.add("key2".getBytes());
      List<byte[]> args = new ArrayList<byte[]>();
      args.add("first".getBytes());
      args.add("second".getBytes());
      args.add("third".getBytes());
      jedisCluster.eval(script, keys, args);
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testBinaryEval() {
      byte[] script = "return redis.call('set',KEYS[1],'bar')".getBytes();
      byte[] args = "foo".getBytes();
      jedisCluster.eval(script, 1, args);
      assertEquals(jedisCluster.get("foo"), "bar");
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testBinaryScriptFlush() {
      byte[] byteKey = "key1".getBytes();
      byte[] sha1 = jedisCluster.scriptLoad("return redis.call('get','foo')".getBytes(), byteKey);
      assertEquals("OK", jedisCluster.scriptFlush(byteKey));
    }
  
    @SuppressWarnings("unchecked")
    @Test(expected = JedisDataException.class)
    public void testBinaryScriptKill() {
      byte[] byteKey = "key1".getBytes();
      jedisCluster.scriptKill(byteKey);
    }
  
    @SuppressWarnings("unchecked")
    @Test
    public void testBinaryScriptExists() {
      byte[] byteKey = "key1".getBytes();
      byte[] sha1 = jedisCluster.scriptLoad("return redis.call('get','foo')".getBytes(), byteKey);
      byte[][] arraySha1 = { sha1 };
      Long result = 1L;
      List<Long> listResult = new ArrayList();
      listResult.add(result);
      assertEquals(listResult, jedisCluster.scriptExists(byteKey, arraySha1));
    }
  
    private static String getNodeId(String infoOutput) {
      for (String infoLine : infoOutput.split("\n")) {
        if (infoLine.contains("myself")) {
          return infoLine.split(" ")[0];
        }
      }
      return "";
    }
  
    private void waitForClusterReady() throws InterruptedException {
      boolean clusterOk = false;
      while (!clusterOk) {
        if (node1.clusterInfo().split("\n")[0].contains("ok")
            && node2.clusterInfo().split("\n")[0].contains("ok")
            && node3.clusterInfo().split("\n")[0].contains("ok")) {
          clusterOk = true;
        }
        Thread.sleep(50);
      }
    }
  }
  