Added tests for DefaultMessageListener and ProofOfWorkService
and some minor improvements
This commit is contained in:
parent
e4a69f42b0
commit
f71671e04a
@ -5,10 +5,10 @@ import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.PlaintextHolder;
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey;
|
||||
import ch.dissem.bitmessage.ports.Cryptography;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkEngine;
|
||||
import ch.dissem.bitmessage.ports.ProofOfWorkRepository;
|
||||
import ch.dissem.bitmessage.ports.Cryptography;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -61,16 +61,14 @@ public class ProofOfWorkService implements ProofOfWorkEngine.Callback, InternalC
|
||||
public void onNonceCalculated(byte[] initialHash, byte[] nonce) {
|
||||
ObjectMessage object = powRepo.getItem(initialHash).object;
|
||||
object.setNonce(nonce);
|
||||
// messageCallback.proofOfWorkCompleted(payload);
|
||||
Plaintext plaintext = messageRepo.getMessage(initialHash);
|
||||
if (plaintext != null) {
|
||||
plaintext.setInventoryVector(object.getInventoryVector());
|
||||
messageRepo.save(plaintext);
|
||||
}
|
||||
ctx.getInventory().storeObject(object);
|
||||
ctx.getProofOfWorkRepository().removeObject(initialHash);
|
||||
powRepo.removeObject(initialHash);
|
||||
ctx.getNetworkHandler().offer(object.getInventoryVector());
|
||||
// messageCallback.messageOffered(payload, object.getInventoryVector());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -196,7 +196,7 @@ public class Factory {
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectPayload getBroadcast(Plaintext plaintext) {
|
||||
public static Broadcast getBroadcast(Plaintext plaintext) {
|
||||
BitmessageAddress sendingAddress = plaintext.getFrom();
|
||||
if (sendingAddress.getVersion() < 4) {
|
||||
return new V4Broadcast(sendingAddress, plaintext);
|
||||
|
@ -19,16 +19,14 @@ package ch.dissem.bitmessage.utils;
|
||||
import ch.dissem.bitmessage.ports.Cryptography;
|
||||
|
||||
/**
|
||||
* Created by chris on 20.07.15.
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class Singleton {
|
||||
private static Cryptography cryptography;
|
||||
|
||||
public static void initialize(Cryptography cryptography) {
|
||||
synchronized (Singleton.class) {
|
||||
if (Singleton.cryptography == null) {
|
||||
Singleton.cryptography = cryptography;
|
||||
}
|
||||
Singleton.cryptography = cryptography;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,12 @@ import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.utils.MessageMatchers;
|
||||
import ch.dissem.bitmessage.utils.Singleton;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -50,10 +52,7 @@ public class BitmessageContextTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Field field = Singleton.class.getDeclaredField("cryptography");
|
||||
field.setAccessible(true);
|
||||
field.set(null, null);
|
||||
|
||||
Singleton.initialize(null);
|
||||
listener = mock(BitmessageContext.Listener.class);
|
||||
ctx = new BitmessageContext.Builder()
|
||||
.addressRepo(mock(AddressRepository.class))
|
||||
@ -93,6 +92,51 @@ public class BitmessageContextTest {
|
||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureV2PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
||||
BitmessageAddress contact = new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT");
|
||||
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
||||
.thenReturn(Collections.singletonList(
|
||||
TestUtils.loadObjectMessage(2, "V2Pubkey.payload")
|
||||
));
|
||||
|
||||
ctx.addContact(contact);
|
||||
|
||||
verify(ctx.addresses(), atLeastOnce()).save(contact);
|
||||
verify(ctx.internals().getProofOfWorkEngine(), never())
|
||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureV4PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
||||
BitmessageAddress contact = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
||||
.thenReturn(Collections.singletonList(
|
||||
TestUtils.loadObjectMessage(2, "V4Pubkey.payload")
|
||||
));
|
||||
final BitmessageAddress stored = new BitmessageAddress(contact.getAddress());
|
||||
stored.setAlias("Test");
|
||||
when(ctx.addresses().getAddress(contact.getAddress())).thenReturn(stored);
|
||||
|
||||
ctx.addContact(contact);
|
||||
|
||||
verify(ctx.addresses(), atLeastOnce()).save(argThat(new BaseMatcher<BitmessageAddress>() {
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
return item instanceof BitmessageAddress
|
||||
&& ((BitmessageAddress) item).getPubkey() != null
|
||||
&& stored.getAlias().equals(((BitmessageAddress) item).getAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("pubkey must not be null and alias must be ").appendValue(stored.getAlias());
|
||||
}
|
||||
}));
|
||||
verify(ctx.internals().getProofOfWorkEngine(), never())
|
||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureSubscriptionIsAddedAndExistingBroadcastsRetrieved() throws Exception {
|
||||
BitmessageAddress address = new BitmessageAddress("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ");
|
||||
|
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.bitmessage;
|
||||
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.Broadcast;
|
||||
import ch.dissem.bitmessage.entity.payload.GetPubkey;
|
||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
||||
import ch.dissem.bitmessage.factory.Factory;
|
||||
import ch.dissem.bitmessage.ports.AddressRepository;
|
||||
import ch.dissem.bitmessage.ports.MessageRepository;
|
||||
import ch.dissem.bitmessage.utils.Singleton;
|
||||
import ch.dissem.bitmessage.utils.TestBase;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Status.PUBKEY_REQUESTED;
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.BROADCAST;
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static ch.dissem.bitmessage.utils.MessageMatchers.plaintext;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class DefaultMessageListenerTest extends TestBase {
|
||||
@Mock
|
||||
private AddressRepository addressRepo;
|
||||
@Mock
|
||||
private MessageRepository messageRepo;
|
||||
|
||||
private InternalContext ctx;
|
||||
private DefaultMessageListener listener;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
ctx = mock(InternalContext.class);
|
||||
Singleton.initialize(new BouncyCryptography());
|
||||
when(ctx.getAddressRepository()).thenReturn(addressRepo);
|
||||
when(ctx.getMessageRepository()).thenReturn(messageRepo);
|
||||
|
||||
listener = new DefaultMessageListener(ctx, mock(BitmessageContext.Listener.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensurePubkeyIsSentOnRequest() throws Exception {
|
||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
when(addressRepo.findIdentity(any(byte[].class)))
|
||||
.thenReturn(identity);
|
||||
listener.receive(new ObjectMessage.Builder()
|
||||
.stream(2)
|
||||
.payload(new GetPubkey(new BitmessageAddress("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8")))
|
||||
.build());
|
||||
verify(ctx).sendPubkey(eq(identity), eq(2L));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureIncomingPubkeyIsAddedToContact() throws Exception {
|
||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
BitmessageAddress contact = new BitmessageAddress(identity.getAddress());
|
||||
when(addressRepo.findContact(any(byte[].class)))
|
||||
.thenReturn(contact);
|
||||
when(messageRepo.findMessages(eq(PUBKEY_REQUESTED), eq(contact)))
|
||||
.thenReturn(Collections.singletonList(
|
||||
new Plaintext.Builder(MSG).from(identity).to(contact).message("S", "T").build()
|
||||
));
|
||||
|
||||
ObjectMessage objectMessage = new ObjectMessage.Builder()
|
||||
.stream(2)
|
||||
.payload(identity.getPubkey())
|
||||
.build();
|
||||
objectMessage.sign(identity.getPrivateKey());
|
||||
objectMessage.encrypt(Singleton.security().createPublicKey(identity.getPublicDecryptionKey()));
|
||||
listener.receive(objectMessage);
|
||||
|
||||
verify(addressRepo).save(any(BitmessageAddress.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureIncomingMessageIsSaved() throws Exception {
|
||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
BitmessageAddress contact = new BitmessageAddress(identity.getAddress());
|
||||
|
||||
when(addressRepo.getIdentities()).thenReturn(Collections.singletonList(identity));
|
||||
|
||||
ObjectMessage objectMessage = new ObjectMessage.Builder()
|
||||
.stream(2)
|
||||
.payload(new Msg(new Plaintext.Builder(MSG)
|
||||
.from(identity)
|
||||
.to(contact)
|
||||
.message("S", "T")
|
||||
.build()))
|
||||
.nonce(new byte[8])
|
||||
.build();
|
||||
objectMessage.sign(identity.getPrivateKey());
|
||||
objectMessage.encrypt(identity.getPubkey());
|
||||
|
||||
listener.receive(objectMessage);
|
||||
|
||||
verify(messageRepo, atLeastOnce()).save(plaintext(MSG));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureIncomingBroadcastIsSaved() throws Exception {
|
||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
|
||||
when(addressRepo.getSubscriptions(anyLong())).thenReturn(Collections.singletonList(identity));
|
||||
|
||||
Broadcast broadcast = Factory.getBroadcast(new Plaintext.Builder(BROADCAST)
|
||||
.from(identity)
|
||||
.message("S", "T")
|
||||
.build());
|
||||
ObjectMessage objectMessage = new ObjectMessage.Builder()
|
||||
.stream(2)
|
||||
.payload(broadcast)
|
||||
.nonce(new byte[8])
|
||||
.build();
|
||||
objectMessage.sign(identity.getPrivateKey());
|
||||
broadcast.encrypt();
|
||||
|
||||
listener.receive(objectMessage);
|
||||
|
||||
verify(messageRepo, atLeastOnce()).save(plaintext(BROADCAST));
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2016 Christian Basler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.bitmessage;
|
||||
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.payload.GetPubkey;
|
||||
import ch.dissem.bitmessage.entity.payload.Msg;
|
||||
import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.utils.Singleton;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class ProofOfWorkServiceTest {
|
||||
private ProofOfWorkService proofOfWorkService;
|
||||
|
||||
private Cryptography cryptography;
|
||||
@Mock
|
||||
private InternalContext ctx;
|
||||
@Mock
|
||||
private ProofOfWorkRepository proofOfWorkRepo;
|
||||
@Mock
|
||||
private Inventory inventory;
|
||||
@Mock
|
||||
private NetworkHandler networkHandler;
|
||||
@Mock
|
||||
private MessageRepository messageRepo;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
cryptography = spy(new BouncyCryptography());
|
||||
Singleton.initialize(cryptography);
|
||||
|
||||
ctx = mock(InternalContext.class);
|
||||
when(ctx.getProofOfWorkRepository()).thenReturn(proofOfWorkRepo);
|
||||
when(ctx.getInventory()).thenReturn(inventory);
|
||||
when(ctx.getNetworkHandler()).thenReturn(networkHandler);
|
||||
when(ctx.getMessageRepository()).thenReturn(messageRepo);
|
||||
|
||||
proofOfWorkService = new ProofOfWorkService();
|
||||
proofOfWorkService.setContext(ctx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureMissingProofOfWorkIsDone() {
|
||||
when(proofOfWorkRepo.getItems()).thenReturn(Arrays.asList(new byte[64]));
|
||||
when(proofOfWorkRepo.getItem(any(byte[].class))).thenReturn(new ProofOfWorkRepository.Item(null, 1001, 1002));
|
||||
doNothing().when(cryptography).doProofOfWork(any(ObjectMessage.class), anyLong(), anyLong(), any(ProofOfWorkEngine.Callback.class));
|
||||
|
||||
proofOfWorkService.doMissingProofOfWork();
|
||||
|
||||
verify(cryptography).doProofOfWork((ObjectMessage) isNull(), eq(1001L), eq(1002L),
|
||||
any(ProofOfWorkEngine.Callback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureCalculatedNonceIsStored() throws Exception {
|
||||
BitmessageAddress identity = TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8");
|
||||
BitmessageAddress address = TestUtils.loadContact();
|
||||
Plaintext plaintext = new Plaintext.Builder(MSG).from(identity).to(address).message("", "").build();
|
||||
ObjectMessage object = new ObjectMessage.Builder()
|
||||
.payload(new Msg(plaintext))
|
||||
.build();
|
||||
object.sign(identity.getPrivateKey());
|
||||
object.encrypt(address.getPubkey());
|
||||
byte[] initialHash = new byte[64];
|
||||
byte[] nonce = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
when(proofOfWorkRepo.getItem(initialHash)).thenReturn(new ProofOfWorkRepository.Item(object, 1001, 1002));
|
||||
when(messageRepo.getMessage(initialHash)).thenReturn(plaintext);
|
||||
|
||||
proofOfWorkService.onNonceCalculated(initialHash, nonce);
|
||||
|
||||
verify(proofOfWorkRepo).removeObject(eq(initialHash));
|
||||
verify(inventory).storeObject(eq(object));
|
||||
verify(networkHandler).offer(eq(object.getInventoryVector()));
|
||||
assertThat(plaintext.getInventoryVector(), equalTo(object.getInventoryVector()));
|
||||
}
|
||||
}
|
@ -17,12 +17,14 @@
|
||||
package ch.dissem.bitmessage.utils;
|
||||
|
||||
import ch.dissem.bitmessage.cryptography.bc.BouncyCryptography;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
/**
|
||||
* Created by chris on 20.07.15.
|
||||
* @author Christian Basler
|
||||
*/
|
||||
public class TestBase {
|
||||
static {
|
||||
@BeforeClass
|
||||
public static void setUpClass() {
|
||||
Singleton.initialize(new BouncyCryptography());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user