Skip to content

Commit b672ea8

Browse files
committed
Add unit tests for the OutputListener API
This code tests that the OutputListeners receive the proper notifications for both stdout and stderr when output is emitted in various ways. It also verifies that output is properly classified when multiple simultaneous Contexts are in play.
1 parent eb46f2e commit b672ea8

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

src/test/java/org/scijava/console/ConsoleServiceTest.java

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,20 @@
3535
import static org.junit.Assert.assertNotNull;
3636
import static org.junit.Assert.assertTrue;
3737

38+
import java.lang.reflect.InvocationTargetException;
39+
import java.util.ArrayList;
40+
import java.util.Collection;
3841
import java.util.LinkedList;
42+
import java.util.concurrent.ExecutionException;
3943

4044
import org.junit.After;
4145
import org.junit.Before;
4246
import org.junit.Test;
4347
import org.scijava.Context;
4448
import org.scijava.Priority;
49+
import org.scijava.console.OutputEvent.Source;
4550
import org.scijava.plugin.Plugin;
51+
import org.scijava.thread.ThreadService;
4652

4753
/**
4854
* Tests {@link ConsoleService}.
@@ -70,6 +76,129 @@ public void testProcessArgs() {
7076
assertTrue(consoleService.getInstance(FooArgument.class).argsHandled);
7177
}
7278

79+
/**
80+
* Tests the {@link OutputListener}-related API:
81+
* <ul>
82+
* <li>{@link ConsoleService#addOutputListener(OutputListener)}</li>
83+
* <li>{@link ConsoleService#removeOutputListener(OutputListener)}</li>
84+
* <li>{@link ConsoleService#notifyListeners(OutputEvent)}</li>
85+
* </ul>
86+
*/
87+
@Test
88+
public void testOutputListeners() throws InterruptedException,
89+
ExecutionException
90+
{
91+
final ThreadService threadService =
92+
consoleService.context().service(ThreadService.class);
93+
94+
final String stdoutBefore = "hoc";
95+
final String stderrBefore = "us-";
96+
final String stdoutGlobal = "poc";
97+
final String stderrGlobal = "us-";
98+
final String stdoutLocal = "abra";
99+
final String stderrLocal = "-cad";
100+
final String stdoutAfter = "ave";
101+
final String stderrAfter = "rs-";
102+
103+
final ArrayList<OutputEvent> events = new ArrayList<OutputEvent>();
104+
final OutputListener outputListener = new OutputTracker(events);
105+
106+
final Runnable r = new Printer(stdoutLocal, stderrLocal);
107+
108+
// This output should _not_ be announced!
109+
System.out.print(stdoutBefore);
110+
System.err.print(stderrBefore);
111+
112+
consoleService.addOutputListener(outputListener);
113+
114+
// This output _should_ be announced!
115+
System.out.print(stdoutGlobal);
116+
System.err.print(stderrGlobal);
117+
threadService.run(r).get();
118+
119+
consoleService.removeOutputListener(outputListener);
120+
121+
// This output should _not_ be announced!
122+
threadService.run(r).get();
123+
System.out.print(stdoutAfter);
124+
System.err.print(stderrAfter);
125+
126+
assertEquals(4, events.size());
127+
128+
assertOutputEvent(Source.STDOUT, stdoutGlobal, false, events.get(0));
129+
assertOutputEvent(Source.STDERR, stderrGlobal, false, events.get(1));
130+
assertOutputEvent(Source.STDOUT, stdoutLocal, true, events.get(2));
131+
assertOutputEvent(Source.STDERR, stderrLocal, true, events.get(3));
132+
}
133+
134+
/** Tests multiple simultaneous {@link Context}s listening for output. */
135+
@Test
136+
public void testMultipleContextOutput() throws InterruptedException,
137+
ExecutionException
138+
{
139+
final Context c1 = consoleService.context();
140+
final Context c2 = new Context();
141+
142+
final ConsoleService cs1 = consoleService;
143+
final ConsoleService cs2 = c2.service(ConsoleService.class);
144+
145+
final ThreadService ts1 = c1.service(ThreadService.class);
146+
final ThreadService ts2 = c2.service(ThreadService.class);
147+
148+
final ArrayList<OutputEvent> events1 = new ArrayList<OutputEvent>();
149+
cs1.addOutputListener(new OutputTracker(events1));
150+
final ArrayList<OutputEvent> events2 = new ArrayList<OutputEvent>();
151+
cs2.addOutputListener(new OutputTracker(events2));
152+
153+
final String globalOut = "and";
154+
final String globalErr = "-zo";
155+
final String c1RunOut = "mbi";
156+
final String c1RunErr = "es-";
157+
final String c2RunOut = "sha";
158+
final String c2RunErr = "zam";
159+
final String c1InvokeOut = "-cl";
160+
final String c1InvokeErr = "eop";
161+
final String c2InvokeOut = "atr";
162+
final String c2InvokeErr = "a";
163+
164+
System.out.print(globalOut);
165+
System.err.print(globalErr);
166+
167+
ts1.run(new Printer(c1RunOut, c1RunErr)).get();
168+
ts2.run(new Printer(c2RunOut, c2RunErr)).get();
169+
170+
ts1.run(new EDTPrinter(ts1, c1InvokeOut, c1InvokeErr));
171+
ts2.run(new EDTPrinter(ts2, c2InvokeOut, c2InvokeErr));
172+
173+
c2.dispose();
174+
175+
assertEquals(6, events1.size());
176+
assertOutputEvent(Source.STDOUT, globalOut, false, events1.get(0));
177+
assertOutputEvent(Source.STDERR, globalErr, false, events1.get(1));
178+
assertOutputEvent(Source.STDOUT, c1RunOut, true, events1.get(2));
179+
assertOutputEvent(Source.STDERR, c1RunErr, true, events1.get(3));
180+
assertOutputEvent(Source.STDOUT, c1InvokeOut, true, events1.get(4));
181+
assertOutputEvent(Source.STDERR, c1InvokeErr, true, events1.get(5));
182+
183+
assertEquals(6, events2.size());
184+
assertOutputEvent(Source.STDOUT, globalOut, false, events2.get(0));
185+
assertOutputEvent(Source.STDERR, globalErr, false, events2.get(1));
186+
assertOutputEvent(Source.STDOUT, c2RunOut, true, events2.get(2));
187+
assertOutputEvent(Source.STDERR, c2RunErr, true, events2.get(3));
188+
assertOutputEvent(Source.STDOUT, c2InvokeOut, true, events2.get(4));
189+
assertOutputEvent(Source.STDERR, c2InvokeErr, true, events2.get(5));
190+
}
191+
192+
// -- Helper methods --
193+
194+
private void assertOutputEvent(final Source source, final String output,
195+
final boolean contextual, final OutputEvent event)
196+
{
197+
assertEquals(source, event.getSource());
198+
assertEquals(output, event.getOutput());
199+
assertEquals(contextual, event.isContextual());
200+
}
201+
73202
// -- Helper classes --
74203

75204
@Plugin(type = ConsoleArgument.class, priority = Priority.HIGH_PRIORITY)
@@ -89,4 +218,64 @@ public void handle(final LinkedList<String> args) {
89218

90219
}
91220

221+
private static class OutputTracker implements OutputListener {
222+
223+
private final Collection<OutputEvent> events;
224+
225+
private OutputTracker(final Collection<OutputEvent> events) {
226+
this.events = events;
227+
}
228+
229+
@Override
230+
public void outputOccurred(final OutputEvent event) {
231+
events.add(event);
232+
}
233+
234+
}
235+
236+
private static class Printer implements Runnable {
237+
238+
private final String out;
239+
private final String err;
240+
241+
private Printer(final String out, final String err) {
242+
this.out = out;
243+
this.err = err;
244+
}
245+
246+
@Override
247+
public void run() {
248+
System.out.print(out);
249+
System.err.print(err);
250+
}
251+
252+
}
253+
254+
private static class EDTPrinter implements Runnable {
255+
256+
private final ThreadService ts;
257+
private final Printer p;
258+
259+
private EDTPrinter(final ThreadService ts, final String out,
260+
final String err)
261+
{
262+
this.ts = ts;
263+
p = new Printer(out, err);
264+
}
265+
266+
@Override
267+
public void run() {
268+
try {
269+
ts.invoke(p);
270+
}
271+
catch (final InvocationTargetException exc) {
272+
throw new RuntimeException(exc);
273+
}
274+
catch (final InterruptedException exc) {
275+
throw new RuntimeException(exc);
276+
}
277+
}
278+
279+
}
280+
92281
}

0 commit comments

Comments
 (0)