blob: 6bcdaef77eb79bf85ff26e87f031766a1244f246 [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 tests.api.java.nio.charset;
import dalvik.annotation.KnownFailure;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
import dalvik.annotation.AndroidOnly;
import junit.framework.TestCase;
import tests.api.java.nio.charset.CharsetTest.MockCharset;
import tests.api.java.nio.charset.CharsetTest.MockSecurityManager;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.charset.spi.CharsetProvider;
import java.util.Iterator;
import java.util.SortedMap;
import java.util.Vector;
@TestTargetClass(CharsetProvider.class)
/**
* Test charset providers managed by Charset.
*/
public class CharsetProviderTest extends TestCase {
// need to be modified, e.g., read from system property
static String PROP_CONFIG_FILE1 = "clear.tests.cp1";
static String CONFIG_FILE1 = null;
static MockCharset charset1 = new MockCharset("mockCharset00",
new String[] { "mockCharset01", "mockCharset02" });
static MockCharset charset2 = new MockCharset("mockCharset10",
new String[] { "mockCharset11", "mockCharset12" });
@Override
protected void setUp() {
String tmpDir = System.getProperty("java.io.tmpdir");
if (tmpDir == null) {
fail("java.io.tmpdir not set");
}
File tmpdir = new File(tmpDir);
if (!tmpdir.isDirectory()) {
fail("java.io.tmpdir is not a directory");
}
String sep = System.getProperty("file.separator");
if (!tmpDir.endsWith(sep)) {
tmpDir += sep;
}
CONFIG_FILE1 = tmpDir + "META-INF" + sep + "services" + sep
+ "java.nio.charset.spi.CharsetProvider";
URL url = null;
try {
url = new URL("file://" + tmpDir);
} catch (MalformedURLException e) {
fail("unexpected exception: " + e);
}
ClassLoader parent = Thread.currentThread().getContextClassLoader();
if (parent == null) {
parent = ClassLoader.getSystemClassLoader();
}
URLClassLoader urlc = new URLClassLoader(new URL[] { url }, parent);
Thread.currentThread().setContextClassLoader(urlc);
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
Thread.currentThread().setContextClassLoader(null);
}
/*
* Write the string to the config file.
*/
private void setupFile(String path, String content) throws Exception {
String sep = System.getProperty("file.separator");
int sepIndex = path.lastIndexOf(sep);
File f = new File(path.substring(0, sepIndex));
f.mkdirs();
FileOutputStream fos = new FileOutputStream(path);
OutputStreamWriter writer = new OutputStreamWriter(fos);// , "UTF-8");
try {
writer.write(content);
} finally {
writer.close();
}
}
/*
* Write the string to the config file.
*/
private void cleanupFile(String path) throws Exception {
File f = new File(path);
f.delete();
}
/*
* Test the method isSupported(String) with charset supported by some
* providers (multiple).
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testIsSupported_And_ForName_NormalProvider() throws Exception {
try {
assertFalse(Charset.isSupported("mockCharset10"));
assertFalse(Charset.isSupported("mockCharset11"));
assertFalse(Charset.isSupported("mockCharset12"));
try {
Charset.forName("mockCharset10");
fail("Should throw UnsupportedCharsetException!");
} catch (UnsupportedCharsetException e) {
// expected
}
try {
Charset.forName("mockCharset11");
fail("Should throw UnsupportedCharsetException!");
} catch (UnsupportedCharsetException e) {
// expected
}
try {
Charset.forName("mockCharset12");
fail("Should throw UnsupportedCharsetException!");
} catch (UnsupportedCharsetException e) {
// expected
}
StringBuffer sb = new StringBuffer();
sb.append("#comment\r");
sb.append("\n");
sb.append("\r\n");
sb.append(" \ttests.api.java.nio.charset."
+ "CharsetTest$MockCharsetProvider \t\n\r");
sb.append(" \ttests.api.java.nio.charset."
+ "CharsetTest$MockCharsetProvider \t");
setupFile(CONFIG_FILE1, sb.toString());
sb = new StringBuffer();
sb.append(" #comment\r");
sb.append("\n");
sb.append("\r\n");
sb.append(" \ttests.api.java.nio.charset."
+ "CharsetProviderTest$MockCharsetProvider \t\n\r");
setupFile(CONFIG_FILE1, sb.toString());
assertTrue(Charset.isSupported("mockCharset10"));
// ignore case problem in mock, intended
assertTrue(Charset.isSupported("MockCharset11"));
assertTrue(Charset.isSupported("MockCharset12"));
assertTrue(Charset.isSupported("MOCKCharset10"));
// intended case problem in mock
assertTrue(Charset.isSupported("MOCKCharset11"));
assertTrue(Charset.isSupported("MOCKCharset12"));
assertTrue(Charset.forName("mockCharset10") instanceof MockCharset);
assertTrue(Charset.forName("mockCharset11") instanceof MockCharset);
assertTrue(Charset.forName("mockCharset12") instanceof MockCharset);
assertTrue(Charset.forName("mockCharset10") == charset2);
// intended case problem in mock
Charset.forName("mockCharset11");
assertTrue(Charset.forName("mockCharset12") == charset2);
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method isSupported(String) when the configuration file contains
* a non-existing class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
public void testIsSupported_NonExistingClass() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("impossible\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.isSupported("impossible");
fail("Should throw Error!");
} catch (Error e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method isSupported(String) when the configuration file contains
* a non-CharsetProvider class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testIsSupported_NotCharsetProviderClass() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("java.lang.String\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.isSupported("impossible");
fail("Should throw ClassCastException!");
} catch (ClassCastException e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method isSupported(String) with insufficient privilege to use
* charset provider.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@KnownFailure("Android throws Error in case of insufficient privileges, " +
"RI throws SecurityException")
public void testIsSupported_InsufficientPrivilege() throws Exception {
SecurityManager oldMan = System.getSecurityManager();
System.setSecurityManager(new MockSecurityManager());
try {
Charset.isSupported("UTF-8");
try {
StringBuffer sb = new StringBuffer();
sb.append("tests.api.java.nio.charset."
+ "CharsetProviderTest$MockCharsetProvider\r");
setupFile(CONFIG_FILE1, sb.toString());
assertFalse(Charset.isSupported("gb180300000"));
} catch (SecurityException e) {
fail("unexpected SecurityException!:" + e);
} finally {
cleanupFile(CONFIG_FILE1);
}
} finally {
System.setSecurityManager(oldMan);
}
}
/*
* Test the method isSupported(String) with insufficient privilege to use
* charset provider.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@KnownFailure("Android throws Error in case of insufficient privileges, " +
"RI throws SecurityException")
public void testForName_InsufficientPrivilege() throws Exception {
SecurityManager oldMan = System.getSecurityManager();
System.setSecurityManager(new MockSecurityManager());
try {
Charset.forName("UTF-8");
try {
StringBuffer sb = new StringBuffer();
sb.append("tests.api.java.nio.charset."
+ "CharsetProviderTest$MockCharsetProvider\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.forName("gb180300000");
fail("expected UnsupportedCharsetException!");
} catch (SecurityException e) {
fail("unexpected SecurityException!:" + e);
} catch (UnsupportedCharsetException e) {
// ok
} finally {
cleanupFile(CONFIG_FILE1);
}
} finally {
System.setSecurityManager(oldMan);
}
}
/*
* Test the method forName(String) when the charset provider supports a
* built-in charset.
*/
@TestTargets({
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsets",
args = {}
),
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
})
public void testForName_DuplicateWithBuiltInCharset() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("tests.api.java.nio.charset." +
"CharsetProviderTest$MockCharsetProviderACSII\r");
setupFile(CONFIG_FILE1, sb.toString());
assertFalse(Charset.forName("us-ascii") instanceof MockCharset);
Charset charset = Charset.availableCharsets().get("us-ascii");
assertFalse(charset instanceof MockCharset);
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method forName(String) when the configuration file contains a
* non-existing class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testForName_NonExistingClass() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("impossible\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.forName("impossible");
fail("Should throw Error!");
} catch (Error e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method forName(String) when the configuration file contains a
* non-CharsetProvider class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsetForName",
args = {String.class}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testForName_NotCharsetProviderClass() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("java.lang.String\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.forName("impossible");
fail("Should throw ClassCastException!");
} catch (ClassCastException e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method availableCharsets() with charset supported by some
* providers (multiple).
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsets",
args = {}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testAvailableCharsets_NormalProvider() throws Exception {
try {
assertFalse(Charset.availableCharsets()
.containsKey("mockCharset10"));
assertFalse(Charset.availableCharsets()
.containsKey("mockCharset11"));
assertFalse(Charset.availableCharsets()
.containsKey("mockCharset12"));
StringBuffer sb = new StringBuffer();
sb.append("#comment\r");
sb.append("\n");
sb.append("\r\n");
sb.append("\ttests.api.java.nio.charset."
+ "CharsetTest$MockCharsetProvider \t\n\r");
sb.append("\ttests.api.java.nio.charset."
+ "CharsetTest$MockCharsetProvider \t");
sb.append("#comment\r");
sb.append("\n");
sb.append("\r\n");
sb.append(" \ttests.api.java.nio.charset."
+ "CharsetProviderTest$MockCharsetProvider \t\n\r");
setupFile(CONFIG_FILE1, sb.toString());
SortedMap<String, Charset> availableCharsets = Charset
.availableCharsets();
assertTrue(availableCharsets.containsKey("mockCharset00"));
assertTrue(availableCharsets.containsKey("MOCKCharset00"));
Charset charset = availableCharsets.get("mockCharset00");
assertTrue(charset instanceof MockCharset);
charset = availableCharsets.get("MOCKCharset00");
assertTrue(charset instanceof MockCharset);
assertFalse(availableCharsets.containsKey("mockCharset01"));
assertFalse(availableCharsets.containsKey("mockCharset02"));
charset = availableCharsets.get("mockCharset10");
assertTrue(charset == charset2);
charset = availableCharsets.get("MOCKCharset10");
assertTrue(charset == charset2);
assertFalse(availableCharsets.containsKey("mockCharset11"));
assertFalse(availableCharsets.containsKey("mockCharset12"));
assertTrue(availableCharsets.containsKey("mockCharset10"));
assertTrue(availableCharsets.containsKey("MOCKCharset10"));
charset = availableCharsets.get("mockCharset10");
assertTrue(charset == charset2);
assertFalse(availableCharsets.containsKey("mockCharset11"));
assertFalse(availableCharsets.containsKey("mockCharset12"));
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method availableCharsets(String) when the configuration file
* contains a non-existing class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsets",
args = {}
)
public void testAvailableCharsets_NonExistingClass() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("impossible\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.availableCharsets();
fail("Should throw Error!");
} catch (Error e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method availableCharsets(String) when the configuration file
* contains a non-CharsetProvider class name.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsets",
args = {}
)
@AndroidOnly("Looks like RI doesn't use current thread's context class "+
"loader to lookup charset providers")
public void testAvailableCharsets_NotCharsetProviderClass()
throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("java.lang.String\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.availableCharsets();
fail("Should throw ClassCastException!");
} catch (ClassCastException e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Test the method availableCharsets(String) when the configuration file
* contains an illegal string.
*/
@TestTargetNew(
level = TestLevel.PARTIAL_COMPLETE,
notes = "",
method = "charsets",
args = {}
)
public void testAvailableCharsets_IllegalString() throws Exception {
try {
StringBuffer sb = new StringBuffer();
sb.append("java String\r");
setupFile(CONFIG_FILE1, sb.toString());
Charset.availableCharsets();
fail("Should throw Error!");
} catch (Error e) {
// expected
} finally {
cleanupFile(CONFIG_FILE1);
}
}
/*
* Mock charset provider.
*/
public static class MockCharsetProvider extends CharsetProvider {
public Charset charsetForName(String charsetName) {
if ("MockCharset10".equalsIgnoreCase(charsetName)
|| "MockCharset11".equalsIgnoreCase(charsetName)
|| "MockCharset12".equalsIgnoreCase(charsetName)) {
return charset2;
}
return null;
}
public Iterator<Charset> charsets() {
Vector<Charset> v = new Vector<Charset>();
v.add(charset2);
return v.iterator();
}
}
/*
* Another mock charset provider providing build-in charset "ascii".
*/
public static class MockCharsetProviderACSII extends CharsetProvider {
public Charset charsetForName(String charsetName) {
if ("US-ASCII".equalsIgnoreCase(charsetName)
|| "ASCII".equalsIgnoreCase(charsetName)) {
return new MockCharset("US-ASCII", new String[] { "ASCII" });
}
return null;
}
public Iterator<Charset> charsets() {
Vector<Charset> v = new Vector<Charset>();
v.add(new MockCharset("US-ASCII", new String[] { "ASCII" }));
return v.iterator();
}
}
}