Updating version to 1.1.0-SNAPSHOT
[aai/rest-client.git] / src / test / java / org / openecomp / restclient / client / RESTClientTest.java
1 package org.openecomp.restclient.client;\r
2 \r
3 import org.junit.Before;\r
4 import org.junit.Test;\r
5 import org.openecomp.restclient.client.OperationResult;\r
6 import org.openecomp.restclient.client.RestClient;\r
7 import org.openecomp.restclient.rest.RestClientBuilder;\r
8 \r
9 import static org.junit.Assert.assertTrue;\r
10 import static org.junit.Assert.assertNull;\r
11 import static org.junit.Assert.assertEquals;\r
12 \r
13 import javax.ws.rs.GET;\r
14 import javax.ws.rs.Path;\r
15 import javax.ws.rs.core.MediaType;\r
16 \r
17 import com.sun.jersey.test.framework.AppDescriptor;\r
18 import com.sun.jersey.test.framework.JerseyTest;\r
19 import com.sun.jersey.test.framework.WebAppDescriptor;\r
20 \r
21 import com.sun.jersey.api.client.Client;\r
22 \r
23 \r
24 /**\r
25  * This suite of tests is intended to exercise the behaviour of the {@link RestClient}.\r
26  */\r
27 public class RESTClientTest extends JerseyTest {\r
28 \r
29   private static final String GOOD_AAI_ENDPOINT = "testaai/good";\r
30   private static final String FAIL_ALWAYS_AAI_ENDPOINT = "testaai/failalways";\r
31   private static final String FAIL_THEN_SUCCEED_ENDPOINT = "testaai/failthensucceed";\r
32   private static final String INVALID_AAI_ENDPOINT = "testaai/bad";\r
33 \r
34   private static final String AAI_GET_REPLY_PAYLOAD = "Reply from AAI";\r
35 \r
36   private static final int SUCCESS_RESULT_CODE = 200;\r
37   private static final int INVALID_END_POINT_RESULT_CODE = 404;\r
38   private static final int INTERNAL_ERR_RESULT_CODE = 500;\r
39   private static final int TIMEOUT_RESULT_CODE = 504;\r
40 \r
41 \r
42   /**\r
43    * Creates a new instance of the {@link RESTClientTest} test suite.\r
44    */\r
45   public RESTClientTest() throws Exception {\r
46 \r
47     // Tell our in memory container to look here for resource endpoints.\r
48     super("org.openecomp.restclient.client");\r
49   }\r
50 \r
51 \r
52   @Override\r
53   protected AppDescriptor configure() {\r
54     return new WebAppDescriptor.Builder().build();\r
55   }\r
56 \r
57 \r
58   /**\r
59    * Perform common initialization actions that need to run before every unit test.\r
60    */\r
61   @Before\r
62   public void setup() {\r
63 \r
64     // Initialize our test endpoints to make sure that all of their\r
65     // counters have valid starting values\r
66     AAI_FailAlways_Stub.initialize();\r
67     AAI_FailThenSucceed_Stub.initialize();\r
68   }\r
69 \r
70 \r
71   /**\r
72    * This test validates that all of the {@link RestClient}'s configurable parameters can be set via\r
73    * its fluent interface and that those values are successfully passed down to the underlying\r
74    * {@link RestClientBuilder} instance.\r
75    */\r
76   @Test\r
77   public void configureAAIClientTest() {\r
78 \r
79     final boolean VALIDATE_SERVER = true;\r
80     final boolean VALIDATE_CERT_CHAIN = true;\r
81     final String CLIENT_CERT_FILE = "myCertFile";\r
82     final String CLIENT_CERT_PASSWORD = "My voice is my password";\r
83     final String TRUST_STORE = "myTrustStore";\r
84     final int CONNECT_TIMEOUT = 5000;\r
85     final int READ_TIMEOUT = 5000;\r
86 \r
87     // Create an instance of our test version of the REST client builder.\r
88     TestRestClientBuilder clientBuilder = new TestRestClientBuilder();\r
89 \r
90     // Now, create a new instance of the {@link AAIClient} and configure\r
91     // its parameters.\r
92     RestClient testClient =\r
93         new RestClient(clientBuilder).validateServerHostname(true).validateServerCertChain(true)\r
94             .clientCertFile("myCertFile").clientCertPassword("My voice is my password")\r
95             .trustStore("myTrustStore").connectTimeoutMs(5000).readTimeoutMs(5000);\r
96 \r
97     // Validate that the parameters of the test REST client builder that\r
98     // we passed to the AAI client have been set according to what we\r
99     // passed in when we instantiated the AAI client.\r
100     assertEquals("Unexpected 'validate server host name' value", VALIDATE_SERVER,\r
101         clientBuilder.isValidateServerHostname());\r
102     assertEquals("Unexpected 'validate certificat chain' value", VALIDATE_CERT_CHAIN,\r
103         clientBuilder.isValidateServerCertChain());\r
104     assertTrue("Unexpected client certificate filename",\r
105         CLIENT_CERT_FILE.equals(clientBuilder.getClientCertFileName()));\r
106     assertTrue("Unexpected client certificate password",\r
107         CLIENT_CERT_PASSWORD.equals(clientBuilder.getClientCertPassword()));\r
108     assertTrue("Unexpected trust store filename",\r
109         TRUST_STORE.equals(clientBuilder.getTruststoreFilename()));\r
110     assertEquals("Unexpected connection timeout value", CONNECT_TIMEOUT,\r
111         clientBuilder.getConnectTimeoutInMs());\r
112     assertEquals("Unexpected read timeout value", READ_TIMEOUT, clientBuilder.getReadTimeoutInMs());\r
113   }\r
114 \r
115 \r
116   /**\r
117    * This test validates that the {@link RestClient} can submit a GET request to a valid REST\r
118    * endpoint and receive a valid response.\r
119    */\r
120   @Test\r
121   public void queryAAI_SuccessTest() {\r
122 \r
123     // Create an instance of the AAIClient that uses our test version of\r
124     // the REST client builder.\r
125     RestClient testClient = new RestClient(new TestRestClientBuilder());\r
126 \r
127     // Query our stubbed out AAI with a URL that we expecte to get a successful\r
128     // reply from.\r
129     OperationResult or =\r
130         testClient.get(getBaseURI() + GOOD_AAI_ENDPOINT, null, MediaType.APPLICATION_JSON_TYPE);\r
131 \r
132     // Validate that a successful query returns a result code of 200.\r
133     assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, or.getResultCode());\r
134 \r
135     // Validate that no error cause gets set on a successful query.\r
136     assertNull("Operation result failure code should not be set for successful GET",\r
137         or.getFailureCause());\r
138 \r
139     // Validate that our query returned the expected payload from our dummy\r
140     // AAI.\r
141     assertTrue("Incorrect payload returned from AAI query",\r
142         AAI_GET_REPLY_PAYLOAD.equals(or.getResult()));\r
143   }\r
144 \r
145 \r
146   /**\r
147    * This test validates that the {@link RestClient} behaves as expected when query requests are\r
148    * unsuccessful.\r
149    * <p>\r
150    * Specifically, the following scenarios are covered:<br>\r
151    * 1) Submitting a GET request to an invalid REST endpoint 2) Submitting a GET request to a valid\r
152    * endpoint which throws an error rather than replying successfully.\r
153    * <p>\r
154    * Note that this test exercises the 'single attempt' variant of the query method.\r
155    */\r
156   @Test\r
157   public void queryAAI_FailureTest() {\r
158 \r
159     // Create an instance of the AAIClient that uses our test version of\r
160     // the REST client builder.\r
161     RestClient testClient = new RestClient(new TestRestClientBuilder());\r
162 \r
163     // Query our stubbed out AAI with a URL that we expecte to get a successful\r
164     // reply from.\r
165     OperationResult or =\r
166         testClient.get(getBaseURI() + INVALID_AAI_ENDPOINT, null, MediaType.APPLICATION_JSON_TYPE);\r
167 \r
168     // Validate that an attempt to query a non-existing endpoint results in\r
169     // a 404 error.\r
170     assertEquals("Unexpected result code", INVALID_END_POINT_RESULT_CODE, or.getResultCode());\r
171 \r
172     // Validate that no payload was set since the query failed.\r
173     assertNull("Payload should not be set on 404 error", or.getResult());\r
174 \r
175     // Now, submit a query request to the stubbed AAI.\r
176     or = testClient.get(getBaseURI() + FAIL_ALWAYS_AAI_ENDPOINT, null,\r
177         MediaType.APPLICATION_JSON_TYPE);\r
178 \r
179     // Validate that a query to a avalid returns a result code of 500.\r
180     assertEquals("Unexpected result code", INTERNAL_ERR_RESULT_CODE, or.getResultCode());\r
181   }\r
182 \r
183 \r
184   /**\r
185    * This test validates the behaviour of querying the AAI with a number of retries requested in the\r
186    * case where we never get a successful reply.\r
187    */\r
188   @Test\r
189   public void queryAAIWithRetries_TimeoutTest() {\r
190 \r
191     int NUM_RETRIES = 3;\r
192 \r
193 \r
194     // Create an instance of the AAIClient that uses our test version of\r
195     // the REST client builder.\r
196     RestClient testClient = new RestClient(new TestRestClientBuilder());\r
197 \r
198     // Initialize our test endpoint to make sure that all of its\r
199     // counters have valid starting values\r
200     // AAI_FailAlways_Stub.initialize();\r
201 \r
202     // Perform a query against the stubbed AAI, specifying a number of times\r
203     // to retry in the event of an error.\r
204     OperationResult or = testClient.get(getBaseURI() + FAIL_ALWAYS_AAI_ENDPOINT, null,\r
205         MediaType.APPLICATION_JSON_TYPE, NUM_RETRIES);\r
206 \r
207     // Validate that failing for all of our retry attempts results in a\r
208     // 504 error.\r
209     assertEquals("Unexpected result code", TIMEOUT_RESULT_CODE, or.getResultCode());\r
210 \r
211     // Validate that our stubbed AAI actually received the expected number\r
212     // of retried requests.\r
213     assertEquals("Unexpected number of retries", NUM_RETRIES, AAI_FailAlways_Stub.getCount);\r
214   }\r
215 \r
216 \r
217   /**\r
218    * This test validates the behaviour of querying the AAI with a number of retries requested in the\r
219    * case where our query initially fails but then succeeds on one of the subsequent retries.\r
220    */\r
221   @Test\r
222   public void queryAAIWithRetries_FailThenSucceedTest() {\r
223 \r
224     int num_retries = AAI_FailThenSucceed_Stub.MAX_FAILURES + 2;\r
225 \r
226     // Create an instance of the AAIClient that uses our test version of\r
227     // the REST client builder.\r
228     RestClient testClient = new RestClient(new TestRestClientBuilder());\r
229 \r
230     // Initialize our test endpoint to make sure that all of its\r
231     // counters have valid starting values.\r
232     // AAI_FailThenSucceed_Stub.initialize();\r
233 \r
234     // Perform a query against the stubbed AAI, specifying a number of times\r
235     // to retry in the event of an error.\r
236     OperationResult or = testClient.get(getBaseURI() + FAIL_THEN_SUCCEED_ENDPOINT, null,\r
237         MediaType.APPLICATION_JSON_TYPE, num_retries);\r
238 \r
239     // Validate that after failing a few attempts we finally got back a\r
240     // success code.\r
241     assertEquals("Unexpected result code", SUCCESS_RESULT_CODE, or.getResultCode());\r
242 \r
243     // Validate that our stubbed AAI actually received the expected number\r
244     // of retried requests.\r
245     assertEquals("Unexpected number of retries", AAI_FailThenSucceed_Stub.MAX_FAILURES + 1,\r
246         AAI_FailThenSucceed_Stub.getCount);\r
247   }\r
248 \r
249 \r
250   /**\r
251    * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
252    * <p>\r
253    * This endpoint always returns a valid reply to a GET request and is used for success path\r
254    * testing.\r
255    */\r
256   @Path(GOOD_AAI_ENDPOINT)\r
257   public static class AAI_Success_Stub {\r
258 \r
259     /**\r
260      * This is the end point for GET requests. It just returns a simple, pre-canned response\r
261      * payload.\r
262      * \r
263      * @return - A pre-canned response.\r
264      */\r
265     @GET\r
266     public String getEndpoint() {\r
267       return AAI_GET_REPLY_PAYLOAD;\r
268     }\r
269   }\r
270 \r
271 \r
272   /**\r
273    * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
274    * <p>\r
275    * This endpoint always returns throws an error instead of responding successfully and is used for\r
276    * certain failure path tests.\r
277    */\r
278   @Path(FAIL_ALWAYS_AAI_ENDPOINT)\r
279   public static class AAI_FailAlways_Stub {\r
280 \r
281     /**\r
282      * Maintains a running count of the number of GET requests that have been received.\r
283      */\r
284     public static int getCount;\r
285 \r
286 \r
287     /**\r
288      * Resets all of the endpoints counters.\r
289      */\r
290     public static void initialize() {\r
291       getCount = 0;\r
292     }\r
293 \r
294 \r
295     /**\r
296      * This is the end point for GET requests. It just throws an error instead of returning a valid\r
297      * response.\r
298      * \r
299      * @return - NONE. We actually throw an exception intentionally instead of returning.\r
300      */\r
301     @GET\r
302     public String getEndpoint() {\r
303 \r
304       // Keep track of the number of get requests that we have received\r
305       // so that this value can be used for validation purposes later.\r
306       getCount++;\r
307 \r
308       // Always just throw an error instead of replying successfully.\r
309       throw new UnsupportedOperationException("Intentional Failure");\r
310     }\r
311   }\r
312 \r
313 \r
314   /**\r
315    * This class provides a simple in-memory REST end point to stand in for a real AAI.\r
316    * <p>\r
317    * This end point will throw errors instead of responding for a certain number of requests, after\r
318    * which it will return a valid, pre-canned response.\r
319    * \r
320    * @return - A pre-canned response.\r
321    */\r
322   @Path(FAIL_THEN_SUCCEED_ENDPOINT)\r
323   public static class AAI_FailThenSucceed_Stub {\r
324 \r
325     /**\r
326      * The number of requests for which we should throw errors before responding successfully.\r
327      */\r
328     public static int MAX_FAILURES = 2;\r
329 \r
330     /**\r
331      * Maintains a running count of the number of GET requests that have been received.\r
332      */\r
333     public static int getCount;\r
334 \r
335     /**\r
336      * Maintains a running count of the number of requests which we have failed, so that we will\r
337      * know when to stop failing and return a valid response.\r
338      */\r
339     private static int failCount;\r
340 \r
341 \r
342     /**\r
343      * Resets all of the endpoints counters.\r
344      */\r
345     public static void initialize() {\r
346       getCount = 0;\r
347       failCount = 0;\r
348     }\r
349 \r
350 \r
351     /**\r
352      * This is the end point for GET requests. It will throw errors for a certain number of requests\r
353      * and then return a valid response.\r
354      * \r
355      * @return - A pre-canned response string.\r
356      */\r
357     @GET\r
358     public String getEndpoint() {\r
359 \r
360       // Keep track of the number of get requests that we have received\r
361       // so that this value can be used for validation purposes later.\r
362       getCount++;\r
363 \r
364       // We only want to fail a set number of times, so check now to\r
365       // see what we should do.\r
366       if (failCount < MAX_FAILURES) {\r
367         failCount++;\r
368         throw new UnsupportedOperationException("Intentional Failure");\r
369 \r
370       } else {\r
371         // We've failed as often as we need to. Time to reply\r
372         // successfully.\r
373         failCount = 0;\r
374         return AAI_GET_REPLY_PAYLOAD;\r
375       }\r
376     }\r
377   }\r
378 \r
379 \r
380   /**\r
381    * This class overrides the behaviour of the {@link RestClientBuilder} used by the\r
382    * {@link RestClient} to just return the in memory client provided by the JerseyTest framework.\r
383    */\r
384   private class TestRestClientBuilder extends RestClientBuilder {\r
385 \r
386     @Override\r
387     public Client getClient() throws Exception {\r
388       return client();\r
389     }\r
390   }\r
391 }\r