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