Skip to content

Commit

Permalink
Merge branch '__rultor'
Browse files Browse the repository at this point in the history
  • Loading branch information
rultor committed Aug 12, 2018
2 parents aef97b4 + 4e9209f commit 6c86827
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 16 deletions.
91 changes: 79 additions & 12 deletions src/main/java/io/zold/api/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,35 @@
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Path;
import org.cactoos.collection.Filtered;
import org.cactoos.iterable.IterableOf;
import org.cactoos.iterable.Joined;
import org.cactoos.iterable.Mapped;
import org.cactoos.iterable.Skipped;
import org.cactoos.list.ListOf;
import org.cactoos.scalar.CheckedScalar;
import org.cactoos.scalar.Or;
import org.cactoos.scalar.UncheckedScalar;
import org.cactoos.text.FormattedText;
import org.cactoos.text.SplitText;
import org.cactoos.text.TextOf;
import org.cactoos.text.UncheckedText;

/**
* Wallet.
*
* @since 0.1
* @todo #16:30min Merge method should update transactions
* in wallet's file and return concrete implementation not a fake one.
* Beware that tests should be refactored to take care of file cleanup
* after each case that merges wallets.
*/
@SuppressWarnings({"PMD.ShortMethodName", "PMD.TooManyMethods"})
public interface Wallet {
/**
* This wallet's ID: an unsigned 64-bit integer.
* @return This wallet's id
* @throws IOException If an IO error occurs
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
* @checkstyle MethodName (2 lines)
*/
long id() throws IOException;
Expand All @@ -63,8 +73,9 @@ public interface Wallet {
* same wallet, as identified by their {@link #id() id}.
* @param other Other wallet
* @return The merged wallet
* @throws IOException If an IO error occurs
*/
Wallet merge(Wallet other);
Wallet merge(Wallet other) throws IOException;

/**
* This wallet's ledger.
Expand All @@ -80,7 +91,6 @@ public interface Wallet {

/**
* A Fake {@link Wallet}.
*
* @since 1.0
*/
final class Fake implements Wallet {
Expand All @@ -90,13 +100,36 @@ final class Fake implements Wallet {
*/
private final long id;

/**
* Transactions.
*/
private final Iterable<Transaction> transactions;

/**
* Ctor.
*
* @param id The wallet id.
*/
public Fake(final long id) {
this(id, new IterableOf<>());
}

/**
* Ctor.
* @param id The wallet id.
* @param transactions Transactions.
*/
public Fake(final long id, final Transaction... transactions) {
this(id, new IterableOf<>(transactions));
}

/**
* Ctor.
* @param id The wallet id.
* @param transactions Transactions.
*/
public Fake(final long id, final Iterable<Transaction> transactions) {
this.id = id;
this.transactions = transactions;
}

@Override
Expand All @@ -116,7 +149,7 @@ public Wallet merge(final Wallet other) {

@Override
public Iterable<Transaction> ledger() {
return new IterableOf<>();
return this.transactions;
}

@Override
Expand Down Expand Up @@ -169,14 +202,48 @@ public void pay(final long amt, final long bnf) throws IOException {
}
}

// @todo #6:30min Implement merge method. This should merge this wallet
// with a copy of the same wallet. It should throw an error if a
// wallet is provided. Also add a unit test to replace
// WalletTest.mergeIsNotYetImplemented().
// @todo #16:30min Following transactions should be ignored according
// to the whitepaper:
// a) If the transaction is negative and its signature is not valid,
// it is ignored;
// b) If the transaction makes the balance of the wallet negative,
// it is ignored;
// c) If the transaction is positive and it’s absent in the paying
// wallet (which exists at the node), it’s ignored; If the paying
// wallet doesn’t exist at the node, the transaction is ignored;
@Override
public Wallet merge(final Wallet other) {
throw new UnsupportedOperationException(
"merge() not yet supported"
public Wallet merge(final Wallet other) throws IOException {
if (other.id() != this.id()) {
throw new IOException(
new UncheckedText(
new FormattedText(
"Wallet ID mismatch, ours is %d, theirs is %d",
other.id(),
this.id()
)
).asString()
);
}
final Iterable<Transaction> ledger = this.ledger();
final Iterable<Transaction> candidates = new Filtered<>(
incoming -> new Filtered<>(
origin -> new UncheckedScalar<>(
new Or(
() -> incoming.equals(origin),
() -> incoming.id() == origin.id()
&& incoming.bnf().equals(origin.bnf()),
() -> incoming.id() == origin.id()
&& incoming.amount() < 0L,
() -> incoming.prefix().equals(origin.prefix())
)
).value(),
ledger
).isEmpty(),
other.ledger()
);
return new Wallet.Fake(
this.id(),
new Joined<Transaction>(ledger, candidates)
);
}

Expand Down
100 changes: 96 additions & 4 deletions src/test/java/io/zold/api/WalletTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.cactoos.collection.CollectionOf;
import org.cactoos.list.ListOf;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
Expand All @@ -45,7 +46,9 @@
* @checkstyle JavadocMethodCheck (500 lines)
* @checkstyle JavadocVariableCheck (500 lines)
* @checkstyle MagicNumberCheck (500 lines)
* @checkstyle ClassDataAbstractionCouplingCheck (3 lines)
*/
@SuppressWarnings("PMD.TooManyMethods")
public final class WalletTest {

@Rule
Expand Down Expand Up @@ -94,10 +97,99 @@ public void pay() throws IOException {
);
}

@Test(expected = UnsupportedOperationException.class)
public void mergeIsNotYetImplemented() throws IOException {
new Wallet.File(this.folder.newFile().toPath()).merge(
new Wallet.File(this.folder.newFile().toPath())
@Test
public void mergesWallets() throws IOException {
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
//@checkstyle LineLengthCheck (1 lines)
new RtTransaction("abcd;2017-07-19T21:25:07Z;0000000000a72366;xxsQuJa9;98bb82c81735c4ee;")
)
);
MatcherAssert.assertThat(
new CollectionOf<>(merged.ledger()).size(),
new IsEqual<>(new CollectionOf<>(wallet.ledger()).size() + 1)
);
}

@Test
public void doesNotMergeWalletsWithDifferentId() throws IOException {
this.error.expect(IOException.class);
//@checkstyle LineLengthCheck (1 lines)
this.error.expectMessage("Wallet ID mismatch, ours is 123, theirs is 5124095577148911");
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
wallet.merge(new Wallet.Fake(123L));
}

@Test
public void doesNotMergeExistingTransactions() throws IOException {
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
//@checkstyle LineLengthCheck (1 lines)
new RtTransaction("003b;2017-07-19T21:25:07Z;0000000000a72366;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
new CollectionOf<>(merged.ledger()).size(),
new IsEqual<>(new CollectionOf<>(wallet.ledger()).size())
);
}

@Test
public void doesNotMergeTransactionsWithSameIdAndBnf() throws IOException {
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
//@checkstyle LineLengthCheck (1 lines)
new RtTransaction("003b;2017-07-18T21:25:07Z;0000000000a72366;xxxxuuuu;98bb82c81735c4ee;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
new CollectionOf<>(merged.ledger()).size(),
new IsEqual<>(new CollectionOf<>(wallet.ledger()).size())
);
}

@Test
public void doesNotMergeTransactionsWithSameIdAndNegativeAmount()
throws IOException {
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
//@checkstyle LineLengthCheck (1 lines)
new RtTransaction("003b;2017-07-18T21:25:07Z;ffffffffffa72366;xxxxuuuu;98bb82c81735c4ff;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
new CollectionOf<>(merged.ledger()).size(),
new IsEqual<>(new CollectionOf<>(wallet.ledger()).size())
);
}

@Test
public void doesNotMergeTransactionsWithSamePrefix() throws IOException {
final long id = 5124095577148911L;
final Wallet wallet = new Wallet.File(this.wallet(id));
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
//@checkstyle LineLengthCheck (1 lines)
new RtTransaction("0011;2017-07-18T21:25:07Z;0000000000a72366;xksQuJa9;99bb82c81735c4ee;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
new CollectionOf<>(merged.ledger()).size(),
new IsEqual<>(new CollectionOf<>(wallet.ledger()).size())
);
}

Expand Down

3 comments on commit 6c86827

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 6c86827 Aug 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 6-af7c6ffd disappeared from src/main/java/io/zold/api/Wallet.java, that's why I closed #16. Please, remember that the puzzle was not necessarily removed in this particular commit. Maybe it happened earlier, but we discovered this fact only now.

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 6c86827 Aug 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 16-e32ec38b discovered in src/main/java/io/zold/api/Wallet.java and submitted as #75. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 6c86827 Aug 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 16-27c16652 discovered in src/main/java/io/zold/api/Wallet.java and submitted as #76. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.