diff --git a/src/main/java/io/wring/agents/Exec.java b/src/main/java/io/wring/agents/Exec.java index 8e9babc..20c4aba 100644 --- a/src/main/java/io/wring/agents/Exec.java +++ b/src/main/java/io/wring/agents/Exec.java @@ -33,6 +33,7 @@ import com.jcabi.log.Logger; import com.jcabi.manifests.Manifests; import io.sentry.Sentry; +import io.wring.model.Errors; import io.wring.model.Events; import io.wring.model.Pipe; import java.io.ByteArrayOutputStream; @@ -52,14 +53,20 @@ * One execution. * * @author Yegor Bugayenko (yegor256@gmail.com) + * @author Paulo Lobo (pauloeduardolobo@gmail.com) * @version $Id$ * @since 0.13 - * @todo #72:30min Errors occurred during execution must be saved and later + * @todo #76:30min Errors occurred during execution must be saved and later * listed to user in a page. User should be able to mark errors as `read` * in this page. Wire Error and Errors implementations in Exec flow so - * these errors are properly saved once they happen. Cover this with tests. + * these errors are properly saved once they happen and remove + * Exec(final Agent agt, final Events evt, final Pipe ppe) constructor so + * errors is injected in Exec every time. Then remove Singularfield and + * UnusedPrivateField check ignores below and uncomment tests for error + * registering in ExecTest.registerErrors. * @checkstyle ClassDataAbstractionCouplingCheck (500 lines) */ +@SuppressWarnings({"PMD.SingularField", "PMD.UnusedPrivateField"}) final class Exec { /** @@ -77,6 +84,11 @@ final class Exec { */ private final transient Pipe pipe; + /** + * Errors. + */ + private final Errors errors; + /** * Ctor. * @param agt Agent @@ -84,9 +96,22 @@ final class Exec { * @param ppe Pipe */ Exec(final Agent agt, final Events evt, final Pipe ppe) { + this(agt, evt, ppe, new Errors.Simple()); + } + + /** + * Ctor. + * @param agt Agent + * @param evt Events + * @param ppe Pipe + * @param err Errors + * @checkstyle ParameterNumberCheck (2 lines) + */ + Exec(final Agent agt, final Events evt, final Pipe ppe, final Errors err) { this.agent = agt; this.events = evt; this.pipe = ppe; + this.errors = err; } /** diff --git a/src/main/java/io/wring/model/Error.java b/src/main/java/io/wring/model/Error.java index 76dfbe9..b8023ae 100644 --- a/src/main/java/io/wring/model/Error.java +++ b/src/main/java/io/wring/model/Error.java @@ -53,4 +53,44 @@ public interface Error { * @throws IOException If fails */ void delete() throws IOException; + + /** + * Simple Error implementation. + * @todo #76:30min Implement Error.Simple asXembly and delete method. + * asXembly must return a xembly directive with element 'error' and + * child elements 'title' + * and 'description'. + */ + final class Simple implements Error { + + /** + * Error title. + */ + private final String title; + + /** + * Error description. + */ + private final String description; + + /** + * Constructor. + * @param title Title + * @param description Description + */ + public Simple(final String title, final String description) { + this.title = title; + this.description = description; + } + + @Override + public Iterable asXembly() throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + + @Override + public void delete() throws IOException { + throw new UnsupportedOperationException("delete() not implemented"); + } + } } diff --git a/src/main/java/io/wring/model/Errors.java b/src/main/java/io/wring/model/Errors.java index 7ac72c7..53b3645 100644 --- a/src/main/java/io/wring/model/Errors.java +++ b/src/main/java/io/wring/model/Errors.java @@ -30,6 +30,8 @@ package io.wring.model; import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; /** * Errors. @@ -54,4 +56,32 @@ public interface Errors { * @throws IOException If fails */ void register(String title, String description); + + /** + * Simple implementation of Error repo. + */ + final class Simple implements Errors { + + /** + * Errors. + */ + private final Collection errors; + + /** + * Constructor. + */ + public Simple() { + this.errors = new ArrayList<>(0); + } + + @Override + public Iterable iterate() { + return this.errors; + } + + @Override + public void register(final String title, final String description) { + this.errors.add(new Error.Simple(title, description)); + } + } } diff --git a/src/test/java/io/wring/agents/ExecTest.java b/src/test/java/io/wring/agents/ExecTest.java index 1f44aca..08af519 100644 --- a/src/test/java/io/wring/agents/ExecTest.java +++ b/src/test/java/io/wring/agents/ExecTest.java @@ -30,9 +30,14 @@ package io.wring.agents; import io.wring.fake.FkPipe; +import io.wring.model.Errors; import io.wring.model.Events; import java.io.IOException; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; +import org.hamcrest.collection.IsIterableWithSize; +import org.hamcrest.core.IsEqual; +import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; import org.mockito.hamcrest.MockitoHamcrest; @@ -40,6 +45,7 @@ /** * Test case for {@link Exec}. * @author Yegor Bugayenko (yegor256@gmail.com) + * @author Paulo Lobo (pauloeduardolobo@gmail.com) * @version $Id$ * @since 0.13 */ @@ -69,4 +75,25 @@ public void catchesExceptions() throws Exception { ); } + /** + * Exec can register an error. + * @throws Exception If some problem inside + */ + @Test + @Ignore + public void registerErrors() throws Exception { + final Agent agent = Mockito.mock(Agent.class); + final Events events = Mockito.mock(Events.class); + final Errors errors = new Errors.Simple(); + Mockito.doThrow(new IOException("")).when(agent).push(events); + new Exec(agent, events, new FkPipe(), errors).run(); + MatcherAssert.assertThat( + "Could not register error", + errors.iterate(), + new IsIterableWithSize<>( + new IsEqual<>(1) + ) + ); + } + }