| /* |
| * Copyright (C) 2015, 2020 Ivan Motsch <ivan.motsch@bsiag.com> and others |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Distribution License v. 1.0 which is available at |
| * https://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| package org.eclipse.jgit.api; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.AUTO_CRLF; |
| import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.AUTO_LF; |
| import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.DIRECT; |
| import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.TEXT_CRLF; |
| import static org.eclipse.jgit.lib.CoreConfig.EolStreamType.TEXT_LF; |
| import static org.junit.Assert.assertArrayEquals; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.Arrays; |
| |
| import org.eclipse.jgit.lib.CoreConfig.EolStreamType; |
| import org.eclipse.jgit.util.IO; |
| import org.eclipse.jgit.util.io.EolStreamTypeUtil; |
| import org.junit.Test; |
| |
| /** |
| * Unit tests for end-of-line conversion streams |
| */ |
| public class EolStreamTypeUtilTest { |
| |
| @Test |
| public void testCheckoutDirect() throws Exception { |
| testCheckout(DIRECT, DIRECT, "", ""); |
| testCheckout(DIRECT, DIRECT, "\r", "\r"); |
| testCheckout(DIRECT, DIRECT, "\n", "\n"); |
| |
| testCheckout(DIRECT, DIRECT, "\r\n", "\r\n"); |
| testCheckout(DIRECT, DIRECT, "\n\r", "\n\r"); |
| |
| testCheckout(DIRECT, DIRECT, "\n\r\n", "\n\r\n"); |
| testCheckout(DIRECT, DIRECT, "\r\n\r", "\r\n\r"); |
| |
| testCheckout(DIRECT, DIRECT, "a\nb\n", "a\nb\n"); |
| testCheckout(DIRECT, DIRECT, "a\rb\r", "a\rb\r"); |
| testCheckout(DIRECT, DIRECT, "a\n\rb\n\r", "a\n\rb\n\r"); |
| testCheckout(DIRECT, DIRECT, "a\r\nb\r\n", "a\r\nb\r\n"); |
| } |
| |
| @Test |
| public void testCheckoutLF() throws Exception { |
| testCheckout(TEXT_LF, AUTO_LF, "", ""); |
| testCheckout(TEXT_LF, AUTO_LF, "\r", "\r"); |
| testCheckout(TEXT_LF, AUTO_LF, "\n", "\n"); |
| |
| testCheckout(TEXT_LF, null, "\r\n", "\n"); |
| testCheckout(null, AUTO_LF, "\r\n", "\r\n"); |
| testCheckout(TEXT_LF, AUTO_LF, "\n\r", "\n\r"); |
| |
| testCheckout(TEXT_LF, null, "\n\r\n", "\n\n"); |
| testCheckout(null, AUTO_LF, "\n\r\n", "\n\r\n"); |
| testCheckout(TEXT_LF, null, "\r\n\r", "\n\r"); |
| testCheckout(null, AUTO_LF, "\r\n\r", "\r\n\r"); |
| |
| testCheckout(TEXT_LF, AUTO_LF, "a\nb\n", "a\nb\n"); |
| testCheckout(TEXT_LF, AUTO_LF, "a\rb\r", "a\rb\r"); |
| testCheckout(TEXT_LF, AUTO_LF, "a\n\rb\n\r", "a\n\rb\n\r"); |
| testCheckout(TEXT_LF, null, "a\r\nb\r\n", "a\nb\n"); |
| testCheckout(null, AUTO_LF, "a\r\nb\r\n", "a\r\nb\r\n"); |
| } |
| |
| @Test |
| public void testCheckoutCRLF() throws Exception { |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "", ""); |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "\r", "\r"); |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "\n", "\r\n"); |
| |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "\r\n", "\r\n"); |
| testCheckout(TEXT_CRLF, null, "\n\r", "\r\n\r"); |
| testCheckout(null, AUTO_CRLF, "\n\r", "\n\r"); // Lone CR |
| |
| testCheckout(null, AUTO_CRLF, "\n\r\n", "\n\r\n"); |
| testCheckout(TEXT_CRLF, null, "\n\r\n", "\r\n\r\n"); |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "\r\n\r", "\r\n\r"); |
| |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "a\nb\n", "a\r\nb\r\n"); |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "a\rb\r", "a\rb\r"); |
| testCheckout(TEXT_CRLF, null, "a\n\rb\n\r", "a\r\n\rb\r\n\r"); |
| testCheckout(null, AUTO_CRLF, "a\n\rb\n\r", "a\n\rb\n\r"); // Lone CR |
| testCheckout(TEXT_CRLF, AUTO_CRLF, "a\r\nb\r\n", "a\r\nb\r\n"); |
| } |
| |
| /** |
| * Test stream type detection based on stream content. |
| * <p> |
| * Tests three things with the output text: |
| * <p> |
| * 1) conversion if output was declared as text |
| * <p> |
| * 2) conversion if output was declared as potentially text (AUTO_...) and |
| * is in fact text |
| * <p> |
| * 3) conversion if modified output (now with binary characters) was |
| * declared as potentially text but now contains binary characters |
| * <p> |
| * |
| * @param streamTypeText |
| * is the enum meaning that the output is definitely text (no |
| * binary check at all) |
| * @param streamTypeWithBinaryCheck |
| * is the enum meaning that the output may be text (binary check |
| * is done) |
| * @param output |
| * is a text output without binary characters |
| * @param expectedConversion |
| * is the expected converted output without binary characters |
| * @throws Exception |
| */ |
| private void testCheckout(EolStreamType streamTypeText, |
| EolStreamType streamTypeWithBinaryCheck, String output, |
| String expectedConversion) throws Exception { |
| ByteArrayOutputStream b; |
| byte[] outputBytes = output.getBytes(UTF_8); |
| byte[] expectedConversionBytes = expectedConversion.getBytes(UTF_8); |
| |
| if (streamTypeText != null) { |
| // test using output text and assuming it was declared TEXT |
| b = new ByteArrayOutputStream(); |
| try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, |
| streamTypeText)) { |
| out.write(outputBytes); |
| } |
| assertArrayEquals(expectedConversionBytes, b.toByteArray()); |
| } |
| if (streamTypeWithBinaryCheck != null) { |
| // test using output text and assuming it was declared AUTO, using |
| // binary detection |
| b = new ByteArrayOutputStream(); |
| try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, |
| streamTypeWithBinaryCheck)) { |
| out.write(outputBytes); |
| } |
| assertArrayEquals(expectedConversionBytes, b.toByteArray()); |
| } |
| // now pollute output text with some binary bytes |
| outputBytes = extendWithBinaryData(outputBytes); |
| expectedConversionBytes = extendWithBinaryData(expectedConversionBytes); |
| |
| if (streamTypeText != null) { |
| // again, test using output text and assuming it was declared TEXT |
| b = new ByteArrayOutputStream(); |
| try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, |
| streamTypeText)) { |
| out.write(outputBytes); |
| } |
| assertArrayEquals(expectedConversionBytes, b.toByteArray()); |
| } |
| if (streamTypeWithBinaryCheck != null) { |
| // again, test using output text and assuming it was declared AUTO, |
| // using binary detection |
| b = new ByteArrayOutputStream(); |
| try (OutputStream out = EolStreamTypeUtil.wrapOutputStream(b, |
| streamTypeWithBinaryCheck)) { |
| out.write(outputBytes); |
| } |
| // expect no conversion |
| assertArrayEquals(outputBytes, b.toByteArray()); |
| } |
| } |
| |
| @Test |
| public void testCheckinDirect() throws Exception { |
| testCheckin(DIRECT, DIRECT, "", ""); |
| testCheckin(DIRECT, DIRECT, "\r", "\r"); |
| testCheckin(DIRECT, DIRECT, "\n", "\n"); |
| |
| testCheckin(DIRECT, DIRECT, "\r\n", "\r\n"); |
| testCheckin(DIRECT, DIRECT, "\n\r", "\n\r"); |
| |
| testCheckin(DIRECT, DIRECT, "\n\r\n", "\n\r\n"); |
| testCheckin(DIRECT, DIRECT, "\r\n\r", "\r\n\r"); |
| |
| testCheckin(DIRECT, DIRECT, "a\nb\n", "a\nb\n"); |
| testCheckin(DIRECT, DIRECT, "a\rb\r", "a\rb\r"); |
| testCheckin(DIRECT, DIRECT, "a\n\rb\n\r", "a\n\rb\n\r"); |
| testCheckin(DIRECT, DIRECT, "a\r\nb\r\n", "a\r\nb\r\n"); |
| } |
| |
| @Test |
| public void testCheckinLF() throws Exception { |
| testCheckin(TEXT_LF, AUTO_LF, "", ""); |
| testCheckin(TEXT_LF, AUTO_LF, "\r", "\r"); |
| testCheckin(TEXT_LF, AUTO_LF, "\n", "\n"); |
| |
| testCheckin(TEXT_LF, AUTO_LF, "\r\n", "\n"); |
| testCheckin(TEXT_LF, AUTO_LF, "\n\r", "\n\r"); |
| |
| testCheckin(TEXT_LF, AUTO_LF, "\n\r\n", "\n\n"); |
| testCheckin(TEXT_LF, null, "\r\n\r", "\n\r"); |
| testCheckin(null, AUTO_LF, "\r\n\r", "\r\n\r"); // Lone CR |
| |
| testCheckin(TEXT_LF, AUTO_LF, "a\nb\n", "a\nb\n"); |
| testCheckin(TEXT_LF, AUTO_LF, "a\rb\r", "a\rb\r"); |
| testCheckin(TEXT_LF, AUTO_LF, "a\n\rb\n\r", "a\n\rb\n\r"); |
| testCheckin(TEXT_LF, AUTO_LF, "a\r\nb\r\n", "a\nb\n"); |
| } |
| |
| @Test |
| public void testCheckinCRLF() throws Exception { |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "", ""); |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "\r", "\r"); |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "\n", "\r\n"); |
| |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "\r\n", "\r\n"); |
| testCheckin(TEXT_CRLF, null, "\n\r", "\r\n\r"); |
| testCheckin(null, AUTO_CRLF, "\n\r", "\n\r"); // Lone CR |
| |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "\n\r\n", "\r\n\r\n"); |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "\r\n\r", "\r\n\r"); |
| |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "a\nb\n", "a\r\nb\r\n"); |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "a\rb\r", "a\rb\r"); |
| testCheckin(TEXT_CRLF, null, "a\n\rb\n\r", "a\r\n\rb\r\n\r"); |
| testCheckin(null, AUTO_CRLF, "a\n\rb\n\r", "a\n\rb\n\r"); // Lone CR |
| testCheckin(TEXT_CRLF, AUTO_CRLF, "a\r\nb\r\n", "a\r\nb\r\n"); |
| } |
| |
| /** |
| * Test stream type detection based on stream content. |
| * <p> |
| * Tests three things with the input text: |
| * <p> |
| * 1) conversion if input was declared as text |
| * <p> |
| * 2) conversion if input was declared as potentially text (AUTO_...) and is |
| * in fact text |
| * <p> |
| * 3) conversion if modified input (now with binary characters) was declared |
| * as potentially text but now contains binary characters |
| * <p> |
| * |
| * @param streamTypeText |
| * is the enum meaning that the input is definitely text (no |
| * binary check at all) |
| * @param streamTypeWithBinaryCheck |
| * is the enum meaning that the input may be text (binary check |
| * is done) |
| * @param input |
| * is a text input without binary characters |
| * @param expectedConversion |
| * is the expected converted input without binary characters |
| * @throws Exception |
| */ |
| private void testCheckin(EolStreamType streamTypeText, |
| EolStreamType streamTypeWithBinaryCheck, String input, |
| String expectedConversion) throws Exception { |
| byte[] inputBytes = input.getBytes(UTF_8); |
| byte[] expectedConversionBytes = expectedConversion.getBytes(UTF_8); |
| |
| if (streamTypeText != null) { |
| // test using input text and assuming it was declared TEXT |
| try (InputStream in = EolStreamTypeUtil.wrapInputStream( |
| new ByteArrayInputStream(inputBytes), streamTypeText)) { |
| byte[] b = new byte[1024]; |
| int len = IO.readFully(in, b, 0); |
| assertArrayEquals(expectedConversionBytes, |
| Arrays.copyOf(b, len)); |
| } |
| } |
| |
| if (streamTypeWithBinaryCheck != null) { |
| // test using input text and assuming it was declared AUTO, using |
| // binary detection |
| try (InputStream in = EolStreamTypeUtil.wrapInputStream( |
| new ByteArrayInputStream(inputBytes), |
| streamTypeWithBinaryCheck)) { |
| byte[] b = new byte[1024]; |
| int len = IO.readFully(in, b, 0); |
| assertArrayEquals(expectedConversionBytes, |
| Arrays.copyOf(b, len)); |
| } |
| } |
| // now pollute input text with some binary bytes |
| inputBytes = extendWithBinaryData(inputBytes); |
| expectedConversionBytes = extendWithBinaryData(expectedConversionBytes); |
| |
| if (streamTypeText != null) { |
| // again, test using input text and assuming it was declared TEXT |
| try (InputStream in = EolStreamTypeUtil.wrapInputStream( |
| new ByteArrayInputStream(inputBytes), streamTypeText)) { |
| byte[] b = new byte[1024]; |
| int len = IO.readFully(in, b, 0); |
| assertArrayEquals(expectedConversionBytes, |
| Arrays.copyOf(b, len)); |
| } |
| } |
| |
| if (streamTypeWithBinaryCheck != null) { |
| // again, test using input text and assuming it was declared AUTO, |
| // using binary detection |
| try (InputStream in = EolStreamTypeUtil.wrapInputStream( |
| new ByteArrayInputStream(inputBytes), |
| streamTypeWithBinaryCheck)) { |
| byte[] b = new byte[1024]; |
| int len = IO.readFully(in, b, 0); |
| // expect no conversion |
| assertArrayEquals(inputBytes, Arrays.copyOf(b, len)); |
| } |
| } |
| } |
| |
| private byte[] extendWithBinaryData(byte[] data) throws Exception { |
| int n = 3; |
| byte[] dataEx = new byte[data.length + n]; |
| System.arraycopy(data, 0, dataEx, 0, data.length); |
| for (int i = 0; i < n; i++) { |
| dataEx[data.length + i] = (byte) i; |
| } |
| return dataEx; |
| } |
| |
| } |