1   package com.atlassian.sal.core.rest;
2   
3   import com.atlassian.sal.api.net.Request.MethodType;
4   import com.atlassian.sal.api.net.Response;
5   import com.atlassian.sal.api.net.ResponseException;
6   import com.atlassian.sal.api.net.ResponseHandler;
7   import com.atlassian.sal.api.user.UserManager;
8   import com.atlassian.sal.core.net.HttpClientRequest;
9   import com.atlassian.sal.core.net.HttpClientResponse;
10  import com.atlassian.sal.core.net.auth.HttpClientAuthenticator;
11  import com.atlassian.sal.core.trusted.CertificateFactory;
12  import junit.framework.TestCase;
13  import org.apache.commons.httpclient.Header;
14  import org.apache.commons.httpclient.HttpClient;
15  import org.apache.commons.httpclient.HttpException;
16  import org.apache.commons.httpclient.HttpMethod;
17  import org.apache.commons.httpclient.methods.GetMethod;
18  import org.apache.commons.httpclient.methods.PostMethod;
19  import org.easymock.classextension.EasyMock;
20  import org.easymock.classextension.IMocksControl;
21  
22  import java.io.IOException;
23  import java.util.concurrent.atomic.AtomicInteger;
24  
25  import static org.mockito.Mockito.mock;
26  
27  public class TestHttpClientRequest extends TestCase
28  {
29  
30      public void testAuthentication() throws IOException, ResponseException
31      {
32          final IMocksControl httpClientMockControl = EasyMock.createNiceControl();
33          final HttpClient mockHttpClient = httpClientMockControl.createMock(HttpClient.class);
34          httpClientMockControl.replay();
35  
36  
37          // counter how many time was authentication called
38          final AtomicInteger authenticatorCounter = new AtomicInteger(0);
39  
40          // lets create new GET request to http://url
41          HttpClientRequest request = new HttpClientRequest(mockHttpClient, MethodType.GET, "http://url",
42                  mock(CertificateFactory.class), mock(UserManager.class));
43  
44          // this is our authenticator
45          final HttpClientAuthenticator authenticator = new HttpClientAuthenticator()
46          {
47              public void process(HttpClient httpClient, HttpMethod method)
48              {
49                  assertEquals("It should use mockClient", httpClient, mockHttpClient);
50                  assertTrue("We asked it for GetMethod", method instanceof GetMethod);
51                  authenticatorCounter.addAndGet(1);
52              }
53          };
54  
55          // lets add 2 authenticator to the request
56          request.addAuthentication(authenticator);
57          request.addAuthentication(authenticator);
58  
59          // and we are ready to execute the request
60          request.execute(EasyMock.createMock(ResponseHandler.class));
61  
62          // and assert that authenticators were used
63          assertEquals("Two authenticator should be called.", 2, authenticatorCounter.intValue());
64      }
65  
66      public void testMaxNumberOfRedirectionReached() throws IOException
67      {
68          // create mock GetMethod - it should redirect few times
69          final IMocksControl mockControl = EasyMock.createNiceControl();
70          final GetMethod mockGetMethod = mockControl.createMock(GetMethod.class);
71          mockGetMethod.getResponseHeader("location");
72          mockControl.andReturn(new Header("location", "http://someRedirectionUrl"));
73          mockControl.times(HttpClientRequest.MAX_REDIRECTS);
74          mockControl.replay();
75  
76          // create HttpClient that will return 301 Moved Permanently
77          final IMocksControl httpClientMockControl = EasyMock.createNiceControl();
78          final HttpClient httpClientMock = httpClientMockControl.createMock(HttpClient.class);
79          httpClientMock.executeMethod(mockGetMethod);
80          httpClientMockControl.andReturn(302);
81          httpClientMockControl.times(HttpClientRequest.MAX_REDIRECTS);
82          httpClientMockControl.replay();
83  
84          // create a request that will return mockGetMethod
85          HttpClientRequest request = new HttpClientRequest(httpClientMock, MethodType.GET, "http://url",
86                  mock(CertificateFactory.class), mock(UserManager.class))
87          {
88              @Override
89              protected HttpMethod makeMethod()
90              {
91                  return mockGetMethod;
92              }
93          };
94  
95          // now use it
96          try
97          {
98              request.execute(EasyMock.createMock(ResponseHandler.class));
99              fail("Should throw IOException - maximum retries reached.");
100         }
101         catch (ResponseException e)
102         {
103             // expect Exception
104         }
105 
106         // and assert results
107         mockControl.verify();
108     }
109     
110     public void testNoFollowRedirect() throws IOException
111     {
112         // create mock GetMethod - it should not redirect automatically
113         final IMocksControl mockControl = EasyMock.createNiceControl();
114         final GetMethod mockGetMethod = mockControl.createMock(GetMethod.class);
115         mockGetMethod.getResponseHeader("location");
116         mockControl.andReturn(new Header("location", "http://someRedirectionUrl")).anyTimes();
117         mockControl.replay();
118 
119         // create HttpClient that will return 301 Moved Permanently
120         final IMocksControl httpClientMockControl = EasyMock.createNiceControl();
121         final HttpClient httpClientMock = httpClientMockControl.createMock(HttpClient.class);
122         httpClientMock.executeMethod(mockGetMethod);
123         httpClientMockControl.andReturn(302).anyTimes();
124         httpClientMockControl.replay();
125 
126         // create a request that will return mockGetMethod
127         HttpClientRequest request = new HttpClientRequest(httpClientMock, MethodType.GET, "http://url",
128                 mock(CertificateFactory.class), mock(UserManager.class))
129         {
130             @Override
131             protected HttpMethod makeMethod()
132             {
133                 return mockGetMethod;
134             }
135         };
136         request.setFollowRedirects(false);
137         
138                
139         // now use it
140         try
141         {
142             request.execute(EasyMock.createMock(ResponseHandler.class));
143             
144         }
145         catch (ResponseException e)
146         {
147             fail(e.getMessage());
148         }
149 
150         // and assert results
151         mockControl.verify();
152     }
153     
154     public void testAddRequestParametersFails()
155     {
156         // Lets try to add parameters to GET method
157         try
158         {
159             HttpClientRequest request = new HttpClientRequest(EasyMock.createMock(HttpClient.class), MethodType.GET, "http://url",
160                     mock(CertificateFactory.class), mock(UserManager.class));
161             request.addRequestParameters("doIt", "quickly!");
162             fail("Should throw exception that only the POST method can have parameters.");
163         }
164         catch (UnsupportedOperationException e)
165         {
166             // expected
167         }
168 
169         // Lets try to add parameters to PUT method
170         try
171         {
172             HttpClientRequest request = new HttpClientRequest(EasyMock.createMock(HttpClient.class), MethodType.PUT, "http://url",
173                     mock(CertificateFactory.class), mock(UserManager.class));
174             request.addRequestParameters("Isaid", "doIt", "now");
175             fail("Should throw exception that only the POST method can have parameters.");
176         }
177         catch (UnsupportedOperationException e)
178         {
179             // expected
180         }
181 
182         // Lets try to add uneven amount of parameters to POST method
183         try
184         {
185             HttpClientRequest request = new HttpClientRequest(EasyMock.createMock(HttpClient.class), MethodType.POST, "http://url",
186                     mock(CertificateFactory.class), mock(UserManager.class));
187             request.addRequestParameters("doIt", "quickly!", "now");
188             fail("Should throw exception that You must enter an even number of arguments.");
189         }
190         catch (IllegalArgumentException e)
191         {
192             // expected
193         }
194     }
195 
196     public void testAddRequestParameters() throws IOException, ResponseException
197     {
198         // create mock PostMethod - someone should call addParamater() on it
199         final IMocksControl mockControl = EasyMock.createNiceControl();
200         final PostMethod mockPostMethod = mockControl.createMock(PostMethod.class);
201         mockPostMethod.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
202         mockPostMethod.addParameter("a", "b");
203         mockPostMethod.addParameter("a", "b");
204         mockPostMethod.addParameter("a", "c");
205         mockPostMethod.addParameter("x", "y");
206         mockControl.replay();
207 
208 
209         final IMocksControl httpClientMockControl = EasyMock.createNiceControl();
210         final HttpClient mockHttpClient = httpClientMockControl.createMock(HttpClient.class);
211         httpClientMockControl.replay();
212 
213 
214         // create a request that will return mockPostMethod
215         HttpClientRequest request = new HttpClientRequest(mockHttpClient, MethodType.POST, "http://url",
216                 mock(CertificateFactory.class), mock(UserManager.class))
217         {
218             @Override
219             protected HttpMethod makeMethod()
220             {
221                 return mockPostMethod;
222             }
223         };
224 
225         // now use it
226         request.addRequestParameters("a", "b", "a", "b", "a", "c", "x", "y");
227         request.execute(EasyMock.createMock(ResponseHandler.class));
228 
229         // and assert results
230         mockControl.verify();
231     }
232 }