Commit | Line | Data |
---|---|---|
fbcc2a2a | 1 | package be.nikiroo.utils.test_code; |
db31c358 | 2 | |
564bbbdb 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; | |
088c1d7a | 8 | import java.net.URL; |
564bbbdb | 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 | ||
6e56dcb6 | 24 | private void encodeRecodeTest(TestCase test, Object data) throws Exception { |
d8b7384a | 25 | byte[] encoded = toBytes(data, true); |
cfb8e516 | 26 | Object redata = fromBytes(toBytes(data, false)); |
d8b7384a | 27 | byte[] reencoded = toBytes(redata, true); |
6e56dcb6 | 28 | |
cfb8e516 NR |
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 | } | |
6e56dcb6 NR |
38 | } |
39 | ||
564bbbdb | 40 | // try to remove pointer addresses |
d8b7384a NR |
41 | private byte[] toBytes(Object data, boolean clearRefs) |
42 | throws NotSerializableException, IOException { | |
564bbbdb NR |
43 | ByteArrayOutputStream out = new ByteArrayOutputStream(); |
44 | new Exporter(out).append(data); | |
45 | out.flush(); | |
d8b7384a NR |
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"); | |
4d319565 | 51 | } |
d8b7384a | 52 | |
4d319565 | 53 | return out.toByteArray(); |
564bbbdb NR |
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); | |
6e56dcb6 | 75 | encodeRecodeTest(this, data); |
3f277541 NR |
76 | } |
77 | }); | |
088c1d7a NR |
78 | addTest(new TestCase() { |
79 | @SuppressWarnings("unused") | |
80 | private TestCase me = setName("Anonymous inner class"); | |
81 | ||
82 | @Override | |
83 | public void test() throws Exception { | |
84 | Data data = new Data() { | |
85 | @SuppressWarnings("unused") | |
86 | int value = 42; | |
87 | }; | |
6e56dcb6 | 88 | encodeRecodeTest(this, data); |
088c1d7a NR |
89 | } |
90 | }); | |
91 | addTest(new TestCase() { | |
92 | @SuppressWarnings("unused") | |
93 | private TestCase me = setName("Array of anonymous inner classes"); | |
94 | ||
95 | @Override | |
96 | public void test() throws Exception { | |
97 | Data[] data = new Data[] { new Data() { | |
98 | @SuppressWarnings("unused") | |
99 | int value = 42; | |
d8b7384a NR |
100 | } }; |
101 | ||
102 | byte[] encoded = toBytes(data, false); | |
6e56dcb6 | 103 | Object redata = fromBytes(encoded); |
d8b7384a | 104 | |
6e56dcb6 NR |
105 | // Comparing the 2 arrays won't be useful, because the @REFs |
106 | // will be ZIP-encoded; so we parse and re-encode each object | |
d8b7384a NR |
107 | |
108 | byte[] encoded1 = toBytes(data[0], true); | |
109 | byte[] reencoded1 = toBytes(((Object[]) redata)[0], true); | |
6e56dcb6 NR |
110 | |
111 | assertEquals("Different data after encode/decode/encode", true, | |
112 | Arrays.equals(encoded1, reencoded1)); | |
088c1d7a NR |
113 | } |
114 | }); | |
115 | addTest(new TestCase("URL Import/Export") { | |
116 | @Override | |
117 | public void test() throws Exception { | |
118 | URL data = new URL("https://fanfan.be/"); | |
d8b7384a | 119 | encodeRecodeTest(this, data); |
088c1d7a NR |
120 | } |
121 | }); | |
122 | addTest(new TestCase("URL-String Import/Export") { | |
123 | @Override | |
124 | public void test() throws Exception { | |
125 | String data = new URL("https://fanfan.be/").toString(); | |
d8b7384a | 126 | encodeRecodeTest(this, data); |
088c1d7a NR |
127 | } |
128 | }); | |
129 | addTest(new TestCase("URL/URL-String arrays Import/Export") { | |
130 | @Override | |
131 | public void test() throws Exception { | |
132 | final String url = "https://fanfan.be/"; | |
133 | Object[] data = new Object[] { new URL(url), url }; | |
d8b7384a NR |
134 | |
135 | byte[] encoded = toBytes(data, false); | |
136 | Object redata = fromBytes(encoded); | |
137 | ||
138 | // Comparing the 2 arrays won't be useful, because the @REFs | |
139 | // will be ZIP-encoded; so we parse and re-encode each object | |
140 | ||
141 | byte[] encoded1 = toBytes(data[0], true); | |
142 | byte[] reencoded1 = toBytes(((Object[]) redata)[0], true); | |
cfb8e516 | 143 | byte[] encoded2 = toBytes(data[1], true); |
d8b7384a NR |
144 | byte[] reencoded2 = toBytes(((Object[]) redata)[1], true); |
145 | ||
146 | assertEquals("Different data 1 after encode/decode/encode", | |
147 | true, Arrays.equals(encoded1, reencoded1)); | |
148 | assertEquals("Different data 2 after encode/decode/encode", | |
149 | true, Arrays.equals(encoded2, reencoded2)); | |
088c1d7a NR |
150 | } |
151 | }); | |
152 | addTest(new TestCase("Import/Export with nested objects") { | |
153 | @Override | |
154 | public void test() throws Exception { | |
155 | Data data = new DataObject(new Data(21)); | |
d8b7384a | 156 | encodeRecodeTest(this, data); |
088c1d7a NR |
157 | } |
158 | }); | |
159 | addTest(new TestCase("Import/Export with nested objects forming a loop") { | |
160 | @Override | |
161 | public void test() throws Exception { | |
162 | DataLoop data = new DataLoop("looping"); | |
163 | data.next = new DataLoop("level 2"); | |
164 | data.next.next = data; | |
d8b7384a | 165 | encodeRecodeTest(this, data); |
088c1d7a NR |
166 | } |
167 | }); | |
168 | addTest(new TestCase("Array in Object Import/Export") { | |
169 | @Override | |
170 | public void test() throws Exception { | |
171 | Object data = new DataArray();// new String[] { "un", "deux" }; | |
d8b7384a | 172 | encodeRecodeTest(this, data); |
088c1d7a NR |
173 | } |
174 | }); | |
175 | addTest(new TestCase("Array Import/Export") { | |
176 | @Override | |
177 | public void test() throws Exception { | |
178 | Object data = new String[] { "un", "deux" }; | |
d8b7384a | 179 | encodeRecodeTest(this, data); |
088c1d7a NR |
180 | } |
181 | }); | |
182 | addTest(new TestCase("Enum Import/Export") { | |
183 | @Override | |
184 | public void test() throws Exception { | |
185 | Object data = EnumToSend.FANFAN; | |
d8b7384a | 186 | encodeRecodeTest(this, data); |
088c1d7a NR |
187 | } |
188 | }); | |
ce0974c4 NR |
189 | } |
190 | ||
191 | class DataArray { | |
192 | public String[] data = new String[] { "un", "deux" }; | |
db31c358 NR |
193 | } |
194 | ||
db31c358 NR |
195 | class Data { |
196 | private int value; | |
197 | ||
198 | private Data() { | |
199 | } | |
200 | ||
201 | public Data(int value) { | |
202 | this.value = value; | |
203 | } | |
3f277541 NR |
204 | |
205 | @Override | |
206 | public boolean equals(Object obj) { | |
207 | if (obj instanceof Data) { | |
208 | Data other = (Data) obj; | |
209 | return other.value == this.value; | |
210 | } | |
211 | ||
212 | return false; | |
213 | } | |
214 | ||
215 | @Override | |
216 | public int hashCode() { | |
b6d4ace8 | 217 | return new Integer(value).hashCode(); |
3f277541 | 218 | } |
db31c358 NR |
219 | } |
220 | ||
221 | @SuppressWarnings("unused") | |
222 | class DataObject extends Data { | |
223 | private Data data; | |
224 | ||
225 | @SuppressWarnings("synthetic-access") | |
226 | private DataObject() { | |
227 | } | |
228 | ||
229 | @SuppressWarnings("synthetic-access") | |
230 | public DataObject(Data data) { | |
231 | this.data = data; | |
232 | } | |
233 | } | |
234 | ||
235 | @SuppressWarnings("unused") | |
236 | class DataLoop extends Data { | |
237 | public DataLoop next; | |
238 | private String value; | |
239 | ||
240 | @SuppressWarnings("synthetic-access") | |
241 | private DataLoop() { | |
242 | } | |
243 | ||
244 | @SuppressWarnings("synthetic-access") | |
245 | public DataLoop(String value) { | |
246 | this.value = value; | |
247 | } | |
248 | } | |
e570f7eb NR |
249 | |
250 | enum EnumToSend { | |
251 | FANFAN, TULIPE, | |
252 | } | |
db31c358 | 253 | } |