/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed 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 com.alibaba.citrus.service.requestcontext.util;
import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.net.URLEncoder;
import java.util.Locale;
import java.util.Map;
import com.alibaba.citrus.util.i18n.LocaleUtil;
import org.junit.Test;
public class QueryStringParserTests {
private QueryStringParser parser;
private MapMock map;
@Test
public void charset() {
LocaleUtil.setContext(Locale.CHINA, "GB2312");
// no charset
parser = new MyParser();
assertEquals("GB2312", parser.getCharacterEncoding());
// no defaults
parser = new MyParser(null);
assertEquals("GB2312", parser.getCharacterEncoding());
parser = new MyParser(" ");
assertEquals("GB2312", parser.getCharacterEncoding());
parser = new MyParser(" UTF-8 ");
assertEquals("UTF-8", parser.getCharacterEncoding());
// with defaults
parser = new MyParser(null, null);
assertEquals("GB2312", parser.getCharacterEncoding());
parser = new MyParser(null, " ");
assertEquals("GB2312", parser.getCharacterEncoding());
parser = new MyParser(null, " UTF-8 ");
assertEquals("UTF-8", parser.getCharacterEncoding());
parser = new MyParser(" GBK ", " UTF-8 ");
assertEquals("GBK", parser.getCharacterEncoding());
LocaleUtil.resetContext();
}
@Test
public void append() throws Exception {
parser = new MyParser("GBK");
parser.append("中", "国1");
parser.append("中", "国2");
parser.append("a", null);
parser.append(null, " ");
parser.append("a", ":=,"); // 对:=,进行编码
assertEquals("%D6%D0=%B9%FA1&%D6%D0=%B9%FA2&a=&=++&a=%3A%3D%2C", parser.toQueryString());
assertEquals(null, parser.toQueryString());
}
@Test
public void append_jsonLike() throws Exception {
parser = new MyParser("GBK");
parser.setEqualSign(" : ").setAndSign(", ");
parser.append("中", "国1");
parser.append("中", "国2");
parser.append("a", null);
parser.append(null, " ");
parser.append("a", ":=,"); // 对:=,进行编码
assertEquals("%D6%D0 : %B9%FA1, %D6%D0 : %B9%FA2, a : , : ++, a : %3A%3D%2C", parser.toQueryString());
assertEquals(null, parser.toQueryString());
// turn off json-like
parser.setEqualSign(null).setAndSign(null);
parser.append("中", "国1");
parser.append("中", "国2");
parser.append("a", null);
parser.append(null, " ");
parser.append("a", ":=,"); // 对:=,进行编码
assertEquals("%D6%D0=%B9%FA1&%D6%D0=%B9%FA2&a=&=++&a=%3A%3D%2C", parser.toQueryString());
assertEquals(null, parser.toQueryString());
}
@Test
public void appendMap() throws Exception {
parser = new MyParser("GBK");
Map<String, String> params = createLinkedHashMap();
params.put("中", "国1");
params.put("a", null);
params.put(null, " ");
params.put("b", ":="); // 对:=进行编码
parser.append(params);
assertEquals("%D6%D0=%B9%FA1&a=&=++&b=%3A%3D", parser.toQueryString());
assertEquals(null, parser.toQueryString());
}
@Test
public void parse() throws Exception {
assertParse(" &a=1&a=2&b=3& ", null, "a", "1", "a", "2", "b", "3"); // key-values
assertParse("a", null, "a", ""); // key only
assertParse("a&b=&=1", null, "a", "", "b", ""); // hybrid
assertParse(" &a = ++&a=+2+&b=+3+& ", null, "a", " ", "a", " 2 ", "b", " 3 "); // with spaces,注意,忽略空格
}
@Test
public void parse_jsonLike() throws Exception {
assertParse(" ,a:1, a:2, b:3, ", null, true, "a", "1", "a", "2", "b", "3"); // key-values,注意,忽略空格
assertParse("a", null, true, "a", ""); // key only
assertParse("a,b:,:1", null, true, "a", "", "b", ""); // hybrid
assertParse(" ,a:++,a:+2+,b:+3+, ", null, true, "a", " ", "a", " 2 ", "b", " 3 "); // with spaces
}
@Test
public void parseNoExtension() throws Exception {
try {
new QueryStringParser().parse("a=1");
fail();
} catch (UnsupportedOperationException e) {
assertThat(e,
exception("You should extend class QueryStringParser and override method add(String, String)"));
}
}
/** 相当于在IE地址栏中直接输入中文,没有URL encoding */
@Test
public void parseRawBytes() throws Exception {
assertParse(reencode("中=国", "UTF-8"), "UTF-8", "中", "国");
assertParse(reencode("&中=国&", "GBK"), "GBK", "中", "国");
assertParse(reencode("name=中华民国", "UTF-8"), "UTF-8", "name", "中华民国");
}
/** 相当于在Firefox地址栏中直接输入中文,有URL encoding */
@Test
public void parseURLEncoded() throws Exception {
assertParse(urlencode("中=国", "UTF-8"), "UTF-8", "中", "国");
assertParse(urlencode("&中=国&", "GBK"), "GBK", "中", "国");
assertParse(urlencode("name=Justin\u00b7Bieber", "GBK"), "GBK", "name", "Justin\u00b7Bieber");
}
/** 直接是unicode字符。 */
@Test
public void parseUnicode() throws Exception {
assertParse("中=" + reencode("国", "UTF-8"), "UTF-8", "中", "国");
assertParse("&" + reencode("中", "GBK") + "国=世界&", "GBK", "中国", "世界");
}
private void assertParse(String queryString, String charset, String... expectedKeyValues) {
assertParse(queryString, charset, false, expectedKeyValues);
}
private void assertParse(String queryString, String charset, boolean jsonLike, String... expectedKeyValues) {
parser = new MyParser(charset);
if (jsonLike) {
parser.setEqualSign(":").setAndSign(",");
}
map = createMock(MapMock.class);
for (int i = 0; i < expectedKeyValues.length; i += 2) {
map.add(expectedKeyValues[i], expectedKeyValues[i + 1]);
}
replay(map);
parser.parse(queryString);
verify(map);
}
private String reencode(String str, String charset) throws Exception {
return new String(str.getBytes(charset), "8859_1");
}
private String urlencode(String str, String charset) throws Exception {
str = str.replaceAll("=", ".equals.").replaceAll("&", ".and.");
str = URLEncoder.encode(str, charset);
str = str.replaceAll(".equals.", "=").replaceAll(".and.", "&");
return str;
}
private class MyParser extends QueryStringParser {
public MyParser() {
super();
}
public MyParser(String charset) {
super(charset);
}
public MyParser(String charset, String defaultCharset) {
super(charset, defaultCharset);
}
@Override
protected void add(String key, String value) {
map.add(key, value);
}
}
public static interface MapMock {
void add(String key, String value);
}
}