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.web.portlet;
018
019import static org.junit.jupiter.api.Assertions.assertEquals;
020import static org.junit.jupiter.api.Assertions.assertFalse;
021import static org.junit.jupiter.api.Assertions.assertInstanceOf;
022import static org.junit.jupiter.api.Assertions.assertNotEquals;
023import static org.junit.jupiter.api.Assertions.assertNotNull;
024import static org.junit.jupiter.api.Assertions.assertNull;
025import static org.junit.jupiter.api.Assertions.assertTrue;
026import static org.junit.jupiter.api.Assertions.fail;
027
028import java.util.Collection;
029import java.util.Collections;
030import java.util.HashMap;
031import java.util.Iterator;
032import java.util.Map;
033import java.util.Map.Entry;
034import java.util.Set;
035
036import javax.portlet.PortletContext;
037import javax.portlet.PortletRequest;
038import javax.portlet.PortletResponse;
039import javax.portlet.PortletSession;
040import javax.servlet.http.Cookie;
041
042import org.apache.commons.chain.Context;
043import org.apache.commons.chain.web.ContextBaseTestWeb;
044import org.apache.commons.chain.web.javax.portlet.PortletWebContext;
045import org.junit.jupiter.api.AfterEach;
046import org.junit.jupiter.api.BeforeEach;
047import org.junit.jupiter.api.Test;
048
049/**
050 * Extension of {@code ContextBaseTestCase} to validate the
051 * extra functionality of this implementation.
052 */
053public class PortletWebContextTestCase extends ContextBaseTestWeb<PortletWebContext> {
054
055    // ----------------------------------------------------- Instance Variables
056
057    /**
058     * Portlet API Objects - Context
059     */
060    protected PortletContext pcontext = null;
061
062    /**
063     * Portlet API Objects - Request
064     */
065    protected PortletRequest request = null;
066
067    /**
068     * Portlet API Objects - Response
069     */
070
071    protected PortletResponse response = null;
072
073    /**
074     * Portlet API Objects - Session
075     */
076    protected PortletSession session = null;
077
078    // ---------------------------------------------------------- Constructors
079
080    /**
081     * The Default-Constructor for this class.
082     */
083    public PortletWebContextTestCase() {
084    }
085
086    // -------------------------------------------------- Overall Test Methods
087
088    /**
089     * Set up instance variables required by this test case.
090     */
091    @Override
092    @BeforeEach
093    public void init() {
094        pcontext = new MockPortletContext();
095        pcontext.setAttribute("akey1", "avalue1");
096        pcontext.setAttribute("akey2", "avalue2");
097        pcontext.setAttribute("akey3", "avalue3");
098        pcontext.setAttribute("akey4", "avalue4");
099        ((MockPortletContext) pcontext).addInitParameter("ikey1", "ivalue1");
100        ((MockPortletContext) pcontext).addInitParameter("ikey2", "ivalue2");
101        ((MockPortletContext) pcontext).addInitParameter("ikey3", "ivalue3");
102        session = new MockPortletSession(pcontext);
103        session.setAttribute("skey1", "svalue1");
104        session.setAttribute("skey2", "svalue2");
105        session.setAttribute("skey3", "svalue3");
106        request = new MockPortletRequest(null, pcontext, session);
107        request.setAttribute("rkey1", "rvalue1");
108        request.setAttribute("rkey2", "rvalue2");
109        ((MockPortletRequest) request).addParameter("pkey1", "pvalue1");
110        ((MockPortletRequest) request).addParameter("pkey2", "pvalue2a");
111        ((MockPortletRequest) request).addParameter("pkey2", "pvalue2b");
112        context = createContext();
113    }
114
115    /**
116     * Tear down instance variables required by this test case.
117     */
118    @Override
119    @AfterEach
120    public void tearDown() {
121        pcontext = null;
122        session = null;
123        request = null;
124        response = null;
125        context = null;
126    }
127
128    // ------------------------------------------------ Individual Test Methods
129
130    /**
131     * Test {@code getApplicationScope()}
132     */
133    @Test
134    public void testApplicationScope() {
135        Map<String, Object> map = context.getApplicationScope();
136        assertNotNull(map);
137
138        // Initial contents
139        checkMapSize(map, 4);
140        assertEquals("avalue1", map.get("akey1"));
141        assertEquals("avalue2", map.get("akey2"));
142        assertEquals("avalue3", map.get("akey3"));
143        assertEquals("avalue4", map.get("akey4"));
144
145        // Transparency - entrySet()
146        checkEntrySet(map, true);
147
148        // Transparency - removal via web object
149        pcontext.removeAttribute("akey1");
150        checkMapSize(map, 3);
151        assertNull(map.get("akey1"));
152
153        // Transparency - removal via map
154        map.remove("akey2");
155        checkMapSize(map, 2);
156        assertNull(pcontext.getAttribute("akey2"));
157
158        // Transparency - addition via web object
159        pcontext.setAttribute("akeyA", "avalueA");
160        checkMapSize(map, 3);
161        assertEquals("avalueA", map.get("akeyA"));
162
163        // Transparency - addition via map
164        map.put("akeyB", "avalueB");
165        checkMapSize(map, 4);
166        assertEquals("avalueB", pcontext.getAttribute("akeyB"));
167
168        // Transparency - replacement via web object
169        pcontext.setAttribute("akeyA", "newvalueA");
170        checkMapSize(map, 4);
171        assertEquals("newvalueA", map.get("akeyA"));
172
173        // Transparency - replacement via map
174        map.put("akeyB", "newvalueB");
175        assertEquals(4, map.size());
176        assertEquals("newvalueB", pcontext.getAttribute("akeyB"));
177
178        // Clearing the map
179        map.clear();
180        checkMapSize(map, 0);
181
182        // Test putAll()
183        Map<String, String> values = new HashMap<>();
184        values.put("1", "One");
185        values.put("2", "Two");
186        map.putAll(values);
187        assertEquals("One", map.get("1"), "putAll(1)");
188        assertEquals("Two", map.get("2"), "putAll(2)");
189        checkMapSize(map, 2);
190    }
191
192    /**
193     * Test {@code equals()} and {@code hashCode()}
194     * Copied from ContextBaseTestCase with customized creation of "other"
195     */
196    @Override
197    @Test
198    public void testEquals() {
199        // Compare to self
200        assertTrue(context.equals(context));
201        assertEquals(context.hashCode(), context.hashCode());
202
203        // Compare to equivalent instance
204        Context other = new PortletWebContext(pcontext, request, response);
205        // assertTrue(context.equals(other));
206        assertEquals(context.hashCode(), other.hashCode());
207
208        // Compare to non-equivalent instance - other modified
209        other.put("bop", "bop value");
210        // assertFalse(context.equals(other));
211        assertNotEquals(context.hashCode(), other.hashCode());
212
213        // Compare to non-equivalent instance - self modified
214        other = new PortletWebContext(pcontext, request, response);
215        context.put("bop", "bop value");
216        // assertFalse(context.equals(other));
217        assertNotEquals(context.hashCode(), other.hashCode());
218    }
219
220    /**
221     * Test {@code getHeader()}
222     */
223    @Test
224    public void testHeader() {
225        Map<String, String> map = context.getHeader();
226        assertNotNull(map, "Header Map Null");
227
228        // Initial contents
229        checkMapSize(map, 0);
230
231        try {
232            map.put("hkey3", "hvalue3");
233            fail("Should have thrown UnsupportedOperationException");
234        } catch (UnsupportedOperationException e) {
235            ; // expected result
236        }
237    }
238
239    /**
240     * Test {@code getHeaderValues()}
241     */
242    @Test
243    public void testHeaderValues() {
244        Map<String, String[]> map = context.getHeaderValues();
245        assertNotNull(map, "HeaderValues Map Null");
246
247        // Initial contents
248        checkMapSize(map, 0);
249
250        try {
251            map.put("hkey3", new String[] {"ABC"});
252            fail("Should have thrown UnsupportedOperationException");
253        } catch (UnsupportedOperationException e) {
254            ; // expected result
255        }
256    }
257
258    /**
259     * Test {@code getInitParam()}
260     */
261    @Test
262    public void testInitParam() {
263        Map<String, String> map = context.getInitParam();
264        assertNotNull(map);
265
266        // Initial contents
267        checkMapSize(map, 3);
268        assertEquals("ivalue1", map.get("ikey1"));
269        assertEquals("ivalue2", map.get("ikey2"));
270        assertEquals("ivalue3", map.get("ikey3"));
271        assertTrue(map.containsKey("ikey1"));
272        assertTrue(map.containsKey("ikey2"));
273        assertTrue(map.containsKey("ikey3"));
274        assertTrue(map.containsValue("ivalue1"));
275        assertTrue(map.containsValue("ivalue2"));
276        assertTrue(map.containsValue("ivalue3"));
277
278        // Transparency - entrySet()
279        checkEntrySet(map, false);
280
281        // Unsupported operations on read-only map
282        try {
283            map.clear();
284            fail("Should have thrown UnsupportedOperationException");
285        } catch (UnsupportedOperationException e) {
286            ; // expected result
287        }
288        try {
289            map.put("ikey4", "ivalue4");
290            fail("Should have thrown UnsupportedOperationException");
291        } catch (UnsupportedOperationException e) {
292            ; // expected result
293        }
294        try {
295            map.putAll(new HashMap<>());
296            fail("Should have thrown UnsupportedOperationException");
297        } catch (UnsupportedOperationException e) {
298            ; // expected result
299        }
300        try {
301            map.remove("ikey1");
302            fail("Should have thrown UnsupportedOperationException");
303        } catch (UnsupportedOperationException e) {
304            ; // expected result
305        }
306    }
307
308    /**
309     * Test {@code getParam()}
310     */
311    @Test
312    public void testParam() {
313        Map<String, String> map = context.getParam();
314        assertNotNull(map);
315
316        // Initial contents
317        checkMapSize(map, 2);
318        assertEquals("pvalue1", map.get("pkey1"));
319        assertEquals("pvalue2a", map.get("pkey2"));
320        assertTrue(map.containsKey("pkey1"));
321        assertTrue(map.containsKey("pkey2"));
322        assertTrue(map.containsValue("pvalue1"));
323        assertTrue(map.containsValue("pvalue2a"));
324
325        checkEntrySet(map, false);
326
327        // Unsupported operations on read-only map
328        try {
329            map.clear();
330            fail("Should have thrown UnsupportedOperationException");
331        } catch (UnsupportedOperationException e) {
332            ; // expected result
333        }
334        try {
335            map.put("pkey3", "pvalue3");
336            fail("Should have thrown UnsupportedOperationException");
337        } catch (UnsupportedOperationException e) {
338            ; // expected result
339        }
340        try {
341            map.putAll(new HashMap<>());
342            fail("Should have thrown UnsupportedOperationException");
343        } catch (UnsupportedOperationException e) {
344            ; // expected result
345        }
346        try {
347            map.remove("pkey1");
348            fail("Should have thrown UnsupportedOperationException");
349        } catch (UnsupportedOperationException e) {
350            ; // expected result
351        }
352    }
353
354    /**
355     * Test {@code getParamValues()}
356     */
357    @Test
358    public void testParamValues() {
359        Map<String, String[]> map = context.getParamValues();
360        assertNotNull(map);
361
362        // Initial contents
363        checkMapSize(map, 2);
364        Object value1 = map.get("pkey1");
365        assertNotNull(value1);
366        assertInstanceOf(String[].class, value1);
367        String values1[] = (String[]) value1;
368        assertEquals(1, values1.length);
369        assertEquals("pvalue1", values1[0]);
370        Object value2 = map.get("pkey2");
371        assertNotNull(value2);
372        assertInstanceOf(String[].class, value2);
373        String values2[] = (String[]) value2;
374        assertEquals(2, values2.length);
375        assertEquals("pvalue2a", values2[0]);
376        assertEquals("pvalue2b", values2[1]);
377        assertTrue(map.containsKey("pkey1"));
378        assertTrue(map.containsKey("pkey2"));
379        assertTrue(map.containsValue(values1));
380        assertTrue(map.containsValue(values2));
381
382        // Unsupported operations on read-only map
383        try {
384            map.clear();
385            fail("Should have thrown UnsupportedOperationException");
386        } catch (UnsupportedOperationException e) {
387            ; // expected result
388        }
389        try {
390            map.put("pkey3", values2);
391            fail("Should have thrown UnsupportedOperationException");
392        } catch (UnsupportedOperationException e) {
393            ; // expected result
394        }
395        try {
396            map.putAll(new HashMap<>());
397            fail("Should have thrown UnsupportedOperationException");
398        } catch (UnsupportedOperationException e) {
399            ; // expected result
400        }
401        try {
402            map.remove("pkey1");
403            fail("Should have thrown UnsupportedOperationException");
404        } catch (UnsupportedOperationException e) {
405            ; // expected result
406        }
407    }
408
409    /**
410     * Test {@code getCookies()}
411     */
412    @Test
413    public void testCookies() {
414        Map<String, Cookie> map = context.getCookies();
415        assertNotNull(map);
416
417        // Initial contents
418        checkMapSize(map, 0);
419
420        try {
421            map.put("ckey3", new Cookie("XXX", "XXX"));
422            fail("map.put() Should have thrown UnsupportedOperationException");
423        } catch (UnsupportedOperationException e) {
424            ; // expected result
425        }
426    }
427
428    /**
429     * Test state of newly created instance
430     */
431    @Override
432    @Test
433    public void testPristine() {
434        super.testPristine();
435
436        // Properties should all be non-null
437        assertNotNull(context.getApplicationScope());
438        assertNotNull(context.getHeader());
439        assertNotNull(context.getHeaderValues());
440        assertNotNull(context.getInitParam());
441        assertNotNull(context.getParam());
442        assertNotNull(context.getParamValues());
443        assertNotNull(context.getCookies());
444        assertNotNull(context.getRequestScope());
445        assertNotNull(context.getSessionScope());
446
447        // Attribute-property transparency
448        assertTrue(context.getApplicationScope() ==
449                     context.get("applicationScope"));
450        assertTrue(context.getHeader() ==
451                     context.get("header"));
452        assertTrue(context.getHeaderValues() ==
453                     context.get("headerValues"));
454        assertTrue(context.getInitParam() ==
455                     context.get("initParam"));
456        assertTrue(context.getParam() ==
457                     context.get("param"));
458        assertTrue(context.getParamValues() ==
459                     context.get("paramValues"));
460        assertTrue(context.getCookies() ==
461                     context.get("cookies"));
462        assertTrue(context.getRequestScope() ==
463                     context.get("requestScope"));
464        assertTrue(context.getSessionScope() ==
465                     context.get("sessionScope"));
466    }
467
468    /**
469     * Test {@code release()}
470     */
471    @Test
472    public void testRelease() {
473        context.release();
474
475        // Properties should all be null
476        assertNull(context.getApplicationScope(), "getApplicationScope()");
477        assertNull(context.getHeader(), "getHeader()");
478        assertNull(context.getHeaderValues(), "getHeaderValues()");
479        assertNull(context.getInitParam(), "getInitParam()");
480        assertNull(context.getParam(), "getParam()");
481        assertNull(context.getParamValues(), "getParamValues()");
482        assertNull(context.getRequestScope(), "getRequestScope()");
483        assertNull(context.getSessionScope(), "getSessionScope()");
484
485        // Attributes should all be null
486        assertNull(context.get("applicationScope"), "applicationScope");
487        assertNull(context.get("header"), "header");
488        assertNull(context.get("headerValues"), "headerValues");
489        assertNull(context.get("initParam"), "initParam");
490        assertNull(context.get("param"), "param");
491        assertNull(context.get("paramValues"), "paramValues");
492        assertNull(context.get("requestScope"), "requestScope");
493        assertNull(context.get("sessionScope"), "sessionScope");
494    }
495
496    /**
497     * Test {@code getRequestScope()}
498     */
499    @Test
500    public void testRequestScope() {
501        Map<String, Object> map = context.getRequestScope();
502        assertNotNull(map);
503
504        // Initial contents
505        checkMapSize(map, 2);
506        assertEquals("rvalue1", map.get("rkey1"));
507        assertEquals("rvalue2", map.get("rkey2"));
508
509        // Transparency - entrySet()
510        checkEntrySet(map, true);
511
512        // Transparency - removal via web object
513        request.removeAttribute("rkey1");
514        checkMapSize(map, 1);
515        assertNull(map.get("rkey1"));
516
517        // Transparency - removal via map
518        map.remove("rkey2");
519        checkMapSize(map, 0);
520        assertNull(request.getAttribute("rkey2"));
521
522        // Transparency - addition via web object
523        request.setAttribute("rkeyA", "rvalueA");
524        checkMapSize(map, 1);
525        assertEquals("rvalueA", map.get("rkeyA"));
526
527        // Transparency - addition via map
528        map.put("rkeyB", "rvalueB");
529        checkMapSize(map, 2);
530        assertEquals("rvalueB", request.getAttribute("rkeyB"));
531
532        // Transparency - replacement via web object
533        request.setAttribute("rkeyA", "newvalueA");
534        checkMapSize(map, 2);
535        assertEquals("newvalueA", map.get("rkeyA"));
536
537        // Transparency - replacement via map
538        map.put("rkeyB", "newvalueB");
539        checkMapSize(map, 2);
540        assertEquals("newvalueB", request.getAttribute("rkeyB"));
541
542        // Clearing the map
543        map.clear();
544        checkMapSize(map, 0);
545
546        // Test putAll()
547        Map<String, String> values = new HashMap<>();
548        values.put("1", "One");
549        values.put("2", "Two");
550        map.putAll(values);
551        assertEquals("One", map.get("1"), "putAll(1)");
552        assertEquals("Two", map.get("2"), "putAll(2)");
553        checkMapSize(map, 2);
554    }
555
556    /**
557     * Test {@code getSessionScope()}
558     */
559    @Test
560    public void testSessionScope() {
561        Map<String, Object> map = context.getSessionScope();
562        assertNotNull(map);
563
564        // Initial contents
565        checkMapSize(map, 3);
566        assertEquals("svalue1", map.get("skey1"));
567        assertEquals("svalue2", map.get("skey2"));
568        assertEquals("svalue3", map.get("skey3"));
569
570        // Transparency - entrySet()
571        checkEntrySet(map, true);
572
573        // Transparency - removal via web object
574        session.removeAttribute("skey1");
575        checkMapSize(map, 2);
576        assertNull(map.get("skey1"));
577
578        // Transparency - removal via map
579        map.remove("skey2");
580        checkMapSize(map, 1);
581        assertNull(session.getAttribute("skey2"));
582
583        // Transparency - addition via web object
584        session.setAttribute("skeyA", "svalueA");
585        checkMapSize(map, 2);
586        assertEquals("svalueA", map.get("skeyA"));
587
588        // Transparency - addition via map
589        map.put("skeyB", "svalueB");
590        checkMapSize(map, 3);
591        assertEquals("svalueB", session.getAttribute("skeyB"));
592
593        // Transparency - replacement via web object
594        session.setAttribute("skeyA", "newvalueA");
595        checkMapSize(map, 3);
596        assertEquals("newvalueA", map.get("skeyA"));
597
598        // Transparency - replacement via map
599        map.put("skeyB", "newvalueB");
600        checkMapSize(map, 3);
601        assertEquals("newvalueB", session.getAttribute("skeyB"));
602
603        // Clearing the map
604        map.clear();
605        checkMapSize(map, 0);
606
607        // Test putAll()
608        Map<String, String> values = new HashMap<>();
609        values.put("1", "One");
610        values.put("2", "Two");
611        map.putAll(values);
612        assertEquals("One", map.get("1"), "putAll(1)");
613        assertEquals("Two", map.get("2"), "putAll(2)");
614        checkMapSize(map, 2);
615    }
616
617    /**
618     * Test {@code getSessionScope()} without Session
619     */
620    @Test
621    public void testSessionScopeWithoutSession() {
622        // Create a Context without a session
623        PortletWebContext ctx = new PortletWebContext(pcontext,
624           new MockPortletRequest(), response);
625        assertNull(ctx.getRequest().getPortletSession(false), "Session(A)");
626
627        // Get the session Map & check session doesn't exist
628        Map<String, Object> sessionMap = ctx.getSessionScope();
629        assertNull(ctx.getRequest().getPortletSession(false), "Session(B)");
630        assertNotNull(sessionMap, "Session Map(A)");
631
632        // test clear()
633        sessionMap.clear();
634        assertNull(ctx.getRequest().getPortletSession(false), "Session(C)");
635
636        // test containsKey()
637        assertFalse(sessionMap.containsKey("ABC"), "containsKey()");
638        assertNull(ctx.getRequest().getPortletSession(false), "Session(D)");
639
640        // test containsValue()
641        assertFalse(sessionMap.containsValue("ABC"), "containsValue()");
642        assertNull(ctx.getRequest().getPortletSession(false), "Session(E)");
643
644        // test entrySet()
645        Set<Entry<String, Object>> entrySet = sessionMap.entrySet();
646        assertNotNull(entrySet, "entrySet");
647        assertEquals(0, entrySet.size(), "entrySet Size");
648        assertNull(ctx.getRequest().getPortletSession(false), "Session(F)");
649
650        // test equals()
651        assertFalse(sessionMap.equals(Collections.singletonMap("ABC", "ABC")), "equals()");
652        assertNull(ctx.getRequest().getPortletSession(false), "Session(G)");
653
654        // test get()
655        assertNull(sessionMap.get("ABC"), "get()");
656        assertNull(ctx.getRequest().getPortletSession(false), "Session(H)");
657
658        // test hashCode()
659        sessionMap.hashCode();
660        assertNull(ctx.getRequest().getPortletSession(false), "Session(I)");
661
662        // test isEmpty()
663        assertTrue(sessionMap.isEmpty(), "isEmpty()");
664        assertNull(ctx.getRequest().getPortletSession(false), "Session(J)");
665
666        // test keySet()
667        Set<String> keySet = sessionMap.keySet();
668        assertNotNull(keySet, "keySet");
669        assertEquals(0, keySet.size(), "keySet Size");
670        assertNull(ctx.getRequest().getPortletSession(false), "Session(K)");
671
672        // test putAll() with an empty Map
673        sessionMap.putAll(new HashMap<>());
674        assertNull(ctx.getRequest().getPortletSession(false), "Session(L)");
675
676        // test remove()
677        assertNull(sessionMap.remove("ABC"), "remove()");
678        assertNull(ctx.getRequest().getPortletSession(false), "Session(M)");
679
680        // test size()
681        assertEquals(0, sessionMap.size(), "size() Size");
682        assertNull(ctx.getRequest().getPortletSession(false), "Session(N)");
683
684        // test values()
685        Collection<Object> values = sessionMap.values();
686        assertNotNull(values, "values");
687        assertEquals(0, values.size(), "values Size");
688        assertNull(ctx.getRequest().getPortletSession(false), "Session(O)");
689
690        // test put()
691        try {
692            assertNull(sessionMap.put("ABC", "XYZ"), "put()");
693            assertNotNull(ctx.getRequest().getPortletSession(false), "Session(P)");
694        } catch(UnsupportedOperationException ex) {
695            // expected: currently MockPortletRequest throws this
696            //           when trying to create a PortletSession
697        }
698    }
699
700    // ------------------------------------------------------- Protected Methods
701
702    protected void checkMapSize(Map<String, ?> map, int size) {
703        // Check reported size of the map
704        assertEquals(size, map.size(), "checkMapSize(A)");
705        // Iterate over key set
706        int nk = 0;
707        Iterator<String> keys = map.keySet().iterator();
708        while (keys.hasNext()) {
709            keys.next();
710            nk++;
711        }
712        assertEquals(size, nk, "checkMapSize(B)");
713        // Iterate over entry set
714        int nv = 0;
715        Iterator<?> values = map.entrySet().iterator();
716        while (values.hasNext()) {
717            values.next();
718            nv++;
719        }
720        assertEquals(size, nv, "checkMapSize(C)");
721        // Count the values
722        assertEquals(size, map.values().size(), "checkMapSize(D)");
723    }
724
725    /**
726     * Test to ensure proper {@code entrySet()} and are modifiable optionally
727     *
728     * @param map to test
729     * @param modifiable {@code true} map is modifiable
730     */
731    protected void checkEntrySet(Map<String, ?> map, boolean modifiable) {
732        assertTrue(map.size() > 1, "checkEntrySet(A)");
733        Set<?> entries = map.entrySet();
734        assertTrue(map.size() == entries.size());
735        Object o = entries.iterator().next();
736
737        assertInstanceOf(Map.Entry.class, o, "checkEntrySet(B)");
738
739        @SuppressWarnings("unchecked")
740        Map.Entry<?, Object> mapEntry = (Map.Entry<?, Object>)o;
741        if (!modifiable) {
742            try {
743                mapEntry.setValue(new Object());
744                fail("Should have thrown UnsupportedOperationException");
745            } catch (UnsupportedOperationException e) {
746                ; // expected result
747            }
748        } else {
749            // Should pass and not throw UnsupportedOperationException
750            mapEntry.setValue(mapEntry.setValue(new Object()));
751        }
752    }
753
754    /**
755     * Create a new instance of the appropriate Context type for this test case
756     *
757     * @return new instance of the appropriate Context type
758     */
759    @Override
760    protected PortletWebContext createContext() {
761        return new PortletWebContext(pcontext, request, response);
762    }
763}