View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.testing.framework;
29  
30  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.BODY;
31  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.CONTENT_TYPE;
32  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.HEADERS;
33  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.METHOD;
34  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.NAME;
35  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.PATH;
36  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.PROTOCOL_VERSION;
37  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.QUERY;
38  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.REQUEST;
39  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.RESPONSE;
40  import static org.apache.hc.core5.testing.framework.ClientPOJOAdapter.STATUS;
41  
42  import java.util.HashMap;
43  import java.util.HashSet;
44  import java.util.Map;
45  import java.util.Set;
46  
47  import org.apache.hc.core5.http.ContentType;
48  import org.apache.hc.core5.http.HttpVersion;
49  import org.apache.hc.core5.http.ProtocolVersion;
50  import org.hamcrest.BaseMatcher;
51  import org.hamcrest.Description;
52  import org.hamcrest.Matcher;
53  import org.junit.Assert;
54  import org.junit.Test;
55  import org.mockito.ArgumentMatchers;
56  import org.mockito.Mockito;
57  
58  public class TestTestingFramework {
59  
60      @Test
61      public void ensureDefaultMapsUnmodifiable() throws Exception {
62          assertUnmodifiable(TestingFramework.DEFAULT_REQUEST_QUERY);
63          assertUnmodifiable(TestingFramework.DEFAULT_RESPONSE_HEADERS);
64      }
65  
66      private void assertUnmodifiable(final Map<String, String> map) {
67          final String aKey = (String) map.keySet().toArray()[0];
68          try {
69              map.remove(aKey);
70              Assert.fail("UnsupportedOperationException should have been thrown.");
71          } catch (final UnsupportedOperationException e) {
72              // expected
73          }
74      }
75  
76      private TestingFramework newWebServerTestingFramework(final ClientTestingAdapter adapter)
77              throws TestingFrameworkException {
78          final TestingFramework framework = new TestingFramework(adapter);
79          // get rid of the default tests.
80          framework.deleteTests();
81  
82          return framework;
83      }
84  
85      private TestingFramework newWebServerTestingFramework() throws TestingFrameworkException {
86          return newWebServerTestingFramework(null); // null adapter
87      }
88  
89      @Test
90      public void runTestsWithoutSettingAdapterThrows() throws Exception {
91          final TestingFramework framework = newWebServerTestingFramework();
92          try {
93              framework.runTests();
94              Assert.fail("WebServerTestingFrameworkException should have been thrown");
95          } catch (final TestingFrameworkException e) {
96              // expected
97          }
98      }
99  
100     @Test
101     public void nullAdapterThrows() throws Exception {
102         final ClientTestingAdapter adapter = null;
103 
104         final TestingFramework framework = newWebServerTestingFramework(adapter);
105         try {
106             framework.runTests();
107             Assert.fail("WebServerTestingFrameworkException should have been thrown");
108         } catch (final TestingFrameworkException e) {
109             // expected
110         }
111     }
112 
113     @Test
114     public void nullSetAdapterThrows() throws Exception {
115         final ClientTestingAdapter adapter = null;
116 
117         final TestingFramework framework = newWebServerTestingFramework(adapter);
118         framework.setAdapter(adapter);
119         try {
120             framework.runTests();
121             Assert.fail("WebServerTestingFrameworkException should have been thrown");
122         } catch (final TestingFrameworkException e) {
123             // expected
124         }
125     }
126 
127     @Test
128     public void goodAdapterWithConstructor() throws Exception {
129         final ClientTestingAdapter adapter = Mockito.mock(ClientTestingAdapter.class);
130 
131         // Have isRequestSupported() return false so no test will run.
132         Mockito.when(adapter.isRequestSupported(ArgumentMatchers.<String, Object>anyMap()))
133                      .thenReturn(false);
134 
135         final TestingFramework framework = newWebServerTestingFramework(adapter);
136 
137         framework.runTests();
138 
139         // since there are no tests, callMethod should not be called.
140         verifyCallMethodNeverCalled(adapter);
141     }
142 
143     private void verifyCallMethodNeverCalled(final ClientTestingAdapter adapter) throws Exception {
144         Mockito.verify(adapter, Mockito.never()).execute(ArgumentMatchers.anyString(), ArgumentMatchers.<String, Object>anyMap(),
145                        ArgumentMatchers.any(TestingFrameworkRequestHandler.class), ArgumentMatchers.<String, Object>anyMap());
146     }
147 
148     private TestingFramework newFrameworkAndSetAdapter(final ClientTestingAdapter adapter)
149             throws TestingFrameworkException {
150         final TestingFramework framework = new TestingFramework();
151         framework.setAdapter(adapter);
152 
153         // get rid of the default tests.
154         framework.deleteTests();
155 
156         return framework;
157     }
158 
159     @Test
160     public void goodAdapterWithSetter() throws Exception {
161         final ClientTestingAdapter adapter = Mockito.mock(ClientTestingAdapter.class);
162 
163         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
164 
165         framework.runTests();
166 
167         // since there are no tests, callMethod should not be called.
168         verifyCallMethodNeverCalled(adapter);
169     }
170 
171     @Test
172     public void addTest() throws Exception {
173         final TestingFrameworkRequestHandler mockRequestHandler = Mockito.mock(TestingFrameworkRequestHandler.class);
174 
175         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
176             @Override
177             public Map<String, Object> execute(
178                                    final String defaultURI,
179                                    final Map<String, Object> request,
180                                    final TestingFrameworkRequestHandler requestHandler,
181                                    final Map<String, Object> responseExpectations) throws TestingFrameworkException {
182                 Assert.assertThat(defaultURI, matchesDefaultURI());
183 
184                 Assert.assertNotNull("request should not be null", request);
185 
186                 // The request should be equal to the default request.
187                 final Map<String, Object> defaultRequest = new FrameworkTest().initRequest();
188                 Assert.assertEquals("The request does not match the default", defaultRequest, request);
189 
190                 Assert.assertSame("The request handler should have been passed to the adapter",
191                                   mockRequestHandler, requestHandler);
192 
193                 // The responseExpectations should be equal to the default.
194                 final Map<String, Object> defaultResponseExpectations = new FrameworkTest().initResponseExpectations();
195                 Assert.assertEquals("The responseExpectations do not match the defaults",
196                                     defaultResponseExpectations, responseExpectations);
197 
198                 final Map<String, Object> response = new HashMap<>();
199                 response.put(STATUS, responseExpectations.get(STATUS));
200                 response.put(BODY, responseExpectations.get(BODY));
201                 response.put(CONTENT_TYPE, responseExpectations.get(CONTENT_TYPE));
202                 response.put(HEADERS, responseExpectations.get(HEADERS));
203                 return response;
204             }
205         };
206 
207         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
208         framework.setRequestHandler(mockRequestHandler);
209 
210         framework.addTest();
211 
212         framework.runTests();
213 
214         // assertNothingThrown() should have been called.
215         Mockito.verify(mockRequestHandler).assertNothingThrown();
216     }
217 
218     private Matcher<String> matchesDefaultURI() {
219         final Matcher<String> matcher = new BaseMatcher<String>() {
220             private final String regex = "http://localhost:\\d+/";
221 
222             @Override
223             public boolean matches(final Object o) {
224                 return ((String) o).matches(regex);
225             }
226 
227             @Override
228             public void describeTo(final Description description) {
229                 description.appendText("matches regex=" + regex);
230             }
231         };
232 
233         return matcher;
234     }
235 
236     @Test
237     public void statusCheck() throws Exception {
238         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
239             @Override
240             public Map<String, Object> execute(
241                                    final String defaultURI,
242                                    final Map<String, Object> request,
243                                    final TestingFrameworkRequestHandler requestHandler,
244                                    final Map<String, Object> responseExpectations) {
245 
246                 Assert.assertEquals(200, responseExpectations.get(STATUS));
247 
248                 // return a different status than expected.
249                 final Map<String, Object> response = new HashMap<>();
250                 response.put(STATUS, 201);
251                 return response;
252             }
253         };
254 
255         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
256 
257         framework.addTest();
258 
259         try {
260             framework.runTests();
261             Assert.fail("WebServerTestingFrameworkException should have been thrown");
262         } catch (final TestingFrameworkException e) {
263             // expected
264         }
265     }
266 
267     private Map<String, Object> alreadyCheckedResponse() {
268         // return an indication that the response has already been checked.
269         final Map<String, Object> response = new HashMap<>();
270         response.put(STATUS, TestingFramework.ALREADY_CHECKED);
271         response.put(BODY, TestingFramework.ALREADY_CHECKED);
272         response.put(CONTENT_TYPE, TestingFramework.ALREADY_CHECKED);
273         response.put(HEADERS, TestingFramework.ALREADY_CHECKED);
274         return response;
275     }
276 
277     @Test
278     public void responseAlreadyChecked() throws Exception {
279             final ClientTestingAdapter adapter = new ClientTestingAdapter() {
280             @Override
281             public Map<String, Object> execute(
282                                    final String defaultURI,
283                                    final Map<String, Object> request,
284                                    final TestingFrameworkRequestHandler requestHandler,
285                                    final Map<String, Object> responseExpectations) {
286 
287                 return alreadyCheckedResponse();
288             }
289         };
290 
291         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
292 
293         framework.addTest();
294 
295         framework.runTests();
296     }
297 
298     @Test
299     public void bodyCheck() throws Exception {
300         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
301             @Override
302             public Map<String, Object> execute(
303                                    final String defaultURI,
304                                    final Map<String, Object> request,
305                                    final TestingFrameworkRequestHandler requestHandler,
306                                    final Map<String, Object> responseExpectations) {
307 
308                 Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_BODY, responseExpectations.get(BODY));
309 
310                 final Map<String, Object> response = new HashMap<>();
311                 response.put(STATUS, TestingFramework.ALREADY_CHECKED);
312 
313                 // return a different body than expected.
314                 response.put(BODY, TestingFramework.DEFAULT_RESPONSE_BODY + "junk");
315                 return response;
316             }
317         };
318 
319         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
320 
321         framework.addTest();
322 
323         try {
324             framework.runTests();
325             Assert.fail("WebServerTestingFrameworkException should have been thrown");
326         } catch (final TestingFrameworkException e) {
327             // expected
328         }
329     }
330 
331     @Test
332     public void responseContentTypeCheck() throws Exception {
333        final ClientTestingAdapter adapter = new ClientTestingAdapter() {
334             @Override
335             public Map<String, Object> execute(
336                                    final String defaultURI,
337                                    final Map<String, Object> request,
338                                    final TestingFrameworkRequestHandler requestHandler,
339                                    final Map<String, Object> responseExpectations) {
340 
341                 Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_CONTENT_TYPE, responseExpectations.get(CONTENT_TYPE));
342 
343                 final Map<String, Object> response = new HashMap<>();
344                 response.put(STATUS, TestingFramework.ALREADY_CHECKED);
345                 response.put(HEADERS, TestingFramework.ALREADY_CHECKED);
346 
347                 // return the expected body
348                 response.put(BODY, TestingFramework.DEFAULT_RESPONSE_BODY);
349                 // return a different content type than expected.
350                 response.put(CONTENT_TYPE, ContentType.DEFAULT_TEXT);
351                 return response;
352             }
353         };
354 
355         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
356 
357         framework.addTest();
358 
359         try {
360             framework.runTests();
361             Assert.fail("WebServerTestingFrameworkException should have been thrown");
362         } catch (final TestingFrameworkException e) {
363             // expected
364         }
365     }
366 
367     @Test
368     public void deepcopy() throws Exception {
369         // save a copy of the headers to make sure they haven't changed at the end of this test.
370         @SuppressWarnings("unchecked")
371         final Map<String, String> headersCopy = (Map<String, String>) TestingFramework.deepcopy(TestingFramework.DEFAULT_RESPONSE_HEADERS);
372         Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_HEADERS, headersCopy);
373 
374         final Map<String, Object> deepMap = new HashMap<>();
375         deepMap.put(HEADERS, TestingFramework.DEFAULT_RESPONSE_HEADERS);
376 
377         @SuppressWarnings("unchecked")
378         final Map<String, Object> deepMapCopy = (Map<String, Object>) TestingFramework.deepcopy(deepMap);
379         Assert.assertEquals(deepMap, deepMapCopy);
380 
381         @SuppressWarnings("unchecked")
382         final Map<String, String> headersMap = (Map<String, String>) deepMapCopy.get(HEADERS);
383         Assert.assertEquals(headersCopy, headersMap);
384 
385         // now make sure the default headers have not changed for some unexpected reason.
386         Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_HEADERS, headersCopy);
387     }
388 
389     @Test
390     public void removedHeaderCheck() throws Exception {
391         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
392             @Override
393             public Map<String, Object> execute(
394                                    final String defaultURI,
395                                    final Map<String, Object> request,
396                                    final TestingFrameworkRequestHandler requestHandler,
397                                    final Map<String, Object> responseExpectations) {
398 
399                 Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_HEADERS, responseExpectations.get(HEADERS));
400 
401                 @SuppressWarnings("unchecked")
402                 final Map<String, String> headersCopy = (Map<String, String>) deepcopy(responseExpectations.get(HEADERS));
403 
404                 // remove a header to force an error
405                 final String headerName = (String) headersCopy.keySet().toArray()[0];
406                 headersCopy.remove(headerName);
407 
408                 final Map<String, Object> response = new HashMap<>();
409                 response.put(STATUS, TestingFramework.ALREADY_CHECKED);
410                 response.put(BODY, TestingFramework.ALREADY_CHECKED);
411 
412                 // return different headers than expected.
413                 response.put(HEADERS, headersCopy);
414                 return response;
415             }
416         };
417 
418         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
419 
420         framework.addTest();
421 
422         try {
423             framework.runTests();
424             Assert.fail("WebServerTestingFrameworkException should have been thrown");
425         } catch (final TestingFrameworkException e) {
426             // expected
427         }
428     }
429 
430     @Test
431     public void changedHeaderCheck() throws Exception {
432         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
433             @Override
434             public Map<String, Object> execute(
435                                    final String defaultURI,
436                                    final Map<String, Object> request,
437                                    final TestingFrameworkRequestHandler requestHandler,
438                                    final Map<String, Object> responseExpectations) {
439 
440                 Assert.assertEquals(TestingFramework.DEFAULT_RESPONSE_HEADERS, responseExpectations.get(HEADERS));
441 
442                 @SuppressWarnings("unchecked")
443                 final Map<String, String> headersCopy = (Map<String, String>) deepcopy(responseExpectations.get(HEADERS));
444 
445                 // change a header to force an error
446                 final String headerName = (String) headersCopy.keySet().toArray()[0];
447                 headersCopy.put(headerName, headersCopy.get(headerName) + "junk");
448 
449                 final Map<String, Object> response = new HashMap<>();
450                 response.put(STATUS, TestingFramework.ALREADY_CHECKED);
451                 response.put(BODY, TestingFramework.ALREADY_CHECKED);
452 
453                 // return different headers than expected.
454                 response.put(HEADERS, headersCopy);
455                 return response;
456             }
457         };
458 
459         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
460 
461         framework.addTest();
462 
463         try {
464             framework.runTests();
465             Assert.fail("WebServerTestingFrameworkException should have been thrown");
466         } catch (final TestingFrameworkException e) {
467             // expected
468         }
469     }
470 
471     private Object deepcopy(final Object obj) {
472         try {
473             return TestingFramework.deepcopy(obj);
474         } catch (final Exception e) {
475             Assert.fail("deepcopy failed: " + e.getMessage());
476             return null;
477         }
478     }
479 
480     @Test
481     public void requestMethodUnexpected() throws Exception {
482         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
483             @Override
484             public Map<String, Object> execute(
485                     final String defaultURI,
486                     final Map<String, Object> request,
487                     final TestingFrameworkRequestHandler requestHandler,
488                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
489                 // change the request from what is expected.
490                 Assert.assertTrue(request.get(METHOD).equals("GET"));
491                 request.put(METHOD, "POST");
492                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
493             }
494         };
495 
496         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
497 
498         final Map<String, Object> test = new HashMap<>();
499         final Map<String, Object> request = new HashMap<>();
500         test.put(REQUEST, request);
501         request.put(NAME, "MyName");
502 
503         framework.addTest(test);
504 
505         try {
506             framework.runTests();
507             Assert.fail("WebServerTestingFrameworkException should have been thrown");
508         } catch (final TestingFrameworkException e) {
509             // expected
510 
511             // make sure the HTTP Client name is in the message.
512             final String message = e.getMessage();
513             final ClientPOJOAdapter pojoAdapter = adapter.getClientPOJOAdapter();
514             final String httpClientName = pojoAdapter == null ?
515                                           TestingFrameworkException.NO_HTTP_CLIENT :
516                                           pojoAdapter.getClientName();
517             Assert.assertTrue(
518                 "Message should contain httpClientName of " + httpClientName + "; message=" + message,
519                 message.contains(httpClientName));
520 
521             Assert.assertTrue(
522                 "Message should contain the test. message=" + message,
523                 message.contains("MyName"));
524         }
525     }
526 
527     @Test
528     public void status201() throws Exception {
529         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter();
530 
531         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
532 
533         final Map<String, Object> test = new HashMap<>();
534         final Map<String, Object> response = new HashMap<>();
535         test.put(RESPONSE, response);
536         response.put(STATUS, 201);
537 
538         framework.addTest(test);
539 
540         framework.runTests();
541     }
542 
543     @Test
544     public void deepcopyOfTest() throws Exception {
545         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
546 
547             @Override
548             public Map<String, Object> execute(
549                     final String defaultURI,
550                     final Map<String, Object> request,
551                     final TestingFrameworkRequestHandler requestHandler,
552                     final Map<String, Object> responseExpectations)
553                        throws TestingFrameworkException {
554                 Assert.assertEquals(201, responseExpectations.get(STATUS));
555                 return alreadyCheckedResponse();
556             }
557         };
558 
559         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
560 
561         final Map<String, Object> test = new HashMap<>();
562         final Map<String, Object> response = new HashMap<>();
563         test.put(RESPONSE, response);
564         response.put(STATUS, 201);
565 
566         framework.addTest(test);
567 
568         // Make sure the framework makes a copy of the test for itself.
569         // This put should be ignored by the framework.
570         response.put(STATUS, 300);
571 
572         framework.runTests();
573     }
574 
575     @Test
576     public void removeParameter() throws Exception {
577         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
578             @Override
579             public Map<String, Object> execute(
580                     final String defaultURI,
581                     final Map<String, Object> request,
582                     final TestingFrameworkRequestHandler requestHandler,
583                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
584                 // change the request from what is expected.
585                 @SuppressWarnings("unchecked")
586                 final Map<String, String> query = (Map<String, String>) request.get(QUERY);
587                 Assert.assertTrue(query.containsKey("p1"));
588                 query.remove("p1");
589                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
590             }
591         };
592 
593         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
594 
595         framework.addTest();
596 
597         try {
598             framework.runTests();
599             Assert.fail("WebServerTestingFrameworkException should have been thrown");
600         } catch (final TestingFrameworkException e) {
601             // expected
602         }
603     }
604 
605     @Test
606     public void changeParameter() throws Exception {
607         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
608             @Override
609             public Map<String, Object> execute(
610                     final String defaultURI,
611                     final Map<String, Object> request,
612                     final TestingFrameworkRequestHandler requestHandler,
613                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
614                 // change the request from what is expected.
615                 @SuppressWarnings("unchecked")
616                 final Map<String, String> query = (Map<String, String>) request.get(QUERY);
617                 Assert.assertTrue(query.containsKey("p1"));
618                 query.put("p1", query.get("p1") + "junk");
619                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
620             }
621         };
622 
623         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
624 
625         framework.addTest();
626 
627         try {
628             framework.runTests();
629             Assert.fail("WebServerTestingFrameworkException should have been thrown");
630         } catch (final TestingFrameworkException e) {
631             // expected
632         }
633     }
634 
635     @Test
636     public void removeHeader() throws Exception {
637         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
638             @Override
639             public Map<String, Object> execute(
640                     final String defaultURI,
641                     final Map<String, Object> request,
642                     final TestingFrameworkRequestHandler requestHandler,
643                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
644                 // change the request from what is expected.
645                 @SuppressWarnings("unchecked")
646                 final Map<String, String> headers = (Map<String, String>) request.get(HEADERS);
647                 Assert.assertTrue(headers.containsKey("header1"));
648                 headers.remove("header1");
649                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
650             }
651         };
652 
653         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
654 
655         framework.addTest();
656 
657         try {
658             framework.runTests();
659             Assert.fail("WebServerTestingFrameworkException should have been thrown");
660         } catch (final TestingFrameworkException e) {
661             // expected
662         }
663     }
664 
665     @Test
666     public void changeHeader() throws Exception {
667         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
668             @Override
669             public Map<String, Object> execute(
670                     final String defaultURI,
671                     final Map<String, Object> request,
672                     final TestingFrameworkRequestHandler requestHandler,
673                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
674                 // change the request from what is expected.
675                 @SuppressWarnings("unchecked")
676                 final Map<String, String> headers = (Map<String, String>) request.get(HEADERS);
677                 Assert.assertTrue(headers.containsKey("header1"));
678                 headers.put("header1", headers.get("header1") + "junk");
679                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
680             }
681         };
682 
683         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
684 
685         framework.addTest();
686 
687         try {
688             framework.runTests();
689             Assert.fail("WebServerTestingFrameworkException should have been thrown");
690         } catch (final TestingFrameworkException e) {
691             // expected
692         }
693     }
694 
695     @Test
696     public void changeBody() throws Exception {
697         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
698             @Override
699             public Map<String, Object> execute(
700                     final String defaultURI,
701                     final Map<String, Object> request,
702                     final TestingFrameworkRequestHandler requestHandler,
703                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
704                 // change the request from what is expected.
705                 final String body = (String) request.get(BODY);
706                 Assert.assertNotNull(body);
707                 request.put(BODY, request.get(BODY) + "junk");
708                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
709             }
710         };
711 
712         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
713 
714         framework.addTest();
715 
716         try {
717             framework.runTests();
718             Assert.fail("WebServerTestingFrameworkException should have been thrown");
719         } catch (final TestingFrameworkException e) {
720             // expected
721         }
722     }
723 
724     @Test
725     public void changeContentType() throws Exception {
726         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
727             @Override
728             public Map<String, Object> execute(
729                     final String defaultURI,
730                     final Map<String, Object> request,
731                     final TestingFrameworkRequestHandler requestHandler,
732                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
733                 // change the request from what is expected.
734                 final String contentType = (String) request.get(CONTENT_TYPE);
735                 Assert.assertNotNull(contentType);
736                 request.put(CONTENT_TYPE, request.get(CONTENT_TYPE) + "junk");
737                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
738             }
739         };
740 
741         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
742 
743         framework.addTest();
744 
745         try {
746             framework.runTests();
747             Assert.fail("WebServerTestingFrameworkException should have been thrown");
748         } catch (final TestingFrameworkException e) {
749             // expected
750         }
751     }
752 
753     @Test
754     public void changeProtocolVersion() throws Exception {
755         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
756             @Override
757             public Map<String, Object> execute(
758                     final String defaultURI,
759                     final Map<String, Object> request,
760                     final TestingFrameworkRequestHandler requestHandler,
761                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
762                 // change the request from what is expected.
763                 final ProtocolVersion protocolVersion = (ProtocolVersion) request.get(PROTOCOL_VERSION);
764                 Assert.assertNotNull(protocolVersion);
765                 request.put(PROTOCOL_VERSION, HttpVersion.HTTP_1_0);
766                 return super.execute(defaultURI, request, requestHandler, responseExpectations);
767             }
768         };
769 
770         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
771 
772         framework.addTest();
773 
774         try {
775             framework.runTests();
776             Assert.fail("WebServerTestingFrameworkException should have been thrown");
777         } catch (final TestingFrameworkException e) {
778             // expected
779         }
780     }
781 
782     @Test
783     public void changeResponseExpectationsFails() throws Exception {
784         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
785             @Override
786             public Map<String, Object> execute(
787                     final String defaultURI,
788                     final Map<String, Object> request,
789                     final TestingFrameworkRequestHandler requestHandler,
790                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
791 
792                 /*
793                  * The adapter should change the responseExpectations in the modifyResponseExpectations()
794                  * method before they are sent to the request handler.  The expectations should not
795                  * be changed here.
796                  */
797                 // the next command should throw.
798                 responseExpectations.put(STATUS, 201);
799                 return null;
800             }
801         };
802 
803         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
804 
805         framework.addTest();
806 
807         try {
808             framework.runTests();
809             Assert.fail("HttpServerTestingFrameworkException should have been thrown");
810         } catch (final TestingFrameworkException e) {
811             // expected
812         }
813     }
814 
815     @Test
816     public void changeResponseStatus() throws Exception {
817         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
818             @Override
819             public Map<String, Object> execute(
820                     final String defaultURI,
821                     final Map<String, Object> request,
822                     final TestingFrameworkRequestHandler requestHandler,
823                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
824                 // change the responseExpectations from what is expected.  The change should be ignored
825                 // by the request handler, and a 200 should actually be returned.
826                 Assert.assertEquals(200, responseExpectations.get(STATUS));
827 
828                 // The next line is needed because we have to make a copy of the responseExpectations.
829                 // It is an unmodifiable map.
830                 final Map<String, Object> tempResponseExpectations = new HashMap<>(responseExpectations);
831                 tempResponseExpectations.put(STATUS, 201);
832                 final Map<String, Object> response = super.execute(defaultURI, request, requestHandler, tempResponseExpectations);
833                 Assert.assertEquals(200,  response.get(STATUS));
834 
835                 return response;
836             }
837         };
838 
839         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
840 
841         framework.addTest();
842 
843         framework.runTests();
844     }
845 
846     @Test
847     public void modifyRequestCalled() throws Exception {
848         final TestingFrameworkRequestHandler mockRequestHandler = Mockito.mock(TestingFrameworkRequestHandler.class);
849         final String UNLIKELY_ITEM = "something_unlikely_to_be_in_a_real_request";
850 
851         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
852             @Override
853             public Map<String, Object> execute(
854                                    final String defaultURI,
855                                    final Map<String, Object> request,
856                                    final TestingFrameworkRequestHandler requestHandler,
857                                    final Map<String, Object> responseExpectations) throws TestingFrameworkException {
858                 // make sure the modifyRequest method was called by seeing if the request was modified.
859                 Assert.assertTrue("modifyRequest should have been called.", request.containsKey(UNLIKELY_ITEM));
860 
861                 final Map<String, Object> response = new HashMap<>();
862                 response.put(STATUS, responseExpectations.get(STATUS));
863                 response.put(BODY, responseExpectations.get(BODY));
864                 response.put(CONTENT_TYPE, responseExpectations.get(CONTENT_TYPE));
865                 response.put(HEADERS, responseExpectations.get(HEADERS));
866                 return response;
867             }
868 
869             @Override
870             public Map<String, Object> modifyRequest(final Map<String, Object> request) {
871                 // let the adapter change the request if needed.
872                 request.put(UNLIKELY_ITEM, new Object());
873                 return super.modifyRequest(request);
874             }
875         };
876 
877         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
878         framework.setRequestHandler(mockRequestHandler);
879 
880         framework.addTest();
881 
882         framework.runTests();
883 
884         // assertNothingThrown() should have been called.
885         Mockito.verify(mockRequestHandler).assertNothingThrown();
886     }
887 
888     @Test
889     public void modifyResponseExpectationsCalled() throws Exception {
890         final TestingFrameworkRequestHandler mockRequestHandler = Mockito.mock(TestingFrameworkRequestHandler.class);
891         final String UNLIKELY_ITEM = "something_unlikely_to_be_in_a_real_response";
892 
893         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
894             @Override
895             public Map<String, Object> execute(
896                                    final String defaultURI,
897                                    final Map<String, Object> request,
898                                    final TestingFrameworkRequestHandler requestHandler,
899                                    final Map<String, Object> responseExpectations) throws TestingFrameworkException {
900                 // make sure the modifyRequest method was called by seeing if the request was modified.
901                 Assert.assertTrue("modifyResponseExpectations should have been called.", responseExpectations.containsKey(UNLIKELY_ITEM));
902 
903                 final Map<String, Object> response = new HashMap<>();
904                 response.put(STATUS, responseExpectations.get(STATUS));
905                 response.put(BODY, responseExpectations.get(BODY));
906                 response.put(CONTENT_TYPE, responseExpectations.get(CONTENT_TYPE));
907                 response.put(HEADERS, responseExpectations.get(HEADERS));
908                 return response;
909             }
910 
911             @Override
912             public Map<String, Object> modifyResponseExpectations(
913                     final Map<String, Object> request,
914                     final Map<String, Object> responseExpectations) {
915                 // let the adapter change the request if needed.
916                 responseExpectations.put(UNLIKELY_ITEM, new Object());
917                 return super.modifyResponseExpectations(request, responseExpectations);
918             }
919         };
920 
921         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
922         framework.setRequestHandler(mockRequestHandler);
923 
924         framework.addTest();
925 
926         framework.runTests();
927 
928         // assertNothingThrown() should have been called.
929         Mockito.verify(mockRequestHandler).assertNothingThrown();
930     }
931 
932     @Test
933     public void adapterDoesNotSupport() throws Exception {
934 
935         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
936             @Override
937             public Map<String, Object> execute(
938                                    final String defaultURI,
939                                    final Map<String, Object> request,
940                                    final TestingFrameworkRequestHandler requestHandler,
941                                    final Map<String, Object> responseExpectations) throws TestingFrameworkException {
942 
943                 Assert.fail("callMethod should not have been called");
944                 return null;
945             }
946 
947             @Override
948             public boolean isRequestSupported(final Map<String, Object> request) {
949                 return false;
950             }
951         };
952 
953         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
954 
955         framework.addTest();
956 
957         framework.runTests();
958     }
959 
960     @Test
961     public void defaultTestsWithMockedAdapter() throws Exception {
962         final Set<String> calledMethodSet = new HashSet<>();
963 
964         final ClientTestingAdapter adapter = new ClientTestingAdapter() {
965             @Override
966             public Map<String, Object> execute(
967                                    final String defaultURI,
968                                    final Map<String, Object> request,
969                                    final TestingFrameworkRequestHandler requestHandler,
970                                    final Map<String, Object> responseExpectations) throws TestingFrameworkException {
971 
972                 calledMethodSet.add((String) request.get(METHOD));
973                 return alreadyCheckedResponse();
974             }
975         };
976 
977         // create the framework without deleting the default tests.
978         final TestingFramework framework = new TestingFramework();
979         framework.setAdapter(adapter);
980 
981         framework.runTests();
982 
983         for (final String method : TestingFramework.ALL_METHODS) {
984             Assert.assertTrue("Method not in default tests.  method=" + method, calledMethodSet.contains(method));
985         }
986     }
987 
988     @Test
989     public void defaultTests() throws Exception {
990         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter();
991 
992         // create the framework without deleting the default tests.
993         final TestingFramework framework = new TestingFramework();
994         framework.setAdapter(adapter);
995 
996         framework.runTests();
997 
998     }
999 
1000     @Test
1001     public void addTestNoMocks() throws TestingFrameworkException {
1002 
1003         final TestingFramework framework = new TestingFramework(new ClassicTestClientTestingAdapter());
1004 
1005 //      The following test could be constructed in Groovy/Spock like this:
1006 //
1007 //      HttpServerTestingFramework.ALL_METHODS.each { method ->
1008 //          framework.addTest(
1009 //                              request: [
1010 //                                  path: '/stuff',
1011 //                                  method:method,
1012 //                                  query: [param : 'something'],
1013 //                                  headers: [header1:'stuff', header2:'more-stuff'],
1014 //                                  contentType: 'text/plain; charset=us-ascii',
1015 //                                  body: 'What is the meaning of life?',
1016 //                              ],
1017 //                              response: [
1018 //                                  status:201,
1019 //                                  headers: [header3:'header_stuff',],
1020 //                                  contentType: 'text/html; charset=us-ascii',
1021 //                                  body: responseBody,
1022 //                              ],
1023 //          )
1024 
1025         final Map<String, Object> test = new HashMap<>();
1026 
1027         // Add request.
1028         final Map<String, Object> request = new HashMap<>();
1029         test.put(REQUEST, request);
1030 
1031         request.put(PATH, "/stuff");
1032 
1033         final Map<String, Object> queryMap = new HashMap<>();
1034         request.put(QUERY, queryMap);
1035 
1036         queryMap.put("param", "something");
1037 
1038         final Map<String, Object> requestHeadersMap = new HashMap<>();
1039         request.put(HEADERS, requestHeadersMap);
1040 
1041         requestHeadersMap.put("header1", "stuff");
1042         requestHeadersMap.put("header2", "more-stuff");
1043 
1044         request.put(CONTENT_TYPE, "text/plain; charset=us-ascii");
1045         request.put(BODY, "What is the meaning of life?");
1046 
1047         // Response
1048         final Map<String, Object> response = new HashMap<>();
1049         test.put(RESPONSE, response);
1050 
1051         response.put(STATUS, 201);
1052 
1053         final Map<String, Object> responseHeadersMap = new HashMap<>();
1054         response.put(HEADERS, responseHeadersMap);
1055 
1056         responseHeadersMap.put("header3", "header_stuff");
1057 
1058         response.put(CONTENT_TYPE, "text/html; charset=us-ascii");
1059         response.put(BODY, "<HTML>42</HTML>");
1060 
1061         for (final String method : TestingFramework.ALL_METHODS) {
1062             request.put(METHOD, method);
1063 
1064             framework.addTest(test);
1065         }
1066         framework.runTests();
1067     }
1068 
1069     @Test
1070     public void nulls() throws TestingFrameworkException {
1071 
1072         final TestingFramework framework = new TestingFramework(new ClassicTestClientTestingAdapter());
1073 
1074 //      The following test could be constructed in Groovy/Spock like this:
1075 //
1076 //      WebServerTestingFramework.ALL_METHODS.each { method ->
1077 //           framework.addTest(
1078 //                              request: [
1079 //                                  path: null,
1080 //                                  method:method,
1081 //                                  query: null,
1082 //                                  headers: null,
1083 //                                  contentType: null,
1084 //                                  body: null,
1085 //                              ],
1086 //                              response: [
1087 //                                  status:null,
1088 //                                  headers: null,
1089 //                                  contentType: null,
1090 //                                  body: null,
1091 //                              ],
1092 //          )
1093 
1094         final Map<String, Object> test = new HashMap<>();
1095 
1096         // Add request.
1097         final Map<String, Object> request = new HashMap<>();
1098         test.put(REQUEST, request);
1099 
1100         request.put(PATH, null);
1101 
1102         request.put(QUERY, null);
1103 
1104 
1105         request.put(HEADERS, null);
1106 
1107         request.put(CONTENT_TYPE, null);
1108         request.put(BODY, null);
1109 
1110         // Response
1111         final Map<String, Object> response = new HashMap<>();
1112         test.put(RESPONSE, response);
1113 
1114         response.put(STATUS, null);
1115 
1116         response.put(HEADERS, null);
1117 
1118         response.put(CONTENT_TYPE, null);
1119         response.put(BODY, null);
1120 
1121         for (final String method : TestingFramework.ALL_METHODS) {
1122             request.put(METHOD, method);
1123 
1124             framework.addTest(test);
1125         }
1126         framework.runTests();
1127     }
1128 
1129     @Test
1130     public void parameterInPath() throws Exception {
1131         final ClientTestingAdapter adapter = new ClassicTestClientTestingAdapter() {
1132             @Override
1133             public Map<String, Object> execute(final String defaultURI, final Map<String, Object> request,
1134                     final TestingFrameworkRequestHandler requestHandler,
1135                     final Map<String, Object> responseExpectations) throws TestingFrameworkException {
1136                 @SuppressWarnings("unchecked")
1137                 final Map<String, String> query = (Map<String, String>) request.get(QUERY);
1138                 Assert.assertTrue("Parameters appended to the path should have been put in the query.",
1139                                    query.containsKey("stuffParm"));
1140 
1141                 Assert.assertTrue(query.containsKey("stuffParm2"));
1142                 Assert.assertEquals("stuff", query.get("stuffParm"));
1143                 Assert.assertEquals("stuff2", query.get("stuffParm2"));
1144 
1145                 Assert.assertEquals("/stuff", request.get(PATH));
1146                 return alreadyCheckedResponse();
1147             }
1148         };
1149 
1150         final TestingFramework framework = newFrameworkAndSetAdapter(adapter);
1151 
1152         final Map<String, Object> test = new HashMap<>();
1153 
1154         // Add request.
1155         final Map<String, Object> request = new HashMap<>();
1156         test.put(REQUEST, request);
1157 
1158         request.put(PATH, "/stuff?stuffParm=stuff&stuffParm2=stuff2");
1159 
1160         framework.addTest(test);
1161 
1162         framework.runTests();
1163     }
1164 
1165 }