package com.lambdaworks.redis;

import static org.assertj.core.api.Assertions.*;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

/**
 * @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a>
 * @since 3.0
 */
@RunWith(Parameterized.class)
public class SyncAsyncApiConvergenceTest {

    private Method method;

    @SuppressWarnings("rawtypes")
    private Class<RedisAsyncConnection> asyncClass = RedisAsyncConnection.class;

    @Parameterized.Parameters(name = "Method {0}/{1}")
    public static List<Object[]> parameters() {

        List<Object[]> result = new ArrayList<Object[]>();
        Method[] methods = RedisConnection.class.getMethods();
        for (Method method : methods) {
            result.add(new Object[] { method.getName(), method });
        }

        return result;
    }

    public SyncAsyncApiConvergenceTest(String methodName, Method method) {
        this.method = method;
    }

    @Test
    public void testMethodPresentOnAsyncApi() throws Exception {
        Method method = asyncClass.getMethod(this.method.getName(), this.method.getParameterTypes());
        assertThat(method).isNotNull();
    }

    @Test
    public void testSameResultType() throws Exception {
        Method method = asyncClass.getMethod(this.method.getName(), this.method.getParameterTypes());
        Class<?> returnType = method.getReturnType();

        if (returnType.equals(RedisFuture.class)) {
            ParameterizedType genericReturnType = (ParameterizedType) method.getGenericReturnType();
            Type[] actualTypeArguments = genericReturnType.getActualTypeArguments();

            if (actualTypeArguments[0] instanceof TypeVariable) {

                assertThat(Object.class).isEqualTo(this.method.getReturnType());
                return;
            }

            if (actualTypeArguments[0] instanceof ParameterizedType) {

                ParameterizedType parameterizedType = (ParameterizedType) actualTypeArguments[0];
                returnType = (Class<?>) parameterizedType.getRawType();
            } else if (actualTypeArguments[0] instanceof GenericArrayType) {

                GenericArrayType arrayType = (GenericArrayType) actualTypeArguments[0];
                returnType = Array.newInstance((Class<?>) arrayType.getGenericComponentType(), 0).getClass();
            } else {
                returnType = (Class<?>) actualTypeArguments[0];
            }
        }

        assertThat(returnType).describedAs(this.method.toString())
            .isEqualTo(this.method.getReturnType());

    }
}

@@ -71,19 +71,211 @@
 ertions.
-*;%0A
+assertThat;%0A%0Aimport java.lang.reflect.Array;%0Aimport java.lang.reflect.GenericArrayType;%0Aimport java.lang.reflect.Method;%0Aimport java.lang.reflect.ParameterizedType;%0Aimport java.lang.reflect.Type;
 %0Aimport 
@@ -292,17 +292,28 @@
 reflect.
-*
+TypeVariable
 ;%0Aimport
@@ -1644,24 +1644,20 @@
         
-Class%3C?%3E
+Type
  returnT
@@ -1664,32 +1664,39 @@
 ype = method.get
+Generic
 ReturnType();%0A%0A 
@@ -1706,17 +1706,27 @@
     if (
-r
+method.getR
 eturnTyp
@@ -1726,16 +1726,18 @@
 turnType
+()
 .equals(
@@ -1987,444 +1987,8 @@
 s%5B0%5D
- instanceof TypeVariable) %7B%0A%0A                assertThat(Object.class).isEqualTo(this.method.getReturnType());%0A                return;%0A            %7D%0A%0A            if (actualTypeArguments%5B0%5D instanceof ParameterizedType) %7B%0A%0A                ParameterizedType parameterizedType = (ParameterizedType) actualTypeArguments%5B0%5D;%0A                returnType = (Class%3C?%3E) parameterizedType.getRawType();%0A            %7D else if (actualTypeArguments%5B0%5D
  ins
@@ -2011,25 +2011,24 @@
 rrayType) %7B%0A
-%0A
             
@@ -2266,19 +2266,8 @@
 pe =
- (Class%3C?%3E)
  act
@@ -2341,16 +2341,27 @@
 turnType
+.toString()
 ).descri
@@ -2389,17 +2389,31 @@
 tring())
-%0A
+.isEqualTo(%0A   
         
@@ -2416,27 +2416,17 @@
         
-.isEqualTo(
+ 
 this.met
@@ -2424,32 +2424,39 @@
  this.method.get
+Generic
 ReturnType());%0A%0A
@@ -2451,20 +2451,30 @@
 rnType()
+.toString()
 );%0A
-%0A
     %7D%0A%7D%0A

Improve api convergence test #65