blob: 4462f81385d66b0b9845d13afbbb49cadba3c94b [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.
*/
/**
* @author Boris V. Kuznetsov
* @version $Revision$
*/
package org.apache.harmony.security.tests.java.security;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.security.NoSuchAlgorithmException;
import java.security.Permission;
import java.security.Provider;
import java.security.Security;
import java.security.SecurityPermission;
import java.security.Provider.Service;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.Map.Entry;
import junit.framework.TestCase;
/**
* Tests for <code>Provider</code> constructor and methods
*
*/
public class ProviderTest extends TestCase {
/*
* Implementation note: The algorithm name ASH-1 might seem a bit strange,
* but since the algorithms cannot be uninstalled anymore we need to make
* sure there are not side-effects on other tests. Simply inserting SHA-1
* destroys the existing provider infrastructure.
*/
Provider[] storedProviders;
Provider p;
/*
* @see TestCase#setUp()
*/
protected void setUp() throws Exception {
super.setUp();
storedProviders = Security.getProviders();
p = new MyProvider();
}
@Override
protected void tearDown() throws Exception {
p.remove("MessageDigest.ASH-1");
p.remove("MessageDigest.abc");
p.remove("Alg.Alias.MessageDigest.ASH1");
for (Provider p: Security.getProviders()) {
Security.removeProvider(p.getName());
}
for (Provider p: storedProviders) {
Security.addProvider(p);
}
super.tearDown();
}
/*
* Class under test for void Provider()
*/
public final void testProvider() {
if (!p.getProperty("Provider.id name").equals(
String.valueOf(p.getName()))) {
fail("Incorrect \"Provider.id name\" value");
}
if (!p.getProperty("Provider.id version").equals(
String.valueOf(p.getVersion()))) {
fail("Incorrect \"Provider.id version\" value");
}
if (!p.getProperty("Provider.id info").equals(
String.valueOf(p.getInfo()))) {
fail("Incorrect \"Provider.id info\" value");
}
if (!p.getProperty("Provider.id className").equals(
p.getClass().getName())) {
fail("Incorrect \"Provider.id className\" value");
}
}
public final void testClear() {
p.clear();
assertNull(p.getProperty("MessageDigest.SHA-1"));
}
/*
* Class under test for void Provider(String, double, String)
*/
public final void testProviderStringdoubleString() {
Provider p = new MyProvider("Provider name", 123.456, "Provider info");
assertEquals("Provider name", p.getName());
assertEquals(123.456, p.getVersion(), 0L);
assertEquals("Provider info", p.getInfo());
}
public final void testGetName() {
assertEquals("MyProvider", p.getName());
}
public final void testGetVersion() {
assertEquals(1.0, p.getVersion(), 0L);
}
public final void testGetInfo() {
assertEquals("Provider for testing", p.getInfo());
}
/*
* Class under test for void putAll(Map)
*/
public final void testPutAllMap() {
HashMap hm = new HashMap();
hm.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
hm.put("Property 1", "value 1");
hm.put("serviceName.algName attrName", "attrValue");
hm.put("Alg.Alias.engineClassName.aliasName", "standardName");
p.putAll(hm);
if (!"value 1".equals(p.getProperty("Property 1").trim()) ||
!"attrValue".equals(p.getProperty("serviceName.algName attrName").trim()) ||
!"standardName".equals(p.getProperty("Alg.Alias.engineClassName.aliasName").trim()) ||
!"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.SHA-1").trim()) ) {
fail("Incorrect property value");
}
}
/*
* Class under test for Set entrySet()
*/
public final void testEntrySet() {
p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
Set s = p.entrySet();
try {
s.clear();
fail("Must return unmodifiable set");
} catch (UnsupportedOperationException e) {
}
assertEquals("Incorrect set size", 8, s.size());
for (Iterator it = s.iterator(); it.hasNext();) {
Entry e = (Entry)it.next();
String key = (String)e.getKey();
String val = (String)e.getValue();
if (key.equals("MessageDigest.SHA-1") && val.equals("SomeClassName")) {
continue;
}
if (key.equals("Alg.Alias.MessageDigest.SHA1") && val.equals("SHA-1")) {
continue;
}
if (key.equals("MessageDigest.abc") && val.equals("SomeClassName")) {
continue;
}
if (key.equals("Provider.id className") && val.equals(p.getClass().getName())) {
continue;
}
if (key.equals("Provider.id name") && val.equals("MyProvider")) {
continue;
}
if (key.equals("MessageDigest.SHA-256") && val.equals("aaa.bbb.ccc.ddd")) {
continue;
}
if (key.equals("Provider.id version") && val.equals("1.0")) {
continue;
}
if (key.equals("Provider.id info") && val.equals("Provider for testing")) {
continue;
}
fail("Incorrect set");
}
}
public final void testForEach() {
p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
p.put("MessageDigest.abc", "value 1");
HashMap<String, String> hm = new HashMap<>();
p.forEach((k,v)-> hm.put((String)k, (String)v));
assertEquals(p.size(), hm.size());
for(String key : hm.keySet()) {
assertEquals(p.get(key), hm.get(key));
}
}
public void testForEachNPE() throws Exception {
try {
p.forEach(null);
fail();
} catch(NullPointerException expected) {}
}
public void testForEachCME() throws Exception {
p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
p.put("MessageDigest.abc", "value 1");
try {
p.forEach(new java.util.function.BiConsumer<Object, Object>() {
@Override
public void accept(Object k, Object v) {p.put("foo", "bar");}
});
fail();
} catch(ConcurrentModificationException expected) {}
}
/*
* Class under test for Set keySet()
*/
public final void testKeySet() {
p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
Set<Object> s = p.keySet();
try {
s.clear();
} catch (UnsupportedOperationException e) {
}
Set s1 = p.keySet();
assertNotSame(s, s1);
assertFalse(s1.isEmpty());
assertEquals(8, s1.size());
assertTrue(s1.contains("MessageDigest.SHA-256"));
assertTrue(s1.contains("MessageDigest.SHA-1"));
assertTrue(s1.contains("Alg.Alias.MessageDigest.SHA1"));
assertTrue(s1.contains("MessageDigest.abc"));
assertTrue(s1.contains("Provider.id info"));
assertTrue(s1.contains("Provider.id className"));
assertTrue(s1.contains("Provider.id version"));
assertTrue(s1.contains("Provider.id name"));
}
/*
* Class under test for Collection values()
*/
public final void testValues() {
p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
Collection<Object> c = p.values();
try {
c.clear();
} catch (UnsupportedOperationException e) {
}
Collection c1 = p.values();
assertNotSame(c, c1);
assertFalse(c1.isEmpty());
assertEquals(8, c1.size());
assertTrue(c1.contains("MyProvider"));
assertTrue(c1.contains("aaa.bbb.ccc.ddd"));
assertTrue(c1.contains("Provider for testing"));
assertTrue(c1.contains("1.0"));
assertTrue(c1.contains("SomeClassName"));
assertTrue(c1.contains("SHA-1"));
assertTrue(c1.contains(p.getClass().getName()));
}
/*
* Class under test for Object put(Object, Object)
*/
public final void testPutObjectObject() {
p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
p.put("Type.Algorithm", "className");
assertEquals("aaa.bbb.ccc.ddd", p.getProperty("MessageDigest.SHA-1")
.trim());
Set services = p.getServices();
assertEquals(3, services.size());
for (Iterator it = services.iterator(); it.hasNext();) {
Provider.Service s = (Provider.Service)it.next();
if ("Type".equals(s.getType()) &&
"Algorithm".equals(s.getAlgorithm()) &&
"className".equals(s.getClassName())) {
continue;
}
if ("MessageDigest".equals(s.getType()) &&
"SHA-1".equals(s.getAlgorithm()) &&
"aaa.bbb.ccc.ddd".equals(s.getClassName())) {
continue;
}
if ("MessageDigest".equals(s.getType()) &&
"abc".equals(s.getAlgorithm()) &&
"SomeClassName".equals(s.getClassName())) {
continue;
}
fail("Incorrect service");
}
}
/*
* Class under test for Object remove(Object)
*/
public final void testRemoveObject() {
Object o = p.remove("MessageDigest.SHA-1");
assertEquals("SomeClassName", o);
assertNull(p.getProperty("MessageDigest.SHA-1"));
assertEquals(1, p.getServices().size());
}
public final void testService1() {
p.put("MessageDigest.SHA-1", "AnotherClassName");
Provider.Service s = p.getService("MessageDigest", "SHA-1");
assertEquals("AnotherClassName", s.getClassName());
}
public final void testGetServiceCaseSensitivity() {
p.put("i.I", "foo");
Locale defaultLocale = Locale.getDefault();
Locale.setDefault(new Locale("tr", "TR"));
try {
assertEquals("foo", p.getService("i", "i").getClassName());
assertEquals("foo", p.getService("i", "I").getClassName());
assertNull(p.getService("\u0130", "\u0130")); // Turkish dotless i and dotted I
assertNull(p.getService("\u0131", "\u0131"));
} finally {
Locale.setDefault(defaultLocale);
}
}
// Regression for HARMONY-2760.
public void testConstructor() {
MyProvider myProvider = new MyProvider(null, 1, null);
assertNull(myProvider.getName());
assertNull(myProvider.getInfo());
assertEquals("null", myProvider.getProperty("Provider.id name"));
assertEquals("null", myProvider.getProperty("Provider.id info"));
}
class MyProvider extends Provider {
MyProvider() {
super("MyProvider", 1.0, "Provider for testing");
put("MessageDigest.SHA-1", "SomeClassName");
put("MessageDigest.abc", "SomeClassName");
put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
}
MyProvider(String name, double version, String info) {
super(name, version, info);
}
// BEGIN android-added
public void putService(Provider.Service s) {
super.putService(s);
}
// END android-added
// BEGIN android-added
public void removeService(Provider.Service s) {
super.removeService(s);
}
// END android-added
// BEGIN android-added
public int getNumServices() {
return getServices().size();
}
// END android-added
}
// BEGIN android-added
public final void testService2() {
Provider[] pp = Security.getProviders("MessageDigest.ASH-1");
if (pp == null) {
return;
}
Provider p2 = pp[0];
String old = p2.getProperty("MessageDigest.ASH-1");
p2.put("MessageDigest.ASH-1", "AnotherClassName");
Provider.Service s = p2.getService("MessageDigest", "ASH-1");
if (!"AnotherClassName".equals(s.getClassName())) {
fail("Incorrect class name " + s.getClassName());
}
try {
s.newInstance(null);
fail("No expected NoSuchAlgorithmException");
} catch (NoSuchAlgorithmException e) {
}
}
// END android-added
// BEGIN android-added
public final void testGetServices() {
MyProvider myProvider = new MyProvider(null, 1, null);
Set<Provider.Service> services = myProvider.getServices();
assertEquals(0, services.size());
Provider.Service s[] = new Provider.Service[3];
s[0] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
null, null);
s[1] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
null, null);
s[2] = new Provider.Service(myProvider, "type3", "algorithm3", "className3",
null, null);
myProvider.putService(s[0]);
myProvider.putService(s[1]);
assertEquals(2, myProvider.getNumServices());
Set<Service> actual = myProvider.getServices();
assertTrue(actual.contains(s[0]));
assertTrue(actual.contains(s[1]));
assertTrue(!actual.contains(s[2]));
myProvider.removeService(s[1]);
actual = myProvider.getServices();
assertEquals(1, myProvider.getNumServices());
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(!actual.contains(s[2]));
myProvider.putService(s[2]);
actual = myProvider.getServices();
assertEquals(2, myProvider.getNumServices());
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
}
// END android-added
// BEGIN android-added
public final void testPutService() {
MyProvider myProvider = new MyProvider(null, 1, null);
Provider.Service s[] = new Provider.Service[3];
s[0] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
null, null);
s[1] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
null, null);
s[2] = new Provider.Service(myProvider, "type3", "algorithm3", "className3",
null, null);
myProvider.putService(s[0]);
myProvider.putService(s[1]);
assertEquals(2, myProvider.getNumServices());
Set<Service> actual = myProvider.getServices();
assertTrue(actual.contains(s[0]));
assertTrue(actual.contains(s[1]));
assertTrue(!actual.contains(s[2]));
myProvider.removeService(s[1]);
assertEquals(1, myProvider.getNumServices());
actual = myProvider.getServices();
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(!actual.contains(s[2]));
myProvider.putService(s[2]);
actual = myProvider.getServices();
assertEquals(2, myProvider.getNumServices());
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
myProvider.putService(s[2]);
actual = myProvider.getServices();
assertEquals(2, myProvider.getNumServices());
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
try {
myProvider.putService(null);
fail("NullPointerException expected");
} catch (NullPointerException e) {
// expected
}
}
// END android-added
// BEGIN android-added
public final void testRemoveService() {
MyProvider myProvider = new MyProvider(null, 1, null);
try {
myProvider.removeService(null);
fail("NullPoiterException expected");
} catch (NullPointerException e) {
// expected
}
Provider.Service s[] = new Provider.Service[3];
s[0] = new Provider.Service(myProvider, "type0", "algorithm0", "className0",
null, null);
s[1] = new Provider.Service(myProvider, "type1", "algorithm1", "className1",
null, null);
s[2] = new Provider.Service(myProvider, "type2", "algorithm2", "className2",
null, null);
try {
myProvider.removeService(s[0]);
} catch (NullPointerException e) {
fail("Unexpected exception");
}
myProvider.putService(s[0]);
myProvider.putService(s[1]);
myProvider.putService(s[2]);
assertEquals(3, myProvider.getNumServices());
Set<Service> actual = myProvider.getServices();
assertTrue(actual.contains(s[0]));
assertTrue(actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
myProvider.removeService(s[1]);
assertEquals(2, myProvider.getNumServices());
actual = myProvider.getServices();
assertTrue(actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
myProvider.removeService(s[0]);
assertEquals(1, myProvider.getNumServices());
actual = myProvider.getServices();
assertTrue(!actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(actual.contains(s[2]));
myProvider.removeService(s[2]);
assertEquals(0, myProvider.getNumServices());
actual = myProvider.getServices();
assertTrue(!actual.contains(s[0]));
assertTrue(!actual.contains(s[1]));
assertTrue(!actual.contains(s[2]));
try {
myProvider.removeService(null);
fail("NullPoiterException expected");
} catch (NullPointerException e) {
// expected
}
}
// END android-added
// BEGIN android-added
public final void testLoad() throws IOException {
InputStream is = new ByteArrayInputStream(writeProperties());
MyProvider myProvider = new MyProvider("name", 1, "info");
myProvider.load(is);
assertEquals("tests.security", myProvider.get("test.pkg"));
assertEquals("Unit Tests", myProvider.get("test.proj"));
assertNull(myProvider.get("#commented.entry"));
assertEquals("info", myProvider.get("Provider.id info"));
String className = myProvider.getClass().toString();
assertEquals(
className.substring("class ".length(), className.length()),
myProvider.get("Provider.id className"));
assertEquals("1.0", myProvider.get("Provider.id version"));
try {
myProvider.load((InputStream) null);
fail("NullPointerException expected");
} catch (NullPointerException e) {
// expected
}
}
// END android-added
// BEGIN android-added
public final void testLoad2() {
class TestInputStream extends InputStream {
@Override
public int read() throws IOException {
throw new IOException();
}
}
MyProvider p = new MyProvider();
try {
p.load(new TestInputStream());
fail("expected IOException");
} catch (IOException e) {
// expected
}
}
// END android-added
// BEGIN android-added
protected byte[] writeProperties() {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bout);
ps.println("#commented.entry=Bogus");
ps.println("test.pkg=tests.security");
ps.println("test.proj=Unit Tests");
ps.close();
return bout.toByteArray();
}
// END android-added
// BEGIN android-added
static class TestSecurityManager extends SecurityManager {
boolean called = false;
private final String permissionName;
public TestSecurityManager(String permissionName) {
this.permissionName = permissionName;
}
@Override
public void checkPermission(Permission permission) {
if (permission instanceof SecurityPermission) {
if (permissionName.equals(permission.getName())) {
called = true;
}
}
}
}
// END android-added
}