Commit | Line | Data |
---|---|---|
fbcc2a2a | 1 | package be.nikiroo.utils.test_code; |
db31c358 | 2 | |
08f80ac5 NR |
3 | import java.io.ByteArrayInputStream; |
4 | import java.io.ByteArrayOutputStream; | |
5 | import java.io.IOException; | |
6 | import java.io.InputStream; | |
7 | import java.io.NotSerializableException; | |
f4053377 | 8 | import java.net.URL; |
08f80ac5 | 9 | import java.util.Arrays; |
f4053377 | 10 | |
db31c358 NR |
11 | import be.nikiroo.utils.serial.Exporter; |
12 | import be.nikiroo.utils.serial.Importer; | |
fbcc2a2a NR |
13 | import be.nikiroo.utils.test.TestCase; |
14 | import be.nikiroo.utils.test.TestLauncher; | |
db31c358 NR |
15 | |
16 | class SerialTest extends TestLauncher { | |
452f38c8 NR |
17 | /** |
18 | * Required for Import/Export of objects. | |
19 | */ | |
20 | public SerialTest() { | |
21 | this(null); | |
22 | } | |
23 | ||
08f80ac5 NR |
24 | private void encodeRecodeTest(TestCase test, Object data) throws Exception { |
25 | byte[] encoded = toBytes(data, true); | |
26 | Object redata = fromBytes(toBytes(data, false)); | |
27 | byte[] reencoded = toBytes(redata, true); | |
28 | ||
29 | // We suppose text mode | |
30 | if (encoded.length < 256 && reencoded.length < 256) { | |
31 | test.assertEquals("Different data after encode/decode/encode", | |
32 | new String(encoded, "UTF-8"), | |
33 | new String(reencoded, "UTF-8")); | |
34 | } else { | |
35 | test.assertEquals("Different data after encode/decode/encode", | |
36 | true, Arrays.equals(encoded, reencoded)); | |
37 | } | |
38 | } | |
39 | ||
40 | // try to remove pointer addresses | |
41 | private byte[] toBytes(Object data, boolean clearRefs) | |
42 | throws NotSerializableException, IOException { | |
43 | ByteArrayOutputStream out = new ByteArrayOutputStream(); | |
44 | new Exporter(out).append(data); | |
45 | out.flush(); | |
46 | ||
47 | if (clearRefs) { | |
48 | String tmp = new String(out.toByteArray(), "UTF-8"); | |
49 | tmp = tmp.replaceAll("@[0-9]*", "@REF"); | |
50 | return tmp.getBytes("UTF-8"); | |
51 | } | |
52 | ||
53 | return out.toByteArray(); | |
54 | } | |
55 | ||
56 | private Object fromBytes(byte[] data) throws NoSuchFieldException, | |
57 | NoSuchMethodException, ClassNotFoundException, | |
58 | NullPointerException, IOException { | |
59 | ||
60 | InputStream in = new ByteArrayInputStream(data); | |
61 | try { | |
62 | return new Importer().read(in).getValue(); | |
63 | } finally { | |
64 | in.close(); | |
65 | } | |
66 | } | |
67 | ||
db31c358 NR |
68 | public SerialTest(String[] args) { |
69 | super("Serial test", args); | |
70 | ||
71 | addTest(new TestCase("Simple class Import/Export") { | |
72 | @Override | |
73 | public void test() throws Exception { | |
74 | Data data = new Data(42); | |
08f80ac5 | 75 | encodeRecodeTest(this, data); |
72648e75 NR |
76 | } |
77 | }); | |
d2219aa0 | 78 | |
72648e75 | 79 | addTest(new TestCase() { |
edeff2ab | 80 | @SuppressWarnings("unused") |
72648e75 NR |
81 | private TestCase me = setName("Anonymous inner class"); |
82 | ||
83 | @Override | |
84 | public void test() throws Exception { | |
85 | Data data = new Data() { | |
3f277541 | 86 | @SuppressWarnings("unused") |
15c2dc9f | 87 | int value = 42; |
72648e75 | 88 | }; |
08f80ac5 | 89 | encodeRecodeTest(this, data); |
db31c358 NR |
90 | } |
91 | }); | |
edeff2ab NR |
92 | addTest(new TestCase() { |
93 | @SuppressWarnings("unused") | |
94 | private TestCase me = setName("Array of anonymous inner classes"); | |
95 | ||
96 | @Override | |
97 | public void test() throws Exception { | |
98 | Data[] data = new Data[] { new Data() { | |
3f277541 | 99 | @SuppressWarnings("unused") |
15c2dc9f | 100 | int value = 42; |
edeff2ab NR |
101 | } }; |
102 | ||
08f80ac5 NR |
103 | byte[] encoded = toBytes(data, false); |
104 | Object redata = fromBytes(encoded); | |
105 | ||
106 | // Comparing the 2 arrays won't be useful, because the @REFs | |
107 | // will be ZIP-encoded; so we parse and re-encode each object | |
edeff2ab | 108 | |
08f80ac5 NR |
109 | byte[] encoded1 = toBytes(data[0], true); |
110 | byte[] reencoded1 = toBytes(((Object[]) redata)[0], true); | |
edeff2ab | 111 | |
08f80ac5 NR |
112 | assertEquals("Different data after encode/decode/encode", true, |
113 | Arrays.equals(encoded1, reencoded1)); | |
edeff2ab NR |
114 | } |
115 | }); | |
f4053377 NR |
116 | addTest(new TestCase("URL Import/Export") { |
117 | @Override | |
118 | public void test() throws Exception { | |
119 | URL data = new URL("https://fanfan.be/"); | |
08f80ac5 | 120 | encodeRecodeTest(this, data); |
f4053377 NR |
121 | } |
122 | }); | |
f4053377 NR |
123 | addTest(new TestCase("URL-String Import/Export") { |
124 | @Override | |
125 | public void test() throws Exception { | |
126 | String data = new URL("https://fanfan.be/").toString(); | |
08f80ac5 | 127 | encodeRecodeTest(this, data); |
f4053377 NR |
128 | } |
129 | }); | |
f4053377 NR |
130 | addTest(new TestCase("URL/URL-String arrays Import/Export") { |
131 | @Override | |
132 | public void test() throws Exception { | |
133 | final String url = "https://fanfan.be/"; | |
f4053377 | 134 | Object[] data = new Object[] { new URL(url), url }; |
f4053377 | 135 | |
08f80ac5 NR |
136 | byte[] encoded = toBytes(data, false); |
137 | Object redata = fromBytes(encoded); | |
138 | ||
139 | // Comparing the 2 arrays won't be useful, because the @REFs | |
140 | // will be ZIP-encoded; so we parse and re-encode each object | |
141 | ||
142 | byte[] encoded1 = toBytes(data[0], true); | |
143 | byte[] reencoded1 = toBytes(((Object[]) redata)[0], true); | |
144 | byte[] encoded2 = toBytes(data[1], true); | |
145 | byte[] reencoded2 = toBytes(((Object[]) redata)[1], true); | |
146 | ||
147 | assertEquals("Different data 1 after encode/decode/encode", | |
148 | true, Arrays.equals(encoded1, reencoded1)); | |
149 | assertEquals("Different data 2 after encode/decode/encode", | |
150 | true, Arrays.equals(encoded2, reencoded2)); | |
f4053377 NR |
151 | } |
152 | }); | |
db31c358 NR |
153 | addTest(new TestCase("Import/Export with nested objects") { |
154 | @Override | |
155 | public void test() throws Exception { | |
156 | Data data = new DataObject(new Data(21)); | |
08f80ac5 | 157 | encodeRecodeTest(this, data); |
db31c358 NR |
158 | } |
159 | }); | |
9e075bff NR |
160 | addTest(new TestCase("Import/Export String in object") { |
161 | @Override | |
162 | public void test() throws Exception { | |
163 | Data data = new DataString("fanfan"); | |
164 | encodeRecodeTest(this, data); | |
165 | data = new DataString("http://example.com/query.html"); | |
166 | encodeRecodeTest(this, data); | |
167 | data = new DataString("Test|Ché|http://|\"\\\"Pouch\\"); | |
168 | encodeRecodeTest(this, data); | |
169 | data = new DataString("Test|Ché\\n|\nhttp://|\"\\\"Pouch\\"); | |
170 | encodeRecodeTest(this, data); | |
171 | } | |
172 | }); | |
db31c358 NR |
173 | addTest(new TestCase("Import/Export with nested objects forming a loop") { |
174 | @Override | |
175 | public void test() throws Exception { | |
176 | DataLoop data = new DataLoop("looping"); | |
177 | data.next = new DataLoop("level 2"); | |
178 | data.next.next = data; | |
08f80ac5 | 179 | encodeRecodeTest(this, data); |
db31c358 NR |
180 | } |
181 | }); | |
ce0974c4 NR |
182 | addTest(new TestCase("Array in Object Import/Export") { |
183 | @Override | |
184 | public void test() throws Exception { | |
185 | Object data = new DataArray();// new String[] { "un", "deux" }; | |
08f80ac5 | 186 | encodeRecodeTest(this, data); |
ce0974c4 NR |
187 | } |
188 | }); | |
ce0974c4 NR |
189 | addTest(new TestCase("Array Import/Export") { |
190 | @Override | |
191 | public void test() throws Exception { | |
192 | Object data = new String[] { "un", "deux" }; | |
08f80ac5 | 193 | encodeRecodeTest(this, data); |
ce0974c4 NR |
194 | } |
195 | }); | |
e570f7eb NR |
196 | addTest(new TestCase("Enum Import/Export") { |
197 | @Override | |
198 | public void test() throws Exception { | |
199 | Object data = EnumToSend.FANFAN; | |
08f80ac5 | 200 | encodeRecodeTest(this, data); |
3f277541 NR |
201 | } |
202 | }); | |
ce0974c4 NR |
203 | } |
204 | ||
205 | class DataArray { | |
206 | public String[] data = new String[] { "un", "deux" }; | |
db31c358 NR |
207 | } |
208 | ||
db31c358 NR |
209 | class Data { |
210 | private int value; | |
211 | ||
212 | private Data() { | |
213 | } | |
214 | ||
215 | public Data(int value) { | |
216 | this.value = value; | |
217 | } | |
3f277541 NR |
218 | |
219 | @Override | |
220 | public boolean equals(Object obj) { | |
221 | if (obj instanceof Data) { | |
222 | Data other = (Data) obj; | |
223 | return other.value == this.value; | |
224 | } | |
225 | ||
226 | return false; | |
227 | } | |
228 | ||
229 | @Override | |
230 | public int hashCode() { | |
b6d4ace8 | 231 | return new Integer(value).hashCode(); |
3f277541 | 232 | } |
db31c358 NR |
233 | } |
234 | ||
235 | @SuppressWarnings("unused") | |
236 | class DataObject extends Data { | |
237 | private Data data; | |
238 | ||
239 | @SuppressWarnings("synthetic-access") | |
240 | private DataObject() { | |
241 | } | |
242 | ||
243 | @SuppressWarnings("synthetic-access") | |
244 | public DataObject(Data data) { | |
245 | this.data = data; | |
246 | } | |
247 | } | |
248 | ||
9e075bff NR |
249 | @SuppressWarnings("unused") |
250 | class DataString extends Data { | |
251 | private String data; | |
252 | ||
253 | @SuppressWarnings("synthetic-access") | |
254 | private DataString() { | |
255 | } | |
256 | ||
257 | @SuppressWarnings("synthetic-access") | |
258 | public DataString(String data) { | |
259 | this.data = data; | |
260 | } | |
261 | } | |
262 | ||
db31c358 NR |
263 | @SuppressWarnings("unused") |
264 | class DataLoop extends Data { | |
265 | public DataLoop next; | |
266 | private String value; | |
267 | ||
268 | @SuppressWarnings("synthetic-access") | |
269 | private DataLoop() { | |
270 | } | |
271 | ||
272 | @SuppressWarnings("synthetic-access") | |
273 | public DataLoop(String value) { | |
274 | this.value = value; | |
275 | } | |
276 | } | |
e570f7eb NR |
277 | |
278 | enum EnumToSend { | |
279 | FANFAN, TULIPE, | |
280 | } | |
db31c358 | 281 | } |