package com.github.phantomthief.jedis;

import static java.util.stream.Collectors.joining;
import static java.util.stream.Stream.of;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.atomic.AtomicInteger;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import com.github.fppt.jedismock.RedisServer;
import com.github.phantomthief.jedis.OpInterceptor.JedisOpCall;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * @author w.vela
 * Created on 2020-05-29.
 */
class JedisHelperBasicTest {

    private static RedisServer server = null;

    @BeforeAll
    static void beforeAll() throws IOException {
        server = RedisServer.newRedisServer();  // bind to a random port
        server.start();
    }

    @AfterAll
    static void afterAll() {
        server.stop();
    }

    @Test
    void testOpListener() {
        try (JedisPool jedisPool = new JedisPool(server.getHost(), server.getBindPort())) {
            Deque<String> ops = new ArrayDeque<>();
            JedisHelper<Jedis> helper = JedisHelper.newBuilder(() -> jedisPool)
                    .addOpListener((pool, requestTime, requestNanoTime, method, args, costInNano, t) -> {
                        ops.add(method.getName() + ":" + of(args).map(Object::toString).collect(joining(":")));
                    })
                    .build();
            helper.get().set("test", "test1");
            assertEquals("set:test:test1", ops.poll());
            assertEquals("test1", helper.get().get("test"));
            assertEquals("get:test", ops.poll());
        }
    }

    @Test
    void testOpInterceptor() {
        try (JedisPool jedisPool = new JedisPool(server.getHost(), server.getBindPort())) {
            Deque<String> ops = new ArrayDeque<>();
            JedisHelper<Jedis> helper = JedisHelper.newBuilder(() -> jedisPool)
                    .addOpInterceptor((pool, method, jedis, args) -> {
                        ops.add(method.getName() + ":" + of(args).map(Object::toString).collect(joining(":")));
                        return new JedisOpCall<>(method, jedis, args);
                    })
                    .build();
            helper.get().set("test", "test1");
            assertEquals("set:test:test1", ops.poll());
            assertEquals("test1", helper.get().get("test"));
            assertEquals("get:test", ops.poll());
        }
    }

    @Test
    void testPoolListener() {
        try (JedisPool jedisPool = new JedisPool(server.getHost(), server.getBindPort())) {
            AtomicInteger counter = new AtomicInteger();
            JedisHelper<Jedis> helper = JedisHelper.newBuilder(() -> jedisPool)
                    .addPoolListener((pool, borrowTime, borrowNanoTime, t) -> counter.incrementAndGet())
                    .build();
            assertEquals(0, counter.get());
            helper.get().set("test", "test1");
            assertEquals(1, counter.get());
            assertEquals("test1", helper.get().get("test"));
            assertEquals(2, counter.get());
        }
    }
}
@@ -186,16 +186,136 @@
 tEquals;
+%0Aimport static org.junit.jupiter.api.Assertions.assertSame;%0Aimport static org.junit.jupiter.api.Assertions.assertThrows;
 %0A%0Aimport
@@ -664,16 +664,89 @@
 sOpCall;
+%0Aimport com.github.phantomthief.jedis.exception.NoAvailablePoolException;
 %0A%0Aimport
@@ -3408,10 +3408,451 @@
  %7D%0A    %7D
+%0A%0A    @Test%0A    void testNoAvailableNode() %7B%0A        Throwable%5B%5D e = %7Bnull%7D;%0A        JedisHelper%3CJedis%3E helper = JedisHelper.newBuilder(() -%3E null)%0A                .addOpListener((pool, requestTime, requestNanoTime, method, args, costInNano, t) -%3E e%5B0%5D = t)%0A                .build();%0A        assertThrows(NoAvailablePoolException.class, () -%3E helper.get().get(%221%22));%0A        assertSame(NoAvailablePoolException.class, e%5B0%5D.getClass());%0A    %7D
 %0A%7D

add no available exception test.