1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.jdkim.canon;
21  
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.io.OutputStream;
25  import java.security.NoSuchAlgorithmException;
26  
27  public class SimpleBodyCanonicalizerTest extends AbstractOutputStreamTestCase {
28  
29      private byte[] testData;
30      private byte[] expectedData;
31  
32      protected void setUp() throws Exception {
33          testData = "this  is a \r\n  canonicalization \ttest\r\n\r\n\r\n"
34                  .getBytes();
35          expectedData = "this  is a \r\n  canonicalization \ttest\r\n"
36                  .getBytes();
37      }
38  
39      public void testSingleBytes() throws NoSuchAlgorithmException, IOException {
40          ByteArrayOutputStream bos = new ByteArrayOutputStream();
41          SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
42          for (int i = 0; i < testData.length; i++) {
43              os.write(testData[i]);
44          }
45          os.close();
46          assertArrayEquals(expectedData, bos.toByteArray());
47      }
48  
49      public void testChunks() throws NoSuchAlgorithmException, IOException {
50          ByteArrayOutputStream bos = new ByteArrayOutputStream();
51          SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
52          chunker(testData, os);
53          assertArrayEquals(expectedData, bos.toByteArray());
54      }
55  
56      public void testCRLFchunk() throws NoSuchAlgorithmException, IOException {
57          ByteArrayOutputStream bos = new ByteArrayOutputStream();
58          SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
59          writeChunk(os, testData, 0, 37);
60          // a buffer consisting of only CRLF was not handled correctly.
61          // this test checks this.
62          writeChunk(os, testData, 37, 6);
63          os.close();
64          assertArrayEquals(expectedData, bos.toByteArray());
65      }
66  
67      public void testProblematicChunks() throws NoSuchAlgorithmException,
68              IOException {
69          ByteArrayOutputStream bos = new ByteArrayOutputStream();
70          SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
71          writeChunk(os, testData, 0, 38);
72          writeChunk(os, testData, 38, 2);
73          // a buffer consisting of only LFCR after a previous chunk
74          // ended with CR was not handled correctly.
75          writeChunk(os, testData, 40, 3);
76          os.close();
77          assertArrayEquals(expectedData, bos.toByteArray());
78      }
79  
80      protected OutputStream newInstance(ByteArrayOutputStream bos) {
81          return new SimpleBodyCanonicalizer(bos);
82      }
83  
84      public void testExtensiveChunks() throws NoSuchAlgorithmException,
85              IOException {
86          extensiveChunker(testData, expectedData);
87      }
88  
89      public void testWrongCRSequences() throws NoSuchAlgorithmException,
90              IOException {
91          // byte[] test = "this is a \r\n canonica\rlizati\r\ron
92          // \ttest\r\n\r\n\r\r".getBytes();
93          // byte[] expected = "this is a \r\n canonica\rlizati\r\ron
94          // \ttest\r\n\r\n\r\r\n".getBytes();
95          byte[] test = "this  is a \r\n  canonica\rlizati".getBytes();
96          byte[] expected = "this  is a \r\n  canonica\rlizati\r\n".getBytes();
97          extensiveChunker(test, expected);
98      }
99  
100     public void testProblematicCRSequences() throws NoSuchAlgorithmException,
101             IOException {
102         byte[] test = "this  is a \r\n  canonica\rlizati".getBytes();
103         byte[] expected = "this  is a \r\n  canonica\rlizati\r\n".getBytes();
104         ByteArrayOutputStream bos = new ByteArrayOutputStream();
105         SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
106         writeChunk(os, test, 0, 24);
107         // this created a problem where a single byte write after a line
108         // ending with \r was buggy
109         writeChunk(os, test, 24, 1);
110         writeChunk(os, test, 25, 5);
111         os.close();
112         assertArrayEquals(expected, bos.toByteArray());
113     }
114 
115     public void testWrongCRSequencesAdv() throws NoSuchAlgorithmException,
116             IOException {
117         // byte[] test = "this is a \r\n canonica\rlizati\r\ron
118         // \ttest\r\n\r\n\r\r".getBytes();
119         // byte[] expected = "this is a \r\n canonica\rlizati\r\ron
120         // \ttest\r\n\r\n\r\r\n".getBytes();
121         byte[] test = "this  is a \r\n  canonica\rlizati\r\ron\r\n\r\n\r"
122                 .getBytes();
123         byte[] expected = "this  is a \r\n  canonica\rlizati\r\ron\r\n"
124                 .getBytes();
125         extensiveChunker(test, expected);
126     }
127 
128     public void testProblematicEndingCRLFCR() throws NoSuchAlgorithmException,
129             IOException {
130         byte[] test = "this  is a \r\n  canonica\rlizati\r\ron\r\n\r\n\r"
131                 .getBytes();
132         byte[] expected = "this  is a \r\n  canonica\rlizati\r\ron\r\n"
133                 .getBytes();
134         ByteArrayOutputStream bos = new ByteArrayOutputStream();
135         SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
136         // checks a bug with an buffer ending with \r\n\r
137         writeChunk(os, test, 0, 39);
138         os.close();
139         assertArrayEquals(expected, bos.toByteArray());
140     }
141 
142     public void testProblematicEndingCR() throws NoSuchAlgorithmException,
143             IOException {
144         byte[] test = "this  is a \r\n  canonica\rlizati\r\ron\r\n\r\n\r"
145                 .getBytes();
146         byte[] expected = "this  is a \r\n  canonica\rlizati\r\ron\r\n"
147                 .getBytes();
148         ByteArrayOutputStream bos = new ByteArrayOutputStream();
149         SimpleBodyCanonicalizer os = new SimpleBodyCanonicalizer(bos);
150         // checks a bug with an buffer ending with \r\n\r
151         writeChunk(os, test, 0, 31);
152         writeChunk(os, test, 31, 1);
153         writeChunk(os, test, 32, 7);
154         os.close();
155         assertArrayEquals(expected, bos.toByteArray());
156     }
157 
158 }