View Javadoc
1   package org.apache.maven.wagon.tck.http;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.wagon.ResourceDoesNotExistException;
23  import org.apache.maven.wagon.TransferFailedException;
24  import org.apache.maven.wagon.WagonException;
25  import org.apache.maven.wagon.authorization.AuthorizationException;
26  import org.apache.maven.wagon.proxy.ProxyInfo;
27  import org.codehaus.plexus.util.IOUtil;
28  import org.codehaus.plexus.util.StringUtils;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  import javax.servlet.http.HttpServletResponse;
33  import java.io.File;
34  import java.io.IOException;
35  import java.io.InputStream;
36  
37  import static org.codehaus.plexus.util.FileUtils.fileRead;
38  import static org.junit.Assert.assertEquals;
39  import static org.junit.Assert.assertNotNull;
40  import static org.junit.Assert.assertTrue;
41  
42  /**
43   *
44   */
45  public final class Assertions
46  {
47  
48      public static final int NO_RESPONSE_STATUS_CODE = -1;
49  
50      protected static final Logger LOGGER = LoggerFactory.getLogger( Assertions.class );
51  
52      public static void assertFileContentsFromResource( final String resourceBase, final String resourceName,
53                                                         final File output, final String whyWouldItFail )
54          throws IOException
55      {
56          String content = readResource( resourceBase, resourceName );
57          String test = fileRead( output );
58  
59          assertEquals( whyWouldItFail, content, test );
60      }
61  
62      private static String readResource( final String base, final String name )
63          throws IOException
64      {
65          String url = base;
66          if ( !url.endsWith( "/" ) && !name.startsWith( "/" ) )
67          {
68              url += "/";
69          }
70          url += name;
71  
72          ClassLoader cloader = Thread.currentThread().getContextClassLoader();
73          InputStream stream = cloader.getResourceAsStream( url );
74  
75          if ( stream == null )
76          {
77              return null;
78          }
79  
80          final String resource = IOUtil.toString( stream );
81          stream.close();
82          return resource;
83      }
84  
85      /**
86       * Assert a WagonException message contains required format and context based on the status code we expected to
87       * trigger it in the first place.
88       * <p>
89       * This implementation represents the most desired assertions, but HttpWagonTestCase sub-classes could override
90       * this method if a specific wagon representation makes it impossible to meet these assertions.
91       *
92       * @param e               an instance of {@link WagonException}
93       * @param forStatusCode   the response status code that triggered the exception
94       * @param forUrl          the url that triggered the exception
95       * @param forReasonPhrase the optional status line reason phrase the server returned
96       */
97      public static void assertWagonExceptionMessage( Exception e, int forStatusCode, String forUrl,
98                                                      String forReasonPhrase, ProxyInfo proxyInfo )
99      {
100         // TODO: handle AuthenticationException for Wagon.connect() calls
101         assertNotNull( e );
102         try
103         {
104             assertTrue( "only verify instances of WagonException", e instanceof WagonException );
105 
106             String reasonPhrase;
107             String assertMessageForBadMessage = "exception message not described properly";
108 
109             if ( proxyInfo != null )
110             {
111                 assertTrue( "message should end with proxy information if proxy was used",
112                         e.getMessage().endsWith( proxyInfo.toString() ) );
113             }
114 
115             switch ( forStatusCode )
116             {
117                 case HttpServletResponse.SC_NOT_FOUND:
118                     // TODO: add test for 410: Gone?
119                     assertTrue( "404 not found response should throw ResourceDoesNotExistException",
120                             e instanceof ResourceDoesNotExistException );
121                     reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Not Found" : ( " " + forReasonPhrase );
122                     assertEquals( assertMessageForBadMessage, "resource missing at " + forUrl + ", status: 404"
123                             + reasonPhrase, e.getMessage() );
124                     break;
125 
126                 case HttpServletResponse.SC_UNAUTHORIZED:
127                     // FIXME assumes Wagon.get()/put() returning 401 instead of Wagon.connect()
128                     assertTrue( "401 Unauthorized should throw AuthorizationException since "
129                                     + " AuthenticationException is not explicitly declared as thrown from wagon "
130                                     + "methods",
131                             e instanceof AuthorizationException );
132                     reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Unauthorized" : ( " " + forReasonPhrase );
133                     assertEquals( assertMessageForBadMessage, "authentication failed for " + forUrl + ", status: 401"
134                             + reasonPhrase, e.getMessage() );
135                     break;
136 
137                 case HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED:
138                     assertTrue( "407 Proxy authentication required should throw AuthorizationException",
139                             e instanceof AuthorizationException );
140                     reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Proxy Authentication Required"
141                             : ( " " + forReasonPhrase );
142                     assertEquals( assertMessageForBadMessage, "proxy authentication failed for "
143                             + forUrl + ", status: 407" + reasonPhrase, e.getMessage() );
144                     break;
145 
146                 case HttpServletResponse.SC_FORBIDDEN:
147                     assertTrue( "403 Forbidden should throw AuthorizationException",
148                             e instanceof AuthorizationException );
149                     reasonPhrase = StringUtils.isEmpty( forReasonPhrase ) ? " Forbidden" : ( " " + forReasonPhrase );
150                     assertEquals( assertMessageForBadMessage, "authorization failed for " + forUrl + ", status: 403"
151                             + reasonPhrase, e.getMessage() );
152                     break;
153 
154                 default:
155                     assertTrue( "transfer failures should at least be wrapped in a TransferFailedException", e
156                             instanceof TransferFailedException );
157 
158                     // the status code and reason phrase cannot always be learned due to implementation limitations
159                     // so the message may not include them, but the implementation should use a consistent format
160                     assertTrue( "message should always include url tried: " + e.getMessage(),
161                             e.getMessage().startsWith( "transfer failed for " + forUrl ) );
162 
163                     String statusCodeStr = forStatusCode == NO_RESPONSE_STATUS_CODE ? ""
164                             : ", status: " +  forStatusCode;
165                     if ( forStatusCode != NO_RESPONSE_STATUS_CODE )
166                     {
167 
168                         assertTrue( "if there was a response status line, the status code should be >= 400",
169                                 forStatusCode >= HttpServletResponse.SC_BAD_REQUEST );
170 
171                         if ( e.getMessage().length() > ( "transfer failed for " + forUrl ).length() )
172                         {
173                             assertTrue( "message should include url and status code: " + e.getMessage(),
174                                     e.getMessage().startsWith( "transfer failed for " + forUrl + statusCodeStr ) );
175                         }
176 
177                         reasonPhrase = forReasonPhrase == null ? "" : " " + forReasonPhrase;
178 
179                         if ( reasonPhrase.length() > 0 && e.getMessage().length() > ( "transfer failed for " + forUrl
180                                 + statusCodeStr ).length() )
181                         {
182                             assertTrue( "message should include url and status code and reason phrase: "
183                                     + e.getMessage(), e.getMessage().startsWith( "transfer failed for "
184                                             + forUrl + statusCodeStr
185                                             + reasonPhrase ) );
186                         }
187 
188                     }
189 
190                     break;
191             }
192         }
193         catch ( AssertionError assertionError )
194         {
195             LOGGER.error( "Exception which failed assertions: ", e );
196             throw assertionError;
197         }
198 
199     }
200 
201 }