blob: 6998ea8f6a17053aa30501986c7bb633d12186ab [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.avatica.remote;
import org.apache.calcite.avatica.ConnectionConfig;
import org.apache.calcite.avatica.ConnectionSpec;
import org.apache.calcite.avatica.server.HttpServer;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertFalse;
/**
* Tests for the HttpClient which manipulate things at the HTTP layer instead of Avatica's
* "application" layer.
*/
@RunWith(Parameterized.class)
public class RemoteHttpClientTest {
private static Map<String, String> getHeaders() {
return HEADERS_REF.get();
}
private static final AtomicReference<Map<String, String>> HEADERS_REF = new AtomicReference<>();
private static final AvaticaServersForTest SERVERS = new AvaticaServersForTest();
@Parameters(name = "{0}")
public static List<Object[]> parameters() throws Exception {
SERVERS.startServers();
return SERVERS.getJUnitParameters();
}
@AfterClass public static void afterClass() throws Exception {
if (null != SERVERS) {
SERVERS.stopServers();
}
}
private final HttpServer server;
private final String url;
private final int port;
private final Driver.Serialization serialization;
public RemoteHttpClientTest(Driver.Serialization serialization, HttpServer server) {
this.server = server;
this.port = this.server.getPort();
this.serialization = serialization;
this.url = SERVERS.getJdbcUrl(port, serialization);
}
static String generateString(int length) {
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) {
sb.append('a');
}
return sb.toString();
}
@Test public void testLargeHeaders() throws Exception {
ConnectionSpec.getDatabaseLock().lock();
// 32K header. Relies on the default value of 64K from HttpServer.Builder
HEADERS_REF.set(Collections.singletonMap("MyLargeHeader", generateString(1024 * 32)));
String modifiedUrl = url + ";httpclient_factory=" + HttpClientFactoryForTest.class.getName();
try (Connection conn = DriverManager.getConnection(modifiedUrl);
Statement stmt = conn.createStatement()) {
assertFalse(stmt.execute("CREATE TABLE largeHeaders(pk integer not null primary key)"));
assertFalse(stmt.execute("DROP TABLE largeHeaders"));
} finally {
ConnectionSpec.getDatabaseLock().unlock();
}
}
/**
* Factory class to inject a custom HttpClient
*/
public static class HttpClientFactoryForTest implements AvaticaHttpClientFactory {
@Override public AvaticaHttpClient getClient(URL url, ConnectionConfig config,
KerberosConnection kerberosUtil) {
Map<String, String> headers = getHeaders();
return new HeaderInjectingHttpClient(headers, url);
}
}
/**
* HttpClient implementation which supports injecting custom HTTP headers
*/
public static class HeaderInjectingHttpClient extends AvaticaHttpClientImpl {
private final Map<String, String> headers;
public HeaderInjectingHttpClient(Map<String, String> headers, URL url) {
super(url);
this.headers = Objects.requireNonNull(headers);
}
@Override HttpURLConnection openConnection() throws IOException {
HttpURLConnection connection = super.openConnection();
for (Entry<String, String> entry : headers.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
return connection;
}
}
}
// End RemoteHttpClientTest.java