blob: d90c8ecb35677984f333af73a751ffb26df1eaf5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Vladimir N. Molotkov
* @version $Revision$
*/
package org.apache.harmony.security.tests.java.security;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import junit.framework.TestCase;
import org.apache.harmony.security.tests.support.MDGoldenData;
import org.apache.harmony.security.tests.support.MyMessageDigest1;
import tests.support.Support_OutputStream;
/**
* Tests for fields and methods of class <code>DigestInputStream</code>
*
*/
public class DigestOutputStreamTest extends TestCase {
/**
* Message digest algorithm name used during testing
*/
private static final String algorithmName[] = {
"SHA-1",
"SHA",
"SHA1",
"SHA-256",
"SHA-384",
"SHA-512",
"MD5",
};
/**
* Chunk size for read(byte, off, len) tests
*/
private static final int CHUNK_SIZE = 32;
/**
* Test message for digest computations
*/
private static final byte[] myMessage = MDGoldenData.getMessage();
/**
* The length of test message
*/
private static final int MY_MESSAGE_LEN = myMessage.length;
//
// Tests
//
/**
* java.security.DigestOutputStream#DigestOutputStream(java.io.OutputStream,
* java.security.MessageDigest)
*/
public void test_CtorLjava_io_OutputStreamLjava_security_MessageDigest() {
// non-null parameters
MessageDigest md = new MyMessageDigest1();
MyOutputStream out = new MyOutputStream();
MyDigestOutputStream dos = new MyDigestOutputStream(out, md);
assertSame(out, dos.myOutputStream());
assertSame(md, dos.myMessageDigest());
// null parameters
dos = new MyDigestOutputStream(null, null);
assertNull(dos.myOutputStream());
assertNull(dos.myMessageDigest());
dos = new MyDigestOutputStream(null, md);
assertNull(dos.myOutputStream());
assertNotNull(dos.myMessageDigest());
dos = new MyDigestOutputStream(out, null);
assertNotNull(dos.myOutputStream());
assertNull(dos.myMessageDigest());
}
/**
* java.security.DigestOutputStream#getMessageDigest()
*/
public void test_getMessageDigest() {
MessageDigest digest = new MyMessageDigest1();
OutputStream out = new MyOutputStream();
// non-null parameter
DigestOutputStream dos = new DigestOutputStream(out, digest);
assertSame(digest, dos.getMessageDigest());
// null parameter
dos = new DigestOutputStream(out, null);
assertNull("getMessageDigest should have returned null", dos.getMessageDigest());
}
/**
* java.security.DigestOutputStream#setMessageDigest(MessageDigest)
*/
public void test_setMessageDigestLjava_security_MessageDigest() {
MessageDigest digest = new MyMessageDigest1();
OutputStream out = new MyOutputStream();
DigestOutputStream dos = new DigestOutputStream(out, null);
// non-null parameter
dos.setMessageDigest(digest);
assertSame(digest, dos.getMessageDigest());
// null parameter
dos.setMessageDigest(null);
assertNull("getMessageDigest should have returned null", dos.getMessageDigest());
}
/**
* Test #1 for <code>write(int)</code> method<br>
*
* Assertion: writes the byte to the output stream<br>
* Assertion: updates associated digest<br>
*/
public final void testWriteint01()
throws IOException {
for (int k=0; k<algorithmName.length; k++) {
try {
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
DigestOutputStream dos = new DigestOutputStream(bos, md);
for (int i=0; i<MY_MESSAGE_LEN; i++) {
dos.write(myMessage[i]);
}
// check that bytes have been written correctly
assertTrue("write", Arrays.equals(MDGoldenData.getMessage(), bos.toByteArray()));
// check that associated digest has been updated properly
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k])));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #2 for <code>write(int)</code> method<br>
* Test #1 for <code>on(boolean)</code> method<br>
*
* Assertion: <code>write(int)</code> must not update digest if it is off<br>
* Assertion: <code>on(boolean)</code> turns digest functionality on
* if <code>true</code> passed as a parameter or off if <code>false</code>
* passed
*/
public final void testWriteint02()
throws IOException {
for (int k=0; k<algorithmName.length; k++) {
try {
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// turn digest off
dos.on(false);
for (int i=0; i<MY_MESSAGE_LEN; i++) {
dos.write(myMessage[i]);
}
// check that bytes have been written correctly
assertTrue("write", Arrays.equals(MDGoldenData.getMessage(), bos.toByteArray()));
// check that digest value has not been updated by write()
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k]+"_NU")));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #3 for <code>write(int)</code> method<br>
*
* Assertion: broken <code>DigestOutputStream</code>instance:
* <code>OutputStream</code> not set. <code>write(int)</code> must
* not work
*/
public final void testWriteint03() throws IOException {
for (int k=0; k<algorithmName.length; k++) {
try {
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(null, md);
// must result in an exception
try {
for (int i=0; i<MY_MESSAGE_LEN; i++) {
dos.write(myMessage[i]);
}
fail("OutputStream not set. write(int) must not work");
} catch (Exception e) {
return;
}
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #4 for <code>write(int)</code> method<br>
*
* Assertion: broken <code>DigestOutputStream</code>instance:
* associated <code>MessageDigest</code> not set.
* <code>write(int)</code> must not work when digest
* functionality is on
*/
public final void testWriteint04() throws IOException {
OutputStream os = new ByteArrayOutputStream(MY_MESSAGE_LEN);
DigestOutputStream dos = new DigestOutputStream(os, null);
// must result in an exception
try {
for (int i=0; i<MY_MESSAGE_LEN; i++) {
dos.write(myMessage[i]);
}
fail("OutputStream not set. write(int) must not work");
} catch (Exception e) {
return;
}
}
/**
* Test #5 for <code>write(int)</code> method<br>
* Test #2 for <code>on(boolean)</code> method<br>
*
* Assertion: broken <code>DigestOutputStream</code>instance:
* associated <code>MessageDigest</code> not set.
* <code>write(int)</code> must work when digest
* functionality is off
*/
public final void testWriteint05() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
DigestOutputStream dos = new DigestOutputStream(bos, null);
// set digest functionality to off
dos.on(false);
// the following must pass without any exception
for (int i=0; i<MY_MESSAGE_LEN; i++) {
dos.write(myMessage[i]);
}
// check that bytes have been written correctly
assertTrue(Arrays.equals(MDGoldenData.getMessage(), bos.toByteArray()));
}
/**
* Test #1 for <code>write(byte[],int,int)</code> method<br>
*
* Assertion: put bytes into output stream<br>
*
* Assertion: updates associated digest<br>
*/
public final void test_write$BII_1() throws IOException {
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// write message at once
dos.write(myMessage, 0, MY_MESSAGE_LEN);
// check write
assertTrue("write", Arrays.equals(myMessage, bos.toByteArray()));
// check that associated digest has been updated properly
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k])));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #2 for <code>write(byte[],int,int)</code> method<br>
*
* Assertion: put bytes into output stream<br>
*
* Assertion: updates associated digest<br>
*/
public final void test_write$BII_2() throws IOException {
// check precondition
assertEquals(0, MY_MESSAGE_LEN % CHUNK_SIZE);
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// write message by chunks
for (int i=0; i<MY_MESSAGE_LEN/CHUNK_SIZE; i++) {
dos.write(myMessage, i*CHUNK_SIZE, CHUNK_SIZE);
}
// check write
assertTrue("write", Arrays.equals(myMessage, bos.toByteArray()));
// check that associated digest has been updated properly
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k])));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #3 for <code>write(byte[],int,int)</code> method<br>
*
* Assertion: put bytes into output stream<br>
*
* Assertion: updates associated digest<br>
*/
public final void test_write$BII_3()
throws NoSuchAlgorithmException,
IOException {
// check precondition
assertTrue(MY_MESSAGE_LEN % (CHUNK_SIZE+1) != 0);
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// write message by chunks
for (int i=0; i<MY_MESSAGE_LEN/(CHUNK_SIZE+1); i++) {
dos.write(myMessage, i*(CHUNK_SIZE+1), CHUNK_SIZE+1);
}
// write remaining bytes
dos.write(myMessage,
MY_MESSAGE_LEN/(CHUNK_SIZE+1)*(CHUNK_SIZE+1),
MY_MESSAGE_LEN % (CHUNK_SIZE+1));
// check write
assertTrue("write", Arrays.equals(myMessage, bos.toByteArray()));
// check that associated digest has been updated properly
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k])));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test #4 for <code>write(byte[],int,int)</code> method<br>
*
* Assertion: put bytes into output stream<br>
*
* Assertion: does not update associated digest if digest
* functionality is off<br>
*/
public final void test_write$BII_4()
throws NoSuchAlgorithmException,
IOException {
// check precondition
assertEquals(0, MY_MESSAGE_LEN % CHUNK_SIZE);
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// set digest functionality off
dos.on(false);
// write message by chunks
for (int i=0; i<MY_MESSAGE_LEN/CHUNK_SIZE; i++) {
dos.write(myMessage, i*CHUNK_SIZE, CHUNK_SIZE);
}
// check write
assertTrue("write", Arrays.equals(myMessage, bos.toByteArray()));
// check that associated digest has not been updated
assertTrue("update", Arrays.equals(dos.getMessageDigest().digest(),
MDGoldenData.getDigest(algorithmName[k]+"_NU")));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* java.security.DigestOutputStream#write(byte[], int, int)
*/
public void test_write$BII_6() throws Exception {
// Regression form HARMONY-1091.
MessageDigest md = new MyMessageDigest1();
byte[] bytes = new byte[] { 1, 2 };
DigestOutputStream dig = new DigestOutputStream(
new ByteArrayOutputStream(), md);
// buf == null
try {
dig.write(null, -1, 0);
fail("No expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// offset + len > buf.length
try {
dig.write(bytes, 0, bytes.length + 1);
fail("No expected IllegalArgumentException");
} catch (IllegalArgumentException e) {
}
// offset < 0
try {
dig.write(bytes, -1, 1);
fail("No expected IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException e) {
}
// len < 0
try {
dig.write(bytes, 0, -1);
fail("No expected IndexOutOfBoundsException");
} catch (IndexOutOfBoundsException e) {
}
}
/**
* java.io.DigestOutputStream#write(byte[], int, int)
*/
public void test_write$BII_7()
throws IOException, NoSuchAlgorithmException {
Support_OutputStream sos = new Support_OutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[0]);
DigestOutputStream dos = new DigestOutputStream(sos, md);
dos.write(myMessage, 0, MY_MESSAGE_LEN);
try {
// Support_OutputStream throws an IOException if the internal
// buffer is full, which it should be now.
dos.write(myMessage, 0, MY_MESSAGE_LEN);
fail("Test 1: IOException expected.");
} catch (IOException e) {
// Expected.
}
}
/**
* Test for <code>on()</code> method<br>
* Assertion: turns digest functionality on or off
*/
public final void testOn() throws IOException {
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
// turn digest off
dos.on(false);
for (int i=0; i<MY_MESSAGE_LEN-1; i++) {
dos.write(myMessage[i]);
}
// turn digest on
dos.on(true);
// read remaining byte
dos.write(myMessage[MY_MESSAGE_LEN-1]);
byte[] digest = dos.getMessageDigest().digest();
// check that digest value has been
// updated by the last write(int) call
assertFalse(Arrays.equals(digest,MDGoldenData.getDigest(algorithmName[k])));
assertFalse(Arrays.equals(digest,MDGoldenData.getDigest(algorithmName[k]+"_NU")));
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* Test for <code>toString()</code> method<br>
* Assertion: returns <code>String</code> representation of this object
*/
public final void testToString() throws NoSuchAlgorithmException {
for (int k=0; k<algorithmName.length; k++) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream(MY_MESSAGE_LEN);
MessageDigest md = MessageDigest.getInstance(algorithmName[k]);
DigestOutputStream dos = new DigestOutputStream(bos, md);
assertNotNull(dos.toString());
return;
} catch (NoSuchAlgorithmException e) {
// allowed failure
}
}
fail(getName() + ": no MessageDigest algorithms available - test not performed");
}
/**
* java.security.DigestOutputStream#on(boolean)
*/
public void test_onZ() throws Exception {
// Test for method void java.security.DigestOutputStream.on(boolean)
DigestOutputStream dos = new DigestOutputStream(
new ByteArrayOutputStream(), MessageDigest.getInstance("SHA"));
dos.on(false);
byte digestArray[] = { 23, 43, 44 };
dos.write(digestArray, 1, 1);
byte digestResult[] = dos.getMessageDigest().digest();
byte expected[] = { -38, 57, -93, -18, 94, 107, 75, 13, 50, 85,
-65, -17, -107, 96, 24, -112, -81, -40, 7, 9 };
assertTrue("Digest did not return expected result.",
Arrays.equals(digestResult, expected));
// now turn on processing and re-run
dos.on(true);
dos.write(digestArray, 1, 1);
digestResult = dos.getMessageDigest().digest();
byte expected1[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33,
107, -118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
assertTrue("Digest did not return expected result.",
Arrays.equals(digestResult, expected1));
}
/**
* java.security.DigestOutputStream#write(byte[], int, int)
*/
public void test_write$BII_5() throws Exception {
// Test for method void java.security.DigestOutputStream.write(byte [],
// int, int)
DigestOutputStream dos = new DigestOutputStream(
new ByteArrayOutputStream(), MessageDigest.getInstance("SHA"));
byte digestArray[] = { 23, 43, 44 };
dos.write(digestArray, 1, 1);
byte digestResult[] = dos.getMessageDigest().digest();
byte expected[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33, 107,
-118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
assertTrue("Digest did not return expected result.",
Arrays.equals(digestResult, expected));
}
/**
* java.security.DigestOutputStream#write(int)
*/
public void test_writeI() throws Exception {
// Test for method void java.security.DigestOutputStream.write(int)
DigestOutputStream dos = new DigestOutputStream(
new ByteArrayOutputStream(), MessageDigest.getInstance("SHA"));
dos.write((byte) 43);
byte digestResult[] = dos.getMessageDigest().digest();
byte expected[] = { -87, 121, -17, 16, -52, 111, 106, 54, -33, 107,
-118, 50, 51, 7, -18, 59, -78, -30, -37, -100 };
assertTrue("Digest did not return expected result.",
Arrays.equals(digestResult, expected));
}
private class MyOutputStream extends OutputStream {
@Override
public void write(int arg0) throws IOException {
}
}
private class MyDigestOutputStream extends DigestOutputStream {
public MyDigestOutputStream(OutputStream out, MessageDigest digest) {
super(out, digest);
}
public MessageDigest myMessageDigest() {
return digest;
}
public OutputStream myOutputStream() {
return out;
}
}
}