blob: 663620743af90c9eaaba33d3fe767d335a7abc7a [file] [log] [blame]
Eugene Susla574b7e12019-03-13 13:16:33 -07001/*
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 */
16package com.android.codegentest;
17
18import static org.hamcrest.CoreMatchers.containsString;
19import static org.hamcrest.CoreMatchers.instanceOf;
20import static org.hamcrest.CoreMatchers.not;
21import static org.hamcrest.Matchers.greaterThanOrEqualTo;
22import static org.junit.Assert.assertEquals;
23import static org.junit.Assert.assertNotNull;
24import static org.junit.Assert.assertNull;
25import static org.junit.Assert.assertSame;
26import static org.junit.Assert.assertThat;
27
28import android.net.LinkAddress;
29import android.os.Parcel;
30import android.os.Parcelable;
31
32import androidx.test.runner.AndroidJUnit4;
33
34import org.junit.Test;
35import org.junit.runner.RunWith;
36
37import java.util.Arrays;
38import java.util.Date;
39import java.util.concurrent.atomic.AtomicInteger;
40
41/**
42 * Tests {@link SampleDataClass} after it's augmented with dataclass codegen.
43 *
44 * Use {@code $ . runTest.sh} to run.
45 */
46@RunWith(AndroidJUnit4.class)
47public class SampleDataClassTest {
48
49 private SampleDataClass mSpecimen = newBuilder().build();
50
51 private static SampleDataClass.Builder newBuilder() {
Eugene Susla3156a4c2019-07-25 14:05:12 -070052 return newInvalidBuilder()
Eugene Susla574b7e12019-03-13 13:16:33 -070053 .setNum(42)
54 .setNum2(42)
55 .setNum4(42)
56 .setName4("foobar")
57 .setLinkAddresses5();
58 }
59
Eugene Susla3156a4c2019-07-25 14:05:12 -070060 private static SampleDataClass.Builder newInvalidBuilder() {
61 return new SampleDataClass.Builder(1, 2, 3, "a", 0, null)
Eugene Susla574b7e12019-03-13 13:16:33 -070062 .setName("some parcelable")
63 .setFlags(SampleDataClass.FLAG_MANUAL_REQUEST);
64 }
65
66 @Test
67 public void testParcelling_producesEqualInstance() {
68 SampleDataClass copy = parcelAndUnparcel(mSpecimen, SampleDataClass.CREATOR);
69 assertEquals(mSpecimen, copy);
70 assertEquals(mSpecimen.hashCode(), copy.hashCode());
71 }
72
73 @Test
74 public void testParcelling_producesInstanceWithEqualFields() {
75 SampleDataClass copy = parcelAndUnparcel(mSpecimen, SampleDataClass.CREATOR);
76 copy.forEachField((self, copyFieldName, copyFieldValue) -> {
77 mSpecimen.forEachField((self2, specimenFieldName, specimenFieldValue) -> {
78 if (copyFieldName.equals(specimenFieldName)
79 && !copyFieldName.equals("pattern")
80 && (specimenFieldValue == null
81 || !specimenFieldValue.getClass().isArray())) {
82 assertEquals("Mismatched field values for " + copyFieldName,
83 specimenFieldValue, copyFieldValue);
84 }
85 });
86 });
87 }
88
89 @Test
90 public void testCustomParcelling_instanceIsCached() {
91 parcelAndUnparcel(mSpecimen, SampleDataClass.CREATOR);
92 parcelAndUnparcel(mSpecimen, SampleDataClass.CREATOR);
Eugene Susla3156a4c2019-07-25 14:05:12 -070093 assertEquals(1, MyDateParcelling.sInstanceCount.get());
Eugene Susla574b7e12019-03-13 13:16:33 -070094 }
95
96 @Test
97 public void testDefaultFieldValue_isPropagated() {
98 assertEquals(new Date(42 * 42), mSpecimen.getDate());
99 }
100
101 @Test
102 public void testForEachField_avoidsBoxing() {
103 AtomicInteger intFieldCount = new AtomicInteger(0);
104 mSpecimen.forEachField(
105 (self, name, intValue) -> intFieldCount.getAndIncrement(),
106 (self, name, objectValue) -> {
107 if (objectValue != null) {
108 assertThat("Boxed field " + name,
109 objectValue, not(instanceOf(Integer.class)));
110 }
111 });
112 assertThat(intFieldCount.get(), greaterThanOrEqualTo(1));
113 }
114
115 @Test
116 public void testToString_containsEachField() {
117 String toString = mSpecimen.toString();
118
119 mSpecimen.forEachField((self, name, value) -> {
120 assertThat(toString, containsString(name));
121 if (value instanceof Integer) {
122 // Could be flags, their special toString tested separately
123 } else if (value instanceof Object[]) {
124 assertThat(toString, containsString(Arrays.toString((Object[]) value)));
125 } else if (value != null && value.getClass().isArray()) {
126 // Primitive array, uses multiple specialized Arrays.toString overloads
127 } else {
128 assertThat(toString, containsString("" + value));
129 }
130 });
131 }
132
133 @Test
134 public void testBuilder_propagatesValuesToInstance() {
135 assertEquals(43, newBuilder().setNum(43).build().getNum());
136 }
137
138 @Test
139 public void testPluralFields_canHaveCustomSingularBuilderName() {
140 newBuilder().addLinkAddress(new LinkAddress("127.0.0.1/24"));
141 }
142
143 @Test(expected = IllegalStateException.class)
144 public void testBuilder_usableOnlyOnce() {
145 SampleDataClass.Builder builder = newBuilder();
146 builder.build();
147 builder.build();
148 }
149
150 @Test(expected = IllegalStateException.class)
Eugene Susla3156a4c2019-07-25 14:05:12 -0700151 public void testBuilder_performsValidation() {
152 newInvalidBuilder().build();
Eugene Susla574b7e12019-03-13 13:16:33 -0700153 }
154
155 @Test
156 public void testIntDefs_haveCorrectToString() {
157 int flagsAsInt = SampleDataClass.FLAG_MANUAL_REQUEST
158 | SampleDataClass.FLAG_COMPATIBILITY_MODE_REQUEST;
159 String flagsAsString = SampleDataClass.requestFlagsToString(flagsAsInt);
160
161 assertThat(flagsAsString, containsString("MANUAL_REQUEST"));
162 assertThat(flagsAsString, containsString("COMPATIBILITY_MODE_REQUEST"));
163 assertThat(flagsAsString, not(containsString("1")));
164 assertThat(flagsAsString, not(containsString("" + flagsAsInt)));
165
166 String dataclassToString = newBuilder()
167 .setFlags(flagsAsInt)
168 .setState(SampleDataClass.STATE_UNDEFINED)
169 .build()
170 .toString();
171 assertThat(dataclassToString, containsString(flagsAsString));
172 assertThat(dataclassToString, containsString("UNDEFINED"));
173 }
174
175 @Test(expected = IllegalArgumentException.class)
176 public void testFlags_getValidated() {
177 newBuilder().setFlags(12345).build();
178 }
179
180 @Test(expected = IllegalArgumentException.class)
181 public void testIntEnums_getValidated() {
182 newBuilder().setState(12345).build();
183 }
184
185 @Test(expected = IllegalArgumentException.class)
186 public void testStringEnums_getValidated() {
187 newBuilder().setStateName("foo").build();
188 }
189
190 @Test(expected = IllegalStateException.class)
191 public void testCustomValidation_isTriggered() {
192 newBuilder().setNum2(-1).setNum4(1).build();
193 }
194
195 @Test
196 public void testLazyInit_isLazilyCalledOnce() {
197 assertNull(mSpecimen.mTmpStorage);
198
199 int[] tmpStorage = mSpecimen.getTmpStorage();
200 assertNotNull(tmpStorage);
201 assertSame(tmpStorage, mSpecimen.mTmpStorage);
202
203 int[] tmpStorageAgain = mSpecimen.getTmpStorage();
204 assertSame(tmpStorage, tmpStorageAgain);
205 }
206
Eugene Susla3156a4c2019-07-25 14:05:12 -0700207 @Test(expected = IllegalStateException.class)
208 public void testCustomAnnotationValidation_isRun() {
209 newBuilder().setDayOfWeek(42).build();
210 }
211
Eugene Susla574b7e12019-03-13 13:16:33 -0700212 private static <T extends Parcelable> T parcelAndUnparcel(
213 T original, Parcelable.Creator<T> creator) {
214 Parcel p = Parcel.obtain();
215 try {
216 original.writeToParcel(p, 0);
217 p.setDataPosition(0);
218 return creator.createFromParcel(p);
219 } finally {
220 p.recycle();
221 }
222 }
223}