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 Vladimir N. Molotkov 20 */ 21 22 package org.apache.harmony.security.tests.x509; 23 24 import java.io.ByteArrayInputStream; 25 import java.io.InputStream; 26 27 import junit.framework.TestCase; 28 29 /** 30 * Test for thread safety of the PolicyQualifierInfo DER decoder 31 * ("DER" stands for "Distinguished Encoding Rules", 32 * see ITU-T Recommendation X.690, 33 * http://asn1.elibel.tm.fr) 34 */ 35 public class PolicyQualifierInfoTest extends TestCase { 36 // Number of test working threads (may be set externally) 37 private static int workersNumber; 38 // Number of test iterations performed by each thread 39 // (may be set externally) 40 private static int iterationsNumber; 41 42 static { 43 try { 44 workersNumber = Integer.parseInt( 45 System.getProperty("PolicyQualifierInfoTest.workersNumber", 46 "10")); 47 iterationsNumber = Integer.parseInt( 48 System.getProperty("PolicyQualifierInfoTest.iterationsNumber", 49 "10000")); 50 } catch (Exception e) { 51 workersNumber = 10; 52 iterationsNumber = 10000; 53 } 54 } 55 56 // Holder for thread-specific PolicyQualifier DER encodings 57 private static final byte[][] enc = new byte [workersNumber][]; 58 59 private volatile boolean arrayPassed = true; 60 private volatile boolean inpstPassed = true; 61 62 // "Valid" reference DER encoding 63 // (generated by own encoder during test development) 64 private static final byte[] encoding = { 65 (byte)0x30, (byte)0x26, // tag Seq, length 66 (byte)0x06, (byte)0x08, // tag OID, length 67 (byte)0x2b, (byte)0x06, (byte)0x01, (byte)0x05, // oid value 68 (byte)0x05, (byte)0x07, (byte)0x02, (byte)0x01, // oid value 69 (byte)0x16, (byte)0x1a, // tag IA5String, length 70 (byte)0x68, (byte)0x74, (byte)0x74, (byte)0x70, // IA5String value 71 (byte)0x3a, (byte)0x2f, (byte)0x2f, (byte)0x77, // IA5String value 72 (byte)0x77, (byte)0x77, (byte)0x2e, (byte)0x71, // IA5String value 73 (byte)0x71, (byte)0x2e, (byte)0x63, (byte)0x6f, // IA5String value 74 (byte)0x6d, (byte)0x2f, (byte)0x73, (byte)0x74, // IA5String value 75 (byte)0x6d, (byte)0x74, (byte)0x2e, (byte)0x74, // IA5String value 76 (byte)0x78, (byte)0x74 // IA5String value 77 }; 78 79 80 // Test worker for decoding from byte array 81 private class TestWorker1 extends Thread { 82 83 private final int myIntValue; 84 85 public TestWorker1(int num) { 86 super("Worker_" + num); 87 myIntValue = num; 88 } 89 90 public void run() { 91 for (int i=0; i<iterationsNumber; i++) { 92 try { 93 // Perform DER decoding: 94 Object[] decoded = 95 (Object[])org.apache.harmony.security.x509. 96 PolicyQualifierInfo.ASN1.decode( 97 getDerEncoding(myIntValue)); 98 // check OID value 99 assertEquals(this.getName()+"(OID)", 100 myIntValue, ((int[])decoded[0])[8]); 101 // check qualifier 102 assertEquals(this.getName()+"(QA)", 103 (byte)myIntValue, ((byte[])decoded[1])[2]); 104 } catch (Throwable e) { 105 System.err.println(e); 106 arrayPassed = false; 107 return; 108 } 109 } 110 } 111 } 112 113 // Test worker for decoding from InputStream 114 private class TestWorker2 extends Thread { 115 116 private final int myIntValue; 117 118 public TestWorker2(int num) { 119 super("Worker_" + num); 120 myIntValue = num; 121 } 122 123 public void run() { 124 for (int i=0; i<iterationsNumber; i++) { 125 try { 126 // Perform DER decoding: 127 Object[] decoded = 128 (Object[])org.apache.harmony.security.x509. 129 PolicyQualifierInfo.ASN1.decode( 130 getDerInputStream(myIntValue)); 131 // check OID value 132 assertEquals(this.getName()+"(OID)", 133 myIntValue, ((int[])decoded[0])[8]); 134 // check qualifier 135 assertEquals(this.getName()+"(QA)", 136 (byte)myIntValue, ((byte[])decoded[1])[2]); 137 } catch (Throwable e) { 138 System.err.println(e); 139 inpstPassed = false; 140 return; 141 } 142 } 143 } 144 } 145 146 /** 147 * Test 1 148 * @throws InterruptedException 149 */ 150 public final void testMtByteArray() throws InterruptedException { 151 Thread[] workers = new Thread[workersNumber]; 152 for(int i=0; i<workersNumber; i++) { 153 workers[i] = new TestWorker1(i); 154 } 155 for(int i=0; i<workersNumber; i++) { 156 workers[i].start(); 157 } 158 for(int i=0; i<workersNumber; i++) { 159 workers[i].join(); 160 } 161 assertTrue(arrayPassed); 162 } 163 164 /** 165 * Test 2 166 * @throws InterruptedException 167 */ 168 public final void testMtInputStream() throws InterruptedException { 169 Thread[] workers = new Thread[workersNumber]; 170 for(int i=0; i<workersNumber; i++) { 171 workers[i] = new TestWorker2(i); 172 } 173 for(int i=0; i<workersNumber; i++) { 174 workers[i].start(); 175 } 176 for(int i=0; i<workersNumber; i++) { 177 workers[i].join(); 178 } 179 assertTrue(inpstPassed); 180 } 181 182 // 183 // Generates unique (based on parameter) DER encoding 184 // @param intVal value to be incorporated into the resulting encoding 185 // @return PolicyQualifier DER encoding 186 // 187 private static final byte[] getDerEncoding(int intVal) { 188 setEncArray(intVal); 189 return enc[intVal]; 190 } 191 192 // 193 // Generates unique (based on parameter) DER encoding 194 // @param intVal value to be incorporated into the resulting encoding 195 // @return PolicyQualifier DER encoding 196 // 197 private static final InputStream getDerInputStream(int intVal) { 198 setEncArray(intVal); 199 return new ByteArrayInputStream(enc[intVal]); 200 } 201 202 // 203 // Init thread specific data 204 // @param intVal worker thread number 205 // 206 private static void setEncArray(int intVal) { 207 if (enc[intVal] == null) { 208 // make encoding thread-specific 209 byte[] a = encoding.clone(); 210 a[11] = (byte)intVal; 211 a[14] = (byte)intVal; 212 enc[intVal] = a; 213 } 214 } 215 } 216