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