/* * 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. */ /* $Id$ */ package org.apache.fop.pdf; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import org.apache.commons.io.output.CountingOutputStream; /** * Test class for {@link PDFName}. */ public class PDFNameTestCase extends PDFObjectTestCase { private PDFName pdfName; /** * Sets up the local variables */ @Before public void setUp() { pdfName = new PDFName("TestName"); pdfName.setParent(parent); pdfName.setDocument(doc); pdfObjectUnderTest = pdfName; } /** * Tests escapeName() - tests that this method escapes the necessary characters. */ @Test public void testEscapeName() { try { // Test for null, this is a programming error thus the NPE PDFName.escapeName(null); fail("NPE not thrown when null object given to escapeName()"); } catch (NullPointerException e) { // PASS } // All names are prefixed by "/", check the PDF spec for further details. assertEquals("/Test", PDFName.escapeName("Test")); // Check that if the name is already prefixed with "/" it doens't do it twice assertEquals("/Test", PDFName.escapeName("/Test")); // Test with a space in the middle assertEquals("/Test#20test", PDFName.escapeName("Test test")); // Test that all chars apart from ASCII '!' --> '~' are escaped nonEscapedCharactersTests(); escapedCharactersTests(); } private void escapedCharactersTests() { for (char i = 0; i < '!'; i++) { String str = Integer.toHexString(i >>> 4 & 0x0f).toUpperCase(); str += Integer.toHexString(i & 0x0f).toUpperCase(); assertEquals("/#" + str, PDFName.escapeName(String.valueOf(i))); } for (char i = '~' + 1; i < 256; i++) { String str = Integer.toHexString(i >>> 4 & 0x0f).toUpperCase(); str += Integer.toHexString(i & 0x0f).toUpperCase(); assertEquals("/#" + str, PDFName.escapeName(String.valueOf(i))); } checkCharacterIsEscaped('#'); checkCharacterIsEscaped('%'); checkCharacterIsEscaped('('); checkCharacterIsEscaped(')'); checkCharacterIsEscaped('<'); checkCharacterIsEscaped('>'); checkCharacterIsEscaped('['); checkCharacterIsEscaped(']'); checkCharacterIsEscaped('>'); } private void checkCharacterIsEscaped(char c) { String str = Integer.toHexString(c >>> 4 & 0x0f).toUpperCase(); str += Integer.toHexString(c & 0x0f).toUpperCase(); assertEquals("/#" + str, PDFName.escapeName(String.valueOf(c))); } private void nonEscapedCharactersTests() { charactersNotEscapedBetween('!', '"'); charactersNotEscapedBetween('*', ';'); charactersNotEscapedBetween('?', 'Z'); charactersNotEscapedBetween('^', '~'); } private void charactersNotEscapedBetween(char c1, char c2) { for (char i = c1; i <= c2; i++) { String str = String.valueOf(i); String expected = !str.equals("/") ? "/" + str : str; assertEquals(expected, PDFName.escapeName(str)); } } /** * Tests toString() - this has been overridden to return the String that PDFName wraps. */ @Test public void testToString() { // The escape characters have already been tested in testEscapeName() so this doesn't need // to be done twice. PDFName test1 = new PDFName("test1"); assertEquals("/test1", test1.toString()); PDFName test2 = new PDFName("another test"); assertEquals("/another#20test", test2.toString()); try { new PDFName(null); fail("NPE not thrown when null passed to constructor"); } catch (NullPointerException e) { // PASS } } /** * Tests output() - check that this object can stream itself in the correct format. * @throws IOException error caused by I/O */ @Test public void testOutput() throws IOException { testOutputStreams("/TestName", pdfName); testOutputStreams("/test#20test", new PDFName("test test")); } /** * Test outputInline() - this writes the object reference if it is a direct object (has an * object number), or writes the String representation if there is no object number. */ @Test public void testOutputInline() { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); CountingOutputStream cout = new CountingOutputStream(outStream); StringBuilder textBuffer = new StringBuilder(); try { // test with no object number set. pdfName.outputInline(outStream, textBuffer); PDFDocument.flushTextBuffer(textBuffer, cout); assertEquals("/TestName", outStream.toString()); outStream.reset(); // test with object number set pdfName.setObjectNumber(1); pdfName.outputInline(outStream, textBuffer); PDFDocument.flushTextBuffer(textBuffer, cout); assertEquals("1 0 R", outStream.toString()); } catch (IOException e) { fail("IOException: " + e.getMessage()); } } }