1 /* 2 * Copyright (C) 2019 The Android Open Source Project 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 17 package com.android.test.protoinputstream; 18 19 import android.util.proto.ProtoInputStream; 20 import android.util.proto.ProtoStream; 21 import android.util.proto.WireTypeMismatchException; 22 23 import com.android.test.protoinputstream.nano.Test; 24 25 import com.google.protobuf.nano.MessageNano; 26 27 import junit.framework.TestCase; 28 29 import java.io.ByteArrayInputStream; 30 import java.io.IOException; 31 import java.io.InputStream; 32 33 public class ProtoInputStreamUInt64Test extends TestCase { 34 testRead()35 public void testRead() throws IOException { 36 testRead(0); 37 testRead(1); 38 testRead(5); 39 } 40 testRead(int chunkSize)41 private void testRead(int chunkSize) throws IOException { 42 final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_UINT64; 43 44 final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); 45 final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); 46 final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); 47 final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); 48 final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); 49 final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); 50 final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); 51 final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); 52 53 final byte[] protobuf = new byte[]{ 54 // 1 -> 0 - default value, not written 55 // 2 -> 1 56 (byte) 0x10, 57 (byte) 0x01, 58 // 8 -> Integer.MAX_VALUE 59 (byte) 0x40, 60 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 61 // 3 -> -1 62 (byte) 0x18, 63 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 64 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 65 // 4 -> Integer.MIN_VALUE 66 (byte) 0x20, 67 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0xf8, 68 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 69 // 5 -> Integer.MAX_VALUE 70 (byte) 0x28, 71 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 72 // 6 -> Long.MIN_VALUE 73 (byte) 0x30, 74 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, 75 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x01, 76 // 7 -> Long.MAX_VALUE 77 (byte) 0x38, 78 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 79 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f, 80 }; 81 82 InputStream stream = new ByteArrayInputStream(protobuf); 83 final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); 84 long[] results = new long[7]; 85 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 86 switch (pi.getFieldNumber()) { 87 case (int) fieldId1: 88 fail("Should never reach this"); 89 break; 90 case (int) fieldId2: 91 results[1] = pi.readLong(fieldId2); 92 break; 93 case (int) fieldId3: 94 results[2] = pi.readLong(fieldId3); 95 break; 96 case (int) fieldId4: 97 results[3] = pi.readLong(fieldId4); 98 break; 99 case (int) fieldId5: 100 results[4] = pi.readLong(fieldId5); 101 break; 102 case (int) fieldId6: 103 results[5] = pi.readLong(fieldId6); 104 break; 105 case (int) fieldId7: 106 results[6] = pi.readLong(fieldId7); 107 break; 108 case (int) fieldId8: 109 // Intentionally don't read the data. Parse should continue normally 110 break; 111 default: 112 fail("Unexpected field id " + pi.getFieldNumber()); 113 } 114 } 115 stream.close(); 116 117 assertEquals(0, results[0]); 118 assertEquals(1, results[1]); 119 assertEquals(-1, results[2]); 120 assertEquals(Integer.MIN_VALUE, results[3]); 121 assertEquals(Integer.MAX_VALUE, results[4]); 122 assertEquals(Long.MIN_VALUE, results[5]); 123 assertEquals(Long.MAX_VALUE, results[6]); 124 } 125 126 /** 127 * Test that reading with ProtoInputStream matches, and can read the output of standard proto. 128 */ testReadCompat()129 public void testReadCompat() throws Exception { 130 testReadCompat(0); 131 testReadCompat(1); 132 testReadCompat(-1); 133 testReadCompat(Integer.MIN_VALUE); 134 testReadCompat(Integer.MAX_VALUE); 135 testReadCompat(Long.MIN_VALUE); 136 testReadCompat(Long.MAX_VALUE); 137 } 138 139 /** 140 * Implementation of testReadCompat with a given value. 141 */ testReadCompat(long val)142 private void testReadCompat(long val) throws Exception { 143 final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_UINT64; 144 final long fieldId = fieldFlags | ((long) 60 & 0x0ffffffffL); 145 146 final Test.All all = new Test.All(); 147 all.uint64Field = val; 148 149 final byte[] proto = MessageNano.toByteArray(all); 150 151 final ProtoInputStream pi = new ProtoInputStream(proto); 152 final Test.All readback = Test.All.parseFrom(proto); 153 154 long result = 0; // start off with default value 155 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 156 switch (pi.getFieldNumber()) { 157 case (int) fieldId: 158 result = pi.readLong(fieldId); 159 break; 160 default: 161 fail("Unexpected field id " + pi.getFieldNumber()); 162 } 163 } 164 165 assertEquals(readback.uint64Field, result); 166 } 167 testRepeated()168 public void testRepeated() throws IOException { 169 testRepeated(0); 170 testRepeated(1); 171 testRepeated(5); 172 } 173 testRepeated(int chunkSize)174 private void testRepeated(int chunkSize) throws IOException { 175 final long fieldFlags = ProtoStream.FIELD_COUNT_REPEATED | ProtoStream.FIELD_TYPE_UINT64; 176 177 final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); 178 final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); 179 final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); 180 final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); 181 final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); 182 final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); 183 final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); 184 final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); 185 186 final byte[] protobuf = new byte[]{ 187 // 1 -> 0 - default value, written when repeated 188 (byte) 0x08, 189 (byte) 0x00, 190 // 2 -> 1 191 (byte) 0x10, 192 (byte) 0x01, 193 // 3 -> -1 194 (byte) 0x18, 195 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 196 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 197 // 4 -> Integer.MIN_VALUE 198 (byte) 0x20, 199 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0xf8, 200 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 201 // 5 -> Integer.MAX_VALUE 202 (byte) 0x28, 203 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 204 // 6 -> Long.MIN_VALUE 205 (byte) 0x30, 206 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, 207 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x01, 208 // 7 -> Long.MAX_VALUE 209 (byte) 0x38, 210 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 211 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f, 212 213 // 8 -> Integer.MAX_VALUE 214 (byte) 0x40, 215 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 216 217 // 1 -> 0 - default value, written when repeated 218 (byte) 0x08, 219 (byte) 0x00, 220 // 2 -> 1 221 (byte) 0x10, 222 (byte) 0x01, 223 // 3 -> -1 224 (byte) 0x18, 225 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 226 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 227 // 4 -> Integer.MIN_VALUE 228 (byte) 0x20, 229 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0xf8, 230 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 231 // 5 -> Integer.MAX_VALUE 232 (byte) 0x28, 233 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 234 // 6 -> Long.MIN_VALUE 235 (byte) 0x30, 236 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, 237 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x01, 238 // 7 -> Long.MAX_VALUE 239 (byte) 0x38, 240 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 241 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f, 242 }; 243 244 InputStream stream = new ByteArrayInputStream(protobuf); 245 final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); 246 long[][] results = new long[7][2]; 247 int[] indices = new int[7]; 248 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 249 250 switch (pi.getFieldNumber()) { 251 case (int) fieldId1: 252 results[0][indices[0]++] = pi.readLong(fieldId1); 253 break; 254 case (int) fieldId2: 255 results[1][indices[1]++] = pi.readLong(fieldId2); 256 break; 257 case (int) fieldId3: 258 results[2][indices[2]++] = pi.readLong(fieldId3); 259 break; 260 case (int) fieldId4: 261 results[3][indices[3]++] = pi.readLong(fieldId4); 262 break; 263 case (int) fieldId5: 264 results[4][indices[4]++] = pi.readLong(fieldId5); 265 break; 266 case (int) fieldId6: 267 results[5][indices[5]++] = pi.readLong(fieldId6); 268 break; 269 case (int) fieldId7: 270 results[6][indices[6]++] = pi.readLong(fieldId7); 271 break; 272 case (int) fieldId8: 273 // Intentionally don't read the data. Parse should continue normally 274 break; 275 default: 276 fail("Unexpected field id " + pi.getFieldNumber()); 277 } 278 } 279 stream.close(); 280 281 assertEquals(0, results[0][0]); 282 assertEquals(0, results[0][1]); 283 assertEquals(1, results[1][0]); 284 assertEquals(1, results[1][1]); 285 assertEquals(-1, results[2][0]); 286 assertEquals(-1, results[2][1]); 287 assertEquals(Integer.MIN_VALUE, results[3][0]); 288 assertEquals(Integer.MIN_VALUE, results[3][1]); 289 assertEquals(Integer.MAX_VALUE, results[4][0]); 290 assertEquals(Integer.MAX_VALUE, results[4][1]); 291 assertEquals(Long.MIN_VALUE, results[5][0]); 292 assertEquals(Long.MIN_VALUE, results[5][1]); 293 assertEquals(Long.MAX_VALUE, results[6][0]); 294 assertEquals(Long.MAX_VALUE, results[6][1]); 295 } 296 297 /** 298 * Test that reading with ProtoInputStream matches, and can read the output of standard proto. 299 */ testRepeatedCompat()300 public void testRepeatedCompat() throws Exception { 301 testRepeatedCompat(new long[0]); 302 testRepeatedCompat(new long[]{0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE}); 303 } 304 305 /** 306 * Implementation of testRepeatedCompat with a given value. 307 */ testRepeatedCompat(long[] val)308 private void testRepeatedCompat(long[] val) throws Exception { 309 final long fieldFlags = ProtoStream.FIELD_COUNT_REPEATED | ProtoStream.FIELD_TYPE_UINT64; 310 final long fieldId = fieldFlags | ((long) 61 & 0x0ffffffffL); 311 312 final Test.All all = new Test.All(); 313 all.uint64FieldRepeated = val; 314 315 final byte[] proto = MessageNano.toByteArray(all); 316 317 final ProtoInputStream pi = new ProtoInputStream(proto); 318 final Test.All readback = Test.All.parseFrom(proto); 319 320 long[] result = new long[val.length]; 321 int index = 0; 322 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 323 switch (pi.getFieldNumber()) { 324 case (int) fieldId: 325 result[index++] = pi.readLong(fieldId); 326 break; 327 default: 328 fail("Unexpected field id " + pi.getFieldNumber()); 329 } 330 } 331 332 assertEquals(readback.uint64FieldRepeated.length, result.length); 333 for (int i = 0; i < result.length; i++) { 334 assertEquals(readback.uint64FieldRepeated[i], result[i]); 335 } 336 } 337 testPacked()338 public void testPacked() throws IOException { 339 testPacked(0); 340 testPacked(1); 341 testPacked(5); 342 } 343 testPacked(int chunkSize)344 private void testPacked(int chunkSize) throws IOException { 345 final long fieldFlags = ProtoStream.FIELD_COUNT_PACKED | ProtoStream.FIELD_TYPE_UINT64; 346 347 final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); 348 final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); 349 final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); 350 final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); 351 final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); 352 final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); 353 final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); 354 final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); 355 356 final byte[] protobuf = new byte[]{ 357 // 1 -> 0 - default value, written when repeated 358 (byte) 0x0a, 359 (byte) 0x02, 360 (byte) 0x00, 361 (byte) 0x00, 362 // 2 -> 1 363 (byte) 0x12, 364 (byte) 0x02, 365 (byte) 0x01, 366 (byte) 0x01, 367 368 // 8 -> Integer.MAX_VALUE 369 (byte) 0x42, 370 (byte) 0x0a, 371 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 372 373 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 374 375 // 3 -> -1 376 (byte) 0x1a, 377 (byte) 0x14, 378 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 379 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 380 381 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 382 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 383 384 // 4 -> Integer.MIN_VALUE 385 (byte) 0x22, 386 (byte) 0x14, 387 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0xf8, 388 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 389 390 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0xf8, 391 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x01, 392 393 // 5 -> Integer.MAX_VALUE 394 (byte) 0x2a, 395 (byte) 0x0a, 396 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 397 398 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x07, 399 400 // 6 -> Long.MIN_VALUE 401 (byte) 0x32, 402 (byte) 0x14, 403 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, 404 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x01, 405 406 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, 407 (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x01, 408 409 // 7 -> Long.MAX_VALUE 410 (byte) 0x3a, 411 (byte) 0x12, 412 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 413 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f, 414 415 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, 416 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x7f, 417 }; 418 419 InputStream stream = new ByteArrayInputStream(protobuf); 420 final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); 421 long[][] results = new long[7][2]; 422 int[] indices = new int[7]; 423 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 424 425 switch (pi.getFieldNumber()) { 426 case (int) fieldId1: 427 results[0][indices[0]++] = pi.readLong(fieldId1); 428 break; 429 case (int) fieldId2: 430 results[1][indices[1]++] = pi.readLong(fieldId2); 431 break; 432 case (int) fieldId3: 433 results[2][indices[2]++] = pi.readLong(fieldId3); 434 break; 435 case (int) fieldId4: 436 results[3][indices[3]++] = pi.readLong(fieldId4); 437 break; 438 case (int) fieldId5: 439 results[4][indices[4]++] = pi.readLong(fieldId5); 440 break; 441 case (int) fieldId6: 442 results[5][indices[5]++] = pi.readLong(fieldId6); 443 break; 444 case (int) fieldId7: 445 results[6][indices[6]++] = pi.readLong(fieldId7); 446 break; 447 case (int) fieldId8: 448 // Intentionally don't read the data. Parse should continue normally 449 break; 450 default: 451 fail("Unexpected field id " + pi.getFieldNumber()); 452 } 453 } 454 stream.close(); 455 456 assertEquals(0, results[0][0]); 457 assertEquals(0, results[0][1]); 458 assertEquals(1, results[1][0]); 459 assertEquals(1, results[1][1]); 460 assertEquals(-1, results[2][0]); 461 assertEquals(-1, results[2][1]); 462 assertEquals(Integer.MIN_VALUE, results[3][0]); 463 assertEquals(Integer.MIN_VALUE, results[3][1]); 464 assertEquals(Integer.MAX_VALUE, results[4][0]); 465 assertEquals(Integer.MAX_VALUE, results[4][1]); 466 assertEquals(Long.MIN_VALUE, results[5][0]); 467 assertEquals(Long.MIN_VALUE, results[5][1]); 468 assertEquals(Long.MAX_VALUE, results[6][0]); 469 assertEquals(Long.MAX_VALUE, results[6][1]); 470 } 471 472 /** 473 * Test that reading with ProtoInputStream matches, and can read the output of standard proto. 474 */ testPackedCompat()475 public void testPackedCompat() throws Exception { 476 testPackedCompat(new long[0]); 477 testPackedCompat(new long[]{0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE}); 478 } 479 480 /** 481 * Implementation of testRepeatedCompat with a given value. 482 */ testPackedCompat(long[] val)483 private void testPackedCompat(long[] val) throws Exception { 484 final long fieldFlags = ProtoStream.FIELD_COUNT_REPEATED | ProtoStream.FIELD_TYPE_UINT64; 485 final long fieldId = fieldFlags | ((long) 62 & 0x0ffffffffL); 486 487 final Test.All all = new Test.All(); 488 all.uint64FieldPacked = val; 489 490 final byte[] proto = MessageNano.toByteArray(all); 491 492 final ProtoInputStream pi = new ProtoInputStream(proto); 493 final Test.All readback = Test.All.parseFrom(proto); 494 495 long[] result = new long[val.length]; 496 int index = 0; 497 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 498 switch (pi.getFieldNumber()) { 499 case (int) fieldId: 500 result[index++] = pi.readLong(fieldId); 501 break; 502 default: 503 fail("Unexpected field id " + pi.getFieldNumber()); 504 } 505 } 506 507 assertEquals(readback.uint64FieldPacked.length, result.length); 508 for (int i = 0; i < result.length; i++) { 509 assertEquals(readback.uint64FieldPacked[i], result[i]); 510 } 511 } 512 513 /** 514 * Test that using the wrong read method throws an exception 515 */ testBadReadType()516 public void testBadReadType() throws IOException { 517 final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_UINT64; 518 519 final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); 520 521 final byte[] protobuf = new byte[]{ 522 // 1 -> 1 523 (byte) 0x08, 524 (byte) 0x01, 525 }; 526 527 ProtoInputStream pi = new ProtoInputStream(protobuf); 528 pi.nextField(); 529 try { 530 pi.readFloat(fieldId1); 531 fail("Should have thrown IllegalArgumentException"); 532 } catch (IllegalArgumentException iae) { 533 // good 534 } 535 536 pi = new ProtoInputStream(protobuf); 537 pi.nextField(); 538 try { 539 pi.readDouble(fieldId1); 540 fail("Should have thrown IllegalArgumentException"); 541 } catch (IllegalArgumentException iae) { 542 // good 543 } 544 545 pi = new ProtoInputStream(protobuf); 546 pi.nextField(); 547 try { 548 pi.readInt(fieldId1); 549 fail("Should have thrown IllegalArgumentException"); 550 } catch (IllegalArgumentException iae) { 551 // good 552 } 553 554 pi = new ProtoInputStream(protobuf); 555 pi.nextField(); 556 try { 557 pi.readBoolean(fieldId1); 558 fail("Should have thrown IllegalArgumentException"); 559 } catch (IllegalArgumentException iae) { 560 // good 561 } 562 563 pi = new ProtoInputStream(protobuf); 564 pi.nextField(); 565 try { 566 pi.readBytes(fieldId1); 567 fail("Should have thrown IllegalArgumentException"); 568 } catch (IllegalArgumentException iae) { 569 // good 570 } 571 572 pi = new ProtoInputStream(protobuf); 573 pi.nextField(); 574 try { 575 pi.readString(fieldId1); 576 fail("Should have thrown IllegalArgumentException"); 577 } catch (IllegalArgumentException iae) { 578 // good 579 } 580 } 581 582 /** 583 * Test that unexpected wrong wire types will throw an exception 584 */ testBadWireType()585 public void testBadWireType() throws IOException { 586 final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_UINT64; 587 588 final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); 589 final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); 590 final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); 591 final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); 592 593 final byte[] protobuf = new byte[]{ 594 // 1 : varint -> 1 595 (byte) 0x08, 596 (byte) 0x01, 597 // 2 : fixed64 -> 0x1 598 (byte) 0x11, 599 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, 600 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, 601 // 3 : length delimited -> { 1 } 602 (byte) 0x1a, 603 (byte) 0x01, 604 (byte) 0x01, 605 // 6 : fixed32 606 (byte) 0x35, 607 (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, 608 }; 609 610 InputStream stream = new ByteArrayInputStream(protobuf); 611 final ProtoInputStream pi = new ProtoInputStream(stream); 612 613 while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { 614 try { 615 switch (pi.getFieldNumber()) { 616 case (int) fieldId1: 617 pi.readLong(fieldId1); 618 // don't fail, varint is ok 619 break; 620 case (int) fieldId2: 621 pi.readLong(fieldId2); 622 fail("Should have thrown a WireTypeMismatchException"); 623 break; 624 case (int) fieldId3: 625 pi.readLong(fieldId3); 626 // don't fail, length delimited is ok (represents packed uint64) 627 break; 628 case (int) fieldId6: 629 pi.readLong(fieldId6); 630 fail("Should have thrown a WireTypeMismatchException"); 631 break; 632 default: 633 fail("Unexpected field id " + pi.getFieldNumber()); 634 } 635 } catch (WireTypeMismatchException wtme) { 636 // good 637 } 638 } 639 stream.close(); 640 } 641 } 642