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
22package org.apache.harmony.security.tests.java.security.spec;
23
24import java.math.BigInteger;
25import java.security.spec.ECFieldF2m;
26import java.util.Arrays;
27
28import junit.framework.TestCase;
29
30/**
31 * Tests for <code>ECFieldF2m</code> class fields and methods.
32 */
33public class ECFieldF2mTest extends TestCase {
34
35    /**
36     * Support class for this test.
37     * Encapsulates <code>ECFieldF2m</code> testing
38     * domain parameters.
39     */
40    private static final class ECFieldF2mDomainParams {
41
42        /**
43         * <code>NPE</code> reference object of class NullPointerException.
44         * NullPointerException must be thrown by <code>ECFieldF2m</code>
45         * ctors in some circumstances
46         */
47        static final NullPointerException NPE = new NullPointerException();
48        /**
49         * <code>IArgE</code> reference object of class IllegalArgumentException.
50         * IllegalArgumentException must be thrown by <code>ECFieldF2m</code>
51         * ctors in some circumstances
52         */
53        static final IllegalArgumentException IArgE = new IllegalArgumentException();
54
55        /**
56         * The <code>m</code> parameter for <code>ECFieldF2m</code>
57         * ctor for the current test.
58         */
59        final int m;
60        /**
61         * The <code>rp</code> parameter for <code>ECFieldF2m</code>
62         * ctor for the current test.
63         */
64        final BigInteger rp;
65        /**
66         * The <code>ks</code> parameter for <code>ECFieldF2m</code>
67         * ctor for the current test.
68         */
69        final int[] ks;
70
71
72        /**
73         * Exception expected with this parameters set or <code>null</code>
74         * if no exception expected.
75         */
76        final Exception x;
77
78        /**
79         * Constructs ECFieldF2mDomainParams
80         *
81         * @param m
82         * @param rp
83         * @param ks
84         * @param expectedException
85         */
86        ECFieldF2mDomainParams(final int m,
87                final BigInteger rp,
88                final int[] ks,
89                final Exception expectedException) {
90            this.m = m;
91            this.rp = rp;
92            this.ks = ks;
93            this.x = expectedException;
94        }
95    }
96
97    /**
98     * Constructor for ECFieldF2mTest.
99     *
100     * @param name
101     */
102    public ECFieldF2mTest(String name) {
103        super(name);
104    }
105
106    //
107    // Tests
108    //
109
110    /**
111     * Set of parameters used for <code>ECFieldF2m(int)</code>
112     * constructor tests.
113     */
114    private final ECFieldF2mDomainParams[] intCtorTestParameters =
115            new ECFieldF2mDomainParams[] {
116                    // set 0: valid m
117                    new ECFieldF2mDomainParams(1, null, null, null),
118                    // set 1: valid m
119                    new ECFieldF2mDomainParams(Integer.MAX_VALUE, null, null, null),
120                    // set 2: invalid m
121                    new ECFieldF2mDomainParams(0, null, null, ECFieldF2mDomainParams.IArgE),
122                    // set 3: invalid m
123                    new ECFieldF2mDomainParams(-1, null, null, ECFieldF2mDomainParams.IArgE)
124            };
125
126    /**
127     * Tests for constructor <code>ECFieldF2m(int)</code><br>
128     * <p/>
129     * Assertion: constructs new <code>ECFieldF2m</code> object
130     * using valid parameter m.
131     * <p/>
132     * Assertion: IllegalArgumentException if m is not positive.
133     */
134    public final void testECFieldF2mint() {
135        for (int i = 0; i < intCtorTestParameters.length; i++) {
136            ECFieldF2mDomainParams tp = intCtorTestParameters[i];
137            try {
138                // perform test
139                new ECFieldF2m(tp.m);
140
141                if (tp.x != null) {
142                    // exception has been expected
143                    fail(getName() + ", set " + i +
144                            " FAILED: expected exception has not been thrown");
145                }
146            } catch (Exception e) {
147                if (tp.x == null || !e.getClass().isInstance(tp.x)) {
148                    // exception: failure
149                    // if it has not been expected
150                    // or wrong one has been thrown
151                    fail(getName() + ", set " + i +
152                            " FAILED: unexpected " + e);
153                }
154            }
155        }
156    }
157
158    /**
159     * Set of parameters used for <code>ECFieldF2m(int, BigInteger)</code>
160     * constructor tests.
161     */
162    private final ECFieldF2mDomainParams[] intIntArrayCtorTestParameters =
163            new ECFieldF2mDomainParams[] {
164                    // set 0: valid m and ks - trinomial basis params
165                    new ECFieldF2mDomainParams(
166                            1999,
167                            null,
168                            new int[] { 367 },
169                            null),
170                    // set 1: valid m and ks - pentanomial basis params
171                    new ECFieldF2mDomainParams(
172                            2000,
173                            null,
174                            new int[] { 981, 2, 1 },
175                            null),
176                    // set 2: valid m, invalid (null) ks
177                    new ECFieldF2mDomainParams(
178                            1963,
179                            null,
180                            null,
181                            ECFieldF2mDomainParams.NPE),
182                    // set 3: valid m, invalid ks - wrong length
183                    new ECFieldF2mDomainParams(
184                            1963,
185                            null,
186                            new int[] { 981, 2 },
187                            ECFieldF2mDomainParams.IArgE),
188                    // set 4: valid m, invalid ks - wrong length
189                    new ECFieldF2mDomainParams(
190                            1963,
191                            null,
192                            new int[] { 981, 124, 2, 1 },
193                            ECFieldF2mDomainParams.IArgE),
194                    // set 5: valid m, invalid ks - wrong value
195                    new ECFieldF2mDomainParams(
196                            1999,
197                            null,
198                            new int[] { 1999 },
199                            ECFieldF2mDomainParams.IArgE),
200                    // set 6: valid m, invalid ks - wrong value
201                    new ECFieldF2mDomainParams(
202                            1999,
203                            null,
204                            new int[] { 0 },
205                            ECFieldF2mDomainParams.IArgE),
206                    // set 7: valid m, invalid ks - wrong values
207                    new ECFieldF2mDomainParams(
208                            2000,
209                            null,
210                            new int[] { 2000, 2, 1 },
211                            ECFieldF2mDomainParams.IArgE),
212                    // set 8: valid m, invalid ks - wrong values
213                    new ECFieldF2mDomainParams(
214                            2000,
215                            null,
216                            new int[] { 981, 2, 0 },
217                            ECFieldF2mDomainParams.IArgE),
218                    // set 9: invalid m
219                    new ECFieldF2mDomainParams(
220                            -5,
221                            null,
222                            new int[] { 981, 2, 1 },
223                            ECFieldF2mDomainParams.IArgE),
224                    // set 10: valid m, invalid ks - wrong order
225                    new ECFieldF2mDomainParams(
226                            2000,
227                            null,
228                            new int[] { 981, 1, 2 },
229                            ECFieldF2mDomainParams.IArgE),
230                    // set 11: valid m, invalid ks - no content
231                    new ECFieldF2mDomainParams(
232                            2000,
233                            null,
234                            new int[3],
235                            ECFieldF2mDomainParams.IArgE),
236                    // set 12: valid m, invalid ks - length is 0
237                    new ECFieldF2mDomainParams(
238                            2000,
239                            null,
240                            new int[0],
241                            ECFieldF2mDomainParams.IArgE),
242            };
243
244    /**
245     * Tests for constructor <code>ECFieldF2m(int m, int[] ks)</code><br>
246     * <p/>
247     * Assertion: constructs new <code>ECFieldF2m</code> object
248     * using valid parameters m and rp. ks represents trinomial basis.
249     * <p/>
250     * Assertion: constructs new <code>ECFieldF2m</code> object
251     * using valid parameters m and ks. ks represents pentanomial basis.
252     * <p/>
253     * Assertion: IllegalArgumentException if m is not positive.
254     * <p/>
255     * Assertion: NullPointerException if ks is null.
256     * <p/>
257     * Assertion: IllegalArgumentException if ks is invalid.
258     */
259    public final void testECFieldF2mintintArray() {
260        for (int i = 0; i < intIntArrayCtorTestParameters.length; i++) {
261            ECFieldF2mDomainParams tp = intIntArrayCtorTestParameters[i];
262            try {
263                // perform test
264                new ECFieldF2m(tp.m, tp.ks);
265
266                if (tp.x != null) {
267                    // exception has been expected
268                    fail(getName() + ", set " + i +
269                            " FAILED: expected exception has not been thrown");
270                }
271            } catch (Exception e) {
272                if (tp.x == null || !e.getClass().isInstance(tp.x)) {
273                    // exception: failure
274                    // if it has not been expected
275                    // or wrong one has been thrown
276                    fail(getName() + ", set " + i +
277                            " FAILED: unexpected " + e);
278                }
279            }
280        }
281    }
282
283    /**
284     * Test #1 for <code>hashCode()</code> method.<br>
285     * <p/>
286     * Assertion: must return the same value if invoked
287     * repeatedly on the same object.
288     */
289    public final void testHashCode01() {
290        ECFieldF2m f = new ECFieldF2m(2000);
291        int hc = f.hashCode();
292        assertTrue(hc == f.hashCode() &&
293                hc == f.hashCode() &&
294                hc == f.hashCode() &&
295                hc == f.hashCode() &&
296                hc == f.hashCode() &&
297                hc == f.hashCode() &&
298                hc == f.hashCode() &&
299                hc == f.hashCode());
300    }
301
302    /**
303     * Test #2 for <code>hashCode()</code> method.<br>
304     * <p/>
305     * Assertion: must return the same value if invoked
306     * repeatedly on the same object.
307     */
308    public final void testHashCode02() {
309        ECFieldF2m f = new ECFieldF2m(2000, new int[] { 981, 2, 1 });
310        int hc = f.hashCode();
311        assertTrue(hc == f.hashCode() &&
312                hc == f.hashCode() &&
313                hc == f.hashCode() &&
314                hc == f.hashCode() &&
315                hc == f.hashCode() &&
316                hc == f.hashCode() &&
317                hc == f.hashCode() &&
318                hc == f.hashCode());
319    }
320
321    /**
322     * Test #3 for <code>hashCode()</code> method.<br>
323     * <p/>
324     * Assertion: must return the same value if invoked
325     * on equal (according to the <code>equals(Object)</code> method) objects.
326     */
327    public final void testHashCode03() {
328        assertTrue(new ECFieldF2m(111).hashCode() ==
329                new ECFieldF2m(111).hashCode());
330    }
331
332    /**
333     * Test #4 for <code>hashCode()</code> method.<br>
334     * <p/>
335     * Assertion: must return the same value if invoked
336     * on equal (according to the <code>equals(Object)</code> method) objects.
337     */
338    public final void testHashCode04() {
339        assertTrue(new ECFieldF2m(2000, new int[] { 981, 2, 1 }).hashCode() ==
340                new ECFieldF2m(2000, new int[] { 981, 2, 1 }).hashCode());
341    }
342
343    /**
344     * Test #5 for <code>hashCode()</code> method.<br>
345     * <p/>
346     * Assertion: must return the same value if invoked
347     * on equal (according to the <code>equals(Object)</code> method) objects.
348     */
349    public final void testHashCode05() {
350        assertTrue(new ECFieldF2m(2000, new int[] { 981, 2, 1 }).hashCode() ==
351                new ECFieldF2m(2000, BigInteger.valueOf(0L).
352                        setBit(0).setBit(1).setBit(2).
353                        setBit(981).setBit(2000)).hashCode());
354    }
355
356    /**
357     * Test #1 for <code>equals()</code> method.<br>
358     * <p/>
359     * Assertion: object equals to itself.
360     */
361    public final void testEqualsObject01() {
362        ECFieldF2m obj = new ECFieldF2m(1999, new int[] { 367 });
363        assertTrue(obj.equals(obj));
364    }
365
366    /**
367     * Test #2 for <code>equals()</code> method.<br>
368     * <p/>
369     * Assertion: normal basis - objects equal if their m are equal.
370     */
371    public final void testEqualsObject02() {
372        assertTrue(new ECFieldF2m(43).equals(new ECFieldF2m(43)));
373    }
374
375    /**
376     * Test #3 for <code>equals()</code> method.<br>
377     * <p/>
378     * Assertion: trinomial basis - objects equal if their m, and rp
379     * are mutually equal.
380     */
381    public final void testEqualsObject03() {
382        assertTrue(new ECFieldF2m(1999, new int[] { 367 }).equals(
383                new ECFieldF2m(1999, BigInteger.valueOf(0L).
384                        setBit(0).setBit(367).setBit(1999))));
385    }
386
387    /**
388     * Test #4 for <code>equals()</code> method.<br>
389     * <p/>
390     * Assertion: pentanomial basis - objects equal if their m, and rp
391     * are mutually equal.
392     */
393    public final void testEqualsObject04() {
394        ECFieldF2m f1 = new ECFieldF2m(2000, new int[] { 981, 2, 1 });
395        ECFieldF2m f2 = new ECFieldF2m(2000, BigInteger.valueOf(0L).
396                setBit(0).setBit(1).setBit(2).
397                setBit(981).setBit(2000));
398        assertTrue(f1.equals(f2) && f2.equals(f1));
399    }
400
401    /**
402     * Test #5 for <code>equals()</code> method.<br>
403     * <p/>
404     * Assertion: objects equal if their m, and rp are mutually equal.
405     */
406    public final void testEqualsObject05() {
407        ECFieldF2m f1 = new ECFieldF2m(2000);
408        ECFieldF2m f2 = new ECFieldF2m(2000, BigInteger.valueOf(0L).
409                setBit(0).setBit(1).setBit(2).
410                setBit(981).setBit(2000));
411        assertFalse(f1.equals(f2) || f2.equals(f1));
412    }
413
414    /**
415     * Test #6 for <code>equals(Object obj)</code> method.<br>
416     * <p/>
417     * Assertion: returns false if obj is <code>null</code>
418     */
419    public final void testEqualsObject06() {
420        assertFalse(new ECFieldF2m(2000).equals(null));
421    }
422
423    /**
424     * Test #7 for <code>equals(Object obj)</code> method.<br>
425     * <p/>
426     * Assertion: returns false if obj is not instance of <code>ECFieldF2m</code>
427     */
428    public final void testEqualsObject07() {
429        assertFalse(new ECFieldF2m(2000).equals(new Object()));
430    }
431
432    /**
433     * Test for <code>getFieldSize()</code> method.<br>
434     * <p/>
435     * Assertion: returns m value for <code>ECFieldF2m</code>
436     */
437    public final void testGetFieldSize() {
438        assertEquals(2000, new ECFieldF2m(2000).getFieldSize());
439    }
440
441    /**
442     * Test for <code>getM()</code> method.<br>
443     * <p/>
444     * Assertion: returns m value for <code>ECFieldF2m</code>
445     */
446    public final void testGetM() {
447        assertEquals(2000, new ECFieldF2m(2000).getM());
448    }
449
450    /**
451     * Test #1 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
452     * <p/>
453     * Assertion: returns mid terms of reduction polynomial
454     */
455    public final void testGetMidTermsOfReductionPolynomial01() {
456        int[] a = new int[] { 981, 2, 1 };
457        int[] b = new ECFieldF2m(2000,
458                BigInteger.valueOf(0L).setBit(0).setBit(1).
459                        setBit(2).setBit(981).setBit(2000)).
460                getMidTermsOfReductionPolynomial();
461        assertTrue(Arrays.equals(a, b));
462    }
463
464    /**
465     * Test #2 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
466     * <p/>
467     * Assertion: returns null for normal basis
468     */
469    public final void testGetMidTermsOfReductionPolynomial02() {
470        assertNull(new ECFieldF2m(2000).getMidTermsOfReductionPolynomial());
471    }
472
473    /**
474     * Test #3 for <code>getMidTermsOfReductionPolynomial()</code> method.<br>
475     * <p/>
476     * Assertion: returns mid terms of reduction polynomial
477     */
478    public final void testGetMidTermsOfReductionPolynomial03() {
479        int[] a = new int[] { 367 };
480        int[] b = new ECFieldF2m(1999, a).getMidTermsOfReductionPolynomial();
481        assertTrue(Arrays.equals(a, b));
482    }
483
484    /**
485     * Test #1 for <code>getReductionPolynomial()</code> method.<br>
486     * <p/>
487     * Assertion: returns reduction polynomial
488     */
489    public final void testGetReductionPolynomial01() {
490        BigInteger rp = BigInteger.valueOf(0L).setBit(0).setBit(1).setBit(2).
491                setBit(981).setBit(2000);
492        assertTrue(new ECFieldF2m(2000, rp).getReductionPolynomial().equals(rp));
493    }
494
495    /**
496     * Test #2 for <code>getReductionPolynomial()</code> method.<br>
497     * <p/>
498     * Assertion: returns null for normal basis
499     */
500    public final void testGetReductionPolynomial02() {
501        assertNull(new ECFieldF2m(2000).getReductionPolynomial());
502    }
503
504    /**
505     * Tests that object state is preserved against modifications
506     * through array reference passed to the constructor.
507     */
508    public final void testIsStatePreserved01() {
509        // reference array
510        int[] a = new int[] { 367 };
511        // reference array copy
512        int[] aCopy = a.clone();
513        // create obj using copy
514        ECFieldF2m f = new ECFieldF2m(1999, aCopy);
515        // modify copy
516        aCopy[0] = 5;
517        // compare reference with returned array
518        assertTrue(Arrays.equals(a, f.getMidTermsOfReductionPolynomial()));
519    }
520
521    /**
522     * Tests that object state is preserved against
523     * modifications through array reference returned by
524     * <code>getMidTermsOfReductionPolynomial()</code> method.
525     */
526    public final void testIsStatePreserved02() {
527        // reference array
528        int[] a = new int[] { 981, 2, 1 };
529        // reference array copy
530        int[] aCopy = a.clone();
531        // create obj using copy
532        ECFieldF2m f = new ECFieldF2m(2000, aCopy);
533        // get array reference and modify returned array
534        f.getMidTermsOfReductionPolynomial()[0] = 1532;
535        // compare reference with returned for the second time array
536        assertTrue(Arrays.equals(a, f.getMidTermsOfReductionPolynomial()));
537    }
538
539}
540