diff --git a/src/main/java/io/zold/api/WalletsIn.java b/src/main/java/io/zold/api/WalletsIn.java index 8e32d6e..4ce5351 100644 --- a/src/main/java/io/zold/api/WalletsIn.java +++ b/src/main/java/io/zold/api/WalletsIn.java @@ -36,11 +36,12 @@ import org.cactoos.iterable.Mapped; import org.cactoos.scalar.IoCheckedScalar; import org.cactoos.scalar.SolidScalar; +import org.cactoos.text.FormattedText; import org.cactoos.text.JoinedText; +import org.cactoos.text.UncheckedText; /** * Wallets in path. - * * @since 0.1 * @checkstyle ClassDataAbstractionCoupling (2 lines) */ @@ -61,6 +62,11 @@ public final class WalletsIn implements Wallets { */ private final String ext; + /** + * Randomizer. + */ + private final Random random; + /** * Ctor. * @param pth Path with wallets @@ -68,26 +74,43 @@ public final class WalletsIn implements Wallets { public WalletsIn(final Path pth) { this( () -> pth, - "z" + "z", + new Random() + ); + } + + /** + * Ctor. + * @param pth Path with wallets + * @param random Randomizer + */ + public WalletsIn(final Path pth, final Random random) { + this( + () -> pth, + "z", + random ); } /** * Ctor. * @param pth Path with wallets + * @param random Randomizer * @param ext Wallets file extension */ - public WalletsIn(final Scalar pth, final String ext) { + public WalletsIn(final Scalar pth, final String ext, + final Random random) { this.path = new IoCheckedScalar<>( new SolidScalar<>(pth) ); this.filter = new IoCheckedFunc( (file) -> file.toFile().isFile() && FileSystems.getDefault() - .getPathMatcher(String.format("glob:**.%s", ext)) - .matches(file) + .getPathMatcher(String.format("glob:**.%s", ext)) + .matches(file) ); this.ext = ext; + this.random = random; } // @todo #12:30min Create the new wallet in the path with all wallets. @@ -98,10 +121,20 @@ public Wallet create() throws IOException { final Path wpth = this.path.value().resolve( new JoinedText( ".", - Long.toHexString(new Random().nextLong()), + Long.toHexString(this.random.nextLong()), this.ext ).asString() ); + if (wpth.toFile().exists()) { + throw new IOException( + new UncheckedText( + new FormattedText( + "Wallet in path %s already exists", + wpth.toUri().getPath() + ) + ).asString() + ); + } Files.createFile(wpth); return new Wallet.File(wpth); } diff --git a/src/test/java/io/zold/api/WalletsInTest.java b/src/test/java/io/zold/api/WalletsInTest.java index 826daf1..5e53c4e 100644 --- a/src/test/java/io/zold/api/WalletsInTest.java +++ b/src/test/java/io/zold/api/WalletsInTest.java @@ -26,10 +26,10 @@ import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Random; import org.hamcrest.MatcherAssert; import org.hamcrest.collection.IsIterableWithSize; import org.hamcrest.core.IsEqual; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; @@ -81,19 +81,43 @@ public void createsWalletInFolder() throws IOException { ); } - // @todo #12:30min Ensure creating a new wallet in a path where a - // wallet with the same id throws an exception and does not - // overwrite the existing one. This could be done using by - // using a Random object with a similar seed in WalletsIn - // and creating a wallet twice for example. When it is done - // enable the test. @Test - @Ignore("see todo above") - public void doesNotOverwriteExistingWallet() throws IOException { + public void doesNotOverwriteExistingWallet() throws Exception { final Path path = this.folder.newFolder().toPath(); - new WalletsIn(path).create(); + final Random random = new FkRandom(16725L); + new WalletsIn(path, random).create(); this.thrown.expect(IOException.class); - this.thrown.expectMessage("duplicate"); - new WalletsIn(path).create(); + this.thrown.expectMessage("already exists"); + new WalletsIn(path, random).create(); + } + + /** + * Fake randomizer that returns the same value each time. + */ + private static class FkRandom extends Random { + + /** + * Serial version. + */ + private static final long serialVersionUID = 2905348968220129619L; + + /** + * Value that represents a random number. + */ + private final long value; + + /** + * Ctor. + * @param val Value that represents a random number. + */ + FkRandom(final long val) { + super(); + this.value = val; + } + + @Override + public long nextLong() { + return this.value; + } } }