1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.apache.harmony.crypto.tests.javax.crypto.func;
17
18import javax.crypto.Cipher;
19
20public abstract class CipherThread implements Runnable {
21    private int[] keyLengthAr = null;
22    private String[] modeAr = null;
23    private String[] paddingModeAr = null;
24    private int kCounter = 0;
25    private int mCounter = 0;
26    private int pCounter = 0;
27    private StringBuffer errorSB = null;
28
29    private boolean flagTestResult = false;
30    private String data = "    Albert Einstein was a German-born " +
31                "theoretical physicist.    ";
32    private String algName = null;
33    private int keyLength = 0;
34    private String mode = null;
35    private String paddingMode = null;
36    private int fails = 0;
37
38    public abstract void crypt() throws Exception;
39
40    CipherThread(String name, int[] keys, String[] modes, String[] paddings) {
41        algName     = name;
42        keyLengthAr   = keys;
43        modeAr        = modes;
44        paddingModeAr = paddings;
45        kCounter = 0;
46        mCounter = 0;
47        pCounter = 0;
48    }
49
50    public void checkEncodedData(byte[] original, byte[] encoded)
51            throws Exception {
52        for(int i = 0; i < original.length; i++) {
53            if (original[i] != encoded[i]) {
54                throw new Exception("Source and encoded data not match " +
55                        getCipherParameters());
56            }
57        }
58    }
59
60    public void checkPaddedEncodedData(byte[] original, byte[] encoded, int offset)
61            throws Exception {
62        for (int i = 0; i < offset; i++) {
63            if (encoded[i] != 0) {
64                throw new Exception("Encoded data is not properly padded at offset " + i);
65            }
66        }
67        for (int i = 0; i < original.length; i++) {
68            if (original[i] != encoded[i + offset]) {
69                throw new Exception("Source and encoded data not match " + getCipherParameters());
70            }
71        }
72    }
73
74    public void launcher() {
75        Thread thread = null;
76
77        do {
78            keyLength = getNextKey();
79            do {
80                mode = getNextMode();
81                do {
82                    paddingMode = getNextPadding();
83                    thread = new Thread(this);
84                    thread.start();
85                    try {
86                        thread.join();
87                    } catch (InterruptedException e) {
88                        e.printStackTrace();
89                    }
90                } while (hasNextPadding());
91            } while (hasNextMode());
92        } while (hasNextKey());
93    }
94
95    public void run() {
96        try {
97            crypt();
98        } catch (Exception e) {
99            if(errorSB == null) {
100                errorSB = new StringBuffer();
101            }
102            errorSB.append(e.getMessage());
103            errorSB.append("\n");
104            errorSB.append(getCipherParameters());
105            errorSB.append("\n");
106            StackTraceElement[] st = e.getStackTrace();
107            for (int i = 0; i < st.length; i++) {
108                errorSB.append(st[i].toString());
109                errorSB.append("\n");
110            }
111            fails++;
112            return;
113        }
114        flagTestResult = true;
115    }
116
117    public String getAlgName() {
118        return algName;
119    }
120
121    public int getKeyLength() {
122        return keyLength;
123    }
124
125    public String getData() {
126        return data;
127    }
128
129    public String getPadding() {
130        return paddingMode;
131    }
132
133    public String getMode() {
134        return mode;
135    }
136
137    public String getCipherParameters() {
138        return "Alg name:" + algName + " Key:" + keyLength + " Mode:" + mode +
139        " Padding:" + paddingMode;
140    }
141
142    public boolean getTestStatus() {
143        return flagTestResult;
144    }
145
146    public String getAlgorithmName() {
147        return algName;
148    }
149
150    public boolean hasNextKey() {
151        return (kCounter < keyLengthAr.length);
152    }
153
154    public boolean hasNextMode() {
155        return (mCounter < modeAr.length);
156    }
157
158    public boolean hasNextPadding() {
159        return (pCounter < paddingModeAr.length);
160    }
161
162    public int getNextKey() {
163        kCounter = (hasNextKey()) ? kCounter : 0;
164        return keyLengthAr[kCounter++];
165    }
166
167    public String getNextMode() {
168        mCounter = (hasNextMode()) ? mCounter : 0;
169        return modeAr[mCounter++];
170    }
171
172    public String getNextPadding() {
173        pCounter = (hasNextPadding()) ? pCounter : 0;
174        return paddingModeAr[pCounter++];
175    }
176
177    public long getTotalCasesNumber() {
178        return keyLengthAr.length * modeAr.length * paddingModeAr.length;
179    }
180
181    public long getTotalFailuresNumber() {
182        return fails;
183    }
184
185    public String getFailureMessages() {
186        return (errorSB == null) ? "" : new String(errorSB);
187    }
188}
189