/* * JacORB - a free Java ORB * * Copyright (C) 1999-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ package org.jacorb.test.orb; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Arrays; import org.jacorb.orb.CDROutputStream; import org.jacorb.orb.CodeSet; import org.jacorb.test.harness.ORBTestCase; import org.jacorb.test.harness.TestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.omg.CORBA.BAD_PARAM; public class CDROutputStreamTest extends ORBTestCase { private CDROutputStream objectUnderTest; @Before public void setUp() throws Exception { objectUnderTest = new CDROutputStream(orb); } @After public void tearDown() throws Exception { objectUnderTest.close(); objectUnderTest = null; } @Test public void testIncreaseSize() { byte[] buffer = new byte[4]; objectUnderTest.setBuffer(buffer); objectUnderTest.increaseSize(8); assertTrue(objectUnderTest.size() >= 8); } /** * Verifies that the public ctor is available and that the releaseBuffer works as expected */ @Test public void testCDRStreamSizeCtor() { CDROutputStream co = new CDROutputStream (orb, 1000); co.increaseSize(8); byte[] result = co.releaseBuffer(); co.close(); assertTrue (result.length == 1023); } /** * Verifies that the default encoding (ISO8859_1) works for char, char arrays, and strings. Reading the string * forces alignment of the 4-byte length, and ignores any null terminator. */ @Test public void testDefaultEncodingChar() throws Exception { objectUnderTest.write_char( 'a' ); objectUnderTest.write_char( 's' ); objectUnderTest.write_char( 'd' ); objectUnderTest.write_char( 'f' ); objectUnderTest.write_char_array( "wxyz".toCharArray(), 1, 3 ); objectUnderTest.write_string( "CAFE" ); byte[] codedText = { 'a', 's', 'd', 'f', 'x', 'y', 'z', 0, 0, 0, 0, 5, 'C', 'A', 'F', 'E', 0 }; assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the default encoding (UTF-16) works for wchar, wchar arrays, and wstrings * with no byte-order-marker. Reading the wstring * forces alignment of the 4-byte length. */ @Test public void testDefaultEncodingWChar() throws Exception { byte[] codedText = { 2, 0x5, (byte) (0xD0 & 0xff), // Hebrew letter aleph 2, 0x30, 0x51, // Hiragana syllable ha 2, 0x30, 0x74, // Hiragana syllable pi 2, 0x5, (byte) (0xD1 & 0xff), // Hebrew letter beis 2, 0x5, (byte) (0xD2 & 0xff), // Hebrew letter gimmel 2, 0x5, (byte) (0xD3 & 0xff), // Hebrew letter dalet 0, 0, // bytes ignored by 'long' alignment 0, 0, 0, 8, // string length in bytes, not chars 0x30, (byte) (0xDF & 0xff), // Mitsubishi, in Katakana 0x30, (byte) (0xC4 & 0xff), 0x30, (byte) (0xFA & 0xff), 0x30, (byte) (0xB7 & 0xff), }; objectUnderTest.write_wchar( '\u05D0' ); objectUnderTest.write_wchar( '\u3051' ); objectUnderTest.write_wchar( '\u3074' ); objectUnderTest.write_wchar_array( "\u05D0\u05D1\u05D2\u05D3".toCharArray(), 1, 3 ); objectUnderTest.write_wstring( "\u30DF\u30C4\u30FA\u30B7" ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the UCS-2 encoding works for wchar, wchar arrays, and wstrings. Unlike UTF-16, * the byte-order-marker is not optional. */ @Test public void testUCS2EncodingWChar() throws Exception { byte[] codedText = { 2, 0x5, (byte) (0xD0 & 0xff), // Hebrew letter aleph 2, 0x30, 0x51, // Hiragana syllable ha 2, 0x30, 0x74, // Hiragana syllable pi 2, 0x5, (byte) (0xD1 & 0xff), // Hebrew letter beis 2, 0x5, (byte) (0xD2 & 0xff), // Hebrew letter gimmel 2, 0x5, (byte) (0xD3 & 0xff), // Hebrew letter dalet 0, 0, // bytes ignored by 'long' alignment 0, 0, 0, 8, // string length in bytes, not chars 0x30, (byte) (0xDF & 0xff), // Mitsubishi, in Katakana 0x30, (byte) (0xC4 & 0xff), 0x30, (byte) (0xFA & 0xff), 0x30, (byte) (0xB7 & 0xff), }; selectCodeSets( "UTF8", "UCS2" ); objectUnderTest.write_wchar( '\u05D0' ); objectUnderTest.write_wchar( '\u3051' ); objectUnderTest.write_wchar( '\u3074' ); objectUnderTest.write_wchar_array( "\u05D0\u05D1\u05D2\u05D3".toCharArray(), 1, 3 ); objectUnderTest.write_wstring( "\u30DF\u30C4\u30FA\u30B7" ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the default encoding (UTF-16) works for wstrings in giop 1.1, which uses the length * indicator to specify the number of characters rather than bytes and require a two-byte null terminator. * Wide characters in 1.1 do not take width bytes */ @Test public void testDefaultEncodingWCharGiop1_1() throws Exception { byte[] codedText = { 0, 0, 0, 5, // string length in bytes, not chars 0x30, (byte) (0xDF & 0xff), // Mitsubishi, in Katakana 0x30, (byte) (0xC4 & 0xff), 0x30, (byte) (0xFA & 0xff), 0x30, (byte) (0xB7 & 0xff), 0, 0, // two-byte null terminator 0x5, (byte) (0xD1 & 0xff), // Hebrew letter beis }; objectUnderTest.setGIOPMinor( 1 ); objectUnderTest.write_wstring( "\u30DF\u30C4\u30FA\u30B7" ); objectUnderTest.write_wchar( '\u05D1' ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the UTF-8 encoding works for strings in giop 1.1. */ @Test public void testUTF8EncodingCharGiop1_1() throws Exception { byte[] codedText = { 0, 0, 0, 5, // string length in bytes, including null pointer 'a', 's', 'd', 'f', 0, // one-byte null terminator 'x' }; selectCodeSets( "UTF8", "UTF8" ); objectUnderTest.setGIOPMinor( 1 ); objectUnderTest.write_string( "asdf" ); objectUnderTest.write_char( 'x' ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the UTF-8 encoding works for strings in giop 1.1. Have to check - this may not be required. */ @Test public void testUTF8EncodingWCharGiop1_1() throws Exception { byte[] codedText = { 0, 0, 0, 13, // string length in bytes, including null terminator (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0x9F & 0xff), // Mitsubishi, in Katakana (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0x84 & 0xff), (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0xBA & 0xff), (byte) (0xE3 & 0xff), (byte) (0x82 & 0xff), (byte) (0xB7 & 0xff), 0, // one-byte null terminator (byte) (0xD7 & 0xff), (byte) (0x91 & 0xff), // Hebrew letter beis (w/o length byte) }; selectCodeSets( "ISO8859_1", "UTF8" ); objectUnderTest.setGIOPMinor( 1 ); objectUnderTest.write_wstring( "\u30DF\u30C4\u30FA\u30B7" ); objectUnderTest.write_wchar( '\u05D1' ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } /** * Verifies that the UTF-8 works for wchar, wchar arrays, and wstrings. Reading the wstring * forces alignment of the 4-byte length. Note that byte-ordering is fixed by the encoding. */ @Test public void testUTF8EncodingWChar() throws Exception { byte[] codedText = { 1, 'x', // Latin-l lowercase x 2, (byte) (0xD7 & 0xff), (byte) (0x90 & 0xff), // Hebrew letter aleph 3, (byte) (0xE3 & 0xff), (byte) (0x81 & 0xff), (byte) (0x91 & 0xff), // Hiragana syllable ha 3, (byte) (0xE3 & 0xff), (byte) (0x81 & 0xff), (byte) (0xB4 & 0xff), // Hiragana syllable pi 2, (byte) (0xD7 & 0xff), (byte) (0x91 & 0xff), // Hebrew letter beis 2, (byte) (0xD7 & 0xff), (byte) (0x92 & 0xff), // Hebrew letter gimmel 2, (byte) (0xD7 & 0xff), (byte) (0x93 & 0xff), // Hebrew letter dalet 0, 0, // bytes ignored by 'long' alignment 0, 0, 0, 12, // string length in bytes, not chars (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0x9F & 0xff), // Mitsubishi, in Katakana (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0x84 & 0xff), (byte) (0xE3 & 0xff), (byte) (0x83 & 0xff), (byte) (0xBA & 0xff), (byte) (0xE3 & 0xff), (byte) (0x82 & 0xff), (byte) (0xB7 & 0xff), }; selectCodeSets( "ISO8859_1", "UTF8" ); objectUnderTest.write_wchar( 'x' ); objectUnderTest.write_wchar( '\u05D0' ); objectUnderTest.write_wchar( '\u3051' ); objectUnderTest.write_wchar( '\u3074' ); objectUnderTest.write_wchar_array( "\u05D0\u05D1\u05D2\u05D3".toCharArray(), 1, 3 ); objectUnderTest.write_wstring( "\u30DF\u30C4\u30FA\u30B7" ); assertEquals( "generated bytes", codedText, objectUnderTest.getBufferCopy() ); } private void selectCodeSets( String charCodeSet, String wideCharCodeSet ) { objectUnderTest.setCodeSets( CodeSet.getCodeSet( charCodeSet ), CodeSet.getCodeSet( wideCharCodeSet ) ); } private static void assertEquals( String comment, byte[] expected, byte[] actual ) { if (Arrays.equals( expected, actual )) return; StringBuffer sb = new StringBuffer( comment ); append( sb, " expected: ", expected ); append( sb, "but was: ", actual ); fail( sb.toString() ); } private static final int BYTES_PER_GROUP = 8; private static final int GROUPS_PER_LINE = 8; private static final int BYTES_PER_LINE = BYTES_PER_GROUP * GROUPS_PER_LINE; private static final int LAST_IN_GROUP = BYTES_PER_GROUP - 1; private static void append( StringBuffer sb, String comment, byte[] bytes ) { sb.append( comment ).append( '\n' ); int pos = 0; while (pos < bytes.length ) { for (int i = 0; i < BYTES_PER_LINE && i < bytes.length - pos; i++) { formatOneByte( sb, bytes[i] ); if ((i % BYTES_PER_GROUP) == LAST_IN_GROUP) sb.append( ' ' ); } sb.append( '\n' ); pos += BYTES_PER_LINE; } } private static void formatOneByte(StringBuffer sb, byte aByte ) { int value = aByte & 0x0ff; if (value < 0x10) sb.append( '0' ); sb.append( Integer.toHexString( value ) ); } @Test public void testDoesNotLikeNonJacORB() { org.omg.CORBA.ORB sunORB = org.omg.CORBA.ORB.init(new String[0], TestUtils.newForeignORBProperties()); try { try { new CDROutputStream(sunORB); } catch(BAD_PARAM e) { } } finally { orb.shutdown(true); } } }