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