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