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.nio.ByteBuffer;
26import java.security.DigestException;
27import java.security.MessageDigest;
28import java.security.MessageDigestSpi;
29import java.security.NoSuchAlgorithmException;
30
31import junit.framework.TestCase;
32
33/**
34 * Tests for <code>MessageDigestSpi</code> constructor and methods
35 */
36public class MessageDigestSpiTest extends TestCase {
37
38    /**
39    * java.security.MessageDigestSpi#MessageDigestSpi()
40    */
41    @SuppressWarnings("cast")
42   public void test_constructor() {
43        MyMessageDigest mds;
44        try {
45            mds = new MyMessageDigest();
46            assertTrue(mds instanceof MessageDigestSpi);
47        } catch (Exception e) {
48            fail("Unexpected exception " + e.getMessage());
49        }
50
51        try {
52            mds = new MyMessageDigest();
53            byte[] ba = {0, 1, 2, 3, 4, 5};
54
55            mds.engineDigest();
56            mds.engineReset();
57            mds.engineUpdate(ba[0]);
58            mds.engineUpdate(ba, 0, ba.length);
59        } catch (Exception e) {
60            fail("Unexpected exception for abstract methods");
61        }
62    }
63
64    /**
65     * java.security.MessageDigestSpi#engineDigest(byte[], int, int)
66     */
67    public void test_engineDigestLB$LILI() throws Exception {
68
69        final int DIGEST_LENGTH = 2;
70
71        MyMessageDigest md = new MyMessageDigest() {
72
73            public int engineGetDigestLength() {
74                return DIGEST_LENGTH;
75            }
76
77            public byte[] engineDigest() {
78                return new byte[DIGEST_LENGTH]; // return non-null value
79            }
80        };
81
82        byte[] b = new byte[5];
83        try {
84            // test: null output buffer
85            md.engineDigest(null, 1, DIGEST_LENGTH);
86            fail("No expected NullPointerException");
87        } catch (NullPointerException e) {
88        }
89        try {
90            //test: len param < digest length
91            md.engineDigest(b, 1, DIGEST_LENGTH - 1);
92            fail("No expected DigestException");
93        } catch (DigestException e) {
94        }
95
96        try {
97            //test: offset param > digest length
98            md.engineDigest(b, b.length + 1, b.length);
99            fail("No expected DigestException - 1");
100        } catch (DigestException e) {
101        }
102
103        try {
104            //test: negative param
105            md.engineDigest(b, -1, b.length);
106            fail("No expected DigestException");
107        } catch (ArrayIndexOutOfBoundsException e) {
108            // on RI
109        } catch (DigestException e) {
110            // ok
111        }
112
113        assertEquals("incorrect result", DIGEST_LENGTH, md
114                .engineDigest(b, 1, 3));
115
116        // Regression for HARMONY-3045
117        md = new MyMessageDigest();
118        try {
119            md.engineDigest(b, 0, 1);
120            fail("should throw NullPointerException");
121        } catch (NullPointerException e) {
122            // expected
123        }
124    }
125
126    /**
127     * java.security.MessageDigestSpi#engineGetDigestLength()
128     */
129    public void test_engineGetDigestLength() {
130        MyMessageDigest md = new MyMessageDigest();
131        assertEquals(0, md.engineGetDigestLength());
132
133        MessageDigest md5Digest = null;
134        try {
135            md5Digest = MessageDigest.getInstance("MD5");
136        } catch (NoSuchAlgorithmException e) {
137            fail("unexpected Exception: " + e);
138        }
139        assertEquals(16, md5Digest.getDigestLength());
140    }
141
142    /**
143     * java.security.MessageDigestSpi#engineUpdate(ByteBuffer)
144     */
145    public void test_engineUpdateLjava_nio_ByteBuffer() {
146        MyMessageDigest md = new MyMessageDigest();
147        byte[] b = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
148
149        ByteBuffer buf = ByteBuffer.wrap(b, 0, b.length);
150        buf.get(b);
151        int limit = buf.limit();
152        md.engineUpdate(buf);
153        assertEquals(limit, buf.limit());
154        assertEquals(limit, buf.position());
155
156        buf = ByteBuffer.wrap(b, 0, b.length);
157        buf.get();
158        buf.get();
159        buf.get();
160        md.engineUpdate(buf);
161        assertEquals(limit, buf.limit());
162        assertEquals(limit, buf.position());
163    }
164
165    /**
166     * java.security.MessageDigestSpi#clone()
167     */
168    public void test_clone() throws CloneNotSupportedException {
169        MyMessageDigest md = new MyMessageDigest();
170        try {
171            md.clone();
172            fail("No expected CloneNotSupportedException");
173        } catch (CloneNotSupportedException e) {
174        }
175
176        MyMessageDigestCloneable mdc = new MyMessageDigestCloneable();
177        assertNotSame(mdc, mdc.clone());
178    }
179
180    private class MyMessageDigest extends MessageDigestSpi {
181
182        @Override
183        public void engineReset() {
184        }
185
186        @Override
187        public byte[] engineDigest() {
188            return null;
189        }
190
191        @Override
192        public void engineUpdate(byte arg0) {
193        }
194
195        @Override
196        public void engineUpdate(byte[] arg0, int arg1, int arg2) {
197        }
198
199        @Override
200        protected int engineDigest(byte[] buf, int offset, int len)
201                throws DigestException {
202            return super.engineDigest(buf, offset, len);
203        }
204
205        @Override
206        protected int engineGetDigestLength() {
207            return super.engineGetDigestLength();
208        }
209
210        @Override
211        protected void engineUpdate(ByteBuffer input) {
212            super.engineUpdate(input);
213        }
214    }
215
216    private class MyMessageDigestCloneable extends MyMessageDigest implements
217            Cloneable {
218    }
219}
220