3131
3232package org .scijava .module ;
3333
34+ import static org .junit .Assert .assertEquals ;
3435import static org .junit .Assert .assertNull ;
3536import static org .junit .Assert .assertSame ;
3637
38+ import java .util .HashMap ;
39+ import java .util .Map ;
40+ import java .util .Map .Entry ;
41+ import java .util .concurrent .ExecutionException ;
42+
43+ import org .junit .After ;
44+ import org .junit .Before ;
3745import org .junit .Test ;
3846import org .scijava .Context ;
3947
4452 */
4553public class ModuleServiceTest {
4654
47- @ Test
48- public void testGetSingleInput () throws ModuleException {
55+ private ModuleService moduleService ;
56+
57+ @ Before
58+ public void setUp () {
4959 final Context context = new Context (ModuleService .class );
50- final ModuleService moduleService = context .getService (ModuleService .class );
60+ moduleService = context .service (ModuleService .class );
61+ }
62+
63+ @ After
64+ public void tearDown () {
65+ moduleService .context ().dispose ();
66+ }
67+
68+ /** Tests {@link ModuleService#run(ModuleInfo, boolean, Object...)}. */
69+ @ Test
70+ public void testRunModuleInfoArray () throws InterruptedException ,
71+ ExecutionException
72+ {
73+ final ModuleInfo info = new FooModuleInfo ();
74+ final Module m = moduleService .run (info , false , createInputArray ()).get ();
75+ assertEquals (expectedResult (), m .getOutput ("result" ));
76+ }
77+
78+ /** Tests {@link ModuleService#run(ModuleInfo, boolean, Map)}. */
79+ @ Test
80+ public void testRunModuleInfoMap () throws InterruptedException ,
81+ ExecutionException
82+ {
83+ final ModuleInfo info = new FooModuleInfo ();
84+ final Module m = moduleService .run (info , false , createInputMap ()).get ();
85+ assertEquals (expectedResult (), m .getOutput ("result" ));
86+ }
87+
88+ /** Tests {@link ModuleService#run(Module, boolean, Object...)}. */
89+ @ Test
90+ public void testRunModuleArray () throws ModuleException , InterruptedException ,
91+ ExecutionException
92+ {
93+ final ModuleInfo info = new FooModuleInfo ();
94+ final Module module = info .createModule ();
95+ final Module m = moduleService .run (module , false , createInputArray ()).get ();
96+ assertSame (module , m );
97+ assertEquals (expectedResult (), m .getOutput ("result" ));
98+ }
99+
100+ /** Tests {@link ModuleService#run(Module, boolean, Map)}. */
101+ @ Test
102+ public void testRunModuleMap () throws ModuleException , InterruptedException ,
103+ ExecutionException
104+ {
105+ final ModuleInfo info = new FooModuleInfo ();
106+ final Module module = info .createModule ();
107+ final Module m = moduleService .run (module , false , createInputMap ()).get ();
108+ assertSame (module , m );
109+ assertEquals (expectedResult (), m .getOutput ("result" ));
110+ }
111+
112+ /**
113+ * Tests that {@link ModuleService#run(ModuleInfo, boolean, Object...)} and
114+ * {@link ModuleService#run(Module, boolean, Object...)} intelligently handle
115+ * a single-element {@link Object} array consisting of a {@code Map<String,
116+ * Object>}.
117+ * <p>
118+ * This situation can happen e.g. due to Jython choosing the wrong overloaded
119+ * {@code run} method. We correct for the issue on our side, for convenience.
120+ * </p>
121+ */
122+ @ Test
123+ public void testRunMapHack () throws ModuleException , InterruptedException ,
124+ ExecutionException
125+ {
126+ final ModuleInfo info = new FooModuleInfo ();
127+ final Object [] inputs = new Object [] { createInputMap () };
128+ final Module m = moduleService .run (info , false , inputs ).get ();
129+ assertEquals (expectedResult (), m .getOutput ("result" ));
130+
131+ final Module module = info .createModule ();
132+ final Module m2 = moduleService .run (module , false , inputs ).get ();
133+ assertEquals (expectedResult (), m2 .getOutput ("result" ));
134+ }
51135
136+ @ Test
137+ public void testGetSingleInput () throws ModuleException {
52138 final ModuleInfo info = new FooModuleInfo ();
53139 final Module module = info .createModule ();
54140
@@ -74,6 +160,44 @@ public void testGetSingleInput() throws ModuleException {
74160 assertSame (info .getInput ("double2" ), singleDouble );
75161 }
76162
163+ // -- Helper methods --
164+
165+ private Object [] createInputArray () {
166+ return new Object [] { //
167+ "string" , "hello" , //
168+ "float" , 1.234f , //
169+ "integer1" , -2 , //
170+ "integer2" , 7 , //
171+ "double1" , Math .E , //
172+ "double2" , Math .PI //
173+ };
174+ }
175+
176+ private Map <String , Object > createInputMap () {
177+ final Map <String , Object > inputMap = new HashMap <>();
178+ inputMap .put ("string" , "hello" );
179+ inputMap .put ("float" , 1.234f );
180+ inputMap .put ("integer1" , -2 );
181+ inputMap .put ("integer2" , 7 );
182+ inputMap .put ("double1" , Math .E );
183+ inputMap .put ("double2" , Math .PI );
184+ return inputMap ;
185+ }
186+
187+ private String expectedResult () {
188+ return mapToString (createInputMap ());
189+ }
190+
191+ private static String mapToString (final Map <String , Object > map ) {
192+ final StringBuilder sb = new StringBuilder ();
193+ for (final Entry <String , Object > entry : map .entrySet ()) {
194+ sb .append (entry .getKey () + " = " + entry .getValue () + "\n " );
195+ }
196+ return sb .toString ();
197+ }
198+
199+ // -- Helper classes --
200+
77201 /** A sample module for testing the module service. */
78202 public static class FooModule extends AbstractModule {
79203
@@ -90,7 +214,7 @@ public ModuleInfo getInfo() {
90214
91215 @ Override
92216 public void run () {
93- // TODO Auto-generated method stub
217+ setOutput ( "result" , mapToString ( getInputs ()));
94218 }
95219
96220 }
@@ -121,6 +245,7 @@ protected void parseParameters() {
121245 addInput ("integer2" , Integer .class , true );
122246 addInput ("double1" , Double .class , false );
123247 addInput ("double2" , Double .class , true );
248+ addOutput ("result" , String .class );
124249 }
125250
126251 private <T > void addInput (final String name , final Class <T > type ,
@@ -146,6 +271,22 @@ public boolean isAutoFill() {
146271 });
147272 }
148273
274+ private <T > void addOutput (final String name , final Class <T > type ) {
275+ registerOutput (new AbstractModuleItem <T >(this ) {
276+
277+ @ Override
278+ public String getName () {
279+ return name ;
280+ }
281+
282+ @ Override
283+ public Class <T > getType () {
284+ return type ;
285+ }
286+
287+ });
288+ }
289+
149290 }
150291
151292}
0 commit comments