View Javadoc
1 /*** 2 * Redistribution and use of this software and associated documentation 3 * ("Software"), with or without modification, are permitted provided 4 * that the following conditions are met: 5 * 6 * 1. Redistributions of source code must retain copyright 7 * statements and notices. Redistributions must also contain a 8 * copy of this document. 9 * 10 * 2. Redistributions in binary form must reproduce the 11 * above copyright notice, this list of conditions and the 12 * following disclaimer in the documentation and/or other 13 * materials provided with the distribution. 14 * 15 * 3. The name "Exolab" must not be used to endorse or promote 16 * products derived from this Software without prior written 17 * permission of Exoffice Technologies. For written permission, 18 * please contact tma@netspace.net.au. 19 * 20 * 4. Products derived from this Software may not be called "Exolab" 21 * nor may "Exolab" appear in their names without prior written 22 * permission of Exoffice Technologies. Exolab is a registered 23 * trademark of Exoffice Technologies. 24 * 25 * 5. Due credit should be given to the Exolab Project 26 * (http://www.exolab.org/). 27 * 28 * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS 29 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT 30 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 31 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 32 * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 33 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 39 * OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Copyright 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved. 42 * 43 * $Id: StreamMessageTest.java,v 1.7 2004/02/03 21:52:10 tanderson Exp $ 44 */ 45 package org.exolab.jmscts.test.message.stream; 46 47 import java.util.Arrays; 48 49 import javax.jms.MessageEOFException; 50 import javax.jms.MessageFormatException; 51 import javax.jms.StreamMessage; 52 53 import junit.framework.Test; 54 55 import org.exolab.jmscts.core.AbstractMessageTestCase; 56 import org.exolab.jmscts.core.ClassHelper; 57 import org.exolab.jmscts.core.MessagePopulator; 58 import org.exolab.jmscts.core.TestContext; 59 import org.exolab.jmscts.core.TestCreator; 60 import org.exolab.jmscts.test.message.util.Conversions; 61 import org.exolab.jmscts.test.message.util.MessageValues; 62 63 64 /*** 65 * This class tests the <code>StreamMessage</code> message type 66 * 67 * @author <a href="mailto:tma@netspace.net.au">Tim Anderson</a> 68 * @version $Revision: 1.7 $ 69 * @see javax.jms.StreamMessage 70 * @jmscts.message StreamMessage 71 */ 72 public class StreamMessageTest extends AbstractMessageTestCase 73 implements MessageValues { 74 75 /*** 76 * Values to test conversions against. String conversions are handled 77 * separately, by the {@link #STRING_CONVERSION_VALUES} attribute 78 */ 79 private static final Object[][] CONVERSION_VALUES = { 80 BOOLEANS, BYTES, SHORTS, CHARS, INTS, LONGS, FLOATS, DOUBLES, 81 BYTE_ARRAYS}; 82 83 /*** 84 * Float values to test string conversions against. String conversions 85 * don't have to support NaN, or +-Infinity, hence the reason they are not 86 * included here 87 */ 88 private static final Float[] FLOAT_CONVERSION_VALUES = { 89 new Float(Float.MIN_VALUE), new Float(Float.MAX_VALUE)}; 90 91 /*** 92 * Double values to test string conversions against. String conversions 93 * don't have to support NaN, or +-Infinity, hence the reason they are not 94 * included here 95 */ 96 private static final Double[] DOUBLE_CONVERSION_VALUES = { 97 new Double(Double.MIN_VALUE), new Double(Double.MAX_VALUE)}; 98 99 /*** 100 * Values to test string conversions against 101 */ 102 private static final Object[][] STRING_CONVERSION_VALUES = { 103 BOOLEANS, BYTES, SHORTS, INTS, LONGS, FLOAT_CONVERSION_VALUES, 104 DOUBLE_CONVERSION_VALUES, STRINGS}; 105 106 /*** 107 * Create an instance of this class for a specific test case 108 * 109 * @param name the name of test case 110 */ 111 public StreamMessageTest(String name) { 112 super(name); 113 } 114 115 /*** 116 * Sets up the test suite 117 * 118 * @return an instance of this class that may be run by 119 * {@link org.exolab.jmscts.core.JMSTestRunner} 120 */ 121 public static Test suite() { 122 return TestCreator.createMessageTest(StreamMessageTest.class); 123 } 124 125 /*** 126 * Get the message populator. This implementation always returns null 127 * 128 * @return null 129 */ 130 public MessagePopulator getMessagePopulator() { 131 return null; 132 } 133 134 /*** 135 * Verifies that if a read method throws MessageFormatException 136 * the current position of the read pointer is not 137 * incremented, and that a subsequent read is capable of recovering from 138 * the exception by re-reading the data as a different type. 139 * 140 * @jmscts.requirement message.stream.read 141 * @throws Exception for any error 142 */ 143 public void testReadFailure() throws Exception { 144 TestContext context = getContext(); 145 StreamMessage message = (StreamMessage) context.getMessage(); 146 147 for (int i = 0; i < ALL_VALUES.length; ++i) { 148 for (int j = 0; j < ALL_VALUES[i].length; ++j) { 149 Object value = ALL_VALUES[i][j]; 150 write(message, value); 151 message.reset(); 152 Class type = value.getClass(); 153 Class[] invalid = Conversions.getInvalidConversions(type); 154 for (int k = 0; k < invalid.length; ++k) { 155 try { 156 read(message, invalid[k]); 157 fail("Expected MessageFormatException to be thrown " 158 + "when reading type=" 159 + ClassHelper.getPrimitiveName(invalid[k]) 160 + " for type=" 161 + ClassHelper.getPrimitiveName(type)); 162 } catch (MessageFormatException expected) { 163 // the expected behaviour 164 } catch (Exception exception) { 165 fail("Expected MessageFormatException to be thrown " 166 + "when reading type=" 167 + ClassHelper.getPrimitiveName(invalid[k]) 168 + " for type=" 169 + ClassHelper.getPrimitiveName(type) 170 + ", but got exception=" 171 + exception.getClass().getName() + ", message=" 172 + exception.getMessage()); 173 } 174 } 175 if (value instanceof byte[]) { 176 byte[] v = (byte[]) value; 177 byte[] buffer = new byte[v.length]; 178 assertEquals(v.length, message.readBytes(buffer)); 179 assertTrue(Arrays.equals(v, buffer)); 180 assertEquals(-1, message.readBytes(buffer)); 181 } else { 182 Object result = read(message, type); 183 assertEquals(value, result); 184 } 185 message.clearBody(); 186 } 187 } 188 } 189 190 /*** 191 * Verifies valid conversions for all types except String 192 * (this is handled by testStringConversion()). 193 * 194 * @jmscts.requirement message.stream.conversion 195 * @throws Exception for any error 196 */ 197 public void testConversion() throws Exception { 198 TestContext context = getContext(); 199 StreamMessage message = (StreamMessage) context.getMessage(); 200 201 for (int i = 0; i < CONVERSION_VALUES.length; ++i) { 202 for (int j = 0; j < CONVERSION_VALUES[i].length; ++j) { 203 Object value = CONVERSION_VALUES[i][j]; 204 write(message, value); 205 Class type = value.getClass(); 206 Class[] valid = Conversions.getValidConversions(type); 207 for (int k = 0; k < valid.length; ++k) { 208 message.reset(); 209 Object result = read(message, valid[k]); 210 Object converted = Conversions.convert(value, valid[k]); 211 if (converted instanceof byte[]) { 212 // byte arrays cannot be converted 213 if (!Arrays.equals((byte[]) result, 214 (byte[]) converted)) { 215 fail("Read byte array different to that written"); 216 } 217 } else { 218 assertEquals( 219 "Conversion of type=" 220 + ClassHelper.getPrimitiveName(type) + " to type=" 221 + ClassHelper.getPrimitiveName(valid[k]) 222 + " failed.", converted, result); 223 } 224 } 225 message.clearBody(); 226 } 227 } 228 } 229 230 /*** 231 * Verifies valid string conversions. 232 * 233 * @jmscts.requirement message.stream.conversion 234 * @throws Exception for any error 235 */ 236 public void testStringConversion() throws Exception { 237 TestContext context = getContext(); 238 StreamMessage message = (StreamMessage) context.getMessage(); 239 240 for (int i = 0; i < STRING_CONVERSION_VALUES.length; ++i) { 241 for (int j = 0; j < STRING_CONVERSION_VALUES[i].length; ++j) { 242 Object value = STRING_CONVERSION_VALUES[i][j]; 243 write(message, value.toString()); 244 Class type = value.getClass(); 245 message.reset(); 246 Object result = read(message, type); 247 if (!value.equals(result)) { 248 fail("Conversion of type=String to type=" 249 + ClassHelper.getPrimitiveName(type) 250 + " failed. Expected value=" + value 251 + ", but got value=" + result); 252 } 253 message.clearBody(); 254 } 255 } 256 } 257 258 /*** 259 * Verifies invalid string to numeric conversions. 260 * 261 * @jmscts.requirement message.stream.conversion 262 * @throws Exception for any error 263 */ 264 public void testInvalidNumericConversion() throws Exception { 265 TestContext context = getContext(); 266 StreamMessage message = (StreamMessage) context.getMessage(); 267 Class[] numerics = {Byte.class, Short.class, Integer.class, Long.class, 268 Float.class, Double.class}; 269 String[] invalidNos = {"a", "0x00", "NaN", "-Infinity", "+Infinity"}; 270 for (int i = 0; i < invalidNos.length; ++i) { 271 String value = invalidNos[i]; 272 message.writeString(value); 273 message.reset(); 274 for (int j = 0; j < numerics.length; ++j) { 275 try { 276 read(message, numerics[j]); 277 fail("Expected NumberFormatException to be thrown when " 278 + "reading value=" + value + " as type=" 279 + ClassHelper.getPrimitiveName(numerics[j])); 280 } catch (NumberFormatException expected) { 281 // the expected behaviour 282 } catch (Exception exception) { 283 fail("Expected NumberFormatException to be thrown when " 284 + "reading value=" + value + " as type=" 285 + ClassHelper.getPrimitiveName(numerics[j]) 286 + ", but got exception=" 287 + exception.getClass().getName() + ", message=" 288 + exception.getMessage()); 289 } 290 } 291 String result = message.readString(); 292 assertEquals(value, result); 293 message.clearBody(); 294 } 295 } 296 297 /*** 298 * Verifies null conversions. 299 * 300 * @jmscts.requirement message.stream.null 301 * @throws Exception for any error 302 */ 303 public void testNull() throws Exception { 304 TestContext context = getContext(); 305 StreamMessage message = (StreamMessage) context.getMessage(); 306 307 try { 308 message.writeObject(null); 309 } catch (Exception exception) { 310 fail("Failed to write a null value to StreamMessage, exception=" 311 + exception.getClass().getName() + ", message=" 312 + exception.getMessage()); 313 } 314 message.reset(); 315 Object result = readNull(message, Boolean.class, null); 316 assertEquals(Boolean.FALSE, result); 317 message.reset(); 318 319 result = readNull(message, String.class, null); 320 assertEquals(null, result); 321 message.reset(); 322 323 byte[] tmp = new byte[0]; 324 assertEquals(-1, message.readBytes(tmp)); 325 message.reset(); 326 327 // no need to call reset() for the following - the message should 328 // do it. 329 readNull(message, Byte.class, NumberFormatException.class); 330 readNull(message, Short.class, NumberFormatException.class); 331 readNull(message, Character.class, NullPointerException.class); 332 readNull(message, Integer.class, NumberFormatException.class); 333 readNull(message, Long.class, NumberFormatException.class); 334 readNull(message, Float.class, NullPointerException.class); 335 readNull(message, Double.class, NullPointerException.class); 336 } 337 338 /*** 339 * Verifies that writeObject() can handle all supported types 340 * 341 * @jmscts.requirement message.bytes.method.writeObject 342 * @throws Exception for any error 343 */ 344 public void testWriteObject() throws Exception { 345 TestContext context = getContext(); 346 StreamMessage message = (StreamMessage) context.getMessage(); 347 348 for (int i = 0; i < ALL_VALUES.length; ++i) { 349 for (int j = 0; j < ALL_VALUES[i].length; ++j) { 350 message.writeObject(ALL_VALUES[i][j]); 351 } 352 } 353 message.reset(); 354 for (int i = 0; i < ALL_VALUES.length; ++i) { 355 for (int j = 0; j < ALL_VALUES[i].length; ++j) { 356 Object value = message.readObject(); 357 if (ALL_VALUES[i][j] instanceof byte[]) { 358 byte[] source = (byte[]) ALL_VALUES[i][j]; 359 byte[] result = (byte[]) value; 360 assertTrue(Arrays.equals(source, result)); 361 } else { 362 assertEquals(ALL_VALUES[i][j], value); 363 } 364 } 365 } 366 } 367 368 /*** 369 * Verifies that an invalid object being written using the writeObject() 370 * method throws <code>MessageFormatException</code> 371 * 372 * @jmscts.requirement message.stream.method.writeObject 373 * @throws Exception for any error 374 */ 375 public void testInvalidObject() throws Exception { 376 TestContext context = getContext(); 377 StreamMessage message = (StreamMessage) context.getMessage(); 378 379 try { 380 message.writeObject(new java.math.BigDecimal(0.0)); 381 fail("StreamMessage.writeObject() should only support " 382 + "objectified primitives"); 383 } catch (MessageFormatException expected) { 384 // the expected behaviour 385 } 386 } 387 388 /*** 389 * Verifies that readBytes returns that written by the writeBytes 390 * methods. 391 * 392 * @jmscts.requirement message.stream.method.writeBytes(1) 393 * @jmscts.requirement message.stream.method.writeBytes(2) 394 * @throws Exception for any error 395 */ 396 public void testReadWriteBytes() throws Exception { 397 final int dataSize = 256; 398 TestContext context = getContext(); 399 StreamMessage message = (StreamMessage) context.getMessage(); 400 401 byte[] bytes = populateByteArray(dataSize, 0); 402 message.writeBytes(bytes); 403 message.reset(); 404 byte[] buffer1 = new byte[bytes.length]; 405 message.readBytes(buffer1); 406 if (!Arrays.equals(bytes, buffer1)) { 407 fail("Read byte array differs to that written"); 408 } 409 int count = message.readBytes(buffer1); 410 if (count != -1) { 411 fail("Expected readBytes to return count=-1 to indicate end of " 412 + "array field, but returned count=" + count); 413 414 } 415 416 message.clearBody(); 417 message.writeBytes(bytes, 1, bytes.length - 2); 418 message.reset(); 419 byte[] expected = populateByteArray(bytes.length - 2, 1); 420 byte[] buffer2 = new byte[expected.length]; 421 message.readBytes(buffer2); 422 if (!Arrays.equals(expected, buffer2)) { 423 fail("Read byte array differs to that written"); 424 } 425 count = message.readBytes(buffer2); 426 if (count != -1) { 427 fail("Expected readBytes to return count=-1 to indicate end of " 428 + "array field, but returned count=" + count); 429 } 430 } 431 432 /*** 433 * Verifies that invoking readBytes() followed by reset() followed by 434 * readBytes() returns the expected result, when the 435 * first readBytes() call has not completed reading the array field. This 436 * verifies that reset() correctly resets the state of the message. 437 * 438 * @jmscts.requirement message.stream.method.readBytes 439 * @throws Exception for any error 440 */ 441 public void testReadBytesReset1() throws Exception { 442 final int dataSize = 256; 443 TestContext context = getContext(); 444 StreamMessage message = (StreamMessage) context.getMessage(); 445 446 byte[] bytes = populateByteArray(dataSize, 0); 447 message.writeBytes(bytes); 448 message.reset(); 449 byte[] buffer = new byte[bytes.length]; 450 message.readBytes(buffer); 451 if (!Arrays.equals(bytes, buffer)) { 452 fail("Read byte array differs to that written"); 453 } 454 455 message.reset(); 456 // NOTE: readBytes() had not completed reading the array field 457 458 message.readBytes(buffer); 459 if (!Arrays.equals(bytes, buffer)) { 460 fail("Read byte array differs to that written"); 461 } 462 } 463 464 /*** 465 * Verifies that invoking readBytes() followed by reset() followed by 466 * readObject() returns the expected result, when the readBytes() call has 467 * not completed reading the array field. This verifies that reset() 468 * correctly resets the state of the message. 469 * 470 * @jmscts.requirement message.stream.method.readBytes 471 * @throws Exception for any error 472 */ 473 public void testReadBytesReset2() throws Exception { 474 final int dataSize = 256; 475 TestContext context = getContext(); 476 StreamMessage message = (StreamMessage) context.getMessage(); 477 478 byte[] bytes = populateByteArray(dataSize, 0); 479 message.writeBytes(bytes); 480 message.reset(); 481 byte[] buffer = new byte[bytes.length]; 482 message.readBytes(buffer); 483 if (!Arrays.equals(bytes, buffer)) { 484 fail("Read byte array differs to that written"); 485 } 486 487 message.reset(); 488 // NOTE: readBytes() had not completed reading the array field 489 490 byte[] result = (byte[]) message.readObject(); 491 if (!Arrays.equals(bytes, buffer)) { 492 fail("Read byte array differs to that written"); 493 } 494 } 495 496 /*** 497 * Verifies that invoking readBytes() followed by clearBody() followed by 498 * readBytes() returns the expected result, when the 499 * first readBytes() call has not completed reading the array field. This 500 * verifies that clearBody() correctly clears the state of the message. 501 * 502 * @jmscts.requirement message.stream.method.readBytes 503 * @throws Exception for any error 504 */ 505 public void testReadBytesClearBody1() throws Exception { 506 final int dataSize = 256; 507 TestContext context = getContext(); 508 StreamMessage message = (StreamMessage) context.getMessage(); 509 510 byte[] bytes = populateByteArray(dataSize, 0); 511 message.writeBytes(bytes); 512 message.reset(); 513 byte[] buffer = new byte[bytes.length]; 514 message.readBytes(buffer); 515 if (!Arrays.equals(bytes, buffer)) { 516 fail("Read byte array differs to that written"); 517 } 518 519 message.clearBody(); 520 // NOTE: readBytes() had not completed reading the array field 521 522 bytes = populateByteArray(dataSize, 1); 523 message.writeBytes(bytes); 524 message.reset(); 525 message.readBytes(buffer); 526 if (!Arrays.equals(bytes, buffer)) { 527 fail("Read byte array differs to that written"); 528 } 529 } 530 531 /*** 532 * Verifies that invoking readBytes() followed by clearBody() followed by 533 * readObject() returns the expected result, when the readBytes() call has 534 * not completed reading the array field. This ensures that clearBody() 535 * correctly clears the state of the message. 536 * 537 * @jmscts.requirement message.stream.method.readBytes 538 * @throws Exception for any error 539 */ 540 public void testReadBytesClearBody2() throws Exception { 541 final int dataSize = 256; 542 TestContext context = getContext(); 543 StreamMessage message = (StreamMessage) context.getMessage(); 544 545 byte[] bytes = populateByteArray(dataSize, 0); 546 message.writeBytes(bytes); 547 message.reset(); 548 byte[] buffer = new byte[bytes.length]; 549 message.readBytes(buffer); 550 if (!Arrays.equals(bytes, buffer)) { 551 fail("Read byte array differs to that written"); 552 } 553 554 message.clearBody(); 555 // NOTE: readBytes() had not completed reading the array field 556 557 bytes = populateByteArray(dataSize, 1); 558 message.writeBytes(bytes); 559 message.reset(); 560 byte[] result = (byte[]) message.readObject(); 561 if (!Arrays.equals(bytes, result)) { 562 fail("Read byte array differs to that written"); 563 } 564 } 565 566 /*** 567 * Verifies that invoking writeBytes does not modify the source array 568 * 569 * @jmscts.requirement message.stream.method.writeBytes(1) 570 * @jmscts.requirement message.stream.method.writeBytes(2) 571 * @throws Exception for any error 572 */ 573 public void testWriteBytes() throws Exception { 574 final int dataSize = 256; 575 TestContext context = getContext(); 576 StreamMessage message = (StreamMessage) context.getMessage(); 577 578 byte[] bytes = populateByteArray(dataSize, 0); 579 byte[] copy = populateByteArray(bytes.length, 0); 580 message.writeBytes(bytes); 581 message.reset(); 582 byte[] buffer = new byte[bytes.length]; 583 message.readBytes(buffer); 584 if (!Arrays.equals(bytes, copy)) { 585 fail("writeBytes(byte[]) modified the source byte array"); 586 } 587 588 message.clearBody(); 589 message.writeBytes(bytes, 0, bytes.length); 590 message.reset(); 591 message.readBytes(buffer); 592 if (!Arrays.equals(bytes, copy)) { 593 fail("writeBytes(byte[], int, int) modified the source byte " 594 + "array"); 595 } 596 } 597 598 /*** 599 * Verifies that readBytes can read an entire byte array, and returns -1 600 * on the subsequent call. 601 * 602 * @jmscts.requirement message.stream.method.readBytes 603 * @throws Exception for any error 604 */ 605 public void testFullReadBytes() throws Exception { 606 final int dataSize = 256; 607 TestContext context = getContext(); 608 StreamMessage message = (StreamMessage) context.getMessage(); 609 610 byte[] bytes = populateByteArray(dataSize, 0); 611 message.writeBytes(bytes); 612 message.reset(); 613 614 byte[] buffer = new byte[bytes.length]; 615 int count = message.readBytes(buffer); 616 if (count != buffer.length) { 617 fail("Expected readBytes to return count=" + buffer.length 618 + ", but returned count=" + count); 619 } 620 if (!Arrays.equals(bytes, buffer)) { 621 fail("Read byte array differs to that written"); 622 } 623 count = message.readBytes(buffer); 624 if (count != -1) { 625 fail("Expected readBytes to return count=-1 to indicate end of " 626 + "array field, but returned count=" + count); 627 } 628 } 629 630 /*** 631 * Verifies that readBytes can read be invoked incrementally. 632 * 633 * @jmscts.requirement message.stream.method.readBytes 634 * @throws Exception for any error 635 */ 636 public void testIncrementalReadBytes() throws Exception { 637 final int chunkSize = 64; 638 final int remainder = (chunkSize / 2); 639 final int chunks = 8; // the number of chunks to read. The last chunk 640 // is only half full 641 final int size = (chunks - 1) * chunkSize + remainder; 642 // the size of the byte array. The result will be read back 643 // incrementally, with the last read only filling a portion of the 644 // buffer 645 646 TestContext context = getContext(); 647 StreamMessage message = (StreamMessage) context.getMessage(); 648 649 byte[] bytes = populateByteArray(size, 0); 650 message.writeBytes(bytes); 651 message.reset(); 652 653 byte[][] buffers = new byte[chunks][chunkSize]; 654 int total = 0; 655 int count = 0; 656 for (int i = 0; i < chunks; ++i) { 657 count = message.readBytes(buffers[i]); 658 total += count; 659 int expected = (i < chunks - 1) ? chunkSize : remainder; 660 if (count != expected) { 661 fail("Expected readBytes to return count=" + expected 662 + ", but returned count=" + count); 663 } 664 } 665 666 // concatenate the buffers together, and check that the read array 667 // matches that written 668 byte[] read = new byte[size]; 669 for (int i = 0; i < chunks; ++i) { 670 int length = (i < chunks - 1) ? chunkSize : remainder; 671 System.arraycopy(buffers[i], 0, read, i * chunkSize, length); 672 } 673 if (!Arrays.equals(bytes, read)) { 674 fail("Byte array read differs to that written"); 675 } 676 677 // verify that MessageEOFException is thrown 678 try { 679 count = message.readBytes(buffers[0]); 680 fail("Expected readBytes to throw MessageEOFException, but " 681 + " returned count=" + count); 682 } catch (MessageEOFException expected) { 683 // the expected behaviour 684 } catch (Exception exception) { 685 fail("Expected MessageFormatException to be thrown, but got " 686 + "exception=" + exception.getClass().getName() 687 + ", message=" + exception.getMessage()); 688 } 689 } 690 691 /*** 692 * Verifies that invoking any read method when a partial byte array has 693 * been read throws <code>MessageFormatException</code>. 694 * 695 * @jmscts.requirement message.stream.method.readBytes 696 * @throws Exception for any error 697 */ 698 public void testPartialReadBytes() throws Exception { 699 final int dataSize = 256; 700 TestContext context = getContext(); 701 StreamMessage message = (StreamMessage) context.getMessage(); 702 703 byte[] bytes = populateByteArray(dataSize, 0); 704 message.writeBytes(bytes); 705 message.reset(); 706 byte[] buffer = new byte[bytes.length]; 707 // read the entire byte array, but don't invoke a second time to 708 // complete the read 709 int size = message.readBytes(buffer); 710 if (size != buffer.length) { 711 fail("Expected readBytes() to return count=" + buffer.length 712 + ", but returned count=" + size); 713 } 714 if (!Arrays.equals(bytes, buffer)) { 715 fail("Byte array read differs to that written"); 716 } 717 718 Class[] types = {Boolean.class, Byte.class, Short.class, 719 Character.class, Integer.class, Long.class, 720 Float.class, Double.class, String.class, 721 Object.class}; 722 for (int i = 0; i < types.length; ++i) { 723 try { 724 read(message, types[i]); 725 fail("Expected MessageFormatException to be thrown when " 726 + "reading type=" + ClassHelper.getPrimitiveName(types[i]) 727 + " after an incomplete read of a byte array"); 728 } catch (MessageFormatException expected) { 729 // the expected behaviour 730 } catch (Exception exception) { 731 fail("Expected MessageFormatException to be thrown when " 732 + "reading type=" + ClassHelper.getPrimitiveName(types[i]) 733 + " after an incomplete read of a byte array, but got " 734 + "exception=" + exception.getClass().getName() 735 + ", message=" + exception.getMessage()); 736 } 737 } 738 assertEquals(-1, message.readBytes(buffer)); 739 } 740 741 /*** 742 * Write an object using the appropriate write<Object>() method 743 * 744 * @param message the message to write to 745 * @param value the value to write 746 * @throws Exception for any error 747 */ 748 private void write(StreamMessage message, Object value) throws Exception { 749 if (value instanceof Boolean) { 750 message.writeBoolean(((Boolean) value).booleanValue()); 751 } else if (value instanceof Byte) { 752 message.writeByte(((Byte) value).byteValue()); 753 } else if (value instanceof Short) { 754 message.writeShort(((Short) value).shortValue()); 755 } else if (value instanceof Character) { 756 message.writeChar(((Character) value).charValue()); 757 } else if (value instanceof Integer) { 758 message.writeInt(((Integer) value).intValue()); 759 } else if (value instanceof Long) { 760 message.writeLong(((Long) value).longValue()); 761 } else if (value instanceof Float) { 762 message.writeFloat(((Float) value).floatValue()); 763 } else if (value instanceof Double) { 764 message.writeDouble(((Double) value).doubleValue()); 765 } else if (value instanceof String) { 766 message.writeString((String) value); 767 } else if (value instanceof byte[]) { 768 message.writeBytes((byte[]) value); 769 } else { 770 // let the message deal with the exception 771 message.writeObject(value); 772 } 773 } 774 775 /*** 776 * Read an object of the specified type 777 * 778 * @param message the message to read from 779 * @param type the type of the object to read 780 * @return the read object 781 * @throws Exception for any error 782 */ 783 private Object read(StreamMessage message, Class type) throws Exception { 784 final int dataSize = 256; 785 Object result = null; 786 if (type.equals(Boolean.class)) { 787 result = new Boolean(message.readBoolean()); 788 } else if (type.equals(Byte.class)) { 789 result = new Byte(message.readByte()); 790 } else if (type.equals(Short.class)) { 791 result = new Short(message.readShort()); 792 } else if (type.equals(Character.class)) { 793 result = new Character(message.readChar()); 794 } else if (type.equals(Integer.class)) { 795 result = new Integer(message.readInt()); 796 } else if (type.equals(Long.class)) { 797 result = new Long(message.readLong()); 798 } else if (type.equals(Float.class)) { 799 result = new Float(message.readFloat()); 800 } else if (type.equals(Double.class)) { 801 result = new Double(message.readDouble()); 802 } else if (type.equals(String.class)) { 803 result = message.readString(); 804 } else if (type.equals(byte[].class)) { 805 byte[] bytes = null; 806 byte[] buffer = new byte[dataSize]; 807 int length = buffer.length; 808 while (length == buffer.length) { 809 length = message.readBytes(buffer); 810 // not particularly efficient, but for our purposes it doesn't 811 // matter 812 813 if (length != -1) { 814 int size = (bytes != null) ? bytes.length : 0; 815 size += length; 816 if (bytes == null) { 817 bytes = new byte[size]; 818 System.arraycopy(buffer, 0, bytes, 0, size); 819 } else { 820 byte[] tmp = new byte[size]; 821 System.arraycopy(bytes, 0, tmp, 0, bytes.length); 822 System.arraycopy(buffer, 0, tmp, bytes.length, length); 823 System.arraycopy(tmp, 0, bytes, 0, size); 824 bytes = tmp; 825 } 826 } 827 } 828 result = bytes; 829 } else if (type.equals(Object.class)) { 830 result = message.readObject(); 831 } 832 return result; 833 } 834 835 /*** 836 * Attempt to read a <code>null</code> as a particular type 837 * 838 * @param message the message to read from 839 * @param type the type to read 840 * @param exceptionType the expected exception type, or <code>null</code> 841 * if no exception is epxected 842 * @return the read object 843 * @throws Exception for any error 844 */ 845 private Object readNull(StreamMessage message, Class type, 846 Class exceptionType) throws Exception { 847 Object result = null; 848 try { 849 result = read(message, type); 850 if (exceptionType != null) { 851 fail("Expected exception, type=" + exceptionType.getName() 852 + " to be thrown when reading null as type=" 853 + ClassHelper.getPrimitiveName(type)); 854 } 855 } catch (Exception exception) { 856 if (exceptionType == null) { 857 fail("Did not expect exception to be thrown when reading " 858 + "null as type=" + ClassHelper.getPrimitiveName(type) 859 + " but got exception=" + exception.getClass().getName() 860 + ", message=" + exception.getMessage()); 861 } else if (!exceptionType.isAssignableFrom(exception.getClass())) { 862 fail("Expected exception, type=" + exceptionType.getName() 863 + " to be thrown when reading null as type=" 864 + ClassHelper.getPrimitiveName(type) + ", but got " 865 + "exception=" + exception.getClass().getName() 866 + ", message=" + exception.getMessage()); 867 } 868 } 869 return result; 870 } 871 872 /*** 873 * Helper to return a byte array of the specified length, populated with 874 * an incrementing sequence of values 875 * 876 * @param length the length of the array 877 * @param start the number to start the sequence at 878 * @return a new byte array 879 */ 880 private byte[] populateByteArray(int length, int start) { 881 byte[] result = new byte[length]; 882 byte j = (byte) start; 883 for (int i = 0; i < length; ++i, ++j) { 884 result[i] = j; 885 } 886 return result; 887 } 888 889 }

This page was automatically generated by Maven