001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.services.impl;
016    
017    import static org.easymock.EasyMock.checkOrder;
018    import static org.easymock.EasyMock.expect;
019    
020    import java.util.ArrayList;
021    import java.util.Collections;
022    import java.util.List;
023    
024    import org.apache.hivemind.ApplicationRuntimeException;
025    import org.apache.hivemind.ErrorLog;
026    import org.apache.hivemind.Location;
027    import org.apache.tapestry.BaseComponentTestCase;
028    import org.apache.tapestry.IRequestCycle;
029    import org.apache.tapestry.engine.IEngineService;
030    import org.testng.annotations.Test;
031    
032    /**
033     * Tests for {@link org.apache.tapestry.services.impl.ServiceMapImpl}.
034     * 
035     * @author Howard Lewis Ship
036     * @since 4.0
037     */
038    @Test
039    public class TestServiceMap extends BaseComponentTestCase
040    {
041        private IEngineService newService(String name)
042        {
043            IEngineService service = newMock(IEngineService.class);
044            checkOrder(service, false);
045            
046            expect(service.getName()).andReturn(name);
047    
048            return service;
049        }
050    
051        private IEngineService newService()
052        {
053            return newMock(IEngineService.class);
054        }
055        
056        private EngineServiceContribution constructService(String name, IEngineService service)
057        {
058            EngineServiceContribution result = new EngineServiceContribution();
059            result.setName(name);
060            result.setService(service);
061    
062            return result;
063        }
064    
065        /**
066         * Gets an application-defined and factory-defined service where there are no naming conflicts.
067         * Because ServiceMap now returns proxies, we have to do a little extra indirection to ensure
068         * that we get what's expected.
069         */
070        public void testGetNoConflict() throws Exception
071        {
072            IRequestCycle cycle1 = newCycle();
073            IRequestCycle cycle2 = newCycle();
074    
075            IEngineService factory = newService("factory");
076            IEngineService application = newService("application");
077    
078            EngineServiceContribution factoryc = constructService("factory", factory);
079            EngineServiceContribution applicationc = constructService("application", application);
080    
081            factory.service(cycle1);
082            application.service(cycle2);
083    
084            replay();
085    
086            ServiceMapImpl m = new ServiceMapImpl();
087    
088            m.setFactoryServices(Collections.singletonList(factoryc));
089            m.setApplicationServices(Collections.singletonList(applicationc));
090    
091            m.initializeService();
092    
093            assertEquals(true, m.isValid("factory"));
094    
095            m.getService("factory").service(cycle1);
096    
097            assertEquals(true, m.isValid("application"));
098    
099            m.getService("application").service(cycle2);
100    
101            verify();
102        }
103    
104        public void testNameMismatch() throws Exception
105        {
106            IRequestCycle cycle = newCycle();
107            Location l = fabricateLocation(1289);
108    
109            IEngineService service = newService("actual-name");
110    
111            EngineServiceContribution contribution = constructService("expected-name", service);
112            contribution.setLocation(l);
113    
114            replay();
115    
116            ServiceMapImpl m = new ServiceMapImpl();
117    
118            m.setFactoryServices(Collections.singletonList(contribution));
119            m.setApplicationServices(Collections.EMPTY_LIST);
120    
121            m.initializeService();
122    
123            IEngineService proxy = m.getService("expected-name");
124    
125            try
126            {
127                proxy.service(cycle);
128                unreachable();
129            }
130            catch (ApplicationRuntimeException ex)
131            {
132                assertEquals(
133                        "Engine service EasyMock for interface org.apache.tapestry.engine.IEngineService is mapped to name 'expected-name' but indicates a name of 'actual-name'.",
134                        ex.getMessage());
135                assertSame(l, ex.getLocation());
136            }
137    
138            verify();
139        }
140    
141        public void testGetServiceRepeated()
142        {
143            IEngineService application = newService();
144            EngineServiceContribution applicationc = constructService("application", application);
145    
146            replay();
147    
148            ServiceMapImpl m = new ServiceMapImpl();
149    
150            m.setFactoryServices(Collections.EMPTY_LIST);
151            m.setApplicationServices(Collections.singletonList(applicationc));
152    
153            m.initializeService();
154    
155            IEngineService service = m.getService("application");
156            assertSame(service, m.getService("application"));
157    
158            verify();
159        }
160    
161        public void testApplicationOverridesFactory() throws Exception
162        {
163            IRequestCycle cycle = newCycle();
164            IEngineService factory = newService();
165            IEngineService application = newService("override");
166    
167            EngineServiceContribution factoryc = constructService("override", factory);
168            EngineServiceContribution applicationc = constructService("override", application);
169    
170            application.service(cycle);
171    
172            replay();
173    
174            ServiceMapImpl m = new ServiceMapImpl();
175    
176            m.setFactoryServices(Collections.singletonList(factoryc));
177            m.setApplicationServices(Collections.singletonList(applicationc));
178    
179            m.initializeService();
180    
181            m.getService("override").service(cycle);
182    
183            verify();
184        }
185    
186        public void testUnknownService()
187        {
188            ServiceMapImpl m = new ServiceMapImpl();
189    
190            m.setFactoryServices(Collections.EMPTY_LIST);
191            m.setApplicationServices(Collections.EMPTY_LIST);
192    
193            m.initializeService();
194    
195            assertEquals(false, m.isValid("missing"));
196    
197            try
198            {
199                m.getService("missing");
200                unreachable();
201            }
202            catch (ApplicationRuntimeException ex)
203            {
204                assertEquals(ImplMessages.noSuchService("missing"), ex.getMessage());
205            }
206    
207            try
208            {
209                m.resolveEngineService("resolve-missing");
210                unreachable();
211            }
212            catch (ApplicationRuntimeException ex)
213            {
214                assertEquals(ImplMessages.noSuchService("resolve-missing"), ex.getMessage());
215    
216            }
217        }
218    
219        public void testDuplicateName() throws Exception
220        {
221            Location l = fabricateLocation(37);
222            IRequestCycle cycle = newCycle();
223    
224            IEngineService first = newService("duplicate");
225            IEngineService second = newService();
226    
227            EngineServiceContribution firstc = constructService("duplicate", first);
228            firstc.setLocation(l);
229            
230            EngineServiceContribution secondc = constructService("duplicate", second);
231            
232            List list = new ArrayList();
233            list.add(firstc);
234            list.add(secondc);
235    
236            ErrorLog log = newMock(ErrorLog.class);
237    
238            first.service(cycle);
239            
240            log.error(ImplMessages.dupeService("duplicate", firstc), l, null);
241    
242            replay();
243    
244            ServiceMapImpl m = new ServiceMapImpl();
245    
246            m.setFactoryServices(list);
247            m.setApplicationServices(Collections.EMPTY_LIST);
248            m.setErrorLog(log);
249    
250            m.initializeService();
251    
252            m.getService("duplicate").service(cycle);
253    
254            verify();
255        }
256    }