Added tests for DefaultMessageListener and ProofOfWorkService

and some minor improvements
This commit is contained in:
Christian Basler 2016-02-15 07:33:38 +01:00
parent e4a69f42b0
commit f71671e04a
7 changed files with 321 additions and 16 deletions

View File

@ -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

View File

@ -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);

View File

@ -19,18 +19,16 @@ 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;
}
}
}
public static Cryptography security() {
return cryptography;

View File

@ -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");

View File

@ -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));
}
}

View File

@ -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()));
}
}

View File

@ -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());
}
}