2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.http
;
21 import java
.io
.BufferedReader
;
23 import java
.io
.IOException
;
24 import java
.io
.InputStream
;
25 import java
.io
.InputStreamReader
;
26 import java
.net
.MalformedURLException
;
27 import java
.net
.ServerSocket
;
30 import java
.net
.URLConnection
;
31 import java
.nio
.charset
.StandardCharsets
;
32 import org
.apache
.hadoop
.conf
.Configuration
;
33 import org
.apache
.hadoop
.hbase
.http
.HttpServer
.Builder
;
34 import org
.apache
.hadoop
.net
.NetUtils
;
35 import org
.apache
.hadoop
.security
.authorize
.AccessControlList
;
36 import org
.junit
.Assert
;
37 import org
.slf4j
.Logger
;
38 import org
.slf4j
.LoggerFactory
;
41 * This is a base class for functional tests of the {@link HttpServer}.
42 * The methods are static for other classes to import statically.
44 public class HttpServerFunctionalTest
extends Assert
{
45 private static final Logger LOG
= LoggerFactory
.getLogger(HttpServerFunctionalTest
.class);
46 /** JVM property for the webapp test dir : {@value} */
47 public static final String TEST_BUILD_WEBAPPS
= "test.build.webapps";
48 /** expected location of the test.build.webapps dir: {@value} */
49 private static final String BUILD_WEBAPPS_DIR
= "src/test/resources/webapps";
51 /** name of the test webapp: {@value} */
52 private static final String TEST
= "test";
55 * Create but do not start the test webapp server. The test webapp dir is
56 * prepared/checked in advance.
58 * @return the server instance
60 * @throws IOException if a problem occurs
61 * @throws AssertionError if a condition was not met
63 public static HttpServer
createTestServer() throws IOException
{
65 return createServer(TEST
);
69 * Create but do not start the test webapp server. The test webapp dir is
70 * prepared/checked in advance.
71 * @param conf the server configuration to use
72 * @return the server instance
74 * @throws IOException if a problem occurs
75 * @throws AssertionError if a condition was not met
77 public static HttpServer
createTestServer(Configuration conf
)
80 return createServer(TEST
, conf
);
83 public static HttpServer
createTestServer(Configuration conf
, AccessControlList adminsAcl
)
86 return createServer(TEST
, conf
, adminsAcl
);
90 * Create but do not start the test webapp server. The test webapp dir is
91 * prepared/checked in advance.
92 * @param conf the server configuration to use
93 * @return the server instance
95 * @throws IOException if a problem occurs
96 * @throws AssertionError if a condition was not met
98 public static HttpServer
createTestServer(Configuration conf
,
99 String
[] pathSpecs
) throws IOException
{
101 return createServer(TEST
, conf
, pathSpecs
);
104 public static HttpServer
createTestServerWithSecurity(Configuration conf
) throws IOException
{
106 return localServerBuilder(TEST
).setFindPort(true).setConf(conf
).setSecurityEnabled(true)
107 // InfoServer normally sets these for us
108 .setUsernameConfKey(HttpServer
.HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_KEY
)
109 .setKeytabConfKey(HttpServer
.HTTP_SPNEGO_AUTHENTICATION_KEYTAB_KEY
)
113 public static HttpServer
createTestServerWithSecurityAndAcl(Configuration conf
, AccessControlList acl
) throws IOException
{
115 return localServerBuilder(TEST
).setFindPort(true).setConf(conf
).setSecurityEnabled(true)
116 // InfoServer normally sets these for us
117 .setUsernameConfKey(HttpServer
.HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_KEY
)
118 .setKeytabConfKey(HttpServer
.HTTP_SPNEGO_AUTHENTICATION_KEYTAB_KEY
)
119 .setSecurityEnabled(true)
125 * Prepare the test webapp by creating the directory from the test properties
126 * fail if the directory cannot be created.
127 * @throws AssertionError if a condition was not met
129 protected static void prepareTestWebapp() {
130 String webapps
= System
.getProperty(TEST_BUILD_WEBAPPS
, BUILD_WEBAPPS_DIR
);
131 File testWebappDir
= new File(webapps
+
132 File
.separatorChar
+ TEST
);
134 if (!testWebappDir
.exists()) {
135 fail("Test webapp dir " + testWebappDir
.getCanonicalPath() + " missing");
138 catch (IOException e
) {
143 * Create an HttpServer instance on the given address for the given webapp
144 * @param host to bind
145 * @param port to bind
147 * @throws IOException if it could not be created
149 public static HttpServer
createServer(String host
, int port
)
152 return new HttpServer
.Builder().setName(TEST
)
153 .addEndpoint(URI
.create("http://" + host
+ ":" + port
))
154 .setFindPort(true).build();
158 * Create an HttpServer instance for the given webapp
159 * @param webapp the webapp to work with
161 * @throws IOException if it could not be created
163 public static HttpServer
createServer(String webapp
) throws IOException
{
164 return localServerBuilder(webapp
).setFindPort(true).build();
167 * Create an HttpServer instance for the given webapp
168 * @param webapp the webapp to work with
169 * @param conf the configuration to use for the server
171 * @throws IOException if it could not be created
173 public static HttpServer
createServer(String webapp
, Configuration conf
)
175 return localServerBuilder(webapp
).setFindPort(true).setConf(conf
).build();
178 public static HttpServer
createServer(String webapp
, Configuration conf
,
179 AccessControlList adminsAcl
) throws IOException
{
180 return localServerBuilder(webapp
).setFindPort(true).setConf(conf
).setACL(adminsAcl
).build();
183 private static Builder
localServerBuilder(String webapp
) {
184 return new HttpServer
.Builder().setName(webapp
).addEndpoint(
185 URI
.create("http://localhost:0"));
189 * Create an HttpServer instance for the given webapp
190 * @param webapp the webapp to work with
191 * @param conf the configuration to use for the server
192 * @param pathSpecs the paths specifications the server will service
194 * @throws IOException if it could not be created
196 public static HttpServer
createServer(String webapp
, Configuration conf
,
197 String
[] pathSpecs
) throws IOException
{
198 return localServerBuilder(webapp
).setFindPort(true).setConf(conf
).setPathSpec(pathSpecs
)
203 * Create and start a server with the test webapp
205 * @return the newly started server
207 * @throws IOException on any failure
208 * @throws AssertionError if a condition was not met
210 public static HttpServer
createAndStartTestServer() throws IOException
{
211 HttpServer server
= createTestServer();
217 * If the server is non null, stop it
218 * @param server to stop
219 * @throws Exception on any failure
221 public static void stop(HttpServer server
) throws Exception
{
222 if (server
!= null) {
228 * Pass in a server, return a URL bound to localhost and its port
229 * @param server server
230 * @return a URL bonded to the base of the server
231 * @throws MalformedURLException if the URL cannot be created.
233 public static URL
getServerURL(HttpServer server
)
234 throws MalformedURLException
{
235 assertNotNull("No server", server
);
236 return new URL("http://"
237 + NetUtils
.getHostPortString(server
.getConnectorAddress(0)));
241 * Read in the content from a URL
242 * @param url URL To read
243 * @return the text from the output
244 * @throws IOException if something went wrong
246 protected static String
readOutput(URL url
) throws IOException
{
247 StringBuilder out
= new StringBuilder();
248 InputStream in
= url
.openConnection().getInputStream();
249 byte[] buffer
= new byte[64 * 1024];
250 int len
= in
.read(buffer
);
252 out
.append(new String(buffer
, 0, len
));
253 len
= in
.read(buffer
);
255 return out
.toString();
259 * Recursively deletes a {@link File}.
261 protected static void deleteRecursively(File d
) {
262 if (d
.isDirectory()) {
263 for (String name
: d
.list()) {
264 File child
= new File(d
, name
);
265 if (child
.isFile()) {
268 deleteRecursively(child
);
276 * Picks a free port on the host by binding a Socket to '0'.
278 protected static int getFreePort() throws IOException
{
279 ServerSocket s
= new ServerSocket(0);
281 s
.setReuseAddress(true);
282 int port
= s
.getLocalPort();
292 * access a url, ignoring some IOException such as the page does not exist
294 public static void access(String urlstring
) throws IOException
{
295 URL url
= new URL(urlstring
);
297 URLConnection connection
= url
.openConnection();
298 connection
.connect();
300 try (BufferedReader in
= new BufferedReader(new InputStreamReader(
301 connection
.getInputStream(), StandardCharsets
.UTF_8
))){
302 for(; in
.readLine() != null;) {
305 } catch(IOException ioe
) {
306 LOG
.info("Got exception: ", ioe
);