1/*
2 * Copyright 2012, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32package org.jf.dexlib2.writer;
33
34import junit.framework.Assert;
35import org.jf.dexlib2.ValueType;
36import org.jf.util.ExceptionWithContext;
37import org.jf.util.NakedByteArrayOutputStream;
38import org.junit.Before;
39import org.junit.Test;
40
41import java.io.IOException;
42import java.util.Arrays;
43import java.util.Random;
44
45public class DexDataWriterTest {
46    private Random random;
47    private NakedByteArrayOutputStream output = new NakedByteArrayOutputStream();
48    private int startPosition;
49    private DexDataWriter writer;
50
51    @Before
52    public void setup() throws IOException {
53        // use a predefined seed, so we get a deterministic result
54        random = new Random();
55        output.reset();
56        startPosition = 123;
57        int bufferSize = 256;
58        writer = new DexDataWriter(output, startPosition, bufferSize);
59    }
60
61    // Note: we use int[] rather than byte[] so that we don't have to cast every value when manually constructing an
62    // array.
63    private void expectData(int... bytes) throws IOException {
64        Assert.assertEquals(startPosition+bytes.length, writer.getPosition());
65
66        writer.flush();
67        byte[] writtenData = output.getBuffer();
68
69        for (int i=0; i<bytes.length; i++) {
70            Assert.assertEquals(String.format("Values not equal at index %d", i), (byte)bytes[i], writtenData[i]);
71        }
72    }
73
74    private void expectData(byte[] bytes) throws IOException {
75        Assert.assertEquals(startPosition+bytes.length, writer.getPosition());
76
77        writer.flush();
78        byte[] writtenData = output.getBuffer();
79
80        for (int i=0; i<bytes.length; i++) {
81            Assert.assertEquals(String.format("Values not equal at index %d", i), bytes[i], writtenData[i]);
82        }
83    }
84
85    @Test
86    public void testWriteByte() throws IOException {
87        byte[] arr = new byte[257];
88        for (int i=0; i<256; i++) {
89            arr[i] = (byte)i;
90            writer.write(i);
91        }
92        arr[256] = (byte)0x80;
93        writer.write(0x180);
94
95        expectData(arr);
96    }
97
98    @Test
99    public void testWriteByteArray() throws IOException {
100        byte[] arr = new byte[345];
101        random.nextBytes(arr);
102        writer.write(arr);
103
104        expectData(arr);
105    }
106
107    @Test
108    public void testWriteByteArrayWithLengthAndOffset() throws IOException {
109        byte[] arr = new byte[345];
110        random.nextBytes(arr);
111        writer.write(arr, 10, 300);
112
113        expectData(Arrays.copyOfRange(arr, 10, 310));
114    }
115
116    @Test
117    public void testWriteLong() throws IOException {
118        writer.writeLong(0x1122334455667788L);
119        writer.writeLong(-0x1122334455667788L);
120
121        expectData(0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11,
122                   0x78, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE);
123    }
124
125    @Test
126    public void testWriteInt() throws IOException {
127        writer.writeInt(0x11223344);
128        writer.writeInt(-0x11223344);
129
130        expectData(0x44, 0x33, 0x22, 0x11,
131                   0xBC, 0xCC, 0xDD, 0xEE);
132    }
133
134    @Test
135    public void testWriteShort() throws IOException {
136        writer.writeShort(0);
137        writer.writeShort(0x1122);
138        writer.writeShort(-0x1122);
139        writer.writeShort(0x7FFF);
140        writer.writeShort(-0x8000);
141
142        expectData(0x00, 0x00,
143                   0x22, 0x11,
144                   0xDE, 0xEE,
145                   0xFF, 0x7F,
146                   0x00, 0x80);
147    }
148
149    @Test(expected=ExceptionWithContext.class)
150    public void testWriteShortOutOfBounds() throws IOException {
151        writer.writeShort(0x8000);
152    }
153
154    @Test(expected=ExceptionWithContext.class)
155    public void testWriteShortOutOfBounds2() throws IOException {
156        writer.writeShort(-0x8001);
157    }
158
159    @Test
160    public void testWriteUshort() throws IOException {
161        writer.writeUshort(0);
162        writer.writeUshort(0x1122);
163        writer.writeUshort(0x8899);
164        writer.writeUshort(0xFFFF);
165
166        expectData(0x00, 0x00,
167                   0x22, 0x11,
168                   0x99, 0x88,
169                   0xFF, 0xFF);
170    }
171
172    @Test(expected=ExceptionWithContext.class)
173    public void testWriteUshortOutOfBounds() throws IOException {
174        writer.writeUshort(-1);
175    }
176
177    @Test(expected=ExceptionWithContext.class)
178    public void testWriteUshortOutOfBounds2() throws IOException {
179        writer.writeUshort(0x10000);
180    }
181
182    @Test
183    public void testWriteUbyte() throws IOException {
184        writer.writeUbyte(0);
185        writer.writeUbyte(1);
186        writer.writeUbyte(0x12);
187        writer.writeUbyte(0xFF);
188
189        expectData(0x00, 0x01, 0x12, 0xFF);
190    }
191
192    @Test(expected=ExceptionWithContext.class)
193    public void testWriteUbyteOutOfBounds() throws IOException {
194        writer.writeUbyte(-1);
195    }
196
197    @Test(expected=ExceptionWithContext.class)
198    public void testWriteUbyteOutOfBounds2() throws IOException {
199        writer.writeUbyte(256);
200    }
201
202    @Test
203    public void testWriteEncodedValueHeader() throws IOException {
204        writer.writeEncodedValueHeader(0x2, 0x1);
205
206        expectData(0x22);
207    }
208
209    private void testWriteEncodedIntHelper(int integerValue, int... encodedValue) throws IOException {
210        setup();
211        writer.writeEncodedInt(ValueType.INT, integerValue);
212
213        int[] arr = new int[encodedValue.length+1];
214        arr[0] = ValueType.INT | ((encodedValue.length-1) << 5);
215        System.arraycopy(encodedValue, 0, arr, 1, encodedValue.length);
216        expectData(arr);
217    }
218
219    @Test
220    public void testWriteEncodedInt() throws IOException {
221        testWriteEncodedIntHelper(0x00, 0x00);
222        testWriteEncodedIntHelper(0x40, 0x40);
223        testWriteEncodedIntHelper(0x7f, 0x7f);
224        testWriteEncodedIntHelper(0xff, 0xff, 0x00);
225        testWriteEncodedIntHelper(0xffff80, 0x80, 0xff, 0xff, 0x00);
226        testWriteEncodedIntHelper(0xffffff80, 0x80);
227        testWriteEncodedIntHelper(0xffffffff, 0xff);
228        testWriteEncodedIntHelper(0x100, 0x00, 0x01);
229        testWriteEncodedIntHelper(0x7fff, 0xff, 0x7f);
230        testWriteEncodedIntHelper(0x8000, 0x00, 0x80, 0x00);
231        testWriteEncodedIntHelper(0xffff8000, 0x00, 0x80);
232        testWriteEncodedIntHelper(0x10000, 0x00, 0x00, 0x01);
233        testWriteEncodedIntHelper(0x10203, 0x03, 0x02, 0x01);
234        testWriteEncodedIntHelper(0x810203, 0x03, 0x02, 0x81, 0x00);
235        testWriteEncodedIntHelper(0xff810203, 0x03, 0x02, 0x81);
236        testWriteEncodedIntHelper(0x1000000, 0x00, 0x00, 0x00, 0x01);
237        testWriteEncodedIntHelper(0x1020304, 0x04, 0x03, 0x02, 0x01);
238        testWriteEncodedIntHelper(0x7fffffff, 0xff, 0xff, 0xff, 0x7f);
239        testWriteEncodedIntHelper(0x80000000, 0x00, 0x00, 0x00, 0x80);
240        testWriteEncodedIntHelper(0x80000001, 0x01, 0x00, 0x00, 0x80);
241    }
242
243    private void testWriteEncodedUintHelper(int integerValue, int... encodedValue) throws IOException {
244        setup();
245        writer.writeEncodedUint(ValueType.METHOD, integerValue);
246
247        int[] arr = new int[encodedValue.length+1];
248        arr[0] = ValueType.METHOD | ((encodedValue.length-1) << 5);
249        System.arraycopy(encodedValue, 0, arr, 1, encodedValue.length);
250        expectData(arr);
251    }
252
253    @Test
254    public void testWriteEncodedUint() throws IOException {
255        testWriteEncodedUintHelper(0x00, 0x00);
256        testWriteEncodedUintHelper(0x01, 0x01);
257        testWriteEncodedUintHelper(0x40, 0x40);
258        testWriteEncodedUintHelper(0x7f, 0x7f);
259        testWriteEncodedUintHelper(0x80, 0x80);
260        testWriteEncodedUintHelper(0x81, 0x81);
261        testWriteEncodedUintHelper(0xff, 0xff);
262        testWriteEncodedUintHelper(0x100, 0x00, 0x01);
263        testWriteEncodedUintHelper(0x180, 0x80, 0x01);
264        testWriteEncodedUintHelper(0x8080, 0x80, 0x80);
265        testWriteEncodedUintHelper(0x1234, 0x34, 0x12);
266        testWriteEncodedUintHelper(0x1000, 0x00, 0x10);
267        testWriteEncodedUintHelper(0x8000, 0x00, 0x80);
268        testWriteEncodedUintHelper(0xff00, 0x00, 0xff);
269        testWriteEncodedUintHelper(0xffff, 0xff, 0xff);
270        testWriteEncodedUintHelper(0x10000, 0x00, 0x00, 0x01);
271        testWriteEncodedUintHelper(0x1ffff, 0xff, 0xff, 0x01);
272        testWriteEncodedUintHelper(0x80ffff, 0xff, 0xff, 0x80);
273        testWriteEncodedUintHelper(0xffffff, 0xff, 0xff, 0xff);
274        testWriteEncodedUintHelper(0x1000000, 0x00, 0x00, 0x00, 0x01);
275        testWriteEncodedUintHelper(0x1020304, 0x04, 0x03, 0x02, 0x01);
276        testWriteEncodedUintHelper(0x80000000, 0x00, 0x00, 0x00, 0x80);
277        testWriteEncodedUintHelper(0x80ffffff, 0xff, 0xff, 0xff, 0x80);
278        testWriteEncodedUintHelper(0xffffffff, 0xff, 0xff, 0xff, 0xff);
279    }
280
281    private void testWriteEncodedLongHelper(long longValue, int... encodedValue) throws IOException {
282        setup();
283        writer.writeEncodedLong(ValueType.LONG, longValue);
284
285        int[] arr = new int[encodedValue.length+1];
286        arr[0] = ValueType.LONG | ((encodedValue.length-1) << 5);
287        System.arraycopy(encodedValue, 0, arr, 1, encodedValue.length);
288        expectData(arr);
289    }
290
291    @Test
292    public void testWriteEncodedLong() throws IOException {
293        testWriteEncodedLongHelper(0x00L, 0x00);
294        testWriteEncodedLongHelper(0x40L, 0x40);
295        testWriteEncodedLongHelper(0x7fL, 0x7f);
296        testWriteEncodedLongHelper(0xffL, 0xff, 0x00);
297        testWriteEncodedLongHelper(0xffffffffffffff80L, 0x80);
298        testWriteEncodedLongHelper(0xffffffffffffffffL, 0xff);
299
300        testWriteEncodedLongHelper(0x100L, 0x00, 0x01);
301        testWriteEncodedLongHelper(0x7fffL, 0xff, 0x7f);
302        testWriteEncodedLongHelper(0x8000L, 0x00, 0x80, 0x00);
303        testWriteEncodedLongHelper(0xffffffffffff8000L, 0x00, 0x80);
304
305        testWriteEncodedLongHelper(0x10000L, 0x00, 0x00, 0x01);
306        testWriteEncodedLongHelper(0x10203L, 0x03, 0x02, 0x01);
307        testWriteEncodedLongHelper(0x810203L, 0x03, 0x02, 0x81, 0x00);
308        testWriteEncodedLongHelper(0xffffffffff810203L, 0x03, 0x02, 0x81);
309
310        testWriteEncodedLongHelper(0x1000000L, 0x00, 0x00, 0x00, 0x01);
311        testWriteEncodedLongHelper(0x1020304L, 0x04, 0x03, 0x02, 0x01);
312        testWriteEncodedLongHelper(0x7fffffffL, 0xff, 0xff, 0xff, 0x7f);
313        testWriteEncodedLongHelper(0x80000000L, 0x00, 0x00, 0x00, 0x80, 0x00);
314        testWriteEncodedLongHelper(0xffffffff80000000L, 0x00, 0x00, 0x00, 0x80);
315        testWriteEncodedLongHelper(0xffffffff80000001L, 0x01, 0x00, 0x00, 0x80);
316
317        testWriteEncodedLongHelper(0x100000000L, 0x00, 0x00, 0x00, 0x00, 0x01);
318        testWriteEncodedLongHelper(0x102030405L, 0x05, 0x04, 0x03, 0x02, 0x01);
319        testWriteEncodedLongHelper(0x7fffffffffL, 0xff, 0xff, 0xff, 0xff, 0x7f);
320        testWriteEncodedLongHelper(0x8000000000L, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00);
321        testWriteEncodedLongHelper(0xffffff8000000000L, 0x00, 0x00, 0x00, 0x00, 0x80);
322        testWriteEncodedLongHelper(0xffffff8000000001L, 0x01, 0x00, 0x00, 0x00, 0x80);
323
324        testWriteEncodedLongHelper(0x10000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
325        testWriteEncodedLongHelper(0x10203040506L, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01);
326        testWriteEncodedLongHelper(0x7fffffffffffL, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
327        testWriteEncodedLongHelper(0x800000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00);
328        testWriteEncodedLongHelper(0xffff800000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80);
329        testWriteEncodedLongHelper(0xffff800000000001L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80);
330
331        testWriteEncodedLongHelper(0x1000000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
332        testWriteEncodedLongHelper(0x1020304050607L, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01);
333        testWriteEncodedLongHelper(0x7fffffffffffffL, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
334        testWriteEncodedLongHelper(0x80000000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00);
335        testWriteEncodedLongHelper(0xff80000000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80);
336        testWriteEncodedLongHelper(0xff80000000000001L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80);
337
338        testWriteEncodedLongHelper(0x100000000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
339        testWriteEncodedLongHelper(0x102030405060708L, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01);
340        testWriteEncodedLongHelper(0x7fffffffffffffffL, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
341        testWriteEncodedLongHelper(0x8000000000000000L, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80);
342        testWriteEncodedLongHelper(0x8000000000000001L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80);
343        testWriteEncodedLongHelper(0xfeffffffffffffffL, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe);
344
345        testWriteEncodedLongHelper(0x123456789ABCDEF0L, 0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12);
346    }
347
348    private void testWriteRightZeroExtendedIntHelper(int intValue, int... encodedValue) throws IOException {
349        setup();
350        writer.writeRightZeroExtendedInt(ValueType.FLOAT, intValue);
351
352        int[] arr = new int[encodedValue.length+1];
353        arr[0] = ValueType.FLOAT | ((encodedValue.length-1) << 5);
354        System.arraycopy(encodedValue, 0, arr, 1, encodedValue.length);
355        expectData(arr);
356    }
357
358    @Test
359    public void testWriteRightZeroExtendedInt() throws IOException {
360        testWriteRightZeroExtendedIntHelper(0, 0x00);
361
362        testWriteRightZeroExtendedIntHelper(0x01000000, 0x01);
363        testWriteRightZeroExtendedIntHelper(0x7f000000, 0x7f);
364        testWriteRightZeroExtendedIntHelper(0x80000000, 0x80);
365        testWriteRightZeroExtendedIntHelper(0xf0000000, 0xf0);
366        testWriteRightZeroExtendedIntHelper(0xff000000, 0xff);
367
368        testWriteRightZeroExtendedIntHelper(0x010000, 0x01, 0x00);
369        testWriteRightZeroExtendedIntHelper(0x01100000, 0x10, 0x01);
370        testWriteRightZeroExtendedIntHelper(0x7f100000, 0x10, 0x7f);
371        testWriteRightZeroExtendedIntHelper(0x80100000, 0x10, 0x80);
372        testWriteRightZeroExtendedIntHelper(0xf0100000, 0x10, 0xf0);
373        testWriteRightZeroExtendedIntHelper(0xff100000, 0x10, 0xff);
374        testWriteRightZeroExtendedIntHelper(0xff000000, 0xff);
375
376        testWriteRightZeroExtendedIntHelper(0x0100, 0x01, 0x00, 0x00);
377        testWriteRightZeroExtendedIntHelper(0x01101000, 0x10, 0x10, 0x01);
378        testWriteRightZeroExtendedIntHelper(0x7f101000, 0x10, 0x10, 0x7f);
379        testWriteRightZeroExtendedIntHelper(0x80101000, 0x10, 0x10, 0x80);
380        testWriteRightZeroExtendedIntHelper(0xf0101000, 0x10, 0x10, 0xf0);
381        testWriteRightZeroExtendedIntHelper(0xff101000, 0x10, 0x10, 0xff);
382
383        testWriteRightZeroExtendedIntHelper(0x01, 0x01, 0x00, 0x00, 0x00);
384        testWriteRightZeroExtendedIntHelper(0x80, 0x80, 0x00, 0x00, 0x00);
385        testWriteRightZeroExtendedIntHelper(0xff, 0xff, 0x00, 0x00, 0x00);
386        testWriteRightZeroExtendedIntHelper(0x01101010, 0x10, 0x10, 0x10, 0x01);
387        testWriteRightZeroExtendedIntHelper(0x7f101010, 0x10, 0x10, 0x10, 0x7f);
388        testWriteRightZeroExtendedIntHelper(0x80101010, 0x10, 0x10, 0x10, 0x80);
389        testWriteRightZeroExtendedIntHelper(0xf0101010, 0x10, 0x10, 0x10, 0xf0);
390        testWriteRightZeroExtendedIntHelper(0xff101010, 0x10, 0x10, 0x10, 0xff);
391    }
392
393    private void testWriteRightZeroExtendedLongHelper(long longValue, int... encodedValue) throws IOException {
394        setup();
395        writer.writeRightZeroExtendedLong(ValueType.DOUBLE, longValue);
396
397        int[] arr = new int[encodedValue.length+1];
398        arr[0] = ValueType.DOUBLE | ((encodedValue.length-1) << 5);
399        System.arraycopy(encodedValue, 0, arr, 1, encodedValue.length);
400        expectData(arr);
401    }
402
403    @Test
404    public void testWriteRightZeroExtendedLong() throws IOException {
405        testWriteRightZeroExtendedLongHelper(0, 0x00);
406
407        testWriteRightZeroExtendedLongHelper(0x0100000000000000L, 0x01);
408        testWriteRightZeroExtendedLongHelper(0x7f00000000000000L, 0x7f);
409        testWriteRightZeroExtendedLongHelper(0x8000000000000000L, 0x80);
410        testWriteRightZeroExtendedLongHelper(0xf000000000000000L, 0xf0);
411        testWriteRightZeroExtendedLongHelper(0xff00000000000000L, 0xff);
412
413        testWriteRightZeroExtendedLongHelper(0x01000000000000L, 0x01, 0x00);
414        testWriteRightZeroExtendedLongHelper(0x0110000000000000L, 0x10, 0x01);
415        testWriteRightZeroExtendedLongHelper(0x7f10000000000000L, 0x10, 0x7f);
416        testWriteRightZeroExtendedLongHelper(0x8010000000000000L, 0x10, 0x80);
417        testWriteRightZeroExtendedLongHelper(0xf010000000000000L, 0x10, 0xf0);
418        testWriteRightZeroExtendedLongHelper(0xff10000000000000L, 0x10, 0xff);
419        testWriteRightZeroExtendedLongHelper(0x7fff000000000000L, 0xff, 0x7f);
420
421        testWriteRightZeroExtendedLongHelper(0x010000000000L, 0x01, 0x00, 0x00);
422        testWriteRightZeroExtendedLongHelper(0x0110100000000000L, 0x10, 0x10, 0x01);
423        testWriteRightZeroExtendedLongHelper(0x7f10100000000000L, 0x10, 0x10, 0x7f);
424        testWriteRightZeroExtendedLongHelper(0x8010100000000000L, 0x10, 0x10, 0x80);
425        testWriteRightZeroExtendedLongHelper(0xf010100000000000L, 0x10, 0x10, 0xf0);
426        testWriteRightZeroExtendedLongHelper(0xff10100000000000L, 0x10, 0x10, 0xff);
427        testWriteRightZeroExtendedLongHelper(0x7fffff0000000000L, 0xff, 0xff, 0x7f);
428
429        testWriteRightZeroExtendedLongHelper(0x0100000000L, 0x01, 0x00, 0x00, 0x00);
430        testWriteRightZeroExtendedLongHelper(0x0110101000000000L, 0x10, 0x10, 0x10, 0x01);
431        testWriteRightZeroExtendedLongHelper(0x7f10101000000000L, 0x10, 0x10, 0x10, 0x7f);
432        testWriteRightZeroExtendedLongHelper(0x8010101000000000L, 0x10, 0x10, 0x10, 0x80);
433        testWriteRightZeroExtendedLongHelper(0xf010101000000000L, 0x10, 0x10, 0x10, 0xf0);
434        testWriteRightZeroExtendedLongHelper(0xff10101000000000L, 0x10, 0x10, 0x10, 0xff);
435        testWriteRightZeroExtendedLongHelper(0x7fffffff00000000L, 0xff, 0xff, 0xff, 0x7f);
436
437        testWriteRightZeroExtendedLongHelper(0x01000000L, 0x01, 0x00, 0x00, 0x00, 0x00);
438        testWriteRightZeroExtendedLongHelper(0x0110101010000000L, 0x10, 0x10, 0x10, 0x10, 0x01);
439        testWriteRightZeroExtendedLongHelper(0x7f10101010000000L, 0x10, 0x10, 0x10, 0x10, 0x7f);
440        testWriteRightZeroExtendedLongHelper(0x8010101010000000L, 0x10, 0x10, 0x10, 0x10, 0x80);
441        testWriteRightZeroExtendedLongHelper(0xf010101010000000L, 0x10, 0x10, 0x10, 0x10, 0xf0);
442        testWriteRightZeroExtendedLongHelper(0xff10101010000000L, 0x10, 0x10, 0x10, 0x10, 0xff);
443        testWriteRightZeroExtendedLongHelper(0x7fffffffff000000L, 0xff, 0xff, 0xff, 0xff, 0x7f);
444
445        testWriteRightZeroExtendedLongHelper(0x010000L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
446        testWriteRightZeroExtendedLongHelper(0x0110101010100000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01);
447        testWriteRightZeroExtendedLongHelper(0x7f10101010100000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f);
448        testWriteRightZeroExtendedLongHelper(0x8010101010100000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80);
449        testWriteRightZeroExtendedLongHelper(0xf010101010100000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0xf0);
450        testWriteRightZeroExtendedLongHelper(0xff10101010100000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0xff);
451        testWriteRightZeroExtendedLongHelper(0x7fffffffffff0000L, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
452
453        testWriteRightZeroExtendedLongHelper(0x0100L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
454        testWriteRightZeroExtendedLongHelper(0x0110101010101000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01);
455        testWriteRightZeroExtendedLongHelper(0x7f10101010101000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f);
456        testWriteRightZeroExtendedLongHelper(0x8010101010101000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80);
457        testWriteRightZeroExtendedLongHelper(0xf010101010101000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xf0);
458        testWriteRightZeroExtendedLongHelper(0xff10101010101000L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xff);
459        testWriteRightZeroExtendedLongHelper(0x7fffffffffffff00L, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
460
461        testWriteRightZeroExtendedLongHelper(0x01L, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
462        testWriteRightZeroExtendedLongHelper(0x0110101010101010L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01);
463        testWriteRightZeroExtendedLongHelper(0x7f10101010101010L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x7f);
464        testWriteRightZeroExtendedLongHelper(0x8010101010101010L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x80);
465        testWriteRightZeroExtendedLongHelper(0xf010101010101010L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xf0);
466        testWriteRightZeroExtendedLongHelper(0xff10101010101010L, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xff);
467        testWriteRightZeroExtendedLongHelper(Long.MAX_VALUE, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f);
468        testWriteRightZeroExtendedLongHelper(Long.MIN_VALUE, 0x80);
469        testWriteRightZeroExtendedLongHelper(-1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff);
470    }
471
472    private void testWriteStringHelper(String stringValue, int... encodedValue) throws IOException {
473        setup();
474
475        writer.writeString(stringValue);
476
477        expectData(encodedValue);
478    }
479
480    @Test
481    public void testWriteString() throws IOException {
482        testWriteStringHelper(new String(new char[]{0x00}), 0xc0, 0x80);
483        testWriteStringHelper(new String(new char[]{0x01}), 0x01);
484        testWriteStringHelper(new String(new char[]{0x40}), 0x40);
485        testWriteStringHelper(new String(new char[]{0x7f}), 0x7f);
486        testWriteStringHelper(new String(new char[]{0x80}), 0xc2, 0x80);
487        testWriteStringHelper(new String(new char[]{0x81}), 0xc2, 0x81);
488        testWriteStringHelper(new String(new char[]{0x100}), 0xc4, 0x80);
489        testWriteStringHelper(new String(new char[]{0x7ff}), 0xdf, 0xbf);
490        testWriteStringHelper(new String(new char[]{0x800}), 0xe0, 0xa0, 0x80);
491        testWriteStringHelper(new String(new char[]{0x801}), 0xe0, 0xa0, 0x81);
492        testWriteStringHelper(new String(new char[]{0x1000}), 0xe1, 0x80, 0x80);
493        testWriteStringHelper(new String(new char[]{0x7fff}), 0xe7, 0xbf, 0xbf);
494        testWriteStringHelper(new String(new char[]{0x8000}), 0xe8, 0x80, 0x80);
495        testWriteStringHelper(new String(new char[]{0x8001}), 0xe8, 0x80, 0x81);
496        testWriteStringHelper(new String(new char[]{0xffff}), 0xef, 0xbf, 0xbf);
497    }
498
499    @Test
500    public void testAlign() throws IOException {
501        // create a new writer so we can start at file position 0
502        startPosition = 0;
503        writer = new DexDataWriter(output, startPosition, 256);
504
505        writer.align();
506        writer.write(1);
507        writer.align();
508        writer.align();
509
510        writer.write(1);
511        writer.write(2);
512        writer.align();
513
514        writer.write(1);
515        writer.write(2);
516        writer.write(3);
517        writer.align();
518        writer.align();
519
520        writer.write(1);
521        writer.write(2);
522        writer.write(3);
523        writer.write(4);
524        writer.align();
525        writer.align();
526        writer.align();
527        writer.align();
528
529        writer.write(1);
530        writer.align();
531
532        expectData(0x01, 0x00, 0x00, 0x00,
533                   0x01, 0x02, 0x00, 0x00,
534                   0x01, 0x02, 0x03, 0x00,
535                   0x01, 0x02, 0x03, 0x04,
536                   0x01, 0x00, 0x00, 0x00);
537    }
538}
539