Skip to content

Commit

Permalink
zold-io#16 merge method implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Vatavuk committed Aug 8, 2018
1 parent 345f962 commit 233dd33
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 8 deletions.
45 changes: 39 additions & 6 deletions src/main/java/io/zold/api/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ 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 @@ -70,6 +71,7 @@ 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) throws IOException;

Expand All @@ -90,6 +92,9 @@ final class Fake implements Wallet {
*/
private final long id;

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

/**
Expand All @@ -100,10 +105,20 @@ 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;
Expand Down Expand Up @@ -175,6 +190,21 @@ public void pay(final long amt, final long bnf) throws IOException {
}

@Override
// @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;
//
// @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.
//
public Wallet merge(final Wallet other) throws IOException {
if (other.id() != this.id()) {
throw new IOException(
Expand All @@ -188,16 +218,17 @@ public Wallet merge(final Wallet other) throws IOException {
);
}
final Iterable<Transaction> ledger = this.ledger();
final Collection<Transaction> candidates = new ArrayList<>();
final Collection<Transaction> candidates = new ArrayList<>(0);
for (final Transaction remote : other.ledger()) {
final Collection<Transaction> filtered =
new Filtered<>(
input -> new UncheckedScalar<>(
new Or(
() -> remote.equals(input),
() -> remote.id() == input.id() &&
remote.bnf() == input.bnf(),
() -> remote.id() == input.id() && remote.amount() < 0L,
() -> remote.id() == input.id()
&& remote.bnf().equals(input.bnf()),
() -> remote.id() == input.id()
&& remote.amount() < 0L,
() -> remote.prefix().equals(input.prefix())
)
).value(),
Expand All @@ -207,10 +238,12 @@ public Wallet merge(final Wallet other) throws IOException {
candidates.add(remote);
}
}
return new Wallet.Fake(this.id(), new Joined<>(ledger, candidates));
return new Wallet.Fake(
this.id(),
new Joined<Transaction>(ledger, candidates)
);
}


@Override
public Iterable<Transaction> ledger() {
return new Mapped<>(
Expand Down
40 changes: 38 additions & 2 deletions src/test/java/io/zold/api/WalletTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
* @checkstyle JavadocMethodCheck (500 lines)
* @checkstyle JavadocVariableCheck (500 lines)
* @checkstyle MagicNumberCheck (500 lines)
* @checkstyle LineLengthCheck (500 lines)
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines)
*/
@SuppressWarnings("PMD.TooManyMethods")
public final class WalletTest {

@Rule
Expand Down Expand Up @@ -127,7 +130,7 @@ public void doesNotMergeExistingTransactions() throws IOException {
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
new RtTransaction("003b;2017-07-19T21:25:07Z;ffffffffffa72367;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...")
new RtTransaction("003b;2017-07-19T21:25:07Z;0000000000a72366;xksQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
Expand All @@ -143,7 +146,40 @@ public void doesNotMergeTransactionsWithSameIdAndBnf() throws IOException {
final Wallet merged = wallet.merge(
new Wallet.Fake(
id,
new RtTransaction("003b;2017-07-18T21:25:07Z;ffffffffffa72367;xxsQuJa9;98bb82c81735c4ee;For food;QCuLuVr4...")
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,
new RtTransaction("003b;2017-07-18T21:25:07Z;ffffffffffa72366;xxxxuuuu;98bb82c81735c4ee;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,
new RtTransaction("0011;2017-07-18T21:25:07Z;0000000000a72366;xksQuJa9;99bb82c81735c4ee;For food;QCuLuVr4...")
)
);
MatcherAssert.assertThat(
Expand Down

0 comments on commit 233dd33

Please sign in to comment.