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