From 7010a2873917f9964200322847ae9b402fd4837b Mon Sep 17 00:00:00 2001 From: Carlos Miranda Date: Thu, 9 Aug 2018 11:26:29 +0800 Subject: [PATCH] #38 Initial implementation of RtRemote --- pom.xml | 17 ++++ src/main/java/io/zold/api/RtRemote.java | 95 ++++++++++++++++++++++ src/test/java/io/zold/api/NetworkTest.java | 6 +- src/test/java/io/zold/api/RemoteTest.java | 82 +++++++++++++++++++ 4 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 src/main/java/io/zold/api/RtRemote.java create mode 100644 src/test/java/io/zold/api/RemoteTest.java diff --git a/pom.xml b/pom.xml index 6811152..7fc31f2 100644 --- a/pom.xml +++ b/pom.xml @@ -214,5 +214,22 @@ SOFTWARE. 2.4.8 test + + com.jcabi + jcabi-http + 1.17.2 + + + com.sun.grizzly + grizzly-servlet-webserver + 1.9.65 + test + + + org.glassfish.jersey.core + jersey-common + 2.27 + test + diff --git a/src/main/java/io/zold/api/RtRemote.java b/src/main/java/io/zold/api/RtRemote.java new file mode 100644 index 0000000..3382c00 --- /dev/null +++ b/src/main/java/io/zold/api/RtRemote.java @@ -0,0 +1,95 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.zold.api; + +import com.jcabi.http.Request; +import com.jcabi.http.request.JdkRequest; +import java.io.IOException; +import org.cactoos.text.FormattedText; +import org.cactoos.text.UncheckedText; + +/** + * Default implementation of {@link Remote}. + * @since 1.0 + */ +public final class RtRemote implements Remote { + + /** + * Request to Node. + */ + private final Request req; + + /** + * Ctor. + * @param host Remote host + * @param port Remote port + */ + public RtRemote(final String host, final int port) { + this.req = new JdkRequest( + new UncheckedText( + new FormattedText("http://%s:%d", host, port) + ).asString() + ); + } + + // @todo #38:30min Let us Implement RtRemote.score() here. When implemented, + // the unit test RemoteTest.scoreIsNotYetImplemented should be removed and + // replaced with an appropriate unit test. + @Override + public Score score() { + throw new UnsupportedOperationException("score() not yet supported"); + } + + // @todo #38:30min Implementation of push() is currently incomplete. We need + // to read the entire contents of Wallet and include it in the request body + // before fetching. Right now there's no way for us to do that. What I'm + // thinking is to add a new method in Wallet interface, Wallet.contents(), + // which reads the entire content of the Wallet and returns it. Then pass + // that the request body here. + @Override + public void push(final Wallet wallet) { + try { + this.req.uri().path( + new UncheckedText( + new FormattedText( + "wallets/%016x", wallet.id() + ) + ).asString() + ).back().method("PUT") + .body().set("zold") + .back() + .fetch(); + } catch (final IOException ex) { + throw new IllegalStateException(ex); + } + } + + // @todo #38:30min Let us Implement RtRemote.pull() here. When implemented, + // the unit test RemoteTest.scoreIsNotYetImplemented should be removed and + // replaced with an appropriate unit test. + @Override + public Wallet pull(final long id) { + throw new UnsupportedOperationException("pull() not yet supported"); + } +} diff --git a/src/test/java/io/zold/api/NetworkTest.java b/src/test/java/io/zold/api/NetworkTest.java index dc7a969..22486f5 100644 --- a/src/test/java/io/zold/api/NetworkTest.java +++ b/src/test/java/io/zold/api/NetworkTest.java @@ -34,16 +34,12 @@ * Test case for {@link Network}. * * @since 0.1 - * @todo #5:30min Implement Remote interface. Remote Interface must be - * implemented because Network depends on Remote behavior. Network.pull - * needs to search all remotes for some wallet id and merge all found - * wallets; Network.push must push a wallet to a remote based in remote. * @checkstyle JavadocMethodCheck (500 lines) */ public final class NetworkTest { @Test - public void pushWalletToAllRemotes() { + public void pushWalletToAllRemotes() throws IOException { final Remote highremote = Mockito.mock(Remote.class); final Remote lowremote = Mockito.mock(Remote.class); final Wallet wallet = Mockito.mock(Wallet.class); diff --git a/src/test/java/io/zold/api/RemoteTest.java b/src/test/java/io/zold/api/RemoteTest.java new file mode 100644 index 0000000..df39c23 --- /dev/null +++ b/src/test/java/io/zold/api/RemoteTest.java @@ -0,0 +1,82 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2018 Yegor Bugayenko + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package io.zold.api; + +import com.jcabi.http.mock.MkAnswer; +import com.jcabi.http.mock.MkContainer; +import com.jcabi.http.mock.MkGrizzlyContainer; +import com.jcabi.http.mock.MkQuery; +import java.io.IOException; +import java.net.HttpURLConnection; +import org.hamcrest.MatcherAssert; +import org.hamcrest.Matchers; +import org.junit.Test; + +/** + * Test case for {@link Remote}. + * @since 1.0 + * @checkstyle JavadocMethod (500 lines) + */ +public final class RemoteTest { + + // @todo #38:30min RtRemote should be able to handle different HTTP response + // codes. Here we test HTTP 202 Accepted. Other possible responses as per + // the white paper are 400 (if data is corrupt), 402 (if taxes are unpaid), + // and 304 (if content is the same as that in the node). Let's handle + // those responses and create new tests as well. + @Test + public void pushesWallet() throws IOException { + try ( + final MkContainer container = new MkGrizzlyContainer().next( + new MkAnswer.Simple(HttpURLConnection.HTTP_ACCEPTED) + ).start() + ) { + final long id = 1000L; + new RtRemote( + container.home().getHost(), container.home().getPort() + ).push(new Wallet.Fake(id)); + final MkQuery query = container.take(); + MatcherAssert.assertThat( + query.uri().getPath(), + Matchers.containsString( + "wallets/00000000000003e8" + ) + ); + MatcherAssert.assertThat( + query.body(), + Matchers.containsString("zold") + ); + } + } + + @Test(expected = UnsupportedOperationException.class) + public void scoreIsNotYetImplemented() { + new RtRemote("foo", 1).score(); + } + + @Test(expected = UnsupportedOperationException.class) + public void pullIsNotYetImplemented() { + new RtRemote("bar", 1).pull(1); + } +}