content: package redis.clients.jedis.tests;
  
  import java.util.HashSet;
  import java.util.Set;
  
  import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
  import org.junit.Before;
  import org.junit.Test;
  
  import redis.clients.jedis.HostAndPort;
  import redis.clients.jedis.Jedis;
  import redis.clients.jedis.JedisSentinelPool;
  import redis.clients.jedis.Transaction;
  import redis.clients.jedis.exceptions.JedisConnectionException;
  import redis.clients.jedis.exceptions.JedisException;
  import redis.clients.jedis.tests.utils.JedisSentinelTestUtil;
  
  public class JedisSentinelPoolTest extends JedisTestBase {
    private static final String MASTER_NAME = "mymaster";
  
    protected static HostAndPort master = HostAndPortUtil.getRedisServers().get(2);
    protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers().get(3);
  
    protected static HostAndPort sentinel1 = HostAndPortUtil.getSentinelServers().get(1);
    protected static HostAndPort sentinel2 = HostAndPortUtil.getSentinelServers().get(3);
  
    protected static Jedis sentinelJedis1;
    protected static Jedis sentinelJedis2;
  
    protected Set<String> sentinels = new HashSet<String>();
  
    @Before
    public void setUp() throws Exception {
      sentinels.add(sentinel1.toString());
      sentinels.add(sentinel2.toString());
  
      sentinelJedis1 = new Jedis(sentinel1.getHost(), sentinel1.getPort());
      sentinelJedis2 = new Jedis(sentinel2.getHost(), sentinel2.getPort());
    }
  
    @Test(expected = JedisConnectionException.class)
    public void initializeWithNotAvailableSentinelsShouldThrowException() {
      Set<String> wrongSentinels = new HashSet<String>();
      wrongSentinels.add(new HostAndPort("localhost", 65432).toString());
      wrongSentinels.add(new HostAndPort("localhost", 65431).toString());
  
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, wrongSentinels);
      pool.destroy();
    }
  
    @Test(expected = JedisException.class)
    public void initializeWithNotMonitoredMasterNameShouldThrowException() {
      final String wrongMasterName = "wrongMasterName";
      JedisSentinelPool pool = new JedisSentinelPool(wrongMasterName, sentinels);
      pool.destroy();
    }
  
    @Test
    public void checkCloseableConnections() throws Exception {
      GenericObjectPoolConfig config = new GenericObjectPoolConfig();
  
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,
          "foobared", 2);
      Jedis jedis = pool.getResource();
      jedis.auth("foobared");
      jedis.set("foo", "bar");
      assertEquals("bar", jedis.get("foo"));
      jedis.close();
      pool.close();
      assertTrue(pool.isClosed());
    }
  
    @Test
    public void ensureSafeTwiceFailover() throws InterruptedException {
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
          new GenericObjectPoolConfig(), 1000, "foobared", 2);
  
      forceFailover(pool);
      // after failover sentinel needs a bit of time to stabilize before a new
      // failover
      Thread.sleep(100);
      forceFailover(pool);
  
      // you can test failover as much as possible
    }
  
    @Test
    public void returnResourceShouldResetState() {
      GenericObjectPoolConfig config = new GenericObjectPoolConfig();
      config.setMaxTotal(1);
      config.setBlockWhenExhausted(false);
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,
          "foobared", 2);
  
      Jedis jedis = pool.getResource();
      Jedis jedis2 = null;
  
      try {
        jedis.set("hello", "jedis");
        Transaction t = jedis.multi();
        t.set("hello", "world");
        jedis.close();
  
        jedis2 = pool.getResource();
  
        assertTrue(jedis == jedis2);
        assertEquals("jedis", jedis2.get("hello"));
      } catch (JedisConnectionException e) {
        if (jedis2 != null) {
          jedis2 = null;
        }
      } finally {
        jedis2.close();
  
        pool.destroy();
      }
    }
  
    @Test
    public void checkResourceIsCloseable() {
      GenericObjectPoolConfig config = new GenericObjectPoolConfig();
      config.setMaxTotal(1);
      config.setBlockWhenExhausted(false);
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,
          "foobared", 2);
  
      Jedis jedis = pool.getResource();
      try {
        jedis.set("hello", "jedis");
      } finally {
        jedis.close();
      }
  
      Jedis jedis2 = pool.getResource();
      try {
        assertEquals(jedis, jedis2);
      } finally {
        jedis2.close();
      }
    }
  
    @Test
    public void customClientName() {
      GenericObjectPoolConfig config = new GenericObjectPoolConfig();
      config.setMaxTotal(1);
      config.setBlockWhenExhausted(false);
      JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, config, 1000,
          "foobared", 0, "my_shiny_client_name");
  
      Jedis jedis = pool.getResource();
  
      try {
        assertEquals("my_shiny_client_name", jedis.clientGetname());
      } finally {
        jedis.close();
        pool.destroy();
      }
  
      assertTrue(pool.isClosed());
    }
  
    private void forceFailover(JedisSentinelPool pool) throws InterruptedException {
      HostAndPort oldMaster = pool.getCurrentHostMaster();
  
      // jedis connection should be master
      Jedis beforeFailoverJedis = pool.getResource();
      assertEquals("PONG", beforeFailoverJedis.ping());
  
      waitForFailover(pool, oldMaster);
  
      Jedis afterFailoverJedis = pool.getResource();
      assertEquals("PONG", afterFailoverJedis.ping());
      assertEquals("foobared", afterFailoverJedis.configGet("requirepass").get(1));
      assertEquals(2, afterFailoverJedis.getDB());
  
      // returning both connections to the pool should not throw
      beforeFailoverJedis.close();
      afterFailoverJedis.close();
    }
  
    private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster)
        throws InterruptedException {
      HostAndPort newMaster = JedisSentinelTestUtil.waitForNewPromotedMaster(MASTER_NAME,
        sentinelJedis1, sentinelJedis2);
  
      waitForJedisSentinelPoolRecognizeNewMaster(pool, newMaster);
    }
  
    private void waitForJedisSentinelPoolRecognizeNewMaster(JedisSentinelPool pool,
        HostAndPort newMaster) throws InterruptedException {
  
      while (true) {
        HostAndPort currentHostMaster = pool.getCurrentHostMaster();
  
        if (newMaster.equals(currentHostMaster)) break;
  
        System.out.println("JedisSentinelPool's master is not yet changed, sleep...");
  
        Thread.sleep(100);
      }
    }
  
  }