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