/* * Copyright (C) 2012 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ /* * Copyright (C) 2012 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ /* * Copyright (C) 2012 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.crsh.shell.impl.command; import org.crsh.cli.Command; import org.crsh.command.BaseCommand; import org.crsh.command.Pipe; import org.crsh.shell.AbstractShellTestCase; import org.crsh.shell.ErrorKind; import javax.naming.CommunicationException; import javax.naming.NamingException; import javax.naming.SizeLimitExceededException; import javax.naming.directory.AttributeInUseException; import javax.naming.directory.SchemaViolationException; import java.io.IOException; import java.util.concurrent.atomic.AtomicInteger; /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ public class PipeLineFailureTestCase extends AbstractShellTestCase { public static class Counter extends Pipe<String, Object> { /** . */ final AtomicInteger openCount = new AtomicInteger(), provideCound = new AtomicInteger(), flushCount = new AtomicInteger(), closeCount = new AtomicInteger(); public void open() throws Exception { openCount.incrementAndGet(); } public void provide(String element) throws Exception { provideCound.incrementAndGet(); } public void flush() throws IOException { flushCount.incrementAndGet(); } public void close() throws Exception { closeCount.incrementAndGet(); } public void reset() { openCount.set(0); provideCound.set(0); flushCount.set(0); closeCount.set(0); } } public static class CallbackCounterCommand extends BaseCommand { public static Class<CallbackCounterCommand> reset() { counter.reset(); return CallbackCounterCommand.class; } /** . */ public static Counter counter = new Counter(); @Command public Pipe<String, Object> main() { return counter; } } public static class FailOnInvoke extends BaseCommand { /** . */ static final AtomicInteger count = new AtomicInteger(); public static Class<FailOnInvoke> reset() { count.set(0); return FailOnInvoke.class; } @Command public Pipe<String, Object> main() throws Exception { count.incrementAndGet(); throw new SchemaViolationException(); } } public static class FailOnOpen extends BaseCommand { public static Class<FailOnOpen> reset() { counter.reset(); return FailOnOpen.class; } /** . */ public static Counter counter = new Counter() { @Override public void open() throws Exception { super.open(); throw new AttributeInUseException(); } }; @Command public Pipe<String, Object> main() { return counter; } } public static class FailOnProvide extends BaseCommand { public static Class<FailOnProvide> reset() { counter.reset(); return FailOnProvide.class; } /** . */ public static Counter counter = new Counter() { @Override public void provide(String element) throws Exception { super.provide(element); throw new CommunicationException(); } }; @Command public Pipe<String, Object> main() { return counter; } } public static class FailOnClose extends BaseCommand { public static Class<FailOnClose> reset() { counter.reset(); return FailOnClose.class; } /** . */ public static Counter counter = new Counter() { @Override public void close() throws Exception { super.close(); throw new SizeLimitExceededException(); } }; @Command public Pipe<String, Object> main() { return counter; } } public static class Producer extends BaseCommand { public static Class<Producer> reset() { count.set(0); return Producer.class; } /** . */ static final AtomicInteger count = new AtomicInteger(); @Command public void main(org.crsh.command.InvocationContext<String> context) throws Exception { count.incrementAndGet(); context.provide("foo"); } } public void testFailOnInvokePipe() { lifeCycle.bindClass("command", FailOnInvoke.reset()); assertError("command", ErrorKind.EVALUATION, SchemaViolationException.class); assertEquals(1, FailOnInvoke.count.get()); } public void testFailOnInvokePipeToPipe() { lifeCycle.bindClass("producer", FailOnInvoke.reset()); lifeCycle.bindClass("consumer", CallbackCounterCommand.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SchemaViolationException.class); assertEquals(1, FailOnInvoke.count.get()); assertEquals(1, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); assertEquals(1, CallbackCounterCommand.counter.flushCount.get()); assertEquals(1, CallbackCounterCommand.counter.closeCount.get()); } public void testPipeToFailOnInvokePipe() { lifeCycle.bindClass("producer", CallbackCounterCommand.reset()); lifeCycle.bindClass("consumer", FailOnInvoke.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SchemaViolationException.class); assertEquals(1, FailOnInvoke.count.get()); assertEquals(0, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); assertEquals(0, CallbackCounterCommand.counter.flushCount.get()); assertEquals(0, CallbackCounterCommand.counter.closeCount.get()); } public void testProducerToFailOnInvokePipe() { lifeCycle.bindClass("producer", Producer.reset()); lifeCycle.bindClass("consumer", FailOnInvoke.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SchemaViolationException.class); assertEquals(1, FailOnInvoke.count.get()); assertEquals(0, Producer.count.get()); } public void testFailOnOpenPipe() { lifeCycle.bindClass("command", FailOnOpen.reset()); assertError("command", ErrorKind.EVALUATION, AttributeInUseException.class); assertEquals(1, FailOnOpen.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(0, FailOnOpen.counter.flushCount.get()); assertEquals(0, FailOnOpen.counter.closeCount.get()); } public void testFailOnOpenPipeToPipe() { lifeCycle.bindClass("producer", FailOnOpen.reset()); lifeCycle.bindClass("consumer", CallbackCounterCommand.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, AttributeInUseException.class); assertEquals(1, FailOnOpen.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(0, FailOnOpen.counter.flushCount.get()); assertEquals(0, FailOnOpen.counter.closeCount.get()); assertEquals(1, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); assertEquals(1, CallbackCounterCommand.counter.flushCount.get()); assertEquals(1, CallbackCounterCommand.counter.closeCount.get()); } public void testPipeToFailOnOpenPipe() { lifeCycle.bindClass("producer", CallbackCounterCommand.reset()); lifeCycle.bindClass("consumer", FailOnOpen.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, AttributeInUseException.class); assertEquals(1, FailOnOpen.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(0, FailOnOpen.counter.flushCount.get()); assertEquals(0, FailOnOpen.counter.closeCount.get()); assertEquals(0, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); assertEquals(0, CallbackCounterCommand.counter.flushCount.get()); assertEquals(0, CallbackCounterCommand.counter.closeCount.get()); } public void testProducerToFailOnOpenPipe() { lifeCycle.bindClass("producer", Producer.reset()); lifeCycle.bindClass("consumer", FailOnOpen.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, AttributeInUseException.class); assertEquals(0, Producer.count.get()); assertEquals(1, FailOnOpen.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(0, FailOnOpen.counter.flushCount.get()); assertEquals(0, FailOnOpen.counter.closeCount.get()); } public void testProducerToFailOnProvidePipe() { lifeCycle.bindClass("producer", Producer.reset()); lifeCycle.bindClass("consumer", FailOnProvide.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, CommunicationException.class); assertEquals(1, Producer.count.get()); assertEquals(1, FailOnProvide.counter.openCount.get()); assertEquals(1, FailOnProvide.counter.provideCound.get()); assertEquals(1, FailOnProvide.counter.flushCount.get()); assertEquals(1, FailOnProvide.counter.closeCount.get()); } public void testProducerToFailOnClosePipe() { lifeCycle.bindClass("producer", Producer.reset()); lifeCycle.bindClass("consumer", FailOnClose.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SizeLimitExceededException.class); assertEquals(1, Producer.count.get()); assertEquals(1, FailOnClose.counter.openCount.get()); assertEquals(1, FailOnClose.counter.provideCound.get()); assertEquals(1, FailOnClose.counter.flushCount.get()); assertEquals(1, FailOnClose.counter.closeCount.get()); } public void testFailOnClosePipe() { lifeCycle.bindClass("command", FailOnClose.reset()); assertError("command", ErrorKind.EVALUATION, SizeLimitExceededException.class); assertEquals(1, FailOnClose.counter.openCount.get()); assertEquals(0, FailOnClose.counter.provideCound.get()); assertEquals(1, FailOnClose.counter.flushCount.get()); assertEquals(1, FailOnClose.counter.closeCount.get()); } public void testFailOnClosePipeToPipe() { lifeCycle.bindClass("producer", FailOnClose.reset()); lifeCycle.bindClass("consumer", CallbackCounterCommand.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SizeLimitExceededException.class); assertEquals(1, FailOnClose.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(1, FailOnClose.counter.flushCount.get()); assertEquals(1, FailOnClose.counter.closeCount.get()); assertEquals(1, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); // assertEquals(1, CallbackCounterCommand.counter.flushCount.get()); <-- not passing at the moment assertEquals(1, CallbackCounterCommand.counter.closeCount.get()); } public void testPipeToFailOnClosePipe() { lifeCycle.bindClass("producer", CallbackCounterCommand.reset()); lifeCycle.bindClass("consumer", FailOnClose.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SizeLimitExceededException.class); assertEquals(1, CallbackCounterCommand.counter.openCount.get()); assertEquals(0, CallbackCounterCommand.counter.provideCound.get()); assertEquals(1, CallbackCounterCommand.counter.flushCount.get()); assertEquals(1, CallbackCounterCommand.counter.closeCount.get()); assertEquals(1, FailOnClose.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); // assertEquals(1 , FailDuringClose.counter.flushCount.get()); <-- not passing at the moment assertEquals(1, FailOnClose.counter.closeCount.get()); } public void testFailOnClosePipeToFailOnOpenPipe() { lifeCycle.bindClass("producer", FailOnOpen.reset()); lifeCycle.bindClass("consumer", FailOnClose.reset()); assertError("producer | consumer", ErrorKind.EVALUATION, SizeLimitExceededException.class); assertEquals(1, FailOnOpen.counter.openCount.get()); assertEquals(0, FailOnOpen.counter.provideCound.get()); assertEquals(0, FailOnOpen.counter.flushCount.get()); assertEquals(0, FailOnOpen.counter.closeCount.get()); assertEquals(1, FailOnClose.counter.openCount.get()); assertEquals(0, FailOnClose.counter.provideCound.get()); assertEquals(1, FailOnClose.counter.flushCount.get()); assertEquals(1, FailOnClose.counter.closeCount.get()); } }