package org.greenplum.pxf.service; /* * 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. */ import com.sun.jersey.core.util.MultivaluedMapImpl; import com.sun.jersey.spi.container.ContainerRequest; import org.apache.commons.codec.CharEncoding; import org.greenplum.pxf.api.model.OutputFormat; import org.greenplum.pxf.api.model.PluginConf; import org.greenplum.pxf.api.model.ProtocolHandler; import org.greenplum.pxf.api.model.RequestContext; import org.greenplum.pxf.api.model.RequestContext.RequestType; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import javax.ws.rs.core.MultivaluedMap; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) public class HttpRequestParserTest { private MultivaluedMap<String, String> parameters; private HttpRequestParser parser; @Mock private ContainerRequest mockRequestHeaders; @Mock private PluginConf mockPluginConf; @Rule public ExpectedException thrown = ExpectedException.none(); @Before public void setUp() { parameters = new MultivaluedMapImpl(); parameters.putSingle("X-GP-ALIGNMENT", "all"); parameters.putSingle("X-GP-SEGMENT-ID", "-44"); parameters.putSingle("X-GP-SEGMENT-COUNT", "2"); parameters.putSingle("X-GP-HAS-FILTER", "0"); parameters.putSingle("X-GP-FORMAT", "TEXT"); parameters.putSingle("X-GP-URL-HOST", "my://bags"); parameters.putSingle("X-GP-URL-PORT", "-8020"); parameters.putSingle("X-GP-ATTRS", "-1"); parameters.putSingle("X-GP-OPTIONS-ACCESSOR", "are"); parameters.putSingle("X-GP-OPTIONS-RESOLVER", "packed"); parameters.putSingle("X-GP-DATA-DIR", "i'm/ready/to/go"); parameters.putSingle("X-GP-FRAGMENT-METADATA", "U29tZXRoaW5nIGluIHRoZSB3YXk="); parameters.putSingle("X-GP-OPTIONS-I'M-STANDING-HERE", "outside-your-door"); parameters.putSingle("X-GP-USER", "alex"); parameters.putSingle("X-GP-OPTIONS-SERVER", "custom_server"); parameters.putSingle("X-GP-XID", "transaction:id"); when(mockRequestHeaders.getRequestHeaders()).thenReturn(parameters); when(mockRequestHeaders.getPath()).thenReturn("foo"); parser = new HttpRequestParser(mockPluginConf); } @After public void tearDown() { // Cleanup the system property RequestContext sets System.clearProperty("greenplum.alignment"); } @Test public void testConvertToCaseInsensitiveMap() throws Exception { List<String> multiCaseKeys = Arrays.asList("X-GP-SHLOMO", "x-gp-shlomo", "X-Gp-ShLoMo"); String value = "\\\"The king"; String replacedValue = "\"The king"; MultivaluedMap<String, String> multivaluedMap = new MultivaluedMapImpl(); for (String key : multiCaseKeys) { multivaluedMap.put(key, Collections.singletonList(value)); } assertEquals("All keys should have existed", multivaluedMap.keySet().size(), multiCaseKeys.size()); Map<String, String> caseInsensitiveMap = new HttpRequestParser.RequestMap(multivaluedMap); assertEquals("Only one key should have exist", caseInsensitiveMap.keySet().size(), 1); for (String key : multiCaseKeys) { assertEquals("All keys should have returned the same value", caseInsensitiveMap.get(key), replacedValue); } } @Test public void testConvertToCaseInsensitiveMapUtf8() throws Exception { byte[] bytes = { (byte) 0x61, (byte) 0x32, (byte) 0x63, (byte) 0x5c, (byte) 0x22, (byte) 0x55, (byte) 0x54, (byte) 0x46, (byte) 0x38, (byte) 0x5f, (byte) 0xe8, (byte) 0xa8, (byte) 0x88, (byte) 0xe7, (byte) 0xae, (byte) 0x97, (byte) 0xe6, (byte) 0xa9, (byte) 0x9f, (byte) 0xe7, (byte) 0x94, (byte) 0xa8, (byte) 0xe8, (byte) 0xaa, (byte) 0x9e, (byte) 0x5f, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x5c, (byte) 0x22, (byte) 0x6f, (byte) 0x35 }; String value = new String(bytes, CharEncoding.ISO_8859_1); MultivaluedMap<String, String> multivaluedMap = new MultivaluedMapImpl(); multivaluedMap.put("one", Collections.singletonList(value)); Map<String, String> caseInsensitiveMap = new HttpRequestParser.RequestMap(multivaluedMap); assertEquals("Only one key should have exist", caseInsensitiveMap.keySet().size(), 1); assertEquals("Value should be converted to UTF-8", caseInsensitiveMap.get("one"), "a2c\"UTF8_計算機用語_00000000\"o5"); } @Test public void contextCreated() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(System.getProperty("greenplum.alignment"), "all"); assertEquals(context.getTotalSegments(), 2); assertEquals(context.getSegmentId(), -44); Assert.assertEquals(context.getOutputFormat(), OutputFormat.TEXT); assertEquals(context.getHost(), "my://bags"); assertEquals(context.getPort(), -8020); assertFalse(context.hasFilter()); assertNull(context.getFilterString()); assertEquals(context.getColumns(), 0); assertEquals(context.getDataFragment(), -1); assertNull(context.getRecordkeyColumn()); assertEquals(context.getAccessor(), "are"); assertEquals(context.getResolver(), "packed"); assertEquals(context.getDataSource(), "i'm/ready/to/go"); assertEquals(context.getOption("i'm-standing-here"), "outside-your-door"); assertEquals(context.getUser(), "alex"); assertNull(context.getLogin()); assertNull(context.getSecret()); assertEquals(context.getServerName(), "custom_server"); // since no profile was defined, these below are null or empty assertNull(context.getProfile()); assertNull(context.getProfileScheme()); assertTrue(context.getAdditionalConfigProps().isEmpty()); } @Test public void profileWithDuplicateProperty() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Profile 'test-profile' already defines: [when YOU get WHAT you WANT, wHEn you trY yOUR bESt]"); Map<String, String> mockedPlugins = new HashMap<>(); // What we read from the XML Plugins file mockedPlugins.put("wHEn you trY yOUR bESt", "but you dont succeed"); mockedPlugins.put("when YOU get WHAT you WANT", "but not what you need"); mockedPlugins.put("when you feel so tired", "but you cant sleep"); when(mockPluginConf.getPlugins("test-profile")).thenReturn(mockedPlugins); // Parameters that are coming from the request parameters.putSingle("x-gp-options-profile", "test-profile"); parameters.putSingle("x-gp-options-when you try your best", "and you do succeed"); parameters.putSingle("x-gp-options-WHEN you GET what YOU want", "and what you need"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void pluginsDefinedByProfileOnly() { Map<String, String> mockedPlugins = new HashMap<>(); mockedPlugins.put("fragmenter", "test-fragmenter"); mockedPlugins.put("accessor", "test-accessor"); mockedPlugins.put("resolver", "test-resolver"); when(mockPluginConf.getPlugins("test-profile")).thenReturn(mockedPlugins); // add profile and remove plugin parameters parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); parameters.remove("X-GP-OPTIONS-ACCESSOR"); parameters.remove("X-GP-OPTIONS-RESOLVER"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(context.getFragmenter(), "test-fragmenter"); assertEquals(context.getAccessor(), "test-accessor"); assertEquals(context.getResolver(), "test-resolver"); } @Test public void pluginsRedefinedByProfileFails() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Profile 'test-profile' already defines: [resolver, accessor]"); Map<String, String> mockedPlugins = new HashMap<>(); mockedPlugins.put("fragmenter", "test-fragmenter"); mockedPlugins.put("accessor", "test-accessor"); mockedPlugins.put("resolver", "test-resolver"); when(mockPluginConf.getPlugins("test-profile")).thenReturn(mockedPlugins); // add profile in addition to plugins parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void undefinedServer() { parameters.remove("X-GP-OPTIONS-SERVER"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals("default", context.getServerName()); } @Test public void threadSafeTrue() { parameters.putSingle("X-GP-OPTIONS-THREAD-SAFE", "TRUE"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertTrue(context.isThreadSafe()); parameters.putSingle("X-GP-OPTIONS-THREAD-SAFE", "true"); context = new HttpRequestParser().parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertTrue(context.isThreadSafe()); } @Test public void threadSafeFalse() { parameters.putSingle("X-GP-OPTIONS-THREAD-SAFE", "False"); RequestContext context = new HttpRequestParser().parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertFalse(context.isThreadSafe()); parameters.putSingle("X-GP-OPTIONS-THREAD-SAFE", "falSE"); context = new HttpRequestParser().parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertFalse(context.isThreadSafe()); } @Test public void threadSafeMaybe() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Illegal boolean value 'maybe'. Usage: [TRUE|FALSE]"); parameters.putSingle("X-GP-OPTIONS-THREAD-SAFE", "maybe"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void threadSafeDefault() { parameters.remove("X-GP-OPTIONS-THREAD-SAFE"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertTrue(context.isThreadSafe()); } @Test public void getFragmentMetadata() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); byte[] location = context.getFragmentMetadata(); assertEquals("Something in the way", new String(location)); } @Test public void getFragmentMetadataNull() { parameters.remove("X-GP-FRAGMENT-METADATA"); RequestContext requestContext = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertNull(requestContext.getFragmentMetadata()); } @Test public void getFragmentMetadataNotBase64() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Fragment metadata information must be Base64 encoded. (Bad value: so [email protected])"); String badValue = "so [email protected]"; parameters.putSingle("X-GP-FRAGMENT-METADATA", badValue); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void nullUserThrowsException() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Property USER has no value in the current request"); parameters.remove("X-GP-USER"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void filterUtf8() { parameters.remove("X-GP-HAS-FILTER"); parameters.putSingle("X-GP-HAS-FILTER", "1"); String isoString = new String("UTF8_計算機用語_00000000".getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1); parameters.putSingle("X-GP-FILTER", isoString); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertTrue(context.hasFilter()); assertEquals("UTF8_計算機用語_00000000", context.getFilterString()); } @Test public void statsParams() { parameters.putSingle("X-GP-OPTIONS-STATS-MAX-FRAGMENTS", "10101"); parameters.putSingle("X-GP-OPTIONS-STATS-SAMPLE-RATIO", "0.039"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(10101, context.getStatsMaxFragments()); assertEquals(0.039, context.getStatsSampleRatio(), 0.01); } @Test public void testInvalidStatsSampleRatioValue() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("For input string: \"a\""); parameters.putSingle("X-GP-OPTIONS-STATS-SAMPLE-RATIO", "a"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void testInvalidStatsMaxFragmentsValue() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("For input string: \"10.101\""); parameters.putSingle("X-GP-OPTIONS-STATS-MAX-FRAGMENTS", "10.101"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void typeMods() { parameters.putSingle("X-GP-ATTRS", "2"); parameters.putSingle("X-GP-ATTR-NAME0", "vc1"); parameters.putSingle("X-GP-ATTR-TYPECODE0", "1043"); parameters.putSingle("X-GP-ATTR-TYPENAME0", "varchar"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-COUNT", "1"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-0", "5"); parameters.putSingle("X-GP-ATTR-NAME1", "dec1"); parameters.putSingle("X-GP-ATTR-TYPECODE1", "1700"); parameters.putSingle("X-GP-ATTR-TYPENAME1", "numeric"); parameters.putSingle("X-GP-ATTR-TYPEMOD1-COUNT", "2"); parameters.putSingle("X-GP-ATTR-TYPEMOD1-0", "10"); parameters.putSingle("X-GP-ATTR-TYPEMOD1-1", "2"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertArrayEquals(new Integer[]{5}, context.getColumn(0).columnTypeModifiers()); assertArrayEquals(new Integer[]{10, 2}, context.getColumn(1).columnTypeModifiers()); } @Test public void typeModCountNonIntegerFails() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("ATTR-TYPEMOD0-COUNT must be an integer"); parameters.putSingle("X-GP-ATTRS", "1"); parameters.putSingle("X-GP-ATTR-NAME0", "vc1"); parameters.putSingle("X-GP-ATTR-TYPECODE0", "1043"); parameters.putSingle("X-GP-ATTR-TYPENAME0", "varchar"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-COUNT", "X"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-0", "42"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void typeModCountNegativeIntegerFails() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("ATTR-TYPEMOD0-COUNT must be a positive integer"); parameters.putSingle("X-GP-ATTRS", "1"); parameters.putSingle("X-GP-ATTR-NAME0", "vc1"); parameters.putSingle("X-GP-ATTR-TYPECODE0", "1043"); parameters.putSingle("X-GP-ATTR-TYPENAME0", "varchar"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-COUNT", "-1"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-0", "42"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void typeModNonIntegerFails() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("ATTR-TYPEMOD0-0 must be an integer"); parameters.putSingle("X-GP-ATTRS", "1"); parameters.putSingle("X-GP-ATTR-NAME0", "vc1"); parameters.putSingle("X-GP-ATTR-TYPECODE0", "1043"); parameters.putSingle("X-GP-ATTR-TYPENAME0", "varchar"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-COUNT", "1"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-0", "Y"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void providedTypeModsLessThanTypeModCountFails() { thrown.expect(IllegalArgumentException.class); thrown.expectMessage("Property ATTR-TYPEMOD0-1 has no value in the current request"); parameters.putSingle("X-GP-ATTRS", "1"); parameters.putSingle("X-GP-ATTR-NAME0", "vc1"); parameters.putSingle("X-GP-ATTR-TYPECODE0", "1043"); parameters.putSingle("X-GP-ATTR-TYPENAME0", "varchar"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-COUNT", "2"); parameters.putSingle("X-GP-ATTR-TYPEMOD0-0", "42"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void protocolIsSetWhenProfileIsSpecified() { parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); when(mockPluginConf.getProtocol("test-profile")).thenReturn("test-protocol"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals("test-protocol", context.getProfileScheme()); } @Test public void whitelistedOptionsAreAddedAsProperties() { parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); parameters.putSingle("X-GP-OPTIONS-CONFIGPROP1", "config-prop-value1"); parameters.putSingle("X-GP-OPTIONS-CONFIGPROP3", "config-prop-value3"); parameters.putSingle("X-GP-OPTIONS-CONFIGPROP4", null); parameters.putSingle("X-GP-OPTIONS-CONFIGPROP5", "config-prop-value5"); Map<String, String> mappings = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); mappings.put("configprop1", "cfg.prop1"); // normal mappings.put("configprop2", "cfg.prop2"); // missing in request mappings.put("configprop3", "cfg.prop3"); // normal mappings.put("configprop4", "cfg.prop4"); // null value in request mappings.put("configprop5", ""); // empty mapping when(mockPluginConf.getOptionMappings("test-profile")).thenReturn(mappings); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); // mappings has 5 props, but only 4 are provided in the request and one has empty mapping assertEquals(3, context.getAdditionalConfigProps().size()); assertEquals("config-prop-value1", context.getAdditionalConfigProps().get("cfg.prop1")); assertEquals("config-prop-value3", context.getAdditionalConfigProps().get("cfg.prop3")); assertEquals("", context.getAdditionalConfigProps().get("cfg.prop4")); // ensure the options are still set as well assertEquals("config-prop-value1", context.getOption("configprop1")); assertEquals("config-prop-value3", context.getOption("configprop3")); assertEquals("", context.getOption("configprop4")); assertEquals("config-prop-value5", context.getOption("configprop5")); } @Test public void testWireFormatIsAbsent() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(OutputFormat.TEXT, context.getOutputFormat()); assertNull(context.getFormat()); } @Test public void testWireFormatIsPresentAndFormatIsInferred() { parameters.putSingle("X-GP-FORMAT", "GPDBWritable"); parameters.putSingle("X-GP-OPTIONS-PROFILE", "foo:bar"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(OutputFormat.GPDBWritable, context.getOutputFormat()); assertEquals("bar", context.getFormat()); } @Test public void testWireFormatIsPresentAndFormatIsInferredToNothing() { parameters.putSingle("X-GP-FORMAT", "GPDBWritable"); parameters.putSingle("X-GP-OPTIONS-PROFILE", "foobar"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(OutputFormat.GPDBWritable, context.getOutputFormat()); assertNull(context.getFormat()); } @Test public void testWireFormatIsPresent() { parameters.putSingle("X-GP-FORMAT", "TEXT"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(OutputFormat.TEXT, context.getOutputFormat()); assertNull(context.getFormat()); } @Test public void testWireFormatAndFormatArePresent() { // wire format parameters.putSingle("X-GP-FORMAT", "TEXT"); // data format parameters.putSingle("X-GP-OPTIONS-FORMAT", "foobar"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(OutputFormat.TEXT, context.getOutputFormat()); assertEquals("foobar", context.getFormat()); } @Test public void testHandlerIsCalled() { when(mockPluginConf.getHandler("test-profile")).thenReturn(TestHandler.class.getName()); parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals("overridden-fragmenter", context.getFragmenter()); assertEquals("overridden-accessor", context.getAccessor()); assertEquals("overridden-resolver", context.getResolver()); } @Test public void testHandlerIsNotCalledWhenNotDefined() { when(mockPluginConf.getHandler("test-profile")).thenReturn(null); parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals("are", context.getAccessor()); assertEquals("packed", context.getResolver()); } @Test public void testInvalidHandlerCausesException() { thrown.expect(RuntimeException.class); thrown.expectMessage("Error when invoking handlerClass 'foo' : java.lang.ClassNotFoundException: foo"); when(mockPluginConf.getHandler("test-profile")).thenReturn("foo"); parameters.putSingle("X-GP-OPTIONS-PROFILE", "test-profile"); parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); } @Test public void testWritePath() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.WRITE_BRIDGE); assertEquals(RequestType.WRITE_BRIDGE, context.getRequestType()); } @Test public void testFragmenterPath() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.FRAGMENTER); assertEquals(RequestType.FRAGMENTER, context.getRequestType()); } @Test public void testReadPath() { RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.READ_BRIDGE); assertEquals(RequestType.READ_BRIDGE, context.getRequestType()); } @Test public void testEncodedHeaderValuesIsFalse() throws UnsupportedEncodingException { parameters.remove("X-GP-DATA-DIR"); parameters.putSingle("X-GP-DATA-DIR", URLEncoder.encode("\u0001", "UTF-8")); parameters.putSingle("X-GP-ENCODED-HEADER-VALUES", "false"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.READ_BRIDGE); assertEquals("%01", context.getDataSource()); // non encoded fields shouldn't be affected assertEquals(context.getAccessor(), "are"); assertEquals(context.getResolver(), "packed"); assertEquals(context.getOption("i'm-standing-here"), "outside-your-door"); assertEquals(context.getUser(), "alex"); } @Test public void testEncodedHeaderValuesIsTrue() throws UnsupportedEncodingException { parameters.remove("X-GP-DATA-DIR"); parameters.putSingle("X-GP-DATA-DIR", URLEncoder.encode("\u0001", "UTF-8")); parameters.putSingle("X-GP-ENCODED-HEADER-VALUES", "trUe"); RequestContext context = parser.parseRequest(mockRequestHeaders, RequestType.READ_BRIDGE); assertEquals("\u0001", context.getDataSource()); // non encoded fields shouldn't be affected assertEquals(context.getAccessor(), "are"); assertEquals(context.getResolver(), "packed"); assertEquals(context.getOption("i'm-standing-here"), "outside-your-door"); assertEquals(context.getUser(), "alex"); } static class TestHandler implements ProtocolHandler { @Override public String getFragmenterClassName(RequestContext context) { return "overridden-fragmenter"; } @Override public String getAccessorClassName(RequestContext context) { return "overridden-accessor"; } @Override public String getResolverClassName(RequestContext context) { return "overridden-resolver"; } } }