1/*
2 * Copyright (C) 2017 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
17package android.os;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22
23import android.support.test.runner.AndroidJUnit4;
24import android.test.suitebuilder.annotation.SmallTest;
25
26import org.junit.Test;
27import org.junit.runner.RunWith;
28
29/**
30 * Unit tests for bundle that requires accessing hidden APS.  Tests that can be written only with
31 * public APIs should go in the CTS counterpart.
32 *
33 * Run with:
34 * bit FrameworksCoreTests:android.os.BundleTest
35 */
36@SmallTest
37@RunWith(AndroidJUnit4.class)
38public class BundleTest {
39    /**
40     * Create a test bundle, parcel it and return the parcel.
41     */
42    private Parcel createBundleParcel(boolean withFd) throws Exception {
43        final Bundle source = new Bundle();
44        source.putString("string", "abc");
45        source.putInt("int", 1);
46        if (withFd) {
47            ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
48            pipe[1].close();
49            source.putParcelable("fd", pipe[0]);
50        }
51        final Parcel p = Parcel.obtain();
52        // Don't use p.writeParcelabe(), which would write the creator, which we don't need.
53        source.writeToParcel(p, 0);
54        p.setDataPosition(0);
55
56        return p;
57    }
58
59    /**
60     * Verify a bundle generated by {@link #createBundleParcel(boolean)}.
61     */
62    private void checkBundle(Bundle b, boolean withFd) {
63        // First, do the checks without actually unparceling the bundle.
64        // (Note looking into the contents will unparcel a bundle, so we'll do it later.)
65        assertTrue("mParcelledData shouldn't be null here.", b.isParcelled());
66
67        // Make sure FLAG_HAS_FDS and FLAG_HAS_FDS_KNOWN are set/cleared properly.
68        if (withFd) {
69            // FLAG_HAS_FDS and FLAG_HAS_FDS_KNOWN should both be set.
70            assertEquals(Bundle.FLAG_HAS_FDS | Bundle.FLAG_HAS_FDS_KNOWN,
71                    b.mFlags & (Bundle.FLAG_HAS_FDS | Bundle.FLAG_HAS_FDS_KNOWN));
72        } else {
73            // FLAG_HAS_FDS_KNOWN should be set, bot not FLAG_HAS_FDS.
74            assertEquals(Bundle.FLAG_HAS_FDS_KNOWN,
75                    b.mFlags & (Bundle.FLAG_HAS_FDS | Bundle.FLAG_HAS_FDS_KNOWN));
76        }
77
78        // Then, check the contents.
79        assertEquals("abc", b.getString("string"));
80        assertEquals(1, b.getInt("int"));
81
82        // Make sure FLAG_HAS_FDS and FLAG_HAS_FDS_KNOWN are set/cleared properly.
83        if (withFd) {
84            assertEquals(ParcelFileDescriptor.class, b.getParcelable("fd").getClass());
85            assertEquals(3, b.keySet().size());
86        } else {
87            assertEquals(2, b.keySet().size());
88        }
89        assertFalse(b.isParcelled());
90    }
91
92    @Test
93    public void testCreateFromParcel() throws Exception {
94        boolean withFd;
95        Parcel p;
96        Bundle b;
97        int length;
98
99        withFd = false;
100
101        // new Bundle with p
102        p = createBundleParcel(withFd);
103        checkBundle(new Bundle(p), withFd);
104        p.recycle();
105
106        // new Bundle with p and length
107        p = createBundleParcel(withFd);
108        length = p.readInt();
109        checkBundle(new Bundle(p, length), withFd);
110        p.recycle();
111
112        // readFromParcel()
113        p = createBundleParcel(withFd);
114        b = new Bundle();
115        b.readFromParcel(p);
116        checkBundle(b, withFd);
117        p.recycle();
118
119        // Same test with FDs.
120        withFd = true;
121
122        // new Bundle with p
123        p = createBundleParcel(withFd);
124        checkBundle(new Bundle(p), withFd);
125        p.recycle();
126
127        // new Bundle with p and length
128        p = createBundleParcel(withFd);
129        length = p.readInt();
130        checkBundle(new Bundle(p, length), withFd);
131        p.recycle();
132
133        // readFromParcel()
134        p = createBundleParcel(withFd);
135        b = new Bundle();
136        b.readFromParcel(p);
137        checkBundle(b, withFd);
138        p.recycle();
139    }
140}
141