Package com.alibaba.citrus.service.pull.impl

Source Code of com.alibaba.citrus.service.pull.impl.PullServiceTests$ExceptionToolSetFactory

/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.citrus.service.pull.impl;

import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.BasicConstant.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static java.util.Collections.*;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.alibaba.citrus.service.pull.PullContext;
import com.alibaba.citrus.service.pull.PullException;
import com.alibaba.citrus.service.pull.PullService;
import com.alibaba.citrus.service.pull.RuntimeToolSetFactory;
import com.alibaba.citrus.service.pull.ToolFactory;
import com.alibaba.citrus.service.pull.ToolNameAware;
import com.alibaba.citrus.service.pull.ToolSetFactory;
import com.alibaba.citrus.service.pull.impl.PullServiceImpl.ToolName;
import com.alibaba.citrus.service.pull.impl.PullServiceImpl.ToolSetInfo;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;

public class PullServiceTests extends AbstractPullServiceTests {
    private PullContext context;
    private String[]    staticToolNames;
    private String[]    allNames;
    private String[]    allValues;
    private String[]    allNamesWithParent;
    private String[]    allValuesWithParent;

    // service instance vars
    private Map<String, ToolFactory>                 tools;
    private Map<String, ToolSetInfo<ToolSetFactory>> toolsInSet;
    private Map<String, RuntimeToolSetFactory>       toolsRuntime;
    private Map<String, Object>                      prePulledTools;
    private Set<ToolName>                            toolNames;

    // context instance vars
    private Map<String, Object>                             context_pulledTools;
    private Map<String, RuntimeToolSetFactory>              context_toolsRuntime;
    private Map<String, ToolSetInfo<RuntimeToolSetFactory>> context_toolsInRuntimeSet;
    private Set<ToolName>                                   context_toolNames;

    @Before
    public void init() {
        populateService();
        initService();
    }

    private void populateService() {
        Map<String, Object> factories = createHashMap();

        // --------------
        // singleton
        // --------------

        // - ToolFactory
        factories.put("singleton.1", newToolFactory(true, "singleton.1"));
        factories.put("singleton.2", newToolFactory(true, null));

        // - ToolSetFactory
        factories.put("singletons.1", newToolSetFactory(true, false, "singletons.1", "a", "1", "b", "2"));
        factories.put("singletons.2", newToolSetFactory(true, false, null, "c", "3", "d", null));

        // - ToolSetFactory & ToolFactory
        factories.put("singletons.3", newToolSetFactory(true, true, "singletons.3", "e", "5", "f", "6"));
        factories.put("singletons.4", newToolSetFactory(true, true, null, "g", "7", "h", null));

        // --------------
        // non-singleton
        // --------------

        // - ToolFactory
        factories.put("prototype.1", newToolFactory(false, "prototype.1"));
        factories.put("prototype.2", newToolFactory(false, null));

        // - ToolSetFactory
        factories.put("prototypes.1", newToolSetFactory(false, false, "prototypes.1", "i", "9", "j", "10"));
        factories.put("prototypes.2", newToolSetFactory(false, false, null, "k", "11", "l", null));

        // - ToolSetFactory & ToolFactory
        factories.put("prototypes.3", newToolSetFactory(false, true, "prototypes.3", "m", "13", "n", "14"));
        factories.put("prototypes.4", newToolSetFactory(false, true, null, "o", "15", "p", null));

        // - RuntimeToolSetFactory
        factories.put("runtime.1", newRuntimeToolSetFactory(false, false, "runtime.1", "q", "17", "r", "18"));
        factories.put("runtime.2", newRuntimeToolSetFactory(false, false, null, "s", "19", "t", null));

        // - RuntimeToolSetFactory & ToolFactory
        factories.put("runtime.3", newRuntimeToolSetFactory(false, true, "runtime.3", "u", "21", "v", "22"));
        factories.put("runtime.4", newRuntimeToolSetFactory(false, true, null, "w", "23", "x", null));

        service.setToolFactories(factories);

        staticToolNames = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
                                         "p", "prototype.1", "prototype.2", "prototypes.3", "prototypes.4", "runtime.3", "runtime.4",
                                         "singleton.1", "singleton.2", "singletons.3", "singletons.4" };

        // all names and values including runtime tools
        allNames = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p",
                                  "prototype.1", "prototype.2", "prototypes.3", "prototypes.4", "q", "r", "runtime.3", "runtime.4", "s",
                                  "singleton.1", "singleton.2", "singletons.3", "singletons.4", "t", "u", "v", "w", "x" };

        allValues = new String[] { "1", "2", "3", null, "5", "6", "7", null, "9", "10", "11", null, "13", "14", "15",
                                   null, "prototype.1", null, "prototypes.3", null, "17", "18", "runtime.3", null, "19", "singleton.1",
                                   null, "singletons.3", null, null, "21", "22", "23", null };
    }

    @SuppressWarnings("unchecked")
    private void initService() {
        try {
            service.afterPropertiesSet();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // service
        assertNull(getFieldValue(service, "toolFactories", Map.class));

        tools = sort(getFieldValue(service, "tools", Map.class));
        toolsInSet = sort(getFieldValue(service, "toolsInSet", Map.class));
        toolsRuntime = sort(getFieldValue(service, "toolsRuntime", Map.class));
        prePulledTools = sort(getFieldValue(service, "prePulledTools", Map.class));
        toolNames = createHashSet(getFieldValue(service, "toolNames", Set.class));

        assertNotNull(tools);
        assertNotNull(toolsInSet);
        assertNotNull(toolsRuntime);
        assertNotNull(prePulledTools);
        assertNotNull(toolNames);

        // context
        context = service.getContext();
        assertNotNull(context);

        context_pulledTools = getFieldValue(context, "pulledTools", Map.class);
        context_toolsRuntime = getFieldValue(context, "toolsRuntime", Map.class);
        context_toolsInRuntimeSet = getFieldValue(context, "toolsInRuntimeSet", Map.class);
        context_toolNames = getFieldValue(context, "toolNames", Set.class);

        assertNotNull(context_pulledTools);
        assertNotNull(context_toolsRuntime);
        assertNotNull(context_toolsInRuntimeSet);
        assertNotNull(context_toolNames);
    }

    private <T> Map<String, T> sort(Map<String, T> map) {
        Map<String, T> sortedMap = createTreeMap();
        sortedMap.putAll(map);
        return sortedMap;
    }

    private void initServiceWithParent() {
        PullService parent = service;
        service = new PullServiceImpl();

        Map<String, Object> factories = createHashMap();

        factories.put("singleton.3", newToolFactory(true, "singleton.3"));
        factories.put("singletons.5", newToolSetFactory(true, true, "singletons.5", "z1", "11"));

        factories.put("prototype.3", newToolFactory(false, "prototype.3"));
        factories.put("prototypes.5", newToolSetFactory(false, true, "prototypes.5", "z2", "22"));

        factories.put("runtime.5", newRuntimeToolSetFactory(false, true, "runtime.5", "z3", "33"));

        service.setToolFactories(factories);
        service.setParent(parent);

        initService();

        // all names and values including runtime tools and parent's tools
        allNamesWithParent = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
                                            "p", "prototype.1", "prototype.2", "prototype.3", "prototypes.3", "prototypes.4", "prototypes.5", "q",
                                            "r", "runtime.3", "runtime.4", "runtime.5", "s", "singleton.1", "singleton.2", "singleton.3",
                                            "singletons.3", "singletons.4", "singletons.5", "t", "u", "v", "w", "x", "z1", "z2", "z3" };

        allValuesWithParent = new String[] { "1", "2", "3", null, "5", "6", "7", null, "9", "10", "11", null, "13",
                                             "14", "15", null, "prototype.1", null, "prototype.3", "prototypes.3", null, "prototypes.5", "17", "18",
                                             "runtime.3", null, "runtime.5", "19", "singleton.1", null, "singleton.3", "singletons.3", null,
                                             "singletons.5", null, "21", "22", "23", null, "11", "22", "33" };
    }

    @Test
    public void service_initParent() throws Exception {
        PullServiceImpl parent = new PullServiceImpl();
        PullServiceImpl sub;

        // no parent
        sub = new PullServiceImpl();
        sub.setApplicationContext(getApplicationContext("pullService", parent, false));
        sub.setBeanName("pullService");
        sub.afterPropertiesSet();

        assertNull(getFieldValue(sub, "parent", PullService.class));

        // with parent, beanName == pullService
        sub = new PullServiceImpl();
        sub.setApplicationContext(getApplicationContext("pullService", parent, true));
        sub.setBeanName("pullService");
        sub.afterPropertiesSet();

        assertSame(parent, getFieldValue(sub, "parent", PullService.class));

        // with parent, beanName == otherName
        sub = new PullServiceImpl();
        sub.setApplicationContext(getApplicationContext("pullService", parent, true));
        sub.setBeanName("otherName");
        sub.afterPropertiesSet();

        assertSame(parent, getFieldValue(sub, "parent", PullService.class));

        // with parent, beanName == otherName
        sub = new PullServiceImpl();
        sub.setApplicationContext(getApplicationContext("otherName", parent, true));
        sub.setBeanName("otherName");
        sub.afterPropertiesSet();

        assertSame(parent, getFieldValue(sub, "parent", PullService.class));

        // with parent, beanName == otherName2
        sub = new PullServiceImpl();
        sub.setApplicationContext(getApplicationContext("otherName", parent, true));
        sub.setBeanName("otherName2");
        sub.afterPropertiesSet();

        assertNull(getFieldValue(sub, "parent", PullService.class));
    }

    private ApplicationContext getApplicationContext(String beanName, PullService parent, boolean withParent) {
        ApplicationContext parentContext = createMock(ApplicationContext.class);
        ApplicationContext thisContext = createMock(ApplicationContext.class);

        if (withParent) {
            expect(thisContext.getParent()).andReturn(parentContext).anyTimes();
        } else {
            expect(thisContext.getParent()).andReturn(null).anyTimes();
        }

        expect(parentContext.containsBean(beanName)).andReturn(true).anyTimes();
        expect(parentContext.containsBean(org.easymock.EasyMock.<String>anyObject())).andReturn(false).anyTimes();
        expect(parentContext.getBean(beanName)).andReturn(parent).anyTimes();

        replay(parentContext, thisContext);

        return thisContext;
    }

    @Test
    public void service_init_noFactories() throws Exception {
        service = new PullServiceImpl();
        initService();

        assertTrue(tools.isEmpty());
        assertTrue(toolsInSet.isEmpty());
        assertTrue(toolsRuntime.isEmpty());
        assertTrue(prePulledTools.isEmpty());
        assertTrue(toolNames.isEmpty());
    }

    @Test
    public void service_init_emptyName() throws Exception {
        service = new PullServiceImpl();

        try {
            Map<String, Object> factories = createHashMap();
            factories.put(null, newToolFactory(true, "111"));

            service.setToolFactories(factories);
            service.afterPropertiesSet();

            fail();
        } catch (IllegalArgumentException e) {
            assertThat(e, exception("tool name"));
        }

        try {
            Map<String, Object> factories = createHashMap();
            factories.put("  ", newToolFactory(true, "111"));

            service.setToolFactories(factories);
            service.afterPropertiesSet();

            fail();
        } catch (IllegalArgumentException e) {
            assertThat(e, exception("tool name"));
        }
    }

    @Test
    public void service_init_unknwonFactory() throws Exception {
        service = new PullServiceImpl();

        try {
            Map<String, Object> factories = createHashMap();
            factories.put("unknwon", "not a factory");

            service.setToolFactories(factories);
            service.afterPropertiesSet();

            fail();
        } catch (IllegalArgumentException e) {
            assertThat(e, exception("unknown pull tool factory type: java.lang.String"));
        }
    }

    @Test
    public void service_init_prePulling_preQueueing() throws Exception {
        List<Object> values;

        // toolNames - all tools and tools in set
        assertArrayEquals(staticToolNames, toStringArray(toolNames));

        // prePulledTools - pre-pulled singletons
        assertArrayEquals(new Object[] { "a", "b", "c", "d", "e", "f", "g", "h", "singleton.1", "singleton.2",
                                         "singletons.3", "singletons.4" }, prePulledTools.keySet().toArray());

        assertArrayEquals(new Object[] { "1", "2", "3", NULL_PLACEHOLDER, "5", "6", "7", NULL_PLACEHOLDER,
                                         "singleton.1", NULL_PLACEHOLDER, "singletons.3", NULL_PLACEHOLDER }, prePulledTools.values().toArray());

        // tools - non-singleton tools only
        assertArrayEquals(new Object[] { "prototype.1", "prototype.2", "prototypes.3", "prototypes.4", "runtime.3",
                                         "runtime.4" }, tools.keySet().toArray());

        values = createArrayList();

        for (ToolFactory factory : tools.values()) {
            values.add(factory.createTool());
        }

        assertArrayEquals(new Object[] { "prototype.1", null, "prototypes.3", null, "runtime.3", null },
                          values.toArray());

        // toolsInSet - non-singleton tools in set only
        assertArrayEquals(new Object[] { "i", "j", "k", "l", "m", "n", "o", "p" }, toolsInSet.keySet().toArray());

        values = createArrayList();

        for (String nameInSet : toolsInSet.keySet()) {
            values.add(toolsInSet.get(nameInSet).getFactory().createTool(nameInSet));
        }

        assertArrayEquals(new Object[] { "9", "10", "11", null, "13", "14", "15", null }, values.toArray());

        // toolsRuntime - runtime tool sets only
        assertArrayEquals(new Object[] { "runtime.1", "runtime.2", "runtime.3", "runtime.4" }, toolsRuntime.keySet()
                                                                                                           .toArray());

        assertEquals(toolNames.size(), tools.size() + toolsInSet.size() + prePulledTools.size());
    }

    @Test
    public void service_init_ToolNameAware() throws Exception {
        service = new PullServiceImpl();

        ToolNameAwareToolFactory f1 = createMock(ToolNameAwareToolFactory.class);
        ToolNameAwareToolSetFactory f2 = createMock(ToolNameAwareToolSetFactory.class);
        ToolNameAwareRuntimeToolSetFactory f3 = createMock(ToolNameAwareRuntimeToolSetFactory.class);

        f1.setToolName("f1");
        f2.setToolName("f2");
        f3.setToolName("f3");

        expect(f1.isSingleton()).andReturn(false);
        expect(f2.isSingleton()).andReturn(false);
        expect(f2.getToolNames()).andReturn(null);

        replay(f1, f2, f3);

        Map<String, Object> factories = createHashMap();
        factories.put("f1", f1);
        factories.put("f2", f2);
        factories.put("f3", f3);
        service.setToolFactories(factories);

        service.afterPropertiesSet();

        verify(f1, f2, f3);
    }

    @Test
    public void service_getContext() {
        // 在web环境中,context被cache,否则不cache
        assertNotSame(service.getContext(), service.getContext());

        setRequestAttrs();
        assertSame(service.getContext(), service.getContext());
    }

    @Test
    public void service_getTools() {
        assertGetTools(service.getTools());

        // 在非web环境中,context不被cache
        assertNotSame(service.getTools(), service.getTools());

        // 在web环境中,context被cache
        setRequestAttrs();
        assertSame(service.getTools(), service.getTools());

        // unmodifiable
        try {
            service.getTools().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void service_getTools_withParent() {
        initServiceWithParent();

        Map<String, Object> tools = sort(service.getTools());

        assertArrayEquals(allNamesWithParent, tools.keySet().toArray());
        assertArrayEquals(allValuesWithParent, tools.values().toArray());

        // 在非web环境中,context不被cache
        assertNotSame(service.getTools(), service.getTools());

        // 在web环境中,context被cache
        setRequestAttrs();
        assertSame(service.getTools(), service.getTools());

        // unmodifiable
        try {
            service.getTools().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void service_toString() {
        // inited with tools
        String str = "";
        str += "PullTools [\n";
        str += "  [ 1/26] /prototype.1\n";
        str += "  [ 2/26] /prototype.2\n";
        str += "  [ 3/26] /prototypes.1/i\n";
        str += "  [ 4/26] /prototypes.1/j\n";
        str += "  [ 5/26] /prototypes.2/k\n";
        str += "  [ 6/26] /prototypes.2/l\n";
        str += "  [ 7/26] /prototypes.3\n";
        str += "  [ 8/26] /prototypes.3/m\n";
        str += "  [ 9/26] /prototypes.3/n\n";
        str += "  [10/26] /prototypes.4\n";
        str += "  [11/26] /prototypes.4/o\n";
        str += "  [12/26] /prototypes.4/p\n";
        str += "  [13/26] /runtime.3\n";
        str += "  [14/26] /runtime.4\n";
        str += "  [15/26] /singleton.1\n";
        str += "  [16/26] /singleton.2\n";
        str += "  [17/26] /singletons.1/a\n";
        str += "  [18/26] /singletons.1/b\n";
        str += "  [19/26] /singletons.2/c\n";
        str += "  [20/26] /singletons.2/d\n";
        str += "  [21/26] /singletons.3\n";
        str += "  [22/26] /singletons.3/e\n";
        str += "  [23/26] /singletons.3/f\n";
        str += "  [24/26] /singletons.4\n";
        str += "  [25/26] /singletons.4/g\n";
        str += "  [26/26] /singletons.4/h\n";
        str += "]";

        assertEquals(str, service.toString());

        // not inited
        service = new PullServiceImpl();
        assertEquals("PullTools[uninitialized]", service.toString());

        // inited empty
        initService();
        assertEquals("PullTools[]", service.toString());
    }

    @Test
    public void service_toString_withParent() {
        initServiceWithParent();

        String str = "";
        str += "PullTools [\n";
        str += "  [1/7] /prototype.3\n";
        str += "  [2/7] /prototypes.5\n";
        str += "  [3/7] /prototypes.5/z2\n";
        str += "  [4/7] /runtime.5\n";
        str += "  [5/7] /singleton.3\n";
        str += "  [6/7] /singletons.5\n";
        str += "  [7/7] /singletons.5/z1\n";
        str += "]\n";
        str += "Parent PullTools [\n";
        str += "  [ 1/26] /prototype.1\n";
        str += "  [ 2/26] /prototype.2\n";
        str += "  [ 3/26] /prototypes.1/i\n";
        str += "  [ 4/26] /prototypes.1/j\n";
        str += "  [ 5/26] /prototypes.2/k\n";
        str += "  [ 6/26] /prototypes.2/l\n";
        str += "  [ 7/26] /prototypes.3\n";
        str += "  [ 8/26] /prototypes.3/m\n";
        str += "  [ 9/26] /prototypes.3/n\n";
        str += "  [10/26] /prototypes.4\n";
        str += "  [11/26] /prototypes.4/o\n";
        str += "  [12/26] /prototypes.4/p\n";
        str += "  [13/26] /runtime.3\n";
        str += "  [14/26] /runtime.4\n";
        str += "  [15/26] /singleton.1\n";
        str += "  [16/26] /singleton.2\n";
        str += "  [17/26] /singletons.1/a\n";
        str += "  [18/26] /singletons.1/b\n";
        str += "  [19/26] /singletons.2/c\n";
        str += "  [20/26] /singletons.2/d\n";
        str += "  [21/26] /singletons.3\n";
        str += "  [22/26] /singletons.3/e\n";
        str += "  [23/26] /singletons.3/f\n";
        str += "  [24/26] /singletons.4\n";
        str += "  [25/26] /singletons.4/g\n";
        str += "  [26/26] /singletons.4/h\n";
        str += "]";

        assertEquals(str, service.toString());
    }

    @Test
    public void context_getToolNames() {
        assertArrayEquals(allNames, context.getToolNames().toArray());

        // cached
        assertSame(context.getToolNames(), context.getToolNames());

        // unmodifiable
        try {
            context.getToolNames().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void context_getToolNames_withParent() {
        initServiceWithParent();

        assertArrayEquals(allNamesWithParent, context.getToolNames().toArray());

        // cached
        assertSame(context.getToolNames(), context.getToolNames());

        // unmodifiable
        try {
            context.getToolNames().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void context_getTools() {
        assertGetTools(context.getTools());

        // cached
        assertSame(context.getTools(), context.getTools());

        // unmodifiable
        try {
            context.getTools().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void context_getTools_withParent() {
        initServiceWithParent();

        Map<String, Object> tools = createTreeMap();
        tools.putAll(context.getTools());

        assertArrayEquals(allNamesWithParent, tools.keySet().toArray());
        assertArrayEquals(allValuesWithParent, tools.values().toArray());

        // cached
        assertSame(context.getTools(), context.getTools());

        // unmodifiable
        try {
            context.getTools().clear();
            fail();
        } catch (UnsupportedOperationException e) {
        }
    }

    @Test
    public void context_pull() {
        assertContext(/* pulledTools */0, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        // tool, singleton
        assertEquals("singleton.1", context.pull("singleton.1"));
        assertEquals(null, context.pull("singleton.2"));

        assertContext(/* pulledTools */0, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        // tool-set, singleton
        assertEquals("singletons.3", context.pull("singletons.3"));
        assertEquals(null, context.pull("singletons.4"));

        assertContext(/* pulledTools */0, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        assertEquals("1", context.pull("a"));
        assertEquals("2", context.pull("b"));
        assertEquals("3", context.pull("c"));
        assertEquals(null, context.pull("d"));

        assertEquals("5", context.pull("e"));
        assertEquals("6", context.pull("f"));
        assertEquals("7", context.pull("g"));
        assertEquals(null, context.pull("h"));

        assertContext(/* pulledTools */0, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        // tool, non-singleton
        assertEquals("prototype.1", context.pull("prototype.1"));
        assertEquals(null, context.pull("prototype.2"));

        assertContext(/* pulledTools */2, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        // tool-set, non-singleton
        assertEquals("prototypes.3", context.pull("prototypes.3"));
        assertEquals(null, context.pull("prototypes.4"));

        assertContext(/* pulledTools */4, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        assertEquals("9", context.pull("i"));
        assertEquals("10", context.pull("j"));
        assertEquals("11", context.pull("k"));
        assertEquals(null, context.pull("l"));

        assertEquals("13", context.pull("m"));
        assertEquals("14", context.pull("n"));
        assertEquals("15", context.pull("o"));
        assertEquals(null, context.pull("p"));

        assertContext(/* pulledTools */12, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        // tool-set, runtime
        assertEquals("runtime.3", context.pull("runtime.3"));
        assertEquals(null, context.pull("runtime.4"));

        assertContext(/* pulledTools */14, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);

        assertEquals("17", context.pull("q"));
        assertContext(/* pulledTools */15, /* toolsRuntime */3, /* toolsInRuntimeSet */2, /* toolNames */28);
        assertEquals("18", context.pull("r"));
        assertContext(/* pulledTools */16, /* toolsRuntime */3, /* toolsInRuntimeSet */2, /* toolNames */28);

        assertEquals("19", context.pull("s"));
        assertContext(/* pulledTools */17, /* toolsRuntime */2, /* toolsInRuntimeSet */4, /* toolNames */30);
        assertEquals(null, context.pull("t"));
        assertContext(/* pulledTools */18, /* toolsRuntime */2, /* toolsInRuntimeSet */4, /* toolNames */30);

        assertEquals("21", context.pull("u"));
        assertContext(/* pulledTools */19, /* toolsRuntime */1, /* toolsInRuntimeSet */6, /* toolNames */32);
        assertEquals("22", context.pull("v"));
        assertContext(/* pulledTools */20, /* toolsRuntime */1, /* toolsInRuntimeSet */6, /* toolNames */32);

        assertEquals("23", context.pull("w"));
        assertContext(/* pulledTools */21, /* toolsRuntime */0, /* toolsInRuntimeSet */8, /* toolNames */34);
        assertEquals(null, context.pull("x"));
        assertContext(/* pulledTools */22, /* toolsRuntime */0, /* toolsInRuntimeSet */8, /* toolNames */34);
    }

    @Test
    public void context_pull_empty() {
        assertEquals(null, context.pull(null));
        assertEquals(null, context.pull("  "));

        assertContext(/* pulledTools */0, /* toolsRuntime */4, /* toolsInRuntimeSet */0, /* toolNames */26);
    }

    @Test
    public void context_pull_notExist() {
        assertEquals(null, context.pull("notexist"));
        assertContext(/* pulledTools */0, /* toolsRuntime */0, /* toolsInRuntimeSet */8, /* toolNames */34);
    }

    @Test
    public void context_pull_exceptions() throws Exception {
        // singleton
        try {
            createPullService("mysingleton", new ExceptionToolFactory(true, "my error"));
            fail();
        } catch (PullException e) {
            assertThat(e,
                       exception(IllegalArgumentException.class, "Could not create tool: \"mysingleton\"", "my error"));
        }

        try {
            createPullService("mysingletonSet", new ExceptionToolSetFactory(true, "my error"));
            fail();
        } catch (PullException e) {
            assertThat(
                    e,
                    exception(IllegalArgumentException.class, "Could not create tool: \"mysingletonSet.subname\"",
                              "my error"));
        }

        // non-singleton
        createPullService("myprototype", new ExceptionToolFactory(false, "my error"));

        try {
            service.getTools();
            fail();
        } catch (PullException e) {
            assertThat(e,
                       exception(IllegalArgumentException.class, "Could not create tool: \"myprototype\"", "my error"));
        }

        createPullService("myprototypeSet", new ExceptionToolSetFactory(false, "my error"));

        try {
            service.getTools();
            fail();
        } catch (PullException e) {
            assertThat(
                    e,
                    exception(IllegalArgumentException.class, "Could not create tool: \"myprototypeSet.subname\"",
                              "my error"));
        }

        // runtime
        createPullService("myruntime", new ExceptionRuntimeToolSetFactory(false, "my error", false));

        try {
            service.getTools();
            fail();
        } catch (PullException e) {
            assertThat(
                    e,
                    exception(IllegalArgumentException.class, "Could not create tool: \"myruntime.subname\"",
                              "my error"));
        }

        // runtime - failure on createTool()
        createPullService("myruntime", new ExceptionRuntimeToolSetFactory(false, "my error", true));

        try {
            service.getTools();
            fail();
        } catch (PullException e) {
            assertThat(
                    e,
                    exception(IllegalArgumentException.class, "Could not create runtime tool-set: \"myruntime\"",
                              "my error"));
        }
    }

    private void createPullService(String name, Object factory) throws Exception {
        service = new PullServiceImpl();

        Map<String, Object> factories = createHashMap();
        factories.put(name, factory);
        service.setToolFactories(factories);

        service.afterPropertiesSet();
    }

    @Test
    public void context_pull_withParent() {
        setRequestAttrs(); // 确保每次取得同一个context,以便于测试

        // init parent context
        Map<String, Object> parent_pulledTools;
        Map<String, RuntimeToolSetFactory> parent_toolsRuntime;
        Map<String, ToolSetInfo<RuntimeToolSetFactory>> parent_toolsInRuntimeSet;
        Set<ToolName> parent_toolNames;

        populateService();
        initService();
        parent_pulledTools = context_pulledTools;
        parent_toolsRuntime = context_toolsRuntime;
        parent_toolsInRuntimeSet = context_toolsInRuntimeSet;
        parent_toolNames = context_toolNames;

        // init this context
        Map<String, Object> this_pulledTools;
        Map<String, RuntimeToolSetFactory> this_toolsRuntime;
        Map<String, ToolSetInfo<RuntimeToolSetFactory>> this_toolsInRuntimeSet;
        Set<ToolName> this_toolNames;

        initServiceWithParent();
        this_pulledTools = context_pulledTools;
        this_toolsRuntime = context_toolsRuntime;
        this_toolsInRuntimeSet = context_toolsInRuntimeSet;
        this_toolNames = context_toolNames;

        assertContext(/* pulledTools */0, /* toolsRuntime */1, /* toolsInRuntimeSet */0, /* toolNames */7);

        // restore parent context and test it
        context_pulledTools = parent_pulledTools;
        context_toolsRuntime = parent_toolsRuntime;
        context_toolsInRuntimeSet = parent_toolsInRuntimeSet;
        context_toolNames = parent_toolNames;

        context_pull();

        // restore this context and test it
        context_pulledTools = this_pulledTools;
        context_toolsRuntime = this_toolsRuntime;
        context_toolsInRuntimeSet = this_toolsInRuntimeSet;
        context_toolNames = this_toolNames;

        assertContext(/* pulledTools */0, /* toolsRuntime */0, /* toolsInRuntimeSet */1, /* toolNames */8);

        assertEquals("singleton.3", context.pull("singleton.3"));
        assertEquals("singletons.5", context.pull("singletons.5"));
        assertEquals("prototype.3", context.pull("prototype.3"));
        assertEquals("prototypes.5", context.pull("prototypes.5"));
        assertEquals("runtime.5", context.pull("runtime.5"));
        assertEquals("11", context.pull("z1"));
        assertEquals("22", context.pull("z2"));
        assertEquals("33", context.pull("z3"));

        assertContext(/* pulledTools */5, /* toolsRuntime */0, /* toolsInRuntimeSet */1, /* toolNames */8);
    }

    private void assertGetTools(Map<String, Object> tools) {
        tools = createTreeMap();
        tools.putAll(context.getTools());

        assertArrayEquals(allNames, tools.keySet().toArray());
        assertArrayEquals(allValues, tools.values().toArray());
    }

    private void assertContext(int pulledTools, int toolsRuntime, int toolsInRuntimeSet, int toolNames) {
        assertEquals(pulledTools, context_pulledTools.size());
        assertEquals(toolsRuntime, context_toolsRuntime.size());
        assertEquals(toolsInRuntimeSet, context_toolsInRuntimeSet.size());
        assertEquals(toolNames, context_toolNames.size());
    }

    @Test
    public void context_toString() {
        String str;

        // has not pulled all
        str = "";
        str += "PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [ 1/12] a            = 1\n";
        str += "                     [ 2/12] b            = 2\n";
        str += "                     [ 3/12] c            = 3\n";
        str += "                     [ 4/12] d            = null\n";
        str += "                     [ 5/12] e            = 5\n";
        str += "                     [ 6/12] f            = 6\n";
        str += "                     [ 7/12] g            = 7\n";
        str += "                     [ 8/12] h            = null\n";
        str += "                     [ 9/12] singleton.1  = singleton.1\n";
        str += "                     [10/12] singleton.2  = null\n";
        str += "                     [11/12] singletons.3 = singletons.3\n";
        str += "                     [12/12] singletons.4 = null\n";
        str += "                   }\n";
        str += "  pulledTools    = {}\n";
        str += "}";

        assertEquals(str, context.toString());

        // pulled all
        context.getTools();

        str = "";
        str += "PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [ 1/12] a            = 1\n";
        str += "                     [ 2/12] b            = 2\n";
        str += "                     [ 3/12] c            = 3\n";
        str += "                     [ 4/12] d            = null\n";
        str += "                     [ 5/12] e            = 5\n";
        str += "                     [ 6/12] f            = 6\n";
        str += "                     [ 7/12] g            = 7\n";
        str += "                     [ 8/12] h            = null\n";
        str += "                     [ 9/12] singleton.1  = singleton.1\n";
        str += "                     [10/12] singleton.2  = null\n";
        str += "                     [11/12] singletons.3 = singletons.3\n";
        str += "                     [12/12] singletons.4 = null\n";
        str += "                   }\n";
        str += "  pulledTools    = {\n";
        str += "                     [ 1/22] i            = 9\n";
        str += "                     [ 2/22] j            = 10\n";
        str += "                     [ 3/22] k            = 11\n";
        str += "                     [ 4/22] l            = null\n";
        str += "                     [ 5/22] m            = 13\n";
        str += "                     [ 6/22] n            = 14\n";
        str += "                     [ 7/22] o            = 15\n";
        str += "                     [ 8/22] p            = null\n";
        str += "                     [ 9/22] prototype.1  = prototype.1\n";
        str += "                     [10/22] prototype.2  = null\n";
        str += "                     [11/22] prototypes.3 = prototypes.3\n";
        str += "                     [12/22] prototypes.4 = null\n";
        str += "                     [13/22] q            = 17\n";
        str += "                     [14/22] r            = 18\n";
        str += "                     [15/22] runtime.3    = runtime.3\n";
        str += "                     [16/22] runtime.4    = null\n";
        str += "                     [17/22] s            = 19\n";
        str += "                     [18/22] t            = null\n";
        str += "                     [19/22] u            = 21\n";
        str += "                     [20/22] v            = 22\n";
        str += "                     [21/22] w            = 23\n";
        str += "                     [22/22] x            = null\n";
        str += "                   }\n";
        str += "}";

        assertEquals(str, context.toString());
    }

    @Test
    public void context_toString_withParent() {
        initServiceWithParent();

        String str;

        // has not pulled all
        str = "";
        str += "PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [1/3] singleton.3  = singleton.3\n";
        str += "                     [2/3] singletons.5 = singletons.5\n";
        str += "                     [3/3] z1           = 11\n";
        str += "                   }\n";
        str += "  pulledTools    = {}\n";
        str += "}\n";
        str += "Parent PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [ 1/12] a            = 1\n";
        str += "                     [ 2/12] b            = 2\n";
        str += "                     [ 3/12] c            = 3\n";
        str += "                     [ 4/12] d            = null\n";
        str += "                     [ 5/12] e            = 5\n";
        str += "                     [ 6/12] f            = 6\n";
        str += "                     [ 7/12] g            = 7\n";
        str += "                     [ 8/12] h            = null\n";
        str += "                     [ 9/12] singleton.1  = singleton.1\n";
        str += "                     [10/12] singleton.2  = null\n";
        str += "                     [11/12] singletons.3 = singletons.3\n";
        str += "                     [12/12] singletons.4 = null\n";
        str += "                   }\n";
        str += "  pulledTools    = {}\n";
        str += "}";

        assertEquals(str, context.toString());

        // pulled all
        context.getTools();

        str = "";
        str += "PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [1/3] singleton.3  = singleton.3\n";
        str += "                     [2/3] singletons.5 = singletons.5\n";
        str += "                     [3/3] z1           = 11\n";
        str += "                   }\n";
        str += "  pulledTools    = {\n";
        str += "                     [1/5] prototype.3  = prototype.3\n";
        str += "                     [2/5] prototypes.5 = prototypes.5\n";
        str += "                     [3/5] runtime.5    = runtime.5\n";
        str += "                     [4/5] z2           = 22\n";
        str += "                     [5/5] z3           = 33\n";
        str += "                   }\n";
        str += "}\n";
        str += "Parent PullContext {\n";
        str += "  prePulledTools = {\n";
        str += "                     [ 1/12] a            = 1\n";
        str += "                     [ 2/12] b            = 2\n";
        str += "                     [ 3/12] c            = 3\n";
        str += "                     [ 4/12] d            = null\n";
        str += "                     [ 5/12] e            = 5\n";
        str += "                     [ 6/12] f            = 6\n";
        str += "                     [ 7/12] g            = 7\n";
        str += "                     [ 8/12] h            = null\n";
        str += "                     [ 9/12] singleton.1  = singleton.1\n";
        str += "                     [10/12] singleton.2  = null\n";
        str += "                     [11/12] singletons.3 = singletons.3\n";
        str += "                     [12/12] singletons.4 = null\n";
        str += "                   }\n";
        str += "  pulledTools    = {\n";
        str += "                     [ 1/22] i            = 9\n";
        str += "                     [ 2/22] j            = 10\n";
        str += "                     [ 3/22] k            = 11\n";
        str += "                     [ 4/22] l            = null\n";
        str += "                     [ 5/22] m            = 13\n";
        str += "                     [ 6/22] n            = 14\n";
        str += "                     [ 7/22] o            = 15\n";
        str += "                     [ 8/22] p            = null\n";
        str += "                     [ 9/22] prototype.1  = prototype.1\n";
        str += "                     [10/22] prototype.2  = null\n";
        str += "                     [11/22] prototypes.3 = prototypes.3\n";
        str += "                     [12/22] prototypes.4 = null\n";
        str += "                     [13/22] q            = 17\n";
        str += "                     [14/22] r            = 18\n";
        str += "                     [15/22] runtime.3    = runtime.3\n";
        str += "                     [16/22] runtime.4    = null\n";
        str += "                     [17/22] s            = 19\n";
        str += "                     [18/22] t            = null\n";
        str += "                     [19/22] u            = 21\n";
        str += "                     [20/22] v            = 22\n";
        str += "                     [21/22] w            = 23\n";
        str += "                     [22/22] x            = null\n";
        str += "                   }\n";
        str += "}";

        assertEquals(str, context.toString());
    }

    @Test
    public void context_sharing() throws Exception {
        setRequestAttrs();

        // init parent
        PullServiceImpl parent = new PullServiceImpl();

        Map<String, Object> factories = createHashMap();
        factories.put("parentSingleton", new MyToolFactory(true));
        factories.put("parentPrototype", new MyToolFactory(false));
        factories.put("parentRuntime", new MyRuntimeToolSetFactory("parentRuntime"));
        parent.setToolFactories(factories);
        parent.afterPropertiesSet();

        // init sub1
        PullServiceImpl sub1 = new PullServiceImpl();
        factories = createHashMap();
        factories.put("subSingleton", new MyToolFactory(true));
        factories.put("subPrototype", new MyToolFactory(false));
        factories.put("subRuntime", new MyRuntimeToolSetFactory("subRuntime"));
        sub1.setParent(parent);
        sub1.setToolFactories(factories);
        sub1.afterPropertiesSet();

        // init sub2
        PullServiceImpl sub2 = new PullServiceImpl();
        factories = createHashMap();
        factories.put("subSingleton", new MyToolFactory(true));
        factories.put("subPrototype", new MyToolFactory(false));
        factories.put("subRuntime", new MyRuntimeToolSetFactory("subRuntime"));
        sub2.setParent(parent);
        sub2.setToolFactories(factories);
        sub2.afterPropertiesSet();

        // parentObject is shared among subs
        assertSameAndNotNull(sub1.getContext().pull("parentSingleton"), sub2.getContext().pull("parentSingleton"));
        assertSameAndNotNull(sub1.getContext().pull("parentPrototype"), sub2.getContext().pull("parentPrototype"));
        assertSameAndNotNull(sub1.getContext().pull("parentRuntime"), sub2.getContext().pull("parentRuntime"));

        assertNotSameAndNotNull(sub1.getContext().pull("subSingleton"), sub2.getContext().pull("subSingleton"));
        assertNotSameAndNotNull(sub1.getContext().pull("subPrototype"), sub2.getContext().pull("subPrototype"));
        assertNotSameAndNotNull(sub1.getContext().pull("subRuntime"), sub2.getContext().pull("subRuntime"));
    }

    private void assertSameAndNotNull(Object o1, Object o2) {
        assertNotNull(o1);
        assertNotNull(o2);
        assertSame(o1, o2);
    }

    private void assertNotSameAndNotNull(Object o1, Object o2) {
        assertNotNull(o1);
        assertNotNull(o2);
        assertNotSame(o1, o2);
    }

    private String[] toStringArray(Collection<ToolName> c) {
        String[] result = new String[c.size()];

        int i = 0;
        for (ToolName o : c) {
            result[i++] = o == null ? null : o.getName();
        }

        Arrays.sort(result);

        return result;
    }

    private static class MyToolFactory implements ToolFactory {
        private boolean singleton;

        public MyToolFactory(boolean singleton) {
            this.singleton = singleton;
        }

        public boolean isSingleton() {
            return singleton;
        }

        public Object createTool() {
            return new Object();
        }
    }

    private static class MyRuntimeToolSetFactory implements RuntimeToolSetFactory {
        private List<String> keys;

        public MyRuntimeToolSetFactory(String name) {
            this.keys = singletonList(name);
        }

        public Object createToolSet() throws Exception {
            return null;
        }

        public Iterable<String> getToolNames(Object toolSet) {
            return keys;
        }

        public Object createTool(Object toolSet, String name) throws Exception {
            return new Object();
        }
    }

    private static class ExceptionBaseFactory {
        private boolean singleton;
        private String  msg;
        private boolean failOnCreatingToolSet;

        public ExceptionBaseFactory(boolean singleton, String msg) {
            this(singleton, msg, true);
        }

        public ExceptionBaseFactory(boolean singleton, String msg, boolean failOnCreatingToolSet) {
            this.singleton = singleton;
            this.msg = msg;
            this.failOnCreatingToolSet = failOnCreatingToolSet;
        }

        public boolean isSingleton() {
            return singleton;
        }

        public Object createTool() throws Exception {
            throw new IllegalArgumentException(msg);
        }

        public Iterable<String> getToolNames() {
            return singletonList("subname");
        }

        public Object createTool(String name) throws Exception {
            throw new IllegalArgumentException(msg);
        }

        public Object createToolSet() throws Exception {
            if (failOnCreatingToolSet) {
                throw new IllegalArgumentException(msg);
            }

            return null;
        }

        public Iterable<String> getToolNames(Object tool) {
            return singletonList("subname");
        }

        public Object createTool(Object tool, String name) throws Exception {
            throw new IllegalArgumentException(msg);
        }
    }

    private static class ExceptionToolFactory extends ExceptionBaseFactory implements ToolFactory {
        public ExceptionToolFactory(boolean singleton, String msg) {
            super(singleton, msg);
        }
    }

    private static class ExceptionToolSetFactory extends ExceptionBaseFactory implements ToolSetFactory {
        public ExceptionToolSetFactory(boolean singleton, String msg) {
            super(singleton, msg);
        }
    }

    private static class ExceptionRuntimeToolSetFactory extends ExceptionBaseFactory implements RuntimeToolSetFactory {
        public ExceptionRuntimeToolSetFactory(boolean singleton, String msg, boolean failOnCreatingTool) {
            super(singleton, msg, failOnCreatingTool);
        }
    }

    private static interface ToolNameAwareToolFactory extends ToolFactory, ToolNameAware {
    }

    private static interface ToolNameAwareToolSetFactory extends ToolSetFactory, ToolNameAware {
    }

    private static interface ToolNameAwareRuntimeToolSetFactory extends RuntimeToolSetFactory, ToolNameAware {
    }
}
TOP

Related Classes of com.alibaba.citrus.service.pull.impl.PullServiceTests$ExceptionToolSetFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.