Home | History | Annotate | Download | only in x509
      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