/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.test.protoinputstream; import android.util.proto.ProtoInputStream; import android.util.proto.ProtoStream; import android.util.proto.WireTypeMismatchException; import com.android.test.protoinputstream.nano.Test; import com.google.protobuf.nano.MessageNano; import junit.framework.TestCase; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; public class ProtoInputStreamFloatTest extends TestCase { public void testRead() throws IOException { testRead(0); testRead(1); testRead(5); } private void testRead(int chunkSize) throws IOException { final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); final long fieldId9 = fieldFlags | ((long) 9 & 0x0ffffffffL); final long fieldId10 = fieldFlags | ((long) 10 & 0x0ffffffffL); final byte[] protobuf = new byte[]{ // 1 -> 0 - default value, not written // 2 -> 1 (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 10 -> 1 (byte) 0x55, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 3 -> -1234.432 (byte) 0x1d, (byte) 0xd3, (byte) 0x4d, (byte) 0x9a, (byte) 0xc4, // 4 -> 42.42 (byte) 0x25, (byte) 0x14, (byte) 0xae, (byte) 0x29, (byte) 0x42, // 5 -> Float.MIN_NORMAL (byte) 0x2d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x00, // 6 -> DOUBLE.MIN_VALUE (byte) 0x35, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 7 -> Float.NEGATIVE_INFINITY (byte) 0x3d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0xff, // 8 -> Float.NaN (byte) 0x45, (byte) 0x00, (byte) 0x00, (byte) 0xc0, (byte) 0x7f, // 9 -> Float.POSITIVE_INFINITY (byte) 0x4d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x7f, }; InputStream stream = new ByteArrayInputStream(protobuf); final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); float[] results = new float[9]; while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId1: fail("Should never reach this"); break; case (int) fieldId2: results[1] = pi.readFloat(fieldId2); break; case (int) fieldId3: results[2] = pi.readFloat(fieldId3); break; case (int) fieldId4: results[3] = pi.readFloat(fieldId4); break; case (int) fieldId5: results[4] = pi.readFloat(fieldId5); break; case (int) fieldId6: results[5] = pi.readFloat(fieldId6); break; case (int) fieldId7: results[6] = pi.readFloat(fieldId7); break; case (int) fieldId8: results[7] = pi.readFloat(fieldId8); break; case (int) fieldId9: results[8] = pi.readFloat(fieldId9); break; case (int) fieldId10: // Intentionally don't read the data. Parse should continue normally break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } stream.close(); assertEquals(0.0f, results[0]); assertEquals(1.0f, results[1]); assertEquals(-1234.432f, results[2]); assertEquals(42.42f, results[3]); assertEquals(Float.MIN_NORMAL, results[4]); assertEquals(Float.MIN_VALUE, results[5]); assertEquals(Float.NEGATIVE_INFINITY, results[6]); assertEquals(Float.NaN, results[7]); assertEquals(Float.POSITIVE_INFINITY, results[8]); } /** * Test that reading with ProtoInputStream matches, and can read the output of standard proto. */ public void testReadCompat() throws Exception { testReadCompat(0); testReadCompat(1); testReadCompat(-1234.432f); testReadCompat(42.42f); testReadCompat(Float.MIN_NORMAL); testReadCompat(Float.MIN_VALUE); testReadCompat(Float.NEGATIVE_INFINITY); testReadCompat(Float.NaN); testReadCompat(Float.POSITIVE_INFINITY); } /** * Implementation of testReadCompat with a given value. */ private void testReadCompat(float val) throws Exception { final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId = fieldFlags | ((long) 20 & 0x0ffffffffL); final Test.All all = new Test.All(); all.floatField = val; final byte[] proto = MessageNano.toByteArray(all); final ProtoInputStream pi = new ProtoInputStream(proto); final Test.All readback = Test.All.parseFrom(proto); float result = 0.0f; // start off with default value while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId: result = pi.readFloat(fieldId); break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } assertEquals(readback.floatField, result); } public void testRepeated() throws IOException { testRepeated(0); testRepeated(1); testRepeated(5); } private void testRepeated(int chunkSize) throws IOException { final long fieldFlags = ProtoStream.FIELD_COUNT_REPEATED | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); final long fieldId9 = fieldFlags | ((long) 9 & 0x0ffffffffL); final long fieldId10 = fieldFlags | ((long) 10 & 0x0ffffffffL); final byte[] protobuf = new byte[]{ // 1 -> 0 - default value, written when repeated (byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 2 -> 1 (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 3 -> -1234.432 (byte) 0x1d, (byte) 0xd3, (byte) 0x4d, (byte) 0x9a, (byte) 0xc4, // 4 -> 42.42 (byte) 0x25, (byte) 0x14, (byte) 0xae, (byte) 0x29, (byte) 0x42, // 5 -> Float.MIN_NORMAL (byte) 0x2d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x00, // 6 -> DOUBLE.MIN_VALUE (byte) 0x35, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 7 -> Float.NEGATIVE_INFINITY (byte) 0x3d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0xff, // 8 -> Float.NaN (byte) 0x45, (byte) 0x00, (byte) 0x00, (byte) 0xc0, (byte) 0x7f, // 9 -> Float.POSITIVE_INFINITY (byte) 0x4d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x7f, // 10 -> 1 (byte) 0x55, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 1 -> 0 - default value, written when repeated (byte) 0x0d, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 2 -> 1 (byte) 0x15, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 3 -> -1234.432 (byte) 0x1d, (byte) 0xd3, (byte) 0x4d, (byte) 0x9a, (byte) 0xc4, // 4 -> 42.42 (byte) 0x25, (byte) 0x14, (byte) 0xae, (byte) 0x29, (byte) 0x42, // 5 -> Float.MIN_NORMAL (byte) 0x2d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x00, // 6 -> DOUBLE.MIN_VALUE (byte) 0x35, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 7 -> Float.NEGATIVE_INFINITY (byte) 0x3d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0xff, // 8 -> Float.NaN (byte) 0x45, (byte) 0x00, (byte) 0x00, (byte) 0xc0, (byte) 0x7f, // 9 -> Float.POSITIVE_INFINITY (byte) 0x4d, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x7f, }; InputStream stream = new ByteArrayInputStream(protobuf); final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); float[][] results = new float[9][2]; int[] indices = new int[9]; while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId1: results[0][indices[0]++] = pi.readFloat(fieldId1); break; case (int) fieldId2: results[1][indices[1]++] = pi.readFloat(fieldId2); break; case (int) fieldId3: results[2][indices[2]++] = pi.readFloat(fieldId3); break; case (int) fieldId4: results[3][indices[3]++] = pi.readFloat(fieldId4); break; case (int) fieldId5: results[4][indices[4]++] = pi.readFloat(fieldId5); break; case (int) fieldId6: results[5][indices[5]++] = pi.readFloat(fieldId6); break; case (int) fieldId7: results[6][indices[6]++] = pi.readFloat(fieldId7); break; case (int) fieldId8: results[7][indices[7]++] = pi.readFloat(fieldId8); break; case (int) fieldId9: results[8][indices[8]++] = pi.readFloat(fieldId9); break; case (int) fieldId10: // Intentionally don't read the data. Parse should continue normally break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } stream.close(); assertEquals(0.0f, results[0][0]); assertEquals(0.0f, results[0][1]); assertEquals(1.0f, results[1][0]); assertEquals(1.0f, results[1][1]); assertEquals(-1234.432f, results[2][0]); assertEquals(-1234.432f, results[2][1]); assertEquals(42.42f, results[3][0]); assertEquals(42.42f, results[3][1]); assertEquals(Float.MIN_NORMAL, results[4][0]); assertEquals(Float.MIN_NORMAL, results[4][1]); assertEquals(Float.MIN_VALUE, results[5][0]); assertEquals(Float.MIN_VALUE, results[5][1]); assertEquals(Float.NEGATIVE_INFINITY, results[6][0]); assertEquals(Float.NEGATIVE_INFINITY, results[6][1]); assertEquals(Float.NaN, results[7][0]); assertEquals(Float.NaN, results[7][1]); assertEquals(Float.POSITIVE_INFINITY, results[8][0]); assertEquals(Float.POSITIVE_INFINITY, results[8][1]); } /** * Test that reading with ProtoInputStream matches, and can read the output of standard proto. */ public void testRepeatedCompat() throws Exception { testRepeatedCompat(new float[0]); testRepeatedCompat(new float[]{0, 1, -1234.432f, 42.42f, Float.MIN_NORMAL, Float.MIN_VALUE, Float.NEGATIVE_INFINITY, Float.NaN, Float.POSITIVE_INFINITY, }); } /** * Implementation of testRepeatedCompat with a given value. */ private void testRepeatedCompat(float[] val) throws Exception { final long fieldFlags = ProtoStream.FIELD_COUNT_REPEATED | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId = fieldFlags | ((long) 21 & 0x0ffffffffL); final Test.All all = new Test.All(); all.floatFieldRepeated = val; final byte[] proto = MessageNano.toByteArray(all); final ProtoInputStream pi = new ProtoInputStream(proto); final Test.All readback = Test.All.parseFrom(proto); float[] result = new float[val.length]; int index = 0; while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId: result[index++] = pi.readFloat(fieldId); break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } assertEquals(readback.floatFieldRepeated.length, result.length); for (int i = 0; i < result.length; i++) { assertEquals(readback.floatFieldRepeated[i], result[i]); } } public void testPacked() throws IOException { testPacked(0); testPacked(1); testPacked(5); } private void testPacked(int chunkSize) throws IOException { final long fieldFlags = ProtoStream.FIELD_COUNT_PACKED | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); final long fieldId4 = fieldFlags | ((long) 4 & 0x0ffffffffL); final long fieldId5 = fieldFlags | ((long) 5 & 0x0ffffffffL); final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); final long fieldId7 = fieldFlags | ((long) 7 & 0x0ffffffffL); final long fieldId8 = fieldFlags | ((long) 8 & 0x0ffffffffL); final long fieldId9 = fieldFlags | ((long) 9 & 0x0ffffffffL); final long fieldId10 = fieldFlags | ((long) 10 & 0x0ffffffffL); final byte[] protobuf = new byte[]{ // 1 -> 0 - default value, written when repeated (byte) 0x0a, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 2 -> 1 (byte) 0x12, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 10 -> 1 (byte) 0x52, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x3f, // 3 -> -1234.432 (byte) 0x1a, (byte) 0x08, (byte) 0xd3, (byte) 0x4d, (byte) 0x9a, (byte) 0xc4, (byte) 0xd3, (byte) 0x4d, (byte) 0x9a, (byte) 0xc4, // 4 -> 42.42 (byte) 0x22, (byte) 0x08, (byte) 0x14, (byte) 0xae, (byte) 0x29, (byte) 0x42, (byte) 0x14, (byte) 0xae, (byte) 0x29, (byte) 0x42, // 5 -> Float.MIN_NORMAL (byte) 0x2a, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x00, // 6 -> DOUBLE.MIN_VALUE (byte) 0x32, (byte) 0x08, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 7 -> Float.NEGATIVE_INFINITY (byte) 0x3a, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0xff, // 8 -> Float.NaN (byte) 0x42, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0xc0, (byte) 0x7f, (byte) 0x00, (byte) 0x00, (byte) 0xc0, (byte) 0x7f, // 9 -> Float.POSITIVE_INFINITY (byte) 0x4a, (byte) 0x08, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x7f, (byte) 0x00, (byte) 0x00, (byte) 0x80, (byte) 0x7f, }; InputStream stream = new ByteArrayInputStream(protobuf); final ProtoInputStream pi = new ProtoInputStream(stream, chunkSize); float[][] results = new float[9][2]; int[] indices = new int[9]; while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId1: results[0][indices[0]++] = pi.readFloat(fieldId1); break; case (int) fieldId2: results[1][indices[1]++] = pi.readFloat(fieldId2); break; case (int) fieldId3: results[2][indices[2]++] = pi.readFloat(fieldId3); break; case (int) fieldId4: results[3][indices[3]++] = pi.readFloat(fieldId4); break; case (int) fieldId5: results[4][indices[4]++] = pi.readFloat(fieldId5); break; case (int) fieldId6: results[5][indices[5]++] = pi.readFloat(fieldId6); break; case (int) fieldId7: results[6][indices[6]++] = pi.readFloat(fieldId7); break; case (int) fieldId8: results[7][indices[7]++] = pi.readFloat(fieldId8); break; case (int) fieldId9: results[8][indices[8]++] = pi.readFloat(fieldId9); break; case (int) fieldId10: // Intentionally don't read the data. Parse should continue normally break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } stream.close(); assertEquals(0.0f, results[0][0]); assertEquals(0.0f, results[0][1]); assertEquals(1.0f, results[1][0]); assertEquals(1.0f, results[1][1]); assertEquals(-1234.432f, results[2][0]); assertEquals(-1234.432f, results[2][1]); assertEquals(42.42f, results[3][0]); assertEquals(42.42f, results[3][1]); assertEquals(Float.MIN_NORMAL, results[4][0]); assertEquals(Float.MIN_NORMAL, results[4][1]); assertEquals(Float.MIN_VALUE, results[5][0]); assertEquals(Float.MIN_VALUE, results[5][1]); assertEquals(Float.NEGATIVE_INFINITY, results[6][0]); assertEquals(Float.NEGATIVE_INFINITY, results[6][1]); assertEquals(Float.NaN, results[7][0]); assertEquals(Float.NaN, results[7][1]); assertEquals(Float.POSITIVE_INFINITY, results[8][0]); assertEquals(Float.POSITIVE_INFINITY, results[8][1]); } /** * Test that reading with ProtoInputStream matches, and can read the output of standard proto. */ public void testPackedCompat() throws Exception { testPackedCompat(new float[0]); testPackedCompat(new float[]{0, 1, -1234.432f, 42.42f, Float.MIN_NORMAL, Float.MIN_VALUE, Float.NEGATIVE_INFINITY, Float.NaN, Float.POSITIVE_INFINITY, }); } /** * Implementation of testPackedCompat with a given value. */ private void testPackedCompat(float[] val) throws Exception { final long fieldFlags = ProtoStream.FIELD_COUNT_PACKED | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId = fieldFlags | ((long) 22 & 0x0ffffffffL); final Test.All all = new Test.All(); all.floatFieldPacked = val; final byte[] proto = MessageNano.toByteArray(all); final ProtoInputStream pi = new ProtoInputStream(proto); final Test.All readback = Test.All.parseFrom(proto); float[] result = new float[val.length]; int index = 0; while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { switch (pi.getFieldNumber()) { case (int) fieldId: result[index++] = pi.readFloat(fieldId); break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } assertEquals(readback.floatFieldPacked.length, result.length); for (int i = 0; i < result.length; i++) { assertEquals(readback.floatFieldPacked[i], result[i]); } } /** * Test that using the wrong read method throws an exception */ public void testBadReadType() throws IOException { final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); final byte[] protobuf = new byte[]{ // 1 -> 1 (byte) 0x0d, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, }; ProtoInputStream pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readBoolean(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readDouble(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readInt(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readLong(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readBytes(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } pi = new ProtoInputStream(protobuf); pi.nextField(); try { pi.readString(fieldId1); fail("Should have thrown IllegalArgumentException"); } catch (IllegalArgumentException iae) { // good } } /** * Test that unexpected wrong wire types will throw an exception */ public void testBadWireType() throws IOException { final long fieldFlags = ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FLOAT; final long fieldId1 = fieldFlags | ((long) 1 & 0x0ffffffffL); final long fieldId2 = fieldFlags | ((long) 2 & 0x0ffffffffL); final long fieldId3 = fieldFlags | ((long) 3 & 0x0ffffffffL); final long fieldId6 = fieldFlags | ((long) 6 & 0x0ffffffffL); final byte[] protobuf = new byte[]{ // 1 : varint -> 1 (byte) 0x08, (byte) 0x01, // 2 : fixed64 -> 0x1 (byte) 0x11, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 3 : length delimited -> { 1 } (byte) 0x1a, (byte) 0x04, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, // 6 : fixed32 (byte) 0x35, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, }; InputStream stream = new ByteArrayInputStream(protobuf); final ProtoInputStream pi = new ProtoInputStream(stream); while (pi.nextField() != ProtoInputStream.NO_MORE_FIELDS) { try { switch (pi.getFieldNumber()) { case (int) fieldId1: pi.readFloat(fieldId1); fail("Should have thrown a WireTypeMismatchException"); break; case (int) fieldId2: pi.readFloat(fieldId2); fail("Should have thrown a WireTypeMismatchException"); break; case (int) fieldId3: pi.readFloat(fieldId3); // don't fail, length delimited is ok (represents packed floats) break; case (int) fieldId6: pi.readFloat(fieldId6); // don't fail, fixed32 is ok break; default: fail("Unexpected field id " + pi.getFieldNumber()); } } catch (WireTypeMismatchException wtme) { // good } } stream.close(); } }