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