1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18/**
19 * @author Boris V. Kuznetsov
20 * @version $Revision$
21 */
22
23package org.apache.harmony.security.tests.java.security;
24
25import java.io.ByteArrayInputStream;
26import java.io.ByteArrayOutputStream;
27import java.io.IOException;
28import java.io.InputStream;
29import java.io.PrintStream;
30import java.security.NoSuchAlgorithmException;
31import java.security.Permission;
32import java.security.Provider;
33import java.security.Security;
34import java.security.SecurityPermission;
35import java.security.Provider.Service;
36import java.util.Collection;
37import java.util.HashMap;
38import java.util.Iterator;
39import java.util.Locale;
40import java.util.Set;
41import java.util.Map.Entry;
42
43import junit.framework.TestCase;
44
45/**
46 * Tests for <code>Provider</code> constructor and methods
47 *
48 */
49public class ProviderTest extends TestCase {
50    /*
51     * Implementation note: The algorithm name ASH-1 might seem a bit strange,
52     * but since the algorithms cannot be uninstalled anymore we need to make
53     * sure there are not side-effects on other tests. Simply inserting SHA-1
54     * destroys the existing provider infrastructure.
55     */
56
57    Provider[] storedProviders;
58
59    Provider p;
60
61    /*
62     * @see TestCase#setUp()
63     */
64    protected void setUp() throws Exception {
65        super.setUp();
66
67        storedProviders = Security.getProviders();
68
69        p = new MyProvider();
70    }
71
72    @Override
73    protected void tearDown() throws Exception {
74        p.remove("MessageDigest.ASH-1");
75        p.remove("MessageDigest.abc");
76        p.remove("Alg.Alias.MessageDigest.ASH1");
77
78        for (Provider p: Security.getProviders()) {
79            Security.removeProvider(p.getName());
80        }
81
82        for (Provider p: storedProviders) {
83            Security.addProvider(p);
84        }
85
86        super.tearDown();
87    }
88
89    /*
90     * Class under test for void Provider()
91     */
92    public final void testProvider() {
93        if (!p.getProperty("Provider.id name").equals(
94                String.valueOf(p.getName()))) {
95            fail("Incorrect \"Provider.id name\" value");
96        }
97        if (!p.getProperty("Provider.id version").equals(
98                String.valueOf(p.getVersion()))) {
99            fail("Incorrect \"Provider.id version\" value");
100        }
101        if (!p.getProperty("Provider.id info").equals(
102                String.valueOf(p.getInfo()))) {
103            fail("Incorrect \"Provider.id info\" value");
104        }
105        if (!p.getProperty("Provider.id className").equals(
106                p.getClass().getName())) {
107            fail("Incorrect \"Provider.id className\" value");
108        }
109    }
110
111    public final void testClear() {
112        p.clear();
113        assertNull(p.getProperty("MessageDigest.SHA-1"));
114    }
115
116    /*
117     * Class under test for void Provider(String, double, String)
118     */
119    public final void testProviderStringdoubleString() {
120        Provider p = new MyProvider("Provider name", 123.456, "Provider info");
121        assertEquals("Provider name", p.getName());
122        assertEquals(123.456, p.getVersion(), 0L);
123        assertEquals("Provider info", p.getInfo());
124    }
125
126    public final void testGetName() {
127        assertEquals("MyProvider", p.getName());
128    }
129
130    public final void testGetVersion() {
131        assertEquals(1.0, p.getVersion(), 0L);
132    }
133
134    public final void testGetInfo() {
135        assertEquals("Provider for testing", p.getInfo());
136    }
137
138    /*
139     * Class under test for void putAll(Map)
140     */
141    public final void testPutAllMap() {
142        HashMap hm = new HashMap();
143        hm.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
144        hm.put("Property 1", "value 1");
145        hm.put("serviceName.algName attrName", "attrValue");
146        hm.put("Alg.Alias.engineClassName.aliasName", "standardName");
147        p.putAll(hm);
148        if (!"value 1".equals(p.getProperty("Property 1").trim()) ||
149                !"attrValue".equals(p.getProperty("serviceName.algName attrName").trim()) ||
150                !"standardName".equals(p.getProperty("Alg.Alias.engineClassName.aliasName").trim()) ||
151                !"aaa.bbb.ccc.ddd".equals(p.getProperty("MessageDigest.SHA-1").trim()) ) {
152            fail("Incorrect property value");
153        }
154    }
155
156    /*
157     * Class under test for Set entrySet()
158     */
159    public final void testEntrySet() {
160        p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
161
162        Set s = p.entrySet();
163        try {
164            s.clear();
165            fail("Must return unmodifiable set");
166        } catch (UnsupportedOperationException e) {
167        }
168
169        assertEquals("Incorrect set size", 8, s.size());
170
171        for (Iterator it = s.iterator(); it.hasNext();) {
172            Entry e = (Entry)it.next();
173            String key = (String)e.getKey();
174            String val = (String)e.getValue();
175            if (key.equals("MessageDigest.SHA-1") && val.equals("SomeClassName")) {
176                continue;
177            }
178            if (key.equals("Alg.Alias.MessageDigest.SHA1") && val.equals("SHA-1")) {
179                continue;
180            }
181            if (key.equals("MessageDigest.abc") && val.equals("SomeClassName")) {
182                continue;
183            }
184            if (key.equals("Provider.id className") && val.equals(p.getClass().getName())) {
185                continue;
186            }
187            if (key.equals("Provider.id name") && val.equals("MyProvider")) {
188                continue;
189            }
190            if (key.equals("MessageDigest.SHA-256") && val.equals("aaa.bbb.ccc.ddd")) {
191                continue;
192            }
193            if (key.equals("Provider.id version") && val.equals("1.0")) {
194                continue;
195            }
196            if (key.equals("Provider.id info") && val.equals("Provider for testing")) {
197                continue;
198            }
199            fail("Incorrect set");
200        }
201    }
202
203    /*
204     * Class under test for Set keySet()
205     */
206    public final void testKeySet() {
207        p.put("MessageDigest.SHA-256", "aaa.bbb.ccc.ddd");
208
209        Set<Object> s = p.keySet();
210        try {
211            s.clear();
212        } catch (UnsupportedOperationException e) {
213        }
214        Set s1 = p.keySet();
215
216        assertNotSame(s, s1);
217        assertFalse(s1.isEmpty());
218        assertEquals(8, s1.size());
219
220        assertTrue(s1.contains("MessageDigest.SHA-256"));
221        assertTrue(s1.contains("MessageDigest.SHA-1"));
222        assertTrue(s1.contains("Alg.Alias.MessageDigest.SHA1"));
223        assertTrue(s1.contains("MessageDigest.abc"));
224        assertTrue(s1.contains("Provider.id info"));
225        assertTrue(s1.contains("Provider.id className"));
226        assertTrue(s1.contains("Provider.id version"));
227        assertTrue(s1.contains("Provider.id name"));
228    }
229
230    /*
231     * Class under test for Collection values()
232     */
233    public final void testValues() {
234        p.put("MessageDigest.ASH-256", "aaa.bbb.ccc.ddd");
235
236        Collection<Object> c = p.values();
237        try {
238            c.clear();
239        } catch (UnsupportedOperationException e) {
240        }
241        Collection c1 = p.values();
242
243        assertNotSame(c, c1);
244        assertFalse(c1.isEmpty());
245        assertEquals(8, c1.size());
246
247        assertTrue(c1.contains("MyProvider"));
248        assertTrue(c1.contains("aaa.bbb.ccc.ddd"));
249        assertTrue(c1.contains("Provider for testing"));
250        assertTrue(c1.contains("1.0"));
251        assertTrue(c1.contains("SomeClassName"));
252        assertTrue(c1.contains("SHA-1"));
253        assertTrue(c1.contains(p.getClass().getName()));
254    }
255
256    /*
257     * Class under test for Object put(Object, Object)
258     */
259    public final void testPutObjectObject() {
260        p.put("MessageDigest.SHA-1", "aaa.bbb.ccc.ddd");
261        p.put("Type.Algorithm", "className");
262        assertEquals("aaa.bbb.ccc.ddd", p.getProperty("MessageDigest.SHA-1")
263                .trim());
264
265        Set services = p.getServices();
266        assertEquals(3, services.size());
267
268        for (Iterator it = services.iterator(); it.hasNext();) {
269            Provider.Service s = (Provider.Service)it.next();
270            if ("Type".equals(s.getType()) &&
271                    "Algorithm".equals(s.getAlgorithm()) &&
272                    "className".equals(s.getClassName())) {
273                continue;
274            }
275            if ("MessageDigest".equals(s.getType()) &&
276                    "SHA-1".equals(s.getAlgorithm()) &&
277                    "aaa.bbb.ccc.ddd".equals(s.getClassName())) {
278                continue;
279            }
280            if ("MessageDigest".equals(s.getType()) &&
281                    "abc".equals(s.getAlgorithm()) &&
282                    "SomeClassName".equals(s.getClassName())) {
283                continue;
284            }
285            fail("Incorrect service");
286        }
287    }
288
289    /*
290     * Class under test for Object remove(Object)
291     */
292    public final void testRemoveObject() {
293        Object o = p.remove("MessageDigest.SHA-1");
294
295        assertEquals("SomeClassName", o);
296        assertNull(p.getProperty("MessageDigest.SHA-1"));
297        assertEquals(1, p.getServices().size());
298    }
299
300    public final void testService1() {
301        p.put("MessageDigest.SHA-1", "AnotherClassName");
302        Provider.Service s = p.getService("MessageDigest", "SHA-1");
303        assertEquals("AnotherClassName", s.getClassName());
304    }
305
306    public final void testGetServiceCaseSensitivity() {
307        p.put("i.I", "foo");
308
309        Locale defaultLocale = Locale.getDefault();
310        Locale.setDefault(new Locale("tr", "TR"));
311        try {
312            assertEquals("foo", p.getService("i", "i").getClassName());
313            assertEquals("foo", p.getService("i", "I").getClassName());
314            assertNull(p.getService("\u0130", "\u0130")); // Turkish dotless i and dotted I
315            assertNull(p.getService("\u0131", "\u0131"));
316        } finally {
317            Locale.setDefault(defaultLocale);
318        }
319    }
320
321    // Regression for HARMONY-2760.
322    public void testConstructor() {
323        MyProvider myProvider = new MyProvider(null, 1, null);
324        assertNull(myProvider.getName());
325        assertNull(myProvider.getInfo());
326        assertEquals("null", myProvider.getProperty("Provider.id name"));
327        assertEquals("null", myProvider.getProperty("Provider.id info"));
328    }
329
330    class MyProvider extends Provider {
331        MyProvider() {
332            super("MyProvider", 1.0, "Provider for testing");
333            put("MessageDigest.SHA-1", "SomeClassName");
334            put("MessageDigest.abc", "SomeClassName");
335            put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
336        }
337
338        MyProvider(String name, double version, String info) {
339            super(name, version, info);
340        }
341
342        // BEGIN android-added
343        public void putService(Provider.Service s) {
344            super.putService(s);
345        }
346        // END android-added
347
348        // BEGIN android-added
349        public void removeService(Provider.Service s) {
350            super.removeService(s);
351        }
352        // END android-added
353
354        // BEGIN android-added
355        public int getNumServices() {
356            return getServices().size();
357        }
358        // END android-added
359    }
360
361    // BEGIN android-added
362    public final void testService2() {
363        Provider[] pp = Security.getProviders("MessageDigest.ASH-1");
364        if (pp == null) {
365            return;
366        }
367        Provider p2 = pp[0];
368        String old = p2.getProperty("MessageDigest.ASH-1");
369        p2.put("MessageDigest.ASH-1", "AnotherClassName");
370        Provider.Service s = p2.getService("MessageDigest", "ASH-1");
371        if (!"AnotherClassName".equals(s.getClassName())) {
372            fail("Incorrect class name " + s.getClassName());
373        }
374        try {
375            s.newInstance(null);
376            fail("No expected NoSuchAlgorithmException");
377        } catch (NoSuchAlgorithmException e) {
378        }
379    }
380    // END android-added
381
382    // BEGIN android-added
383    public final void testGetServices() {
384        MyProvider myProvider = new MyProvider(null, 1, null);
385        Set<Provider.Service> services = myProvider.getServices();
386        assertEquals(0, services.size());
387
388        Provider.Service s[] = new Provider.Service[3];
389
390        s[0] = new Provider.Service(p, "type1", "algorithm1", "className1",
391                null, null);
392        s[1] = new Provider.Service(p, "type2", "algorithm2", "className2",
393                null, null);
394        s[2] = new Provider.Service(p, "type3", "algorithm3", "className3",
395                null, null);
396        myProvider.putService(s[0]);
397        myProvider.putService(s[1]);
398        assertEquals(2, myProvider.getNumServices());
399        Set<Service> actual = myProvider.getServices();
400
401        assertTrue(actual.contains(s[0]));
402        assertTrue(actual.contains(s[1]));
403        assertTrue(!actual.contains(s[2]));
404
405        myProvider.removeService(s[1]);
406        actual = myProvider.getServices();
407        assertEquals(1, myProvider.getNumServices());
408
409        assertTrue(actual.contains(s[0]));
410        assertTrue(!actual.contains(s[1]));
411        assertTrue(!actual.contains(s[2]));
412
413        myProvider.putService(s[2]);
414        actual = myProvider.getServices();
415        assertEquals(2, myProvider.getNumServices());
416        assertTrue(actual.contains(s[0]));
417        assertTrue(!actual.contains(s[1]));
418        assertTrue(actual.contains(s[2]));
419    }
420    // END android-added
421
422    // BEGIN android-added
423    public final void testPutService() {
424        MyProvider myProvider = new MyProvider(null, 1, null);
425        Provider.Service s[] = new Provider.Service[3];
426
427        s[0] = new Provider.Service(p, "type1", "algorithm1", "className1",
428                null, null);
429        s[1] = new Provider.Service(p, "type2", "algorithm2", "className2",
430                null, null);
431        s[2] = new Provider.Service(p, "type3", "algorithm3", "className3",
432                null, null);
433        myProvider.putService(s[0]);
434        myProvider.putService(s[1]);
435        assertEquals(2, myProvider.getNumServices());
436        Set<Service> actual = myProvider.getServices();
437
438        assertTrue(actual.contains(s[0]));
439        assertTrue(actual.contains(s[1]));
440        assertTrue(!actual.contains(s[2]));
441
442        myProvider.removeService(s[1]);
443        assertEquals(1, myProvider.getNumServices());
444        actual = myProvider.getServices();
445
446        assertTrue(actual.contains(s[0]));
447        assertTrue(!actual.contains(s[1]));
448        assertTrue(!actual.contains(s[2]));
449
450        myProvider.putService(s[2]);
451        actual = myProvider.getServices();
452        assertEquals(2, myProvider.getNumServices());
453        assertTrue(actual.contains(s[0]));
454        assertTrue(!actual.contains(s[1]));
455        assertTrue(actual.contains(s[2]));
456
457        myProvider.putService(s[2]);
458        actual = myProvider.getServices();
459        assertEquals(2, myProvider.getNumServices());
460        assertTrue(actual.contains(s[0]));
461        assertTrue(!actual.contains(s[1]));
462        assertTrue(actual.contains(s[2]));
463
464        try {
465            myProvider.putService(null);
466            fail("NullPointerException expected");
467        } catch (NullPointerException e) {
468            // expected
469        }
470    }
471    // END android-added
472
473    // BEGIN android-added
474    public final void testRemoveService() {
475        MyProvider myProvider = new MyProvider(null, 1, null);
476        try {
477            myProvider.removeService(null);
478            fail("NullPoiterException expected");
479        } catch (NullPointerException e) {
480            // expected
481        }
482
483        Provider.Service s[] = new Provider.Service[3];
484
485        s[0] = new Provider.Service(p, "type0", "algorithm0", "className0",
486                null, null);
487        s[1] = new Provider.Service(p, "type1", "algorithm1", "className1",
488                null, null);
489        s[2] = new Provider.Service(p, "type2", "algorithm2", "className2",
490                null, null);
491
492        try {
493            myProvider.removeService(s[0]);
494        } catch (NullPointerException e) {
495            fail("Unexpected exception");
496        }
497
498        myProvider.putService(s[0]);
499        myProvider.putService(s[1]);
500        myProvider.putService(s[2]);
501        assertEquals(3, myProvider.getNumServices());
502        Set<Service> actual = myProvider.getServices();
503
504        assertTrue(actual.contains(s[0]));
505        assertTrue(actual.contains(s[1]));
506        assertTrue(actual.contains(s[2]));
507
508        myProvider.removeService(s[1]);
509        assertEquals(2, myProvider.getNumServices());
510        actual = myProvider.getServices();
511
512        assertTrue(actual.contains(s[0]));
513        assertTrue(!actual.contains(s[1]));
514        assertTrue(actual.contains(s[2]));
515
516        myProvider.removeService(s[0]);
517        assertEquals(1, myProvider.getNumServices());
518        actual = myProvider.getServices();
519
520        assertTrue(!actual.contains(s[0]));
521        assertTrue(!actual.contains(s[1]));
522        assertTrue(actual.contains(s[2]));
523
524        myProvider.removeService(s[2]);
525        assertEquals(0, myProvider.getNumServices());
526        actual = myProvider.getServices();
527
528        assertTrue(!actual.contains(s[0]));
529        assertTrue(!actual.contains(s[1]));
530        assertTrue(!actual.contains(s[2]));
531
532        try {
533            myProvider.removeService(null);
534            fail("NullPoiterException expected");
535        } catch (NullPointerException e) {
536            // expected
537        }
538    }
539    // END android-added
540
541    // BEGIN android-added
542    public final void testLoad() throws IOException {
543        InputStream is = new ByteArrayInputStream(writeProperties());
544        MyProvider myProvider = new MyProvider("name", 1, "info");
545        myProvider.load(is);
546        assertEquals("tests.security", myProvider.get("test.pkg"));
547        assertEquals("Unit Tests", myProvider.get("test.proj"));
548        assertNull(myProvider.get("#commented.entry"));
549
550        assertEquals("info", myProvider.get("Provider.id info"));
551        String className = myProvider.getClass().toString();
552        assertEquals(
553                className.substring("class ".length(), className.length()),
554                myProvider.get("Provider.id className"));
555        assertEquals("1.0", myProvider.get("Provider.id version"));
556
557        try {
558            myProvider.load((InputStream) null);
559            fail("NullPointerException expected");
560        } catch (NullPointerException e) {
561            // expected
562        }
563    }
564    // END android-added
565
566    // BEGIN android-added
567    public final void testLoad2() {
568        class TestInputStream extends InputStream {
569            @Override
570            public int read() throws IOException {
571                throw new IOException();
572            }
573        }
574
575        MyProvider p = new MyProvider();
576        try {
577            p.load(new TestInputStream());
578            fail("expected IOException");
579        } catch (IOException e) {
580            // expected
581        }
582    }
583    // END android-added
584
585    // BEGIN android-added
586    protected byte[] writeProperties() {
587        ByteArrayOutputStream bout = new ByteArrayOutputStream();
588        PrintStream ps = new PrintStream(bout);
589        ps.println("#commented.entry=Bogus");
590        ps.println("test.pkg=tests.security");
591        ps.println("test.proj=Unit Tests");
592        ps.close();
593        return bout.toByteArray();
594    }
595    // END android-added
596
597    // BEGIN android-added
598    static class TestSecurityManager extends SecurityManager {
599        boolean called = false;
600        private final String permissionName;
601
602        public TestSecurityManager(String permissionName) {
603            this.permissionName = permissionName;
604        }
605
606        @Override
607        public void checkPermission(Permission permission) {
608            if (permission instanceof SecurityPermission) {
609                if (permissionName.equals(permission.getName())) {
610                    called = true;
611                }
612            }
613        }
614    }
615    // END android-added
616}
617