1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.window;
18  
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  
23  import junit.framework.Assert;
24  import junit.framework.Test;
25  import junit.framework.TestCase;
26  import junit.framework.TestSuite;
27  
28  import org.apache.jetspeed.HashMapWindowCache;
29  import org.apache.jetspeed.PortletFactoryMock;
30  import org.apache.jetspeed.components.portletentity.PortletEntityAccessComponent;
31  import org.apache.jetspeed.container.window.PortletWindowAccessor;
32  import org.apache.jetspeed.container.window.impl.PortletWindowAccessorImpl;
33  import org.apache.jetspeed.om.common.portlet.MutablePortletEntity;
34  import org.apache.jetspeed.om.page.ContentFragment;
35  import org.apache.jetspeed.om.page.Fragment;
36  import org.apache.jetspeed.om.page.ContentFragmentImpl;
37  import org.apache.jetspeed.util.JetspeedObjectID;
38  import org.apache.pluto.om.window.PortletWindow;
39  import org.apache.pluto.om.window.PortletWindowList;
40  import org.apache.pluto.om.window.PortletWindowListCtrl;
41  import org.jmock.Mock;
42  import org.jmock.core.Invocation;
43  import org.jmock.core.InvocationMatcher;
44  import org.jmock.core.matcher.InvokeAtLeastOnceMatcher;
45  import org.jmock.core.matcher.InvokeOnceMatcher;
46  import org.jmock.core.stub.CustomStub;
47  import org.jmock.core.stub.ReturnStub;
48  
49  /***
50   * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
51   * 
52  */
53  public class TestWindows extends TestCase
54  {
55      protected PortletWindowAccessor windowAccess;
56      protected Mock fragMock;
57      protected Mock entityAccessMock;
58      protected Mock entityMock;
59      protected Mock windowListMock;
60  
61      public static Test suite()
62      {
63          // All methods starting with "test" will be executed in the test suite.
64          return new TestSuite(TestWindows.class);
65      }
66  
67      /***
68       * <p>
69       * setUp
70       * </p>
71       * 
72       * @see junit.framework.TestCase#setUp()
73       * @throws java.lang.Exception
74       */
75      protected void setUp() throws Exception
76      {
77          super.setUp();
78          entityAccessMock = new Mock(PortletEntityAccessComponent.class);
79          fragMock = new Mock(Fragment.class);
80          entityMock = new Mock(MutablePortletEntity.class);
81          windowListMock = new Mock(CompositeWindowList.class);
82          windowAccess = new PortletWindowAccessorImpl((PortletEntityAccessComponent) entityAccessMock.proxy(), PortletFactoryMock.instance, new HashMapWindowCache(),true);
83      }
84  
85      public void testWindowAccess() throws Exception
86      {
87          List windows = new ArrayList();
88          ContentFragment f1 = new ContentFragmentImpl((Fragment) fragMock.proxy(), new HashMap());
89          MutablePortletEntity entity = (MutablePortletEntity) entityMock.proxy();
90          CompositeWindowList windowList = (CompositeWindowList) windowListMock.proxy();
91          entityAccessMock.expects(new InvokeAtLeastOnceMatcher()).method("getPortletEntityForFragment")
92                  .withAnyArguments().will(new ReturnStub(entity));
93          fragMock.expects(new InvokeAtLeastOnceMatcher()).method("getId").withNoArguments()
94                  .will(new ReturnStub("frag1"));
95          entityMock.expects(new InvokeAtLeastOnceMatcher()).method("getPortletWindowList").withNoArguments().will(
96                  new ReturnStub(windowList));
97          entityMock.expects(new InvokeAtLeastOnceMatcher()).method("getId").withNoArguments().will(
98              new ReturnStub(new JetspeedObjectID("entity1")));
99  
100         windowListMock.expects(new InvokeCountMatcher(4)).method("add").withAnyArguments().will(
101                 new ListAppendStub(windows));
102         
103 
104         PortletWindow window = windowAccess.getPortletWindow(f1);
105         assertNotNull(window);
106         assertEquals("frag1", window.getId().toString());
107 
108         // Make sure the portlet entity's window list got updated
109         assertEquals(1, windows.size());
110 
111         PortletWindow windowInList = (PortletWindow) windows.get(0);
112 
113         // The window in the entities list should be the same as the one
114         // returned by getPortletWindow(f1)
115         assertEquals(windowInList, window);
116 
117         // remove the window
118         windowAccess.removeWindow(window);
119 
120         // Calling this after a remove go through th procedure of adding a newly
121         // created window
122         // back the portlet entity's list. We check this through vefirying calls
123         // to our mocks
124         windowAccess.getPortletWindow(f1);
125         
126         // Test same remove but via entity
127         windowAccess.removeWindow(window);              
128 
129         assertNotNull(windowAccess.getPortletWindow(f1));                
130         
131         windowListMock.expects(new InvokeOnceMatcher()).method("iterator").withNoArguments().will(new ReturnStub(windows.iterator()));
132 
133 /*        
134         windowAccess.removeWindows(entity);  
135         
136         windowAccess.getPortletWindow(f1);
137         // Double that second call bypasses creating a new window
138         //windowAccess.getPortletWindow(f1);
139         
140         windowListMock.verify();         
141 */
142     }
143 
144     interface CompositeWindowList extends PortletWindowList, PortletWindowListCtrl
145     {
146 
147     }
148 
149     class ListAppendStub extends CustomStub
150     {
151        
152         List list;
153 
154         /***
155          * @param arg0
156          */
157         public ListAppendStub( List list )
158         {
159             super("Appends object to a list");
160             this.list = list;
161         }
162 
163         /***
164          * <p>
165          * invoke
166          * </p>
167          * 
168          * @see org.jmock.core.Stub#invoke(org.jmock.core.Invocation)
169          * @param arg0
170          * @return @throws
171          *         java.lang.Throwable
172          */
173         public Object invoke( Invocation invocation ) throws Throwable
174         {
175             list.add(invocation.parameterValues.get(0));
176             return null;
177         }
178     }
179 
180     /***
181      * Inline copy of InvokeCountMatcher from latest jMock Development Snapshot: 20050628-175146
182      * so we don't need to depend on their SNAPSHOT release anymore but can fallback on their 1.0.1 version.
183      * (doesn't seem they are going to release a new real version soon as it has been ages since 1.0.1 came out)
184      * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
185      *
186      */
187     private static class InvokeCountMatcher implements InvocationMatcher
188     {
189         private int invocationCount = 0;
190 
191         private int expectedCount;
192 
193         public InvokeCountMatcher(int expectedCount)
194         {
195             this.expectedCount = expectedCount;
196         }
197 
198         public boolean matches(Invocation invocation)
199         {
200             return getInvocationCount() < expectedCount;
201         }
202 
203         public void verify()
204         {
205             verifyHasBeenInvokedExactly(expectedCount);
206         }
207 
208         public boolean hasDescription()
209         {
210             return true;
211         }
212 
213         public StringBuffer describeTo(StringBuffer buffer)
214         {
215             return buffer.append("expected ").append(expectedCount).append(" times, invoked ").append(
216                             getInvocationCount()).append(" times");
217         }
218 
219         public int getInvocationCount()
220         {
221             return invocationCount;
222         }
223 
224         public boolean hasBeenInvoked()
225         {
226             return invocationCount > 0;
227         }
228 
229         public void invoked(Invocation invocation)
230         {
231             invocationCount++;
232         }
233 
234         public void verifyHasBeenInvoked()
235         {
236             Assert.assertTrue("expected method was not invoked", hasBeenInvoked());
237         }
238 
239         public void verifyHasBeenInvokedExactly(int expectedCount)
240         {
241             Assert.assertTrue("expected method was not invoked the expected number of times: expected " + expectedCount
242                             + " times, was invoked " + invocationCount + " times", invocationCount == expectedCount);
243         }
244 
245     }
246 }