/*
 *  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
}
