diff options
| author | 2015-03-16 19:22:22 -0400 | |
|---|---|---|
| committer | 2015-03-16 19:22:22 -0400 | |
| commit | 5e3743a0aca3529eacf9be400c8b8d7547f66e7f (patch) | |
| tree | ea601747547f78e1b83ab828650932126440e221 /test | |
| parent | update to new javassist version to (hopefully) get bug fixes (diff) | |
| download | enigma-5e3743a0aca3529eacf9be400c8b8d7547f66e7f.tar.gz enigma-5e3743a0aca3529eacf9be400c8b8d7547f66e7f.tar.xz enigma-5e3743a0aca3529eacf9be400c8b8d7547f66e7f.zip | |
started adding minimal support for generics
fixed mark-as-deobfuscated issue
Diffstat (limited to 'test')
| -rw-r--r-- | test/cuchaz/enigma/TestSourceIndex.java | 2 | ||||
| -rw-r--r-- | test/cuchaz/enigma/TestTranslator.java | 17 | ||||
| -rw-r--r-- | test/cuchaz/enigma/TestType.java | 163 | ||||
| -rw-r--r-- | test/cuchaz/enigma/resources/translation.mappings | 11 |
4 files changed, 184 insertions, 9 deletions
diff --git a/test/cuchaz/enigma/TestSourceIndex.java b/test/cuchaz/enigma/TestSourceIndex.java index 13971249..94bf941d 100644 --- a/test/cuchaz/enigma/TestSourceIndex.java +++ b/test/cuchaz/enigma/TestSourceIndex.java | |||
| @@ -24,7 +24,7 @@ import cuchaz.enigma.mapping.ClassEntry; | |||
| 24 | 24 | ||
| 25 | public class TestSourceIndex { | 25 | public class TestSourceIndex { |
| 26 | 26 | ||
| 27 | // TEMP @Test | 27 | @Test |
| 28 | public void indexEverything() | 28 | public void indexEverything() |
| 29 | throws Exception { | 29 | throws Exception { |
| 30 | 30 | ||
diff --git a/test/cuchaz/enigma/TestTranslator.java b/test/cuchaz/enigma/TestTranslator.java index 45c69bb2..1b617405 100644 --- a/test/cuchaz/enigma/TestTranslator.java +++ b/test/cuchaz/enigma/TestTranslator.java | |||
| @@ -125,7 +125,22 @@ public class TestTranslator { | |||
| 125 | 125 | ||
| 126 | @Test | 126 | @Test |
| 127 | public void testGenerics() { | 127 | public void testGenerics() { |
| 128 | // TODO | 128 | |
| 129 | // classes | ||
| 130 | assertMapping(newClass("none/i"), newClass("deobf/I_Generics")); | ||
| 131 | assertMapping(newClass("none/i$a"), newClass("deobf/I_Generics$A_Type")); | ||
| 132 | assertMapping(newClass("none/i$b"), newClass("deobf/I_Generics$B_Generic")); | ||
| 133 | |||
| 134 | // fields | ||
| 135 | assertMapping(newField("none/i", "a", "Ljava/util/List;"), newField("deobf/I_Generics", "f1", "Ljava/util/List;")); | ||
| 136 | assertMapping(newField("none/i", "b", "Ljava/util/List;"), newField("deobf/I_Generics", "f2", "Ljava/util/List;")); | ||
| 137 | assertMapping(newField("none/i", "a", "Ljava/util/Map;"), newField("deobf/I_Generics", "f3", "Ljava/util/Map;")); | ||
| 138 | assertMapping(newField("none/i$b", "a", "Ljava/lang/Object;"), newField("deobf/I_Generics$B_Generic", "f4", "Ljava/lang/Object;")); | ||
| 139 | assertMapping(newField("none/i", "a", "Lnone/i$b;"), newField("deobf/I_Generics", "f5", "Ldeobf/I_Generics$B_Generic;")); | ||
| 140 | assertMapping(newField("none/i", "b", "Lnone/i$b;"), newField("deobf/I_Generics", "f6", "Ldeobf/I_Generics$B_Generic;")); | ||
| 141 | |||
| 142 | // methods | ||
| 143 | assertMapping(newMethod("none/i$b", "a", "()Ljava/lang/Object;"), newMethod("deobf/I_Generics$B_Generic", "m1", "()Ljava/lang/Object;")); | ||
| 129 | } | 144 | } |
| 130 | 145 | ||
| 131 | private void assertMapping(Entry obf, Entry deobf) { | 146 | private void assertMapping(Entry obf, Entry deobf) { |
diff --git a/test/cuchaz/enigma/TestType.java b/test/cuchaz/enigma/TestType.java index 93f864b0..544a10c1 100644 --- a/test/cuchaz/enigma/TestType.java +++ b/test/cuchaz/enigma/TestType.java | |||
| @@ -1,13 +1,13 @@ | |||
| 1 | package cuchaz.enigma; | 1 | package cuchaz.enigma; |
| 2 | 2 | ||
| 3 | import org.junit.Test; | 3 | import static cuchaz.enigma.TestEntryFactory.*; |
| 4 | |||
| 5 | import static org.hamcrest.MatcherAssert.*; | 4 | import static org.hamcrest.MatcherAssert.*; |
| 6 | import static org.hamcrest.Matchers.*; | 5 | import static org.hamcrest.Matchers.*; |
| 7 | 6 | ||
| 8 | import cuchaz.enigma.mapping.Type; | 7 | import org.junit.Test; |
| 9 | 8 | ||
| 10 | import static cuchaz.enigma.TestEntryFactory.*; | 9 | import cuchaz.enigma.mapping.ParameterizedType; |
| 10 | import cuchaz.enigma.mapping.Type; | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | public class TestType { | 13 | public class TestType { |
| @@ -24,6 +24,7 @@ public class TestType { | |||
| 24 | assertThat(new Type("D").isVoid(), is(false)); | 24 | assertThat(new Type("D").isVoid(), is(false)); |
| 25 | assertThat(new Type("LFoo;").isVoid(), is(false)); | 25 | assertThat(new Type("LFoo;").isVoid(), is(false)); |
| 26 | assertThat(new Type("[I").isVoid(), is(false)); | 26 | assertThat(new Type("[I").isVoid(), is(false)); |
| 27 | assertThat(new Type("TFoo;").isVoid(), is(false)); | ||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | @Test | 30 | @Test |
| @@ -38,6 +39,7 @@ public class TestType { | |||
| 38 | assertThat(new Type("D").isPrimitive(), is(true)); | 39 | assertThat(new Type("D").isPrimitive(), is(true)); |
| 39 | assertThat(new Type("LFoo;").isPrimitive(), is(false)); | 40 | assertThat(new Type("LFoo;").isPrimitive(), is(false)); |
| 40 | assertThat(new Type("[I").isPrimitive(), is(false)); | 41 | assertThat(new Type("[I").isPrimitive(), is(false)); |
| 42 | assertThat(new Type("TFoo;").isPrimitive(), is(false)); | ||
| 41 | } | 43 | } |
| 42 | 44 | ||
| 43 | @Test | 45 | @Test |
| @@ -62,13 +64,20 @@ public class TestType { | |||
| 62 | assertThat(new Type("F").isClass(), is(false)); | 64 | assertThat(new Type("F").isClass(), is(false)); |
| 63 | assertThat(new Type("D").isClass(), is(false)); | 65 | assertThat(new Type("D").isClass(), is(false)); |
| 64 | assertThat(new Type("LFoo;").isClass(), is(true)); | 66 | assertThat(new Type("LFoo;").isClass(), is(true)); |
| 67 | assertThat(new Type("LFoo<LCow;>;").isClass(), is(true)); | ||
| 68 | assertThat(new Type("LFoo<LCow;LBeer;>;").isClass(), is(true)); | ||
| 69 | assertThat(new Type("LFoo<LPair<LCow;LBeer;>;>;").isClass(), is(true)); | ||
| 65 | assertThat(new Type("[I").isClass(), is(false)); | 70 | assertThat(new Type("[I").isClass(), is(false)); |
| 71 | assertThat(new Type("TFoo;").isClass(), is(false)); | ||
| 66 | } | 72 | } |
| 67 | 73 | ||
| 68 | @Test | 74 | @Test |
| 69 | public void getClassEntry() { | 75 | public void getClassEntry() { |
| 70 | assertThat(new Type("LFoo;").getClassEntry(), is(newClass("Foo"))); | 76 | assertThat(new Type("LFoo;").getClassEntry(), is(newClass("Foo"))); |
| 71 | assertThat(new Type("LFoo<Ljava/lang/String;>;").getClassEntry(), is(newClass("Foo"))); | 77 | assertThat(new Type("LFoo<Ljava/lang/String;>;").getClassEntry(), is(newClass("Foo"))); |
| 78 | assertThat(new Type("LFoo<LCow;>;").getClassEntry(), is(newClass("Foo"))); | ||
| 79 | assertThat(new Type("LFoo<LCow;LBeer;>;").getClassEntry(), is(newClass("Foo"))); | ||
| 80 | assertThat(new Type("LFoo<LPair<LCow;LBeer;>;>;").getClassEntry(), is(newClass("Foo"))); | ||
| 72 | } | 81 | } |
| 73 | 82 | ||
| 74 | @Test | 83 | @Test |
| @@ -89,6 +98,7 @@ public class TestType { | |||
| 89 | assertThat(new Type("D").isArray(), is(false)); | 98 | assertThat(new Type("D").isArray(), is(false)); |
| 90 | assertThat(new Type("LFoo;").isArray(), is(false)); | 99 | assertThat(new Type("LFoo;").isArray(), is(false)); |
| 91 | assertThat(new Type("[I").isArray(), is(true)); | 100 | assertThat(new Type("[I").isArray(), is(true)); |
| 101 | assertThat(new Type("TFoo;").isArray(), is(false)); | ||
| 92 | } | 102 | } |
| 93 | 103 | ||
| 94 | @Test | 104 | @Test |
| @@ -107,6 +117,30 @@ public class TestType { | |||
| 107 | } | 117 | } |
| 108 | 118 | ||
| 109 | @Test | 119 | @Test |
| 120 | public void isTemplate() { | ||
| 121 | assertThat(new Type("V").isTemplate(), is(false)); | ||
| 122 | assertThat(new Type("Z").isTemplate(), is(false)); | ||
| 123 | assertThat(new Type("B").isTemplate(), is(false)); | ||
| 124 | assertThat(new Type("C").isTemplate(), is(false)); | ||
| 125 | assertThat(new Type("I").isTemplate(), is(false)); | ||
| 126 | assertThat(new Type("J").isTemplate(), is(false)); | ||
| 127 | assertThat(new Type("F").isTemplate(), is(false)); | ||
| 128 | assertThat(new Type("D").isTemplate(), is(false)); | ||
| 129 | assertThat(new Type("LFoo;").isTemplate(), is(false)); | ||
| 130 | assertThat(new Type("LFoo<LCow;>;").isTemplate(), is(false)); | ||
| 131 | assertThat(new Type("LFoo<LCow;LBeer;>;").isTemplate(), is(false)); | ||
| 132 | assertThat(new Type("LFoo<LPair<LCow;LBeer;>;>;").isTemplate(), is(false)); | ||
| 133 | assertThat(new Type("[I").isTemplate(), is(false)); | ||
| 134 | assertThat(new Type("TFoo;").isTemplate(), is(true)); | ||
| 135 | } | ||
| 136 | |||
| 137 | @Test | ||
| 138 | public void getTemplate() { | ||
| 139 | assertThat(new Type("TT;").getTemplate(), is("T")); | ||
| 140 | assertThat(new Type("TFoo;").getTemplate(), is("Foo")); | ||
| 141 | } | ||
| 142 | |||
| 143 | @Test | ||
| 110 | public void hasClass() { | 144 | public void hasClass() { |
| 111 | assertThat(new Type("LFoo;").hasClass(), is(true)); | 145 | assertThat(new Type("LFoo;").hasClass(), is(true)); |
| 112 | assertThat(new Type("LCow<LCheese;>;").hasClass(), is(true)); | 146 | assertThat(new Type("LCow<LCheese;>;").hasClass(), is(true)); |
| @@ -117,6 +151,37 @@ public class TestType { | |||
| 117 | assertThat(new Type("[I").hasClass(), is(false)); | 151 | assertThat(new Type("[I").hasClass(), is(false)); |
| 118 | assertThat(new Type("[[[I").hasClass(), is(false)); | 152 | assertThat(new Type("[[[I").hasClass(), is(false)); |
| 119 | assertThat(new Type("Z").hasClass(), is(false)); | 153 | assertThat(new Type("Z").hasClass(), is(false)); |
| 154 | assertThat(new Type("TFoo;").hasClass(), is(false)); | ||
| 155 | } | ||
| 156 | |||
| 157 | @Test | ||
| 158 | public void parameters() { | ||
| 159 | assertThat(new Type("LFoo<I>;").parameters(), contains( | ||
| 160 | new Type("I") | ||
| 161 | )); | ||
| 162 | assertThat(new Type("LFoo<IIII>;").parameters(), contains( | ||
| 163 | new Type("I"), | ||
| 164 | new Type("I"), | ||
| 165 | new Type("I"), | ||
| 166 | new Type("I") | ||
| 167 | )); | ||
| 168 | assertThat(new Type("LFoo<LBar;>;").parameters(), contains( | ||
| 169 | new Type("LBar;") | ||
| 170 | )); | ||
| 171 | assertThat(new Type("LFoo<LBar;LCow;LCheese;>;").parameters(), contains( | ||
| 172 | new Type("LBar;"), | ||
| 173 | new Type("LCow;"), | ||
| 174 | new Type("LCheese;") | ||
| 175 | )); | ||
| 176 | |||
| 177 | assertThat(new Type("LFoo<LBar<LCow;LCheese;>;>;").parameters(), contains( | ||
| 178 | new Type("LBar<LCow;LCheese;>;") | ||
| 179 | )); | ||
| 180 | |||
| 181 | assertThat(new Type("LFoo<LBar<LCow;LCheese;>;>;").parameters().iterator().next().parameters(), contains( | ||
| 182 | new Type("LCow;"), | ||
| 183 | new Type("LCheese;") | ||
| 184 | )); | ||
| 120 | } | 185 | } |
| 121 | 186 | ||
| 122 | @Test | 187 | @Test |
| @@ -171,7 +236,18 @@ public class TestType { | |||
| 171 | assertThat(Type.parseFirst("LFoo<LFoo;,LBar;>;[LFoo;"), is(answer)); | 236 | assertThat(Type.parseFirst("LFoo<LFoo;,LBar;>;[LFoo;"), is(answer)); |
| 172 | } | 237 | } |
| 173 | } | 238 | } |
| 174 | 239 | ||
| 240 | @Test | ||
| 241 | public void parseTemplate() { | ||
| 242 | final String answer = "TFoo;"; | ||
| 243 | assertThat(Type.parseFirst("TFoo;"), is(answer)); | ||
| 244 | assertThat(Type.parseFirst("TFoo;I"), is(answer)); | ||
| 245 | assertThat(Type.parseFirst("TFoo;JZ"), is(answer)); | ||
| 246 | assertThat(Type.parseFirst("TFoo;[I"), is(answer)); | ||
| 247 | assertThat(Type.parseFirst("TFoo;LFoo;"), is(answer)); | ||
| 248 | assertThat(Type.parseFirst("TFoo;[LFoo;"), is(answer)); | ||
| 249 | } | ||
| 250 | |||
| 175 | @Test | 251 | @Test |
| 176 | public void parseArray() { | 252 | public void parseArray() { |
| 177 | { | 253 | { |
| @@ -215,15 +291,90 @@ public class TestType { | |||
| 215 | assertThat(new Type("[[[I"), is(new Type("[[[I"))); | 291 | assertThat(new Type("[[[I"), is(new Type("[[[I"))); |
| 216 | assertThat(new Type("[LFoo;"), is(new Type("[LFoo;"))); | 292 | assertThat(new Type("[LFoo;"), is(new Type("[LFoo;"))); |
| 217 | assertThat(new Type("LFoo<LBar;>;"), is(new Type("LFoo<LBar;>;"))); | 293 | assertThat(new Type("LFoo<LBar;>;"), is(new Type("LFoo<LBar;>;"))); |
| 294 | assertThat(new Type("LFoo<LBar;>;"), is(new Type("LFoo<LCow;>;"))); | ||
| 295 | assertThat(new Type("TFoo;"), is(new Type("TFoo;"))); | ||
| 218 | 296 | ||
| 219 | assertThat(new Type("V"), is(not(new Type("I")))); | 297 | assertThat(new Type("V"), is(not(new Type("I")))); |
| 220 | assertThat(new Type("I"), is(not(new Type("J")))); | 298 | assertThat(new Type("I"), is(not(new Type("J")))); |
| 221 | assertThat(new Type("I"), is(not(new Type("LBar;")))); | 299 | assertThat(new Type("I"), is(not(new Type("LBar;")))); |
| 222 | assertThat(new Type("I"), is(not(new Type("[I")))); | 300 | assertThat(new Type("I"), is(not(new Type("[I")))); |
| 223 | assertThat(new Type("LFoo;"), is(not(new Type("LBar;")))); | 301 | assertThat(new Type("LFoo;"), is(not(new Type("LBar;")))); |
| 224 | assertThat(new Type("LFoo<LBar;>;"), is(not(new Type("LFoo<LCow;>;")))); | ||
| 225 | assertThat(new Type("[I"), is(not(new Type("[Z")))); | 302 | assertThat(new Type("[I"), is(not(new Type("[Z")))); |
| 226 | assertThat(new Type("[[[I"), is(not(new Type("[I")))); | 303 | assertThat(new Type("[[[I"), is(not(new Type("[I")))); |
| 227 | assertThat(new Type("[LFoo;"), is(not(new Type("[LBar;")))); | 304 | assertThat(new Type("[LFoo;"), is(not(new Type("[LBar;")))); |
| 305 | assertThat(new Type("TFoo;"), is(not(new Type("TBar;")))); | ||
| 306 | } | ||
| 307 | |||
| 308 | @Test | ||
| 309 | public void testToString() { | ||
| 310 | assertThat(new Type("V").toString(), is("V")); | ||
| 311 | assertThat(new Type("Z").toString(), is("Z")); | ||
| 312 | assertThat(new Type("B").toString(), is("B")); | ||
| 313 | assertThat(new Type("C").toString(), is("C")); | ||
| 314 | assertThat(new Type("I").toString(), is("I")); | ||
| 315 | assertThat(new Type("J").toString(), is("J")); | ||
| 316 | assertThat(new Type("F").toString(), is("F")); | ||
| 317 | assertThat(new Type("D").toString(), is("D")); | ||
| 318 | assertThat(new Type("LFoo;").toString(), is("LFoo;")); | ||
| 319 | assertThat(new Type("[I").toString(), is("[I")); | ||
| 320 | assertThat(new Type("[[[I").toString(), is("[[[I")); | ||
| 321 | assertThat(new Type("[LFoo;").toString(), is("[LFoo;")); | ||
| 322 | assertThat(new Type("LFoo<LBar;>;").toString(), is("LFoo;")); | ||
| 323 | assertThat(new Type("LFoo<LCow;LCheese;>;").toString(), is("LFoo;")); | ||
| 324 | assertThat(new Type("LFoo<LPair<LCow;LCheese;>;>;").toString(), is("LFoo;")); | ||
| 325 | assertThat(new Type("TFoo;").toString(), is("TFoo;")); | ||
| 326 | } | ||
| 327 | |||
| 328 | private ParameterizedType ptype(String name) { | ||
| 329 | return new ParameterizedType(new Type(name)); | ||
| 330 | } | ||
| 331 | |||
| 332 | @Test | ||
| 333 | public void equalsWithParameters() { | ||
| 334 | assertThat(ptype("V"), is(ptype("V"))); | ||
| 335 | assertThat(ptype("Z"), is(ptype("Z"))); | ||
| 336 | assertThat(ptype("B"), is(ptype("B"))); | ||
| 337 | assertThat(ptype("C"), is(ptype("C"))); | ||
| 338 | assertThat(ptype("I"), is(ptype("I"))); | ||
| 339 | assertThat(ptype("J"), is(ptype("J"))); | ||
| 340 | assertThat(ptype("F"), is(ptype("F"))); | ||
| 341 | assertThat(ptype("D"), is(ptype("D"))); | ||
| 342 | assertThat(ptype("LFoo;"), is(ptype("LFoo;"))); | ||
| 343 | assertThat(ptype("[I"), is(ptype("[I"))); | ||
| 344 | assertThat(ptype("[[[I"), is(ptype("[[[I"))); | ||
| 345 | assertThat(ptype("[LFoo;"), is(ptype("[LFoo;"))); | ||
| 346 | assertThat(ptype("LFoo<LBar;>;"), is(ptype("LFoo<LBar;>;"))); | ||
| 347 | assertThat(ptype("TFoo;"), is(ptype("TFoo;"))); | ||
| 348 | |||
| 349 | assertThat(ptype("V"), is(not(ptype("I")))); | ||
| 350 | assertThat(ptype("I"), is(not(ptype("J")))); | ||
| 351 | assertThat(ptype("I"), is(not(ptype("LBar;")))); | ||
| 352 | assertThat(ptype("I"), is(not(ptype("[I")))); | ||
| 353 | assertThat(ptype("LFoo;"), is(not(ptype("LBar;")))); | ||
| 354 | assertThat(ptype("[I"), is(not(ptype("[Z")))); | ||
| 355 | assertThat(ptype("[[[I"), is(not(ptype("[I")))); | ||
| 356 | assertThat(ptype("[LFoo;"), is(not(ptype("[LBar;")))); | ||
| 357 | assertThat(ptype("LFoo<LBar;>;"), is(not(ptype("LFoo<LCow;>;")))); | ||
| 358 | assertThat(ptype("TFoo;"), is(not(ptype("TBar;")))); | ||
| 359 | } | ||
| 360 | |||
| 361 | @Test | ||
| 362 | public void testToStringWithParams() { | ||
| 363 | assertThat(ptype("V").toString(), is("V")); | ||
| 364 | assertThat(ptype("Z").toString(), is("Z")); | ||
| 365 | assertThat(ptype("B").toString(), is("B")); | ||
| 366 | assertThat(ptype("C").toString(), is("C")); | ||
| 367 | assertThat(ptype("I").toString(), is("I")); | ||
| 368 | assertThat(ptype("J").toString(), is("J")); | ||
| 369 | assertThat(ptype("F").toString(), is("F")); | ||
| 370 | assertThat(ptype("D").toString(), is("D")); | ||
| 371 | assertThat(ptype("LFoo;").toString(), is("LFoo;")); | ||
| 372 | assertThat(ptype("[I").toString(), is("[I")); | ||
| 373 | assertThat(ptype("[[[I").toString(), is("[[[I")); | ||
| 374 | assertThat(ptype("[LFoo;").toString(), is("[LFoo;")); | ||
| 375 | assertThat(ptype("LFoo<LBar;>;").toString(), is("LFoo<LBar;>;")); | ||
| 376 | assertThat(ptype("LFoo<LCow;LCheese;>;").toString(), is("LFoo<LCow;LCheese;>;")); | ||
| 377 | assertThat(ptype("LFoo<LPair<LCow;LCheese;>;>;").toString(), is("LFoo<LPair<LCow;LCheese;>;>;")); | ||
| 378 | assertThat(ptype("TFoo;").toString(), is("TFoo;")); | ||
| 228 | } | 379 | } |
| 229 | } | 380 | } |
diff --git a/test/cuchaz/enigma/resources/translation.mappings b/test/cuchaz/enigma/resources/translation.mappings index 55bd7e5c..db78c19d 100644 --- a/test/cuchaz/enigma/resources/translation.mappings +++ b/test/cuchaz/enigma/resources/translation.mappings | |||
| @@ -29,4 +29,13 @@ CLASS none/g deobf/G_OuterClass | |||
| 29 | CLASS none/g$b$a A_NamedInnerClass | 29 | CLASS none/g$b$a A_NamedInnerClass |
| 30 | FIELD a f4 I | 30 | FIELD a f4 I |
| 31 | CLASS none/h | 31 | CLASS none/h |
| 32 | CLASS none/i I_Generics | 32 | CLASS none/i deobf/I_Generics |
| 33 | CLASS none/i$a A_Type | ||
| 34 | CLASS none/i$b B_Generic | ||
| 35 | FIELD a f4 Ljava/lang/Object; | ||
| 36 | METHOD a m1 ()Ljava/lang/Object; | ||
| 37 | FIELD a f1 Ljava/util/List; | ||
| 38 | FIELD b f2 Ljava/util/List; | ||
| 39 | FIELD a f3 Ljava/util/Map; | ||
| 40 | FIELD a f5 Lnone/i$b; | ||
| 41 | FIELD b f6 Lnone/i$b; | ||