@Extension("impl1")
public interface SimpleExt {
    String echo(Map<String, String> config, String s);

    String yell(Map<String, String> config, String s);
    
    String bang(Map<String, String> config, int i);
} public class SimpleExtImpl1 implements SimpleExt {
    public String echo(Map<String, String> config, String s) {
        return "Ext1Impl1-echo";
    }

    public String yell(Map<String, String> config, String s) {
        return "Ext1Impl1-yell";
    }

    public String bang(Map<String, String> config, int i) {
        return "bang1";
    }
} @Extension
public interface NoDefaultExt {
    String echo(String s);
} @Extension("impl1")
public interface WrappedExt {
    String echo(Map<String, String> config, String s);

    String yell(Map<String, String> config, String s);
} public class Ext3Impl1 implements WrappedExt {
    public String echo(Map<String, String> config, String s) {
        return "Ext3Impl1-echo";
    }

    public String yell(Map<String, String> config, String s) {
        return "Ext3Impl1-yell";
    }
} public class Ext3Wrapper1 implements WrappedExt {
    WrappedExt instance;

    public static AtomicInteger echoCount = new AtomicInteger();
    public static AtomicInteger yellCount = new AtomicInteger();

    public Ext3Wrapper1(WrappedExt instance) {
        this.instance = instance;
    }

    public String echo(Map<String, String> config, String s) {
        echoCount.incrementAndGet();
        return instance.echo(config, s);
    }

    public String yell(Map<String, String> config, String s) {
        yellCount.incrementAndGet();
        return instance.yell(config, s);
    }
} @Extension("impl1")
public interface WithAttributeExt {
    String echo(Map<String, String> config, String s);
} @Extension
public interface InjectExt {
    String echo(Map<String, String> config, String s);
} public class Ext6Impl2 implements InjectExt {
    List<String> list;

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public String echo(Map<String, String> config, String s) {
        throw new UnsupportedOperationException();
    }

} @Extension
public interface InitErrorExt {
    String echo(Map<String, String> config, String s);
}
 @Extension("invalid-name&")
public interface InvalidNameExt {
    String echo(Map<String, String> config, String s);
}
 @Extension("impl1")
public interface ImplNoDefaultConstructorExt {
    String echo(Map<String, String> config, String s);
} public class Utils {
    public static Map<String, String> kv2Map(String... kv) {
        Map<String, String> cs = new HashMap<String, String>();

        for (int i = 0; i < kv.length; i += 2) {
            String key = kv[i];
            if (key == null) {
                throw new IllegalArgumentException("Key must not null!");
            }
            if (i + 1 < kv.length) {
                cs.put(key, kv[i + 1]);
            } else {
                cs.put(key, null);
            }
        }

        return cs;
    }

}

import com.alibaba.cooma.ext1.SimpleExt;
import com.alibaba.cooma.ext1.impl.SimpleExtImpl1;
import com.alibaba.cooma.ext1.impl.SimpleExtImpl2;
import com.alibaba.cooma.ext2.NoDefaultExt;
import com.alibaba.cooma.ext3.WrappedExt;
import com.alibaba.cooma.ext3.impl.Ext3Impl1;
import com.alibaba.cooma.ext3.impl.Ext3Impl2;
import com.alibaba.cooma.ext3.impl.Ext3Wrapper1;
import com.alibaba.cooma.ext3.impl.Ext3Wrapper2;
import com.alibaba.cooma.ext4.WithAttributeExt;
import com.alibaba.cooma.ext6.InjectExt;
import com.alibaba.cooma.ext6.impl.Ext6Impl2;
import com.alibaba.cooma.ext7.InitErrorExt;
import com.alibaba.cooma.ext8.InvalidNameExt;
import com.alibaba.cooma.ext8.InvalidNameExt2;
import com.alibaba.cooma.ext5.ImplNoDefaultConstructorExt;
import com.alibaba.util.Utils;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.matchers.JUnitMatchers.containsString;

            fail();
        } catch (IllegalStateException expected) {
            assertThat(expected.getMessage(), containsString("No such extension com.alibaba.cooma.ext3.WrappedExt by name wrapper1"));
        }
    }

    @Test
    public void test_getExtension_ExceptionNullArg() throws Exception {
        try {
            ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension((String) null);
            fail();
        } catch (IllegalArgumentException expected) {
            assertThat(expected.getMessage(), containsString("Extension name == null"));
        }
    }

    @Test
    public void test_hasExtension() throws Exception {
        assertTrue(ExtensionLoader.getExtensionLoader(SimpleExt.class).hasExtension("impl1"));
        assertFalse(ExtensionLoader.getExtensionLoader(SimpleExt.class).hasExtension("impl1,impl2"));
        assertFalse(ExtensionLoader.getExtensionLoader(SimpleExt.class).hasExtension("xxx"));

        try {
            ExtensionLoader.getExtensionLoader(SimpleExt.class).hasExtension(null);
            fail();
        } catch (IllegalArgumentException expected) {
            assertThat(expected.getMessage(), containsString("Extension name == null"));
        }
    }

    @Test
    public void test_hasDefaultExtension() throws Exception {
        assertTrue(ExtensionLoader.getExtensionLoader(SimpleExt.class).hasDefaultExtension());
        assertFalse(ExtensionLoader.getExtensionLoader(NoDefaultExt.class).hasDefaultExtension());
    }

    @Test
    public void test_hasExtension_wrapperIsNotExt() throws Exception {
        ExtensionLoader<WrappedExt> extensionLoader = ExtensionLoader.getExtensionLoader(WrappedExt.class);

        assertTrue(extensionLoader.hasExtension("impl1"));
        assertFalse(extensionLoader.hasExtension("impl1,impl2"));
        assertFalse(extensionLoader.hasExtension("xxx"));

        assertFalse(extensionLoader.hasExtension("wrapper1"));

        try {
            extensionLoader.hasExtension(null);
            fail();
        } catch (IllegalArgumentException expected) {
            assertThat(expected.getMessage(), containsString("Extension name == null"));
        }
    }

    @Test
    public void test_getSupportedExtensions() throws Exception {
        Set<String> extensions = ExtensionLoader.getExtensionLoader(SimpleExt.class).getSupportedExtensions();

        Set<String> expected = new HashSet<String>();
        expected.add("impl1");
        expected.add("impl2");
        expected.add("impl3");

        assertEquals(expected, extensions);
    }

    @Test
    public void test_getSupportedExtensions_wrapperIsNotExt() throws Exception {
        Set<String> extensions = ExtensionLoader.getExtensionLoader(WrappedExt.class).getSupportedExtensions();

        Set<String> expected = new HashSet<String>();
        expected.add("impl1");
        expected.add("impl2");

        assertEquals(expected, extensions);
    }

    @Test
    public void test_getExtensionAttribute_all() throws Exception {
        ExtensionLoader<WithAttributeExt> extensionLoader = ExtensionLoader.getExtensionLoader(WithAttributeExt.class);

        Map<String, Map<String, String>> extensionAttribute = extensionLoader.getExtensionAttribute();

        Map<String, Map<String, String>> expected = new HashMap<String, Map<String, String>>();
        expected.put("impl1", Utils.kv2Map("k1", "v1", "k2", "", "k3", "v3", "k4", "", "k5", "v5"));
        expected.put("impl2", new HashMap<String, String>());
        expected.put("impl3", Utils.kv2Map("key1", "value1", "key2", "value2", "key3", ""));

        assertEquals(expected, extensionAttribute);
    }

    @Test
    public void test_getExtensionAttribute_one() throws Exception {
        ExtensionLoader<WithAttributeExt> extensionLoader = ExtensionLoader.getExtensionLoader(WithAttributeExt.class);
        Map<String, String> extensionAttribute = extensionLoader.getExtensionAttribute("impl1");
        assertEquals(Utils.kv2Map("k1", "v1", "k2", "", "k3", "v3", "k4", "", "k5", "v5"), extensionAttribute);
    }

    @Test
    public void test_getExtensionAttribute_oneNotExisted() throws Exception {
        ExtensionLoader<WithAttributeExt> extensionLoader = ExtensionLoader.getExtensionLoader(WithAttributeExt.class);

        try {
            Map<String, String> extensionAttribute = extensionLoader.getExtensionAttribute("NotExisted");
            fail();
        } catch (IllegalStateException expected) {
            assertThat(expected.getMessage(), containsString("No such extension com.alibaba.cooma.ext4.WithAttributeExt by name NotExisted"));
        }
    }

    @Test
    public void test_getAdaptiveInstance_InjectNotExtFail() throws Exception {
        InjectExt ext = ExtensionLoader.getExtensionLoader(InjectExt.class).getExtension("impl2");

        Ext6Impl2 impl = (Ext6Impl2) ext;
        assertNull(impl.getList());
    }

    @Test
    public void test_InitError() throws Exception {

        ExtensionLoader<InitErrorExt> loader = ExtensionLoader.getExtensionLoader(InitErrorExt.class);
