Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 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 android.util.proto.cts;
     18 
     19 import android.util.proto.ProtoOutputStream;
     20 import android.util.proto.cts.nano.Test;
     21 
     22 import com.google.protobuf.nano.MessageNano;
     23 import junit.framework.TestCase;
     24 import org.junit.Assert;
     25 
     26 /**
     27  * Test the enum methods on the ProtoOutputStream class.
     28  *
     29  * Nano proto CodedOutputByteBufferNano has writeEnum that writes a raw varint,
     30  * but the generated code uses writeInt32.  So we will follow that implementation.
     31  */
     32 public class ProtoOutputStreamEnumTest extends TestCase {
     33 
     34     // ----------------------------------------------------------------------
     35     //  writeEnum
     36     // ----------------------------------------------------------------------
     37 
     38     /**
     39      * Test writeEnum.
     40      */
     41     public void testWrite() throws Exception {
     42         testWrite(0);
     43         testWrite(1);
     44         testWrite(5);
     45     }
     46 
     47     /**
     48      * Implementation of testWrite with a given chunkSize.
     49      */
     50     public void testWrite(int chunkSize) throws Exception {
     51         final ProtoOutputStream po = new ProtoOutputStream(chunkSize);
     52         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_ENUM;
     53 
     54         po.writeEnum(ProtoOutputStream.makeFieldId(1, fieldFlags), 0);
     55         po.writeEnum(ProtoOutputStream.makeFieldId(2, fieldFlags), 1);
     56         po.writeEnum(ProtoOutputStream.makeFieldId(3, fieldFlags), -1);
     57         po.writeEnum(ProtoOutputStream.makeFieldId(4, fieldFlags), Integer.MIN_VALUE);
     58         po.writeEnum(ProtoOutputStream.makeFieldId(5, fieldFlags), Integer.MAX_VALUE);
     59 
     60         final byte[] result = po.getBytes();
     61         Assert.assertArrayEquals(new byte[] {
     62                 // 1 -> 0 - default value, not written
     63                 // 2 -> 1
     64                 (byte)0x10,
     65                 (byte)0x01,
     66                 // 3 -> -1
     67                 (byte)0x18,
     68                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
     69                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
     70                 // 4 -> MIN_VALUE
     71                 (byte)0x20,
     72                 (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf8,
     73                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
     74                 // 5 -> MAX_VALUE
     75                 (byte)0x28,
     76                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
     77             }, result);
     78     }
     79 
     80     /**
     81      * Test that writing a with ProtoOutputStream matches, and can be read by standard proto.
     82      */
     83     public void testWriteCompat() throws Exception {
     84         testWriteCompat(0);
     85         testWriteCompat(1);
     86         testWriteCompat(-1);
     87         testWriteCompat(Integer.MIN_VALUE);
     88         testWriteCompat(Integer.MAX_VALUE);
     89     }
     90 
     91     /**
     92      * Implementation of testWriteCompat with a given value.
     93      */
     94     public void testWriteCompat(int val) throws Exception {
     95         final int fieldId = 160;
     96         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_ENUM;
     97 
     98         final Test.All all = new Test.All();
     99         final ProtoOutputStream po = new ProtoOutputStream(0);
    100 
    101         all.outsideField = val;
    102         po.writeEnum(ProtoOutputStream.makeFieldId(fieldId, fieldFlags), val);
    103 
    104         final byte[] result = po.getBytes();
    105         final byte[] expected = MessageNano.toByteArray(all);
    106 
    107         Assert.assertArrayEquals(expected, result);
    108 
    109         final Test.All readback = Test.All.parseFrom(result);
    110 
    111         // The generated code filters the values, so only check those.
    112         if (val == Test.OUTSIDE_0 || val == Test.OUTSIDE_1) {
    113             assertEquals(val, readback.outsideField);
    114         }
    115     }
    116 
    117     // ----------------------------------------------------------------------
    118     //  writeRepeatedEnum
    119     // ----------------------------------------------------------------------
    120 
    121     /**
    122      * Test writeEnum.
    123      */
    124     public void testRepeated() throws Exception {
    125         testRepeated(0);
    126         testRepeated(1);
    127         testRepeated(5);
    128     }
    129 
    130     /**
    131      * Implementation of testRepeated with a given chunkSize.
    132      */
    133     public void testRepeated(int chunkSize) throws Exception {
    134         final ProtoOutputStream po = new ProtoOutputStream(chunkSize);
    135         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM;
    136 
    137         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(1, fieldFlags), 0);
    138         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(2, fieldFlags), 1);
    139         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(3, fieldFlags), -1);
    140         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(4, fieldFlags), Integer.MIN_VALUE);
    141         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(5, fieldFlags), Integer.MAX_VALUE);
    142 
    143         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(1, fieldFlags), 0);
    144         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(2, fieldFlags), 1);
    145         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(3, fieldFlags), -1);
    146         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(4, fieldFlags), Integer.MIN_VALUE);
    147         po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(5, fieldFlags), Integer.MAX_VALUE);
    148 
    149         final byte[] result = po.getBytes();
    150         Assert.assertArrayEquals(new byte[] {
    151                 // 1 -> 0 - default value, written when repeated
    152                 (byte)0x08,
    153                 (byte)0x00,
    154                 // 2 -> 1
    155                 (byte)0x10,
    156                 (byte)0x01,
    157                 // 3 -> -1
    158                 (byte)0x18,
    159                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
    160                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    161                 // 4 -> MIN_VALUE
    162                 (byte)0x20,
    163                 (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf8,
    164                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    165                 // 5 -> MAX_VALUE
    166                 (byte)0x28,
    167                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
    168 
    169                 // 1 -> 0 - default value, written when repeated
    170                 (byte)0x08,
    171                 (byte)0x00,
    172                 // 2 -> 1
    173                 (byte)0x10,
    174                 (byte)0x01,
    175                 // 3 -> -1
    176                 (byte)0x18,
    177                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
    178                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    179                 // 4 -> MIN_VALUE
    180                 (byte)0x20,
    181                 (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf8,
    182                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    183                 // 5 -> MAX_VALUE
    184                 (byte)0x28,
    185                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
    186             }, result);
    187     }
    188 
    189     /**
    190      * Test that writing a with ProtoOutputStream matches, and can be read by standard proto.
    191      */
    192     public void testRepeatedCompat() throws Exception {
    193         testRepeatedCompat(new int[0]);
    194         testRepeatedCompat(new int[] { 0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE });
    195     }
    196 
    197     /**
    198      * Implementation of testRepeatedCompat with a given value.
    199      */
    200     public void testRepeatedCompat(int[] val) throws Exception {
    201         final int fieldId = 161;
    202         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM;
    203 
    204         final Test.All all = new Test.All();
    205         final ProtoOutputStream po = new ProtoOutputStream(0);
    206 
    207         all.outsideFieldRepeated = val;
    208         for (int i=0; i<val.length; i++) {
    209             po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(fieldId, fieldFlags), val[i]);
    210         }
    211 
    212         final byte[] result = po.getBytes();
    213         final byte[] expected = MessageNano.toByteArray(all);
    214 
    215         Assert.assertArrayEquals(expected, result);
    216 
    217         final Test.All readback = Test.All.parseFrom(result);
    218 
    219         // Nano proto drops values that are outside the range, so disable
    220         // this test.
    221         /*
    222         assertNotNull(readback.outsideFieldRepeated);
    223         assertEquals(val.length, readback.outsideFieldRepeated.length);
    224         for (int i=0; i<val.length; i++) {
    225             assertEquals(val[i], readback.outsideFieldRepeated[i]);
    226         }
    227         */
    228     }
    229 
    230     // ----------------------------------------------------------------------
    231     //  writePackedEnum
    232     // ----------------------------------------------------------------------
    233 
    234     /**
    235      * Test writeEnum.
    236      */
    237     public void testPacked() throws Exception {
    238         testPacked(0);
    239         testPacked(1);
    240         testPacked(5);
    241     }
    242 
    243     /**
    244      * Create an array of the val, and write it.
    245      */
    246     private void writePackedEnum(ProtoOutputStream po, int fieldId, int val) {
    247         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_ENUM;
    248         po.writePackedEnum(ProtoOutputStream.makeFieldId(fieldId, fieldFlags), new int[] { val, val });
    249     }
    250 
    251     /**
    252      * Implementation of testPacked with a given chunkSize.
    253      */
    254     public void testPacked(int chunkSize) throws Exception {
    255         final ProtoOutputStream po = new ProtoOutputStream(chunkSize);
    256         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_ENUM;
    257 
    258         po.writePackedEnum(ProtoOutputStream.makeFieldId(1000, fieldFlags), null);
    259         po.writePackedEnum(ProtoOutputStream.makeFieldId(1001, fieldFlags), new int[0]);
    260         writePackedEnum(po, 1, 0);
    261         writePackedEnum(po, 2, 1);
    262         writePackedEnum(po, 3, -1);
    263         writePackedEnum(po, 4, Integer.MIN_VALUE);
    264         writePackedEnum(po, 5, Integer.MAX_VALUE);
    265 
    266         final byte[] result = po.getBytes();
    267         Assert.assertArrayEquals(new byte[] {
    268                 // 1 -> 0 - default value, written when repeated
    269                 (byte)0x0a,
    270                 (byte)0x02,
    271                 (byte)0x00,
    272                 (byte)0x00,
    273                 // 2 -> 1
    274                 (byte)0x12,
    275                 (byte)0x02,
    276                 (byte)0x01,
    277                 (byte)0x01,
    278                 // 3 -> -1
    279                 (byte)0x1a,
    280                 (byte)0x14,
    281                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
    282                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    283 
    284                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
    285                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    286 
    287                 // 4 -> MIN_VALUE
    288                 (byte)0x22,
    289                 (byte)0x14,
    290                 (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf8,
    291                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    292 
    293                 (byte)0x80, (byte)0x80, (byte)0x80, (byte)0x80, (byte)0xf8,
    294                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x01,
    295 
    296                 // 5 -> MAX_VALUE
    297                 (byte)0x2a,
    298                 (byte)0x0a,
    299                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
    300 
    301                 (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x07,
    302             }, result);
    303     }
    304 
    305     /**
    306      * Test that writing a with ProtoOutputStream matches, and can be read by standard proto.
    307      */
    308     public void testPackedCompat() throws Exception {
    309         testPackedCompat(new int[] {});
    310         testPackedCompat(new int[] { 0, 1 });
    311 
    312         // Nano proto has a bug.  It gets the size with computeInt32SizeNoTag (correctly)
    313         // but incorrectly uses writeRawVarint32 to write the value for negative numbers.
    314         //testPackedCompat(new int[] { 0, 1, -1, Integer.MIN_VALUE, Integer.MAX_VALUE });
    315     }
    316 
    317     /**
    318      * Implementation of testPackedEnumCompat with a given value.
    319      */
    320     public void testPackedCompat(int[] val) throws Exception {
    321         final int fieldId = 162;
    322         final long fieldFlags = ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_ENUM;
    323 
    324         final Test.All all = new Test.All();
    325         final ProtoOutputStream po = new ProtoOutputStream(0);
    326 
    327         all.outsideFieldPacked = val;
    328         po.writePackedEnum(ProtoOutputStream.makeFieldId(fieldId, fieldFlags), val);
    329 
    330         final byte[] result = po.getBytes();
    331         final byte[] expected = MessageNano.toByteArray(all);
    332 
    333         Assert.assertArrayEquals(expected, result);
    334 
    335         final Test.All readback = Test.All.parseFrom(result);
    336 
    337         Assert.assertArrayEquals(val, readback.outsideFieldPacked);
    338     }
    339 
    340     /**
    341      * Test that if you pass in the wrong type of fieldId, it throws.
    342      */
    343     public void testBadFieldIds() {
    344         // Single
    345 
    346         // Good Count / Bad Type
    347         try {
    348             final ProtoOutputStream po = new ProtoOutputStream();
    349             po.writeEnum(ProtoOutputStream.makeFieldId(1,
    350                         ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_DOUBLE), 0);
    351         } catch (IllegalArgumentException ex) {
    352             // good
    353         }
    354 
    355         // Bad Count / Good Type
    356         try {
    357             final ProtoOutputStream po = new ProtoOutputStream();
    358             po.writeEnum(ProtoOutputStream.makeFieldId(1,
    359                         ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_ENUM), 0);
    360         } catch (IllegalArgumentException ex) {
    361             // good
    362         }
    363 
    364         // Repeated
    365 
    366         // Good Count / Bad Type
    367         try {
    368             final ProtoOutputStream po = new ProtoOutputStream();
    369             po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(1,
    370                         ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_DOUBLE), 0);
    371         } catch (IllegalArgumentException ex) {
    372             // good
    373         }
    374 
    375         // Bad Count / Good Type
    376         try {
    377             final ProtoOutputStream po = new ProtoOutputStream();
    378             po.writeRepeatedEnum(ProtoOutputStream.makeFieldId(1,
    379                         ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_ENUM), 0);
    380         } catch (IllegalArgumentException ex) {
    381             // good
    382         }
    383 
    384         // Packed
    385 
    386         // Good Count / Bad Type
    387         try {
    388             final ProtoOutputStream po = new ProtoOutputStream();
    389             po.writePackedEnum(ProtoOutputStream.makeFieldId(1,
    390                         ProtoOutputStream.FIELD_COUNT_PACKED | ProtoOutputStream.FIELD_TYPE_DOUBLE),
    391                     new int[0]);
    392         } catch (IllegalArgumentException ex) {
    393             // good
    394         }
    395 
    396         // Bad Count / Good Type
    397         try {
    398             final ProtoOutputStream po = new ProtoOutputStream();
    399             po.writePackedEnum(ProtoOutputStream.makeFieldId(1,
    400                         ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_ENUM),
    401                     new int[0]);
    402         } catch (IllegalArgumentException ex) {
    403             // good
    404         }
    405     }
    406 }
    407 
    408