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 Alexander Y. Kleymenov
20*/
21
22package javax.crypto;
23
24import java.io.ByteArrayInputStream;
25import javax.crypto.NullCipher;
26
27import junit.framework.TestCase;
28
29/**
30 */
31
32public class CipherInputStreamTest extends TestCase {
33
34    private static class TestInputStream extends ByteArrayInputStream {
35        private boolean closed = false;
36
37        public TestInputStream(byte[] data) {
38            super(data);
39        }
40
41        public void close() {
42            closed = true;
43        }
44
45        public boolean wasClosed() {
46            return closed;
47        }
48    }
49
50    /**
51     * CipherInputStream(InputStream is) method testing. Tests that
52     * CipherInputStream uses NullCipher if Cipher is not specified
53     * in the constructor.
54     */
55    public void testCipherInputStream() throws Exception {
56        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
57        TestInputStream tis = new TestInputStream(data);
58        CipherInputStream cis = new CipherInputStream(tis);
59
60        for (int i = 0; i < data.length; i++) {
61            if ((byte) cis.read() != data[i]) {
62                fail("NullCipher should be used "
63                        + "if Cipher is not specified.");
64            }
65        }
66        if (cis.read() != -1) {
67            fail("NullCipher should be used if Cipher is not specified.");
68        }
69    }
70
71    /**
72     * read() method testing. Tests that method returns the correct value
73     * (related to the InputStream) and that it returns -1 at the end of stream.
74     */
75    public void testRead1() throws Exception {
76        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
77        TestInputStream tis = new TestInputStream(data);
78        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
79        byte res;
80        for (int i = 0; i < data.length; i++) {
81            if ((res = (byte) cis.read()) != data[i]) {
82                fail("read() returned the incorrect value. " + "Expected: "
83                        + data[i] + ", Got: " + res + ".");
84            }
85        }
86        if (cis.read() != -1) {
87            fail("read() should return -1 at the end of the stream.");
88        }
89    }
90
91    /**
92     * read(byte[] b) method testing. Tests that method returns the correct
93     * value (related to the InputStream) and that it returns -1 at the end of
94     * stream.
95     */
96    public void testRead2() throws Exception {
97        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
98        TestInputStream tis = new TestInputStream(data);
99        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
100
101        int expected = data.length;
102        byte[] result = new byte[expected];
103
104        int ind = 0; // index into the data array (to check the got data)
105        int got = cis.read(result); // the number of got bytes
106        while (true) {
107            for (int j = 0; j < got - ind; j++) {
108                if (result[j] != data[ind + j]) {
109                    fail("read(byte[] b) returned incorrect data.");
110                }
111            }
112            if (got == expected) {
113                break;
114            } else if (got > expected) {
115                fail("The data returned by read(byte[] b) "
116                        + "is larger than expected.");
117            } else {
118                ind = got;
119                got += cis.read(result);
120            }
121        }
122        if (cis.read(result) != -1) {
123            fail("read(byte[] b) should return -1 "
124                    + "at the end of the stream.");
125        }
126    }
127
128    /**
129     * read(byte[] b, int off, int len) method testing. Tests that method
130     * returns the correct value (related to the InputStream), that it discards
131     * bytes in the case of null buffer, and that it returns -1 at the end of
132     * stream.
133     */
134    public void testRead3() throws Exception {
135        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
136        TestInputStream tis = new TestInputStream(data);
137        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
138
139        int expected = data.length;
140        byte[] result = new byte[expected];
141
142        int skip = 2;
143        int ind = skip; // index into the data array (to check the got data)
144        // should read and discard bytes;
145        cis.read(null, 0, skip);
146        int got = skip + cis.read(result, 0, 1); // the number of got bytes
147        while (true) {
148            for (int j = 0; j < got - ind; j++) {
149                assertEquals("read(byte[] b, int off, int len) "
150                        + "returned incorrect data.", result[j], data[ind + j]);
151            }
152            if (got == expected) {
153                break;
154            } else if (got > expected) {
155                fail("The data returned by "
156                        + "read(byte[] b, int off, int len) "
157                        + "is larger than expected.");
158            } else {
159                ind = got;
160                got += cis.read(result, 0, 3);
161            }
162        }
163        if (cis.read(result, 0, 1) != -1) {
164            fail("read() should return -1 at the end of the stream.");
165        }
166    }
167
168    /**
169     * skip(long n) method testing. Tests that the method correctly skips the
170     * bytes.
171     */
172    public void testSkip() throws Exception {
173        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
174        TestInputStream tis = new TestInputStream(data);
175        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
176        int expected = data.length;
177        byte[] result = new byte[expected];
178
179        int skipped = (int) cis.skip(2);
180        int ind = skipped;
181        int got = skipped + cis.read(result, 0, 1); // the number of got bytes
182        while (true) {
183            for (int j = 0; j < got - ind; j++) {
184                if (result[j] != data[ind + j]) {
185                    fail("read(byte[] b, int off, int len) "
186                            + "returned incorrect data: Expected "
187                            + data[ind + j] + ", got: " + result[j]);
188                }
189            }
190            if (got == expected) {
191                break;
192            } else if (got > expected) {
193                fail("The data returned by "
194                        + "read(byte[] b, int off, int len) "
195                        + "is larger than expected.");
196            } else {
197                ind = got;
198                got += cis.read(result, 0, 1);
199            }
200        }
201        if ((got = cis.read(result, 0, 1)) != -1) {
202            fail("read() should return -1 at the end of the stream. "
203                    + "Output is: " + got + ".");
204        }
205    }
206
207    /**
208     * available() method testing. Tests that the method always return 0.
209     */
210    public void testAvailable() throws Exception {
211        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
212        TestInputStream tis = new TestInputStream(data);
213        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
214        assertEquals("The returned by available() method value "
215                + "should be 0.", cis.available(), 0);
216    }
217
218    /**
219     * close() method testing. Tests that the method calls the close()
220     * method of the underlying input stream.
221     */
222    public void testClose() throws Exception {
223        byte[] data = new byte[] { -127, -100, -50, -10, -1, 0, 1, 10, 50, 127 };
224        TestInputStream tis = new TestInputStream(data);
225        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
226        cis.close();
227        assertTrue("The close() method should call the close() method "
228                + "of its underlying input stream.", tis.wasClosed());
229    }
230
231    /**
232     * markSupported() method testing. Tests that mark is not supported.
233     */
234    public void testMarkSupported() {
235        byte[] data = new byte[] {-127, -100, -50, -10, -1, 0, 1, 10, 50, 127};
236        TestInputStream tis = new TestInputStream(data);
237        CipherInputStream cis = new CipherInputStream(tis, new NullCipher());
238        assertFalse("The returned by markSupported() method value "
239                + "should be false.", cis.markSupported());
240    }
241
242}
243
244