1/*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.io;
18
19import com.google.common.base.Function;
20import com.google.common.collect.Lists;
21
22import java.io.BufferedReader;
23import java.io.FilterReader;
24import java.io.IOException;
25import java.io.Reader;
26import java.io.StringReader;
27import java.nio.CharBuffer;
28import java.util.Arrays;
29import java.util.List;
30
31/**
32 * Unit tests for {@link LineBuffer} and {@link LineReader}.
33 *
34 * @author Chris Nokleberg
35 */
36public class LineBufferTest extends IoTestCase {
37
38  public void testProcess() throws IOException {
39    bufferHelper("");
40    bufferHelper("\n", "\n");
41    bufferHelper("\r\n", "\r\n");
42    bufferHelper("\n\r", "\n", "\r");
43    bufferHelper("\r", "\r");
44    bufferHelper("\n\n", "\n", "\n");
45    bufferHelper("\r\n\r\n", "\r\n", "\r\n");
46    bufferHelper("\r\r", "\r", "\r");
47    bufferHelper("\ra\r\n\n\r\r", "\r", "a\r\n", "\n", "\r", "\r");
48    bufferHelper("no newlines at all", "no newlines at all");
49    bufferHelper("two lines\nbut no newline at end",
50        "two lines\n", "but no newline at end");
51    bufferHelper("\nempty first line\nno newline at end",
52        "\n", "empty first line\n", "no newline at end");
53    bufferHelper("three\rlines\rno newline at end",
54        "three\r", "lines\r", "no newline at end");
55    bufferHelper("mixed\nline\rendings\r\n",
56        "mixed\n", "line\r", "endings\r\n");
57  }
58
59  private static final int[] CHUNK_SIZES = { 1, 2, 3, Integer.MAX_VALUE };
60
61  private static void bufferHelper(String input, String... expect)
62      throws IOException {
63
64    List<String> expectProcess = Arrays.asList(expect);
65    List<String> expectRead = Lists.transform(expectProcess,
66        new Function<String, String>() {
67          @Override
68          public String apply(String value) {
69            return value.replaceAll("[\\r\\n]", "");
70          }
71        });
72
73    for (int chunk : CHUNK_SIZES) {
74      chunk = Math.max(1, Math.min(chunk, input.length()));
75      assertEquals(expectProcess, bufferHelper(input, chunk));
76      assertEquals(expectRead, readUsingJava(input, chunk));
77      assertEquals(expectRead, readUsingReader(input, chunk, true));
78      assertEquals(expectRead, readUsingReader(input, chunk, false));
79    }
80  }
81
82  private static List<String> bufferHelper(String input, int chunk)
83      throws IOException {
84    final List<String> lines = Lists.newArrayList();
85    LineBuffer lineBuf = new LineBuffer() {
86      @Override protected void handleLine(String line, String end) {
87        lines.add(line + end);
88      }
89    };
90    char[] chars = input.toCharArray();
91    int off = 0;
92    while (off < chars.length) {
93      int len = Math.min(chars.length, off + chunk) - off;
94      lineBuf.add(chars, off, len);
95      off += len;
96    }
97    lineBuf.finish();
98    return lines;
99  }
100
101  private static List<String> readUsingJava(String input, int chunk)
102      throws IOException {
103    BufferedReader r = new BufferedReader(getChunkedReader(input, chunk));
104    List<String> lines = Lists.newArrayList();
105    String line;
106    while ((line = r.readLine()) != null) {
107      lines.add(line);
108    }
109    r.close();
110    return lines;
111  }
112
113  private static List<String> readUsingReader(String input, int chunk,
114      boolean asReader) throws IOException {
115    Readable readable = asReader
116        ? getChunkedReader(input, chunk)
117        : getChunkedReadable(input, chunk);
118    LineReader r = new LineReader(readable);
119    List<String> lines = Lists.newArrayList();
120    String line;
121    while ((line = r.readLine()) != null) {
122      lines.add(line);
123    }
124    return lines;
125  }
126
127  // Returns a Readable that is *not* a Reader.
128  private static Readable getChunkedReadable(String input, int chunk) {
129    final Reader reader = getChunkedReader(input, chunk);
130    return new Readable() {
131      @Override
132      public int read(CharBuffer cbuf) throws IOException {
133        return reader.read(cbuf);
134      }
135    };
136  }
137
138  private static Reader getChunkedReader(String input, final int chunk) {
139    return new FilterReader(new StringReader(input)) {
140      @Override public int read(char[] cbuf, int off, int len)
141          throws IOException {
142        return super.read(cbuf, off, Math.min(chunk, len));
143      }
144    };
145  }
146}
147