001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.chain.generic;
018
019import static org.junit.jupiter.api.Assertions.assertEquals;
020import static org.junit.jupiter.api.Assertions.assertNotNull;
021import static org.junit.jupiter.api.Assertions.assertThrows;
022import static org.junit.jupiter.api.Assertions.assertTrue;
023import static org.junit.jupiter.api.Assertions.fail;
024
025import org.apache.commons.chain.Catalog;
026import org.apache.commons.chain.CatalogFactory;
027import org.apache.commons.chain.Context;
028import org.apache.commons.chain.impl.CatalogBase;
029import org.apache.commons.chain.impl.ContextBase;
030import org.apache.commons.chain.impl.NonDelegatingCommand;
031import org.junit.jupiter.api.AfterEach;
032import org.junit.jupiter.api.BeforeEach;
033import org.junit.jupiter.api.Test;
034
035/**
036 * Test case for the {@code DispatchLookupCommand} class.
037 *
038 * @author Sean Schofield
039 * @version $Revision$
040 */
041public class DispatchLookupCommandTestCase {
042
043    // ---------------------------------------------------- Instance Variables
044
045    /**
046     * The instance of {@link Catalog} to use when looking up commands
047     */
048    protected Catalog<Context> catalog;
049
050    /**
051     * The {@link DispatchLookupCommand} instance under test.
052     */
053    protected DispatchLookupCommand<Context> command;
054
055    /**
056     * The {@link Context} instance on which to execute the chain.
057     */
058    protected Context context = null;
059
060    // ---------------------------------------------------------- Constructors
061
062    /**
063     * The Default-Constructor for this class.
064     */
065    public DispatchLookupCommandTestCase() {
066    }
067
068    // -------------------------------------------------- Overall Test Methods
069
070    /**
071     * Set up instance variables required by this test case.
072     */
073    @BeforeEach
074    public void init() {
075        catalog = new CatalogBase<>();
076        CatalogFactory.getInstance().setCatalog(catalog);
077        command = new DispatchLookupCommand<>();
078        context = new ContextBase();
079    }
080
081    /**
082     * Tear down instance variables required by this test case.
083     */
084    @AfterEach
085    public void tearDown() {
086        catalog = null;
087        CatalogFactory.clear();
088        command = null;
089        context = null;
090    }
091
092    // ------------------------------------------------ Individual Test Methods
093
094    /**
095     * Test ability to lookup and execute a dispatch method on a single
096     * non-delegating command
097     */
098    @Test
099    public void testExecuteDispatchLookup_1a() {
100        // use default catalog
101        catalog.addCommand("fooCommand", new TestCommand("1"));
102
103        // command should lookup the fooCommand and execute the fooMethod
104        command.setName("fooCommand");
105        command.setMethod("fooMethod");
106
107        try {
108            assertTrue(command.execute(context),
109                       "Command should return true");
110        } catch (Exception e) {
111            fail("Threw exception: " + e);
112        }
113
114        // command should lookup the fooCommand and execute the barMethod
115        command.setMethod("barMethod");
116
117        try {
118            assertTrue(command.execute(context),
119                       "Command should return true");
120        } catch (Exception e) {
121            fail("Threw exception: " + e);
122        }
123
124        checkExecuteLog("1/1");
125    }
126
127    /**
128     * Test IllegalArgumentException when incorrect command name specified
129     */
130    @Test
131    public void testExecuteDispatchLookup_2() {
132        // use default catalog
133        catalog.addCommand("barCommand", new TestCommand("2"));
134
135        // command should lookup the fooCommand and execute the fooMethod
136        command.setName("fooCommand");
137        command.setMethod("fooMethod");
138
139        assertThrows(IllegalArgumentException.class,
140                     () ->command.execute(context),
141                     "Expected IllegalArgumentException");
142    }
143
144    /**
145     * Test ability to lookup and execute a dispatch method on a single
146     * non-delegating command (using context to specify method name)
147     */
148    @Test
149    public void testExecuteDispatchLookup_3() {
150        // use default catalog
151        catalog.addCommand("fooCommand", new TestCommand("3"));
152
153        // command should lookup the fooCommand and execute the fooMethod
154        command.setName("fooCommand");
155        command.setMethodKey("methodKey");
156        context.put("methodKey", "fooMethod");
157
158        try {
159            assertTrue(command.execute(context),
160                       "Command should return true");
161        } catch (Exception e) {
162            fail("Threw exception: " + e);
163        }
164
165        // command should lookup the fooCommand and execute the barMethod
166        command.setMethodKey("methodKey");
167        context.put("methodKey", "barMethod");
168
169        try {
170            assertTrue(command.execute(context),
171                       "Command should return true");
172        } catch (Exception e) {
173            fail("Threw exception: " + e);
174        }
175
176        checkExecuteLog("3/3");
177    }
178
179    // -------------------------------------------------------- Support Methods
180
181    /**
182     * Verify the contents of the execution log
183     *
184     * @param expected the expected value
185     */
186    protected void checkExecuteLog(String expected) {
187        StringBuffer log = (StringBuffer) context.get("log");
188        assertNotNull(log, "Context failed to return log");
189        assertEquals(expected, log.toString(),
190                     "Context returned correct log");
191    }
192
193    // ---------------------------------------------------------- Inner Classes
194
195    public class TestCommand extends NonDelegatingCommand {
196        public TestCommand(String id) {
197            super(id);
198        }
199
200        public boolean fooMethod(Context context) {
201            log(context, id);
202            return true;
203        }
204
205        public boolean barMethod(Context context) {
206            log(context, id);
207            return true;
208        }
209    }
210}