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