001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Vladimir N. Molotkov
020: * @version $Revision$
021: */package org.apache.harmony.security.tests.java.security;
022:
023: import java.security.*;
024: import java.io.ByteArrayOutputStream;
025: import java.io.IOException;
026: import java.io.OutputStream;
027: import java.util.Arrays;
028:
029: import org.apache.harmony.security.tests.support.MDGoldenData;
030: import org.apache.harmony.security.tests.support.MyMessageDigest1;
031:
032: import junit.framework.TestCase;
033:
034: /**
035: * Tests for fields and methods of class <code>DigestInputStream</code>
036: *
037: */
038: public class DigestOutputStreamTest extends TestCase {
039:
040: /**
041: * Message digest algorithm name used during testing
042: */
043: private static final String algorithmName[] = { "SHA-1", "SHA",
044: "SHA1", "SHA-256", "SHA-384", "SHA-512", "MD5", };
045: /**
046: * Chunk size for read(byte, off, len) tests
047: */
048: private static final int CHUNK_SIZE = 32;
049: /**
050: * Test message for digest computations
051: */
052: private static final byte[] myMessage = MDGoldenData.getMessage();
053: /**
054: * The length of test message
055: */
056: private static final int MY_MESSAGE_LEN = myMessage.length;
057:
058: /**
059: * Constructor for DigestInputStreamTest.
060: * @param name
061: */
062: public DigestOutputStreamTest(String name) {
063: super (name);
064: }
065:
066: //
067: // Tests
068: //
069:
070: /**
071: * @tests java.security.DigestOutputStream#DigestOutputStream(java.io.OutputStream,
072: * java.security.MessageDigest)
073: */
074: public void test_CtorLjava_io_OutputStreamLjava_security_MessageDigest() {
075:
076: // non-null parameters
077: MessageDigest md = new MyMessageDigest1();
078: MyOutputStream out = new MyOutputStream();
079:
080: MyDigestOutputStream dos = new MyDigestOutputStream(out, md);
081: assertSame(out, dos.myOutputStream());
082: assertSame(md, dos.myMessageDigest());
083:
084: // null parameters
085: dos = new MyDigestOutputStream(null, null);
086: assertNull(dos.myOutputStream());
087: assertNull(dos.myMessageDigest());
088: }
089:
090: /**
091: * @tests java.security.DigestOutputStream#getMessageDigest()
092: */
093: public void test_getMessageDigest() {
094:
095: MessageDigest digest = new MyMessageDigest1();
096: OutputStream out = new MyOutputStream();
097:
098: // non-null parameter
099: DigestOutputStream dos = new DigestOutputStream(out, digest);
100: assertSame(digest, dos.getMessageDigest());
101:
102: // null parameter
103: dos = new DigestOutputStream(out, null);
104: assertNull("getMessageDigest should have returned null", dos
105: .getMessageDigest());
106: }
107:
108: /**
109: * @tests java.security.DigestOutputStream#setMessageDigest(MessageDigest)
110: */
111: public void test_setMessageDigestLjava_security_MessageDigest() {
112:
113: MessageDigest digest = new MyMessageDigest1();
114: OutputStream out = new MyOutputStream();
115:
116: DigestOutputStream dos = new DigestOutputStream(out, null);
117:
118: // non-null parameter
119: dos.setMessageDigest(digest);
120: assertSame(digest, dos.getMessageDigest());
121:
122: // null parameter
123: dos.setMessageDigest(null);
124: assertNull("getMessageDigest should have returned null", dos
125: .getMessageDigest());
126: }
127:
128: /**
129: * Test #1 for <code>write(int)</code> method<br>
130: *
131: * Assertion: writes the byte to the output stream<br>
132: * Assertion: updates associated digest<br>
133: */
134: public final void testWriteint01() throws IOException {
135: for (int k = 0; k < algorithmName.length; k++) {
136: try {
137: MessageDigest md = MessageDigest
138: .getInstance(algorithmName[k]);
139: ByteArrayOutputStream bos = new ByteArrayOutputStream(
140: MY_MESSAGE_LEN);
141: DigestOutputStream dos = new DigestOutputStream(bos, md);
142: for (int i = 0; i < MY_MESSAGE_LEN; i++) {
143: dos.write(myMessage[i]);
144: }
145: // check that bytes have been written correctly
146: assertTrue("write", Arrays.equals(MDGoldenData
147: .getMessage(), bos.toByteArray()));
148: // check that associated digest has been updated properly
149: assertTrue("update", Arrays.equals(dos
150: .getMessageDigest().digest(), MDGoldenData
151: .getDigest(algorithmName[k])));
152: return;
153: } catch (NoSuchAlgorithmException e) {
154: // allowed failure
155: }
156: }
157: fail(getName()
158: + ": no MessageDigest algorithms available - test not performed");
159: }
160:
161: /**
162: * Test #2 for <code>write(int)</code> method<br>
163: * Test #1 for <code>on(boolean)</code> method<br>
164: *
165: * Assertion: <code>write(int)</code> must not update digest if it is off<br>
166: * Assertion: <code>on(boolean)</code> turns digest functionality on
167: * if <code>true</code> passed as a parameter or off if <code>false</code>
168: * passed
169: */
170: public final void testWriteint02() throws IOException {
171: for (int k = 0; k < algorithmName.length; k++) {
172: try {
173: MessageDigest md = MessageDigest
174: .getInstance(algorithmName[k]);
175: ByteArrayOutputStream bos = new ByteArrayOutputStream(
176: MY_MESSAGE_LEN);
177: DigestOutputStream dos = new DigestOutputStream(bos, md);
178:
179: // turn digest off
180: dos.on(false);
181:
182: for (int i = 0; i < MY_MESSAGE_LEN; i++) {
183: dos.write(myMessage[i]);
184: }
185:
186: // check that bytes have been written correctly
187: assertTrue("write", Arrays.equals(MDGoldenData
188: .getMessage(), bos.toByteArray()));
189: // check that digest value has not been updated by write()
190: assertTrue("update", Arrays.equals(dos
191: .getMessageDigest().digest(), MDGoldenData
192: .getDigest(algorithmName[k] + "_NU")));
193: return;
194: } catch (NoSuchAlgorithmException e) {
195: // allowed failure
196: }
197: }
198: fail(getName()
199: + ": no MessageDigest algorithms available - test not performed");
200: }
201:
202: /**
203: * Test #3 for <code>write(int)</code> method<br>
204: *
205: * Assertion: broken <code>DigestOutputStream</code>instance:
206: * <code>OutputStream</code> not set. <code>write(int)</code> must
207: * not work
208: */
209: public final void testWriteint03() throws IOException {
210: for (int k = 0; k < algorithmName.length; k++) {
211: try {
212: MessageDigest md = MessageDigest
213: .getInstance(algorithmName[k]);
214: DigestOutputStream dos = new DigestOutputStream(null,
215: md);
216: // must result in an exception
217: try {
218: for (int i = 0; i < MY_MESSAGE_LEN; i++) {
219: dos.write(myMessage[i]);
220: }
221: fail("OutputStream not set. write(int) must not work");
222: } catch (Exception e) {
223: return;
224: }
225: } catch (NoSuchAlgorithmException e) {
226: // allowed failure
227: }
228: }
229: fail(getName()
230: + ": no MessageDigest algorithms available - test not performed");
231: }
232:
233: /**
234: * Test #4 for <code>write(int)</code> method<br>
235: *
236: * Assertion: broken <code>DigestOutputStream</code>instance:
237: * associated <code>MessageDigest</code> not set.
238: * <code>write(int)</code> must not work when digest
239: * functionality is on
240: */
241: public final void testWriteint04() throws IOException {
242: OutputStream os = new ByteArrayOutputStream(MY_MESSAGE_LEN);
243: DigestOutputStream dos = new DigestOutputStream(os, null);
244:
245: // must result in an exception
246: try {
247: for (int i = 0; i < MY_MESSAGE_LEN; i++) {
248: dos.write(myMessage[i]);
249: }
250: fail("OutputStream not set. write(int) must not work");
251: } catch (Exception e) {
252: return;
253: }
254: }
255:
256: /**
257: * Test #5 for <code>write(int)</code> method<br>
258: * Test #2 for <code>on(boolean)</code> method<br>
259: *
260: * Assertion: broken <code>DigestOutputStream</code>instance:
261: * associated <code>MessageDigest</code> not set.
262: * <code>write(int)</code> must work when digest
263: * functionality is off
264: */
265: public final void testWriteint05() throws IOException {
266: ByteArrayOutputStream bos = new ByteArrayOutputStream(
267: MY_MESSAGE_LEN);
268: DigestOutputStream dos = new DigestOutputStream(bos, null);
269: // set digest functionality to off
270: dos.on(false);
271: // the following must pass without any exception
272: for (int i = 0; i < MY_MESSAGE_LEN; i++) {
273: dos.write(myMessage[i]);
274: }
275: // check that bytes have been written correctly
276: assertTrue(Arrays.equals(MDGoldenData.getMessage(), bos
277: .toByteArray()));
278: }
279:
280: /**
281: * Test #1 for <code>write(byte[],int,int)</code> method<br>
282: *
283: * Assertion: put bytes into output stream<br>
284: *
285: * Assertion: updates associated digest<br>
286: */
287: public final void testWritebyteArrayintint01() throws IOException {
288: for (int k = 0; k < algorithmName.length; k++) {
289: try {
290: ByteArrayOutputStream bos = new ByteArrayOutputStream(
291: MY_MESSAGE_LEN);
292: MessageDigest md = MessageDigest
293: .getInstance(algorithmName[k]);
294: DigestOutputStream dos = new DigestOutputStream(bos, md);
295:
296: // write message at once
297: dos.write(myMessage, 0, MY_MESSAGE_LEN);
298:
299: // check write
300: assertTrue("write", Arrays.equals(myMessage, bos
301: .toByteArray()));
302: // check that associated digest has been updated properly
303: assertTrue("update", Arrays.equals(dos
304: .getMessageDigest().digest(), MDGoldenData
305: .getDigest(algorithmName[k])));
306: return;
307: } catch (NoSuchAlgorithmException e) {
308: // allowed failure
309: }
310: }
311: fail(getName()
312: + ": no MessageDigest algorithms available - test not performed");
313: }
314:
315: /**
316: * Test #2 for <code>write(byte[],int,int)</code> method<br>
317: *
318: * Assertion: put bytes into output stream<br>
319: *
320: * Assertion: updates associated digest<br>
321: */
322: public final void testWritebyteArrayintint02() throws IOException {
323: // check precondition
324: assertEquals(0, MY_MESSAGE_LEN % CHUNK_SIZE);
325: for (int k = 0; k < algorithmName.length; k++) {
326: try {
327:
328: ByteArrayOutputStream bos = new ByteArrayOutputStream(
329: MY_MESSAGE_LEN);
330: MessageDigest md = MessageDigest
331: .getInstance(algorithmName[k]);
332: DigestOutputStream dos = new DigestOutputStream(bos, md);
333:
334: // write message by chunks
335: for (int i = 0; i < MY_MESSAGE_LEN / CHUNK_SIZE; i++) {
336: dos.write(myMessage, i * CHUNK_SIZE, CHUNK_SIZE);
337: }
338: // check write
339: assertTrue("write", Arrays.equals(myMessage, bos
340: .toByteArray()));
341: // check that associated digest has been updated properly
342: assertTrue("update", Arrays.equals(dos
343: .getMessageDigest().digest(), MDGoldenData
344: .getDigest(algorithmName[k])));
345: return;
346: } catch (NoSuchAlgorithmException e) {
347: // allowed failure
348: }
349: }
350: fail(getName()
351: + ": no MessageDigest algorithms available - test not performed");
352: }
353:
354: /**
355: * Test #3 for <code>write(byte[],int,int)</code> method<br>
356: *
357: * Assertion: put bytes into output stream<br>
358: *
359: * Assertion: updates associated digest<br>
360: */
361: public final void testWritebyteArrayintint03()
362: throws NoSuchAlgorithmException, IOException {
363: // check precondition
364: assertTrue(MY_MESSAGE_LEN % (CHUNK_SIZE + 1) != 0);
365:
366: for (int k = 0; k < algorithmName.length; k++) {
367: try {
368: ByteArrayOutputStream bos = new ByteArrayOutputStream(
369: MY_MESSAGE_LEN);
370: MessageDigest md = MessageDigest
371: .getInstance(algorithmName[k]);
372: DigestOutputStream dos = new DigestOutputStream(bos, md);
373:
374: // write message by chunks
375: for (int i = 0; i < MY_MESSAGE_LEN / (CHUNK_SIZE + 1); i++) {
376: dos.write(myMessage, i * (CHUNK_SIZE + 1),
377: CHUNK_SIZE + 1);
378: }
379: // write remaining bytes
380: dos.write(myMessage, MY_MESSAGE_LEN / (CHUNK_SIZE + 1)
381: * (CHUNK_SIZE + 1), MY_MESSAGE_LEN
382: % (CHUNK_SIZE + 1));
383: // check write
384: assertTrue("write", Arrays.equals(myMessage, bos
385: .toByteArray()));
386: // check that associated digest has been updated properly
387: assertTrue("update", Arrays.equals(dos
388: .getMessageDigest().digest(), MDGoldenData
389: .getDigest(algorithmName[k])));
390: return;
391: } catch (NoSuchAlgorithmException e) {
392: // allowed failure
393: }
394: }
395: fail(getName()
396: + ": no MessageDigest algorithms available - test not performed");
397: }
398:
399: /**
400: * Test #4 for <code>write(byte[],int,int)</code> method<br>
401: *
402: * Assertion: put bytes into output stream<br>
403: *
404: * Assertion: does not update associated digest if digest
405: * functionality is off<br>
406: */
407: public final void testWritebyteArrayintint04()
408: throws NoSuchAlgorithmException, IOException {
409: // check precondition
410: assertEquals(0, MY_MESSAGE_LEN % CHUNK_SIZE);
411:
412: for (int k = 0; k < algorithmName.length; k++) {
413: try {
414: ByteArrayOutputStream bos = new ByteArrayOutputStream(
415: MY_MESSAGE_LEN);
416: MessageDigest md = MessageDigest
417: .getInstance(algorithmName[k]);
418: DigestOutputStream dos = new DigestOutputStream(bos, md);
419:
420: // set digest functionality off
421: dos.on(false);
422:
423: // write message by chunks
424: for (int i = 0; i < MY_MESSAGE_LEN / CHUNK_SIZE; i++) {
425: dos.write(myMessage, i * CHUNK_SIZE, CHUNK_SIZE);
426: }
427:
428: // check write
429: assertTrue("write", Arrays.equals(myMessage, bos
430: .toByteArray()));
431: // check that associated digest has not been updated
432: assertTrue("update", Arrays.equals(dos
433: .getMessageDigest().digest(), MDGoldenData
434: .getDigest(algorithmName[k] + "_NU")));
435: return;
436: } catch (NoSuchAlgorithmException e) {
437: // allowed failure
438: }
439: }
440: fail(getName()
441: + ": no MessageDigest algorithms available - test not performed");
442: }
443:
444: /**
445: * @tests java.security.DigestOutputStream#write(byte[], int, int)
446: */
447: public void test_writeLB$LILI() throws Exception {
448:
449: // Regression form HARMONY-1091.
450: MessageDigest md = new MyMessageDigest1();
451: byte[] bytes = new byte[] { 1, 2 };
452: DigestOutputStream dig = new DigestOutputStream(
453: new ByteArrayOutputStream(), md);
454: // buf == null
455: try {
456: dig.write(null, -1, 0);
457: fail("No expected IllegalArgumentException");
458: } catch (IllegalArgumentException e) {
459: }
460: // offset + len > buf.length
461: try {
462: dig.write(bytes, 0, bytes.length + 1);
463: fail("No expected IllegalArgumentException");
464: } catch (IllegalArgumentException e) {
465: }
466: // offset < 0
467: try {
468: dig.write(bytes, -1, 1);
469: fail("No expected IndexOutOfBoundsException");
470: } catch (IndexOutOfBoundsException e) {
471: }
472: // len < 0
473: try {
474: dig.write(bytes, 0, -1);
475: fail("No expected IndexOutOfBoundsException");
476: } catch (IndexOutOfBoundsException e) {
477: }
478: }
479:
480: /**
481: * Test for <code>on()</code> method<br>
482: * Assertion: turns digest functionality on or off
483: */
484: public final void testOn() throws IOException {
485: for (int k = 0; k < algorithmName.length; k++) {
486: try {
487: ByteArrayOutputStream bos = new ByteArrayOutputStream(
488: MY_MESSAGE_LEN);
489: MessageDigest md = MessageDigest
490: .getInstance(algorithmName[k]);
491: DigestOutputStream dos = new DigestOutputStream(bos, md);
492:
493: // turn digest off
494: dos.on(false);
495:
496: for (int i = 0; i < MY_MESSAGE_LEN - 1; i++) {
497: dos.write(myMessage[i]);
498: }
499:
500: // turn digest on
501: dos.on(true);
502:
503: // read remaining byte
504: dos.write(myMessage[MY_MESSAGE_LEN - 1]);
505:
506: byte[] digest = dos.getMessageDigest().digest();
507:
508: // check that digest value has been
509: // updated by the last write(int) call
510: assertFalse(Arrays.equals(digest, MDGoldenData
511: .getDigest(algorithmName[k]))
512: || Arrays.equals(digest, MDGoldenData
513: .getDigest(algorithmName[k] + "_NU")));
514: return;
515: } catch (NoSuchAlgorithmException e) {
516: // allowed failure
517: }
518: }
519: fail(getName()
520: + ": no MessageDigest algorithms available - test not performed");
521: }
522:
523: /**
524: * Test for <code>toString()</code> method<br>
525: * Assertion: returns <code>String</code> representation of this object
526: */
527: public final void testToString() throws NoSuchAlgorithmException {
528: for (int k = 0; k < algorithmName.length; k++) {
529: try {
530: ByteArrayOutputStream bos = new ByteArrayOutputStream(
531: MY_MESSAGE_LEN);
532: MessageDigest md = MessageDigest
533: .getInstance(algorithmName[k]);
534: DigestOutputStream dos = new DigestOutputStream(bos, md);
535:
536: assertNotNull(dos.toString());
537: return;
538: } catch (NoSuchAlgorithmException e) {
539: // allowed failure
540: }
541: }
542: fail(getName()
543: + ": no MessageDigest algorithms available - test not performed");
544: }
545:
546: /**
547: * @tests java.security.DigestOutputStream#on(boolean)
548: */
549: public void test_onZ() throws Exception {
550: // Test for method void java.security.DigestOutputStream.on(boolean)
551: DigestOutputStream dos = new DigestOutputStream(
552: new ByteArrayOutputStream(), MessageDigest
553: .getInstance("SHA"));
554: dos.on(false);
555: byte digestArray[] = { 23, 43, 44 };
556: dos.write(digestArray, 1, 1);
557: byte digestResult[] = dos.getMessageDigest().digest();
558: byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
559: -65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
560: assertTrue("Digest did not return expected result.",
561: java.util.Arrays.equals(digestResult, expected));
562: // now turn on processing and re-run
563: dos.on(true);
564: dos.write(digestArray, 1, 1);
565: digestResult = dos.getMessageDigest().digest();
566: byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
567: 107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
568:
569: assertTrue("Digest did not return expected result.",
570: java.util.Arrays.equals(digestResult, expected1));
571: }
572:
573: /**
574: * @tests java.security.DigestOutputStream#write(byte[], int, int)
575: */
576: public void test_write$BII() throws Exception {
577: // Test for method void java.security.DigestOutputStream.write(byte [],
578: // int, int)
579: DigestOutputStream dos = new DigestOutputStream(
580: new ByteArrayOutputStream(), MessageDigest
581: .getInstance("SHA"));
582: byte digestArray[] = { 23, 43, 44 };
583: dos.write(digestArray, 1, 1);
584: byte digestResult[] = dos.getMessageDigest().digest();
585: byte expected[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
586: 107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
587:
588: assertTrue("Digest did not return expected result.",
589: java.util.Arrays.equals(digestResult, expected));
590: }
591:
592: /**
593: * @tests java.security.DigestOutputStream#write(int)
594: */
595: public void test_writeI() throws Exception {
596: // Test for method void java.security.DigestOutputStream.write(int)
597: DigestOutputStream dos = new DigestOutputStream(
598: new ByteArrayOutputStream(), MessageDigest
599: .getInstance("SHA"));
600: dos.write((byte) 43);
601: byte digestResult[] = dos.getMessageDigest().digest();
602: byte expected[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
603: 107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
604:
605: assertTrue("Digest did not return expected result.",
606: java.util.Arrays.equals(digestResult, expected));
607: }
608:
609: private class MyOutputStream extends OutputStream {
610: @Override
611: public void write(int arg0) throws IOException {
612: }
613: }
614:
615: private class MyDigestOutputStream extends DigestOutputStream {
616: public MyDigestOutputStream(OutputStream out,
617: MessageDigest digest) {
618: super (out, digest);
619: }
620:
621: public MessageDigest myMessageDigest() {
622: return digest;
623: }
624:
625: public OutputStream myOutputStream() {
626: return out;
627: }
628: }
629: }
|