Fixed some bugs and some tests
This commit is contained in:
parent
702ac6cb82
commit
732032b1b5
@ -254,7 +254,10 @@ public class BitmessageContext {
|
|||||||
public void addContact(BitmessageAddress contact) {
|
public void addContact(BitmessageAddress contact) {
|
||||||
ctx.getAddressRepository().save(contact);
|
ctx.getAddressRepository().save(contact);
|
||||||
if (contact.getPubkey() == null) {
|
if (contact.getPubkey() == null) {
|
||||||
ctx.requestPubkey(contact);
|
BitmessageAddress stored = ctx.getAddressRepository().getAddress(contact.getAddress());
|
||||||
|
if (stored.getPubkey() == null) {
|
||||||
|
ctx.requestPubkey(contact);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,6 +377,18 @@ public class Plaintext implements Streamable {
|
|||||||
return extendedData;
|
return extendedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends ExtendedEncoding.ExtendedType> T getExtendedData(Class<T> type) {
|
||||||
|
ExtendedEncoding extendedData = getExtendedData();
|
||||||
|
if (extendedData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (type == null || type.isInstance(extendedData.getContent())) {
|
||||||
|
return (T) extendedData.getContent();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public List<InventoryVector> getParents() {
|
public List<InventoryVector> getParents() {
|
||||||
if (Message.TYPE.equals(getExtendedData().getType())) {
|
if (Message.TYPE.equals(getExtendedData().getType())) {
|
||||||
return ((Message) extendedData.getContent()).getParents();
|
return ((Message) extendedData.getContent()).getParents();
|
||||||
|
@ -37,15 +37,28 @@ public abstract class AbstractMessageRepository implements MessageRepository, In
|
|||||||
this.ctx = context;
|
this.ctx = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link #saveContactIfNecessary(BitmessageAddress)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
protected void safeSenderIfNecessary(Plaintext message) {
|
protected void safeSenderIfNecessary(Plaintext message) {
|
||||||
if (message.getId() == null) {
|
if (message.getId() == null) {
|
||||||
BitmessageAddress savedAddress = ctx.getAddressRepository().getAddress(message.getFrom().getAddress());
|
saveContactIfNecessary(message.getFrom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void saveContactIfNecessary(BitmessageAddress contact) {
|
||||||
|
if (contact != null) {
|
||||||
|
BitmessageAddress savedAddress = ctx.getAddressRepository().getAddress(contact.getAddress());
|
||||||
if (savedAddress == null) {
|
if (savedAddress == null) {
|
||||||
ctx.getAddressRepository().save(message.getFrom());
|
ctx.getAddressRepository().save(contact);
|
||||||
} else if (savedAddress.getPubkey() == null && message.getFrom().getPubkey() != null) {
|
} else if (savedAddress.getPubkey() == null && contact.getPubkey() != null) {
|
||||||
savedAddress.setPubkey(message.getFrom().getPubkey());
|
savedAddress.setPubkey(contact.getPubkey());
|
||||||
ctx.getAddressRepository().save(savedAddress);
|
ctx.getAddressRepository().save(savedAddress);
|
||||||
}
|
}
|
||||||
|
if (savedAddress != null) {
|
||||||
|
contact.setAlias(savedAddress.getAlias());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +108,7 @@ public abstract class AbstractMessageRepository implements MessageRepository, In
|
|||||||
@Override
|
@Override
|
||||||
public List<Plaintext> findMessagesToResend() {
|
public List<Plaintext> findMessagesToResend() {
|
||||||
return find("status='" + Plaintext.Status.SENT.name() + "'" +
|
return find("status='" + Plaintext.Status.SENT.name() + "'" +
|
||||||
" AND next_try < " + UnixTime.now());
|
" AND next_try < " + UnixTime.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -119,7 +132,7 @@ public abstract class AbstractMessageRepository implements MessageRepository, In
|
|||||||
return collection.iterator().next();
|
return collection.iterator().next();
|
||||||
default:
|
default:
|
||||||
throw new ApplicationException("This shouldn't happen, found " + collection.size() +
|
throw new ApplicationException("This shouldn't happen, found " + collection.size() +
|
||||||
" items, one or none was expected");
|
" items, one or none was expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,11 @@ public interface AddressRepository {
|
|||||||
*/
|
*/
|
||||||
List<BitmessageAddress> getContacts();
|
List<BitmessageAddress> getContacts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations must not delete cryptographic keys if they're not provided by <code>address</code>.
|
||||||
|
*
|
||||||
|
* @param address to save or update
|
||||||
|
*/
|
||||||
void save(BitmessageAddress address);
|
void save(BitmessageAddress address);
|
||||||
|
|
||||||
void remove(BitmessageAddress address);
|
void remove(BitmessageAddress address);
|
||||||
|
@ -57,64 +57,65 @@ public class BitmessageContextTest {
|
|||||||
Singleton.initialize(null);
|
Singleton.initialize(null);
|
||||||
listener = mock(BitmessageContext.Listener.class);
|
listener = mock(BitmessageContext.Listener.class);
|
||||||
ctx = new BitmessageContext.Builder()
|
ctx = new BitmessageContext.Builder()
|
||||||
.addressRepo(mock(AddressRepository.class))
|
.addressRepo(mock(AddressRepository.class))
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography())
|
||||||
.inventory(mock(Inventory.class))
|
.inventory(mock(Inventory.class))
|
||||||
.listener(listener)
|
.listener(listener)
|
||||||
.messageRepo(mock(MessageRepository.class))
|
.messageRepo(mock(MessageRepository.class))
|
||||||
.networkHandler(mock(NetworkHandler.class))
|
.networkHandler(mock(NetworkHandler.class))
|
||||||
.nodeRegistry(mock(NodeRegistry.class))
|
.nodeRegistry(mock(NodeRegistry.class))
|
||||||
.labeler(spy(new DefaultLabeler()))
|
.labeler(spy(new DefaultLabeler()))
|
||||||
.powRepo(spy(new ProofOfWorkRepository() {
|
.powRepo(spy(new ProofOfWorkRepository() {
|
||||||
Map<InventoryVector, Item> items = new HashMap<>();
|
Map<InventoryVector, Item> items = new HashMap<>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Item getItem(byte[] initialHash) {
|
public Item getItem(byte[] initialHash) {
|
||||||
return items.get(new InventoryVector(initialHash));
|
return items.get(new InventoryVector(initialHash));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<byte[]> getItems() {
|
public List<byte[]> getItems() {
|
||||||
List<byte[]> result = new LinkedList<>();
|
List<byte[]> result = new LinkedList<>();
|
||||||
for (InventoryVector iv : items.keySet()) {
|
for (InventoryVector iv : items.keySet()) {
|
||||||
result.add(iv.getHash());
|
result.add(iv.getHash());
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putObject(Item item) {
|
public void putObject(Item item) {
|
||||||
items.put(new InventoryVector(cryptography().getInitialHash(item.object)), item);
|
items.put(new InventoryVector(cryptography().getInitialHash(item.object)), item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
|
public void putObject(ObjectMessage object, long nonceTrialsPerByte, long extraBytes) {
|
||||||
items.put(new InventoryVector(cryptography().getInitialHash(object)), new Item(object, nonceTrialsPerByte, extraBytes));
|
items.put(new InventoryVector(cryptography().getInitialHash(object)), new Item(object, nonceTrialsPerByte, extraBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeObject(byte[] initialHash) {
|
public void removeObject(byte[] initialHash) {
|
||||||
items.remove(initialHash);
|
items.remove(initialHash);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.proofOfWorkEngine(spy(new ProofOfWorkEngine() {
|
.proofOfWorkEngine(spy(new ProofOfWorkEngine() {
|
||||||
@Override
|
@Override
|
||||||
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
public void calculateNonce(byte[] initialHash, byte[] target, Callback callback) {
|
||||||
callback.onNonceCalculated(initialHash, new byte[8]);
|
callback.onNonceCalculated(initialHash, new byte[8]);
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.build();
|
.build();
|
||||||
TTL.msg(2 * MINUTE);
|
TTL.msg(2 * MINUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureContactIsSavedAndPubkeyRequested() {
|
public void ensureContactIsSavedAndPubkeyRequested() {
|
||||||
BitmessageAddress contact = new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT");
|
BitmessageAddress contact = new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT");
|
||||||
|
when(ctx.addresses().getAddress(contact.getAddress())).thenReturn(contact);
|
||||||
ctx.addContact(contact);
|
ctx.addContact(contact);
|
||||||
|
|
||||||
verify(ctx.addresses(), times(2)).save(contact);
|
verify(ctx.addresses(), timeout(1000).atLeastOnce()).save(contact);
|
||||||
verify(ctx.internals().getProofOfWorkEngine())
|
verify(ctx.internals().getProofOfWorkEngine(), timeout(1000))
|
||||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -128,52 +129,41 @@ public class BitmessageContextTest {
|
|||||||
|
|
||||||
verify(ctx.addresses(), times(1)).save(contact);
|
verify(ctx.addresses(), times(1)).save(contact);
|
||||||
verify(ctx.internals().getProofOfWorkEngine(), never())
|
verify(ctx.internals().getProofOfWorkEngine(), never())
|
||||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureV2PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
public void ensureV2PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
||||||
BitmessageAddress contact = new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT");
|
BitmessageAddress contact = new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT");
|
||||||
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
||||||
.thenReturn(Collections.singletonList(
|
.thenReturn(Collections.singletonList(
|
||||||
TestUtils.loadObjectMessage(2, "V2Pubkey.payload")
|
TestUtils.loadObjectMessage(2, "V2Pubkey.payload")
|
||||||
));
|
));
|
||||||
|
when(ctx.addresses().getAddress(contact.getAddress())).thenReturn(contact);
|
||||||
|
|
||||||
ctx.addContact(contact);
|
ctx.addContact(contact);
|
||||||
|
|
||||||
verify(ctx.addresses(), atLeastOnce()).save(contact);
|
verify(ctx.addresses(), atLeastOnce()).save(contact);
|
||||||
verify(ctx.internals().getProofOfWorkEngine(), never())
|
verify(ctx.internals().getProofOfWorkEngine(), never())
|
||||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureV4PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
public void ensureV4PubkeyIsNotRequestedIfItExistsInInventory() throws Exception {
|
||||||
BitmessageAddress contact = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
BitmessageAddress contact = new BitmessageAddress("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||||
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
when(ctx.internals().getInventory().getObjects(anyLong(), anyLong(), any(ObjectType.class)))
|
||||||
.thenReturn(Collections.singletonList(
|
.thenReturn(Collections.singletonList(
|
||||||
TestUtils.loadObjectMessage(2, "V4Pubkey.payload")
|
TestUtils.loadObjectMessage(2, "V4Pubkey.payload")
|
||||||
));
|
));
|
||||||
final BitmessageAddress stored = new BitmessageAddress(contact.getAddress());
|
final BitmessageAddress stored = new BitmessageAddress(contact.getAddress());
|
||||||
stored.setAlias("Test");
|
stored.setAlias("Test");
|
||||||
when(ctx.addresses().getAddress(contact.getAddress())).thenReturn(stored);
|
when(ctx.addresses().getAddress(contact.getAddress())).thenReturn(stored);
|
||||||
|
|
||||||
ctx.addContact(contact);
|
ctx.addContact(contact);
|
||||||
|
|
||||||
verify(ctx.addresses(), atLeastOnce()).save(argThat(new BaseMatcher<BitmessageAddress>() {
|
verify(ctx.addresses(), atLeastOnce()).save(any(BitmessageAddress.class));
|
||||||
@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())
|
verify(ctx.internals().getProofOfWorkEngine(), never())
|
||||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -184,7 +174,7 @@ public class BitmessageContextTest {
|
|||||||
objects.add(TestUtils.loadObjectMessage(4, "V4Broadcast.payload"));
|
objects.add(TestUtils.loadObjectMessage(4, "V4Broadcast.payload"));
|
||||||
objects.add(TestUtils.loadObjectMessage(5, "V5Broadcast.payload"));
|
objects.add(TestUtils.loadObjectMessage(5, "V5Broadcast.payload"));
|
||||||
when(ctx.internals().getInventory().getObjects(eq(address.getStream()), anyLong(), any(ObjectType.class)))
|
when(ctx.internals().getInventory().getObjects(eq(address.getStream()), anyLong(), any(ObjectType.class)))
|
||||||
.thenReturn(objects);
|
.thenReturn(objects);
|
||||||
when(ctx.addresses().getSubscriptions(anyLong())).thenReturn(Collections.singletonList(address));
|
when(ctx.addresses().getSubscriptions(anyLong())).thenReturn(Collections.singletonList(address));
|
||||||
|
|
||||||
ctx.addSubscribtion(address);
|
ctx.addSubscribtion(address);
|
||||||
@ -203,48 +193,48 @@ public class BitmessageContextTest {
|
|||||||
@Test
|
@Test
|
||||||
public void ensureMessageIsSent() throws Exception {
|
public void ensureMessageIsSent() throws Exception {
|
||||||
ctx.send(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"), TestUtils.loadContact(),
|
ctx.send(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"), TestUtils.loadContact(),
|
||||||
"Subject", "Message");
|
"Subject", "Message");
|
||||||
assertEquals(2, ctx.internals().getProofOfWorkRepository().getItems().size());
|
assertEquals(2, ctx.internals().getProofOfWorkRepository().getItems().size());
|
||||||
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
||||||
.putObject(object(MSG), eq(1000L), eq(1000L));
|
.putObject(object(MSG), eq(1000L), eq(1000L));
|
||||||
verify(ctx.messages(), timeout(10000).atLeastOnce()).save(MessageMatchers.plaintext(Type.MSG));
|
verify(ctx.messages(), timeout(10000).atLeastOnce()).save(MessageMatchers.plaintext(Type.MSG));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensurePubkeyIsRequestedIfItIsMissing() throws Exception {
|
public void ensurePubkeyIsRequestedIfItIsMissing() throws Exception {
|
||||||
ctx.send(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"),
|
ctx.send(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"),
|
||||||
new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
||||||
"Subject", "Message");
|
"Subject", "Message");
|
||||||
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
||||||
.putObject(object(GET_PUBKEY), eq(1000L), eq(1000L));
|
.putObject(object(GET_PUBKEY), eq(1000L), eq(1000L));
|
||||||
verify(ctx.messages(), timeout(10000).atLeastOnce()).save(MessageMatchers.plaintext(Type.MSG));
|
verify(ctx.messages(), timeout(10000).atLeastOnce()).save(MessageMatchers.plaintext(Type.MSG));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void ensureSenderMustBeIdentity() {
|
public void ensureSenderMustBeIdentity() {
|
||||||
ctx.send(new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
ctx.send(new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
||||||
new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
new BitmessageAddress("BM-opWQhvk9xtMFvQA2Kvetedpk8LkbraWHT"),
|
||||||
"Subject", "Message");
|
"Subject", "Message");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ensureBroadcastIsSent() throws Exception {
|
public void ensureBroadcastIsSent() throws Exception {
|
||||||
ctx.broadcast(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"),
|
ctx.broadcast(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"),
|
||||||
"Subject", "Message");
|
"Subject", "Message");
|
||||||
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
verify(ctx.internals().getProofOfWorkRepository(), timeout(10000).atLeastOnce())
|
||||||
.putObject(object(BROADCAST), eq(1000L), eq(1000L));
|
.putObject(object(BROADCAST), eq(1000L), eq(1000L));
|
||||||
verify(ctx.internals().getProofOfWorkEngine())
|
verify(ctx.internals().getProofOfWorkEngine())
|
||||||
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
.calculateNonce(any(byte[].class), any(byte[].class), any(ProofOfWorkEngine.Callback.class));
|
||||||
verify(ctx.messages(), timeout(10000).atLeastOnce())
|
verify(ctx.messages(), timeout(10000).atLeastOnce())
|
||||||
.save(MessageMatchers.plaintext(Type.BROADCAST));
|
.save(MessageMatchers.plaintext(Type.BROADCAST));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void ensureSenderWithoutPrivateKeyThrowsException() {
|
public void ensureSenderWithoutPrivateKeyThrowsException() {
|
||||||
Plaintext msg = new Plaintext.Builder(Type.BROADCAST)
|
Plaintext msg = new Plaintext.Builder(Type.BROADCAST)
|
||||||
.from(new BitmessageAddress("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
.from(new BitmessageAddress("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||||
.message("Subject", "Message")
|
.message("Subject", "Message")
|
||||||
.build();
|
.build();
|
||||||
ctx.send(msg);
|
ctx.send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,11 +291,11 @@ public class BitmessageContextTest {
|
|||||||
@Test
|
@Test
|
||||||
public void ensureUnacknowledgedMessageIsResent() throws Exception {
|
public void ensureUnacknowledgedMessageIsResent() throws Exception {
|
||||||
Plaintext plaintext = new Plaintext.Builder(Type.MSG)
|
Plaintext plaintext = new Plaintext.Builder(Type.MSG)
|
||||||
.ttl(1)
|
.ttl(1)
|
||||||
.message("subject", "message")
|
.message("subject", "message")
|
||||||
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
.from(TestUtils.loadIdentity("BM-2cSqjfJ8xK6UUn5Rw3RpdGQ9RsDkBhWnS8"))
|
||||||
.to(TestUtils.loadContact())
|
.to(TestUtils.loadContact())
|
||||||
.build();
|
.build();
|
||||||
assertTrue(plaintext.getTo().has(Pubkey.Feature.DOES_ACK));
|
assertTrue(plaintext.getTo().has(Pubkey.Feature.DOES_ACK));
|
||||||
when(ctx.messages().findMessagesToResend()).thenReturn(Collections.singletonList(plaintext));
|
when(ctx.messages().findMessagesToResend()).thenReturn(Collections.singletonList(plaintext));
|
||||||
when(ctx.messages().getMessage(any(byte[].class))).thenReturn(plaintext);
|
when(ctx.messages().getMessage(any(byte[].class))).thenReturn(plaintext);
|
||||||
|
@ -54,10 +54,11 @@ public class SystemTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Parameterized.Parameters
|
@Parameterized.Parameters
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static List<Object[]> parameters() {
|
public static List<Object[]> parameters() {
|
||||||
return Arrays.asList(new Object[][]{
|
return Arrays.asList(new Object[][]{
|
||||||
{new NioNetworkHandler(), new DefaultNetworkHandler()},
|
{new NioNetworkHandler(), new DefaultNetworkHandler()},
|
||||||
{new NioNetworkHandler(), new NioNetworkHandler()}
|
{new NioNetworkHandler(), new NioNetworkHandler()}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,33 +71,33 @@ public class SystemTest {
|
|||||||
TTL.pubkey(5 * MINUTE);
|
TTL.pubkey(5 * MINUTE);
|
||||||
JdbcConfig aliceDB = new JdbcConfig("jdbc:h2:mem:alice;DB_CLOSE_DELAY=-1", "sa", "");
|
JdbcConfig aliceDB = new JdbcConfig("jdbc:h2:mem:alice;DB_CLOSE_DELAY=-1", "sa", "");
|
||||||
alice = new BitmessageContext.Builder()
|
alice = new BitmessageContext.Builder()
|
||||||
.addressRepo(new JdbcAddressRepository(aliceDB))
|
.addressRepo(new JdbcAddressRepository(aliceDB))
|
||||||
.inventory(new JdbcInventory(aliceDB))
|
.inventory(new JdbcInventory(aliceDB))
|
||||||
.messageRepo(new JdbcMessageRepository(aliceDB))
|
.messageRepo(new JdbcMessageRepository(aliceDB))
|
||||||
.powRepo(new JdbcProofOfWorkRepository(aliceDB))
|
.powRepo(new JdbcProofOfWorkRepository(aliceDB))
|
||||||
.port(alicePort)
|
.port(alicePort)
|
||||||
.nodeRegistry(new TestNodeRegistry(bobPort))
|
.nodeRegistry(new TestNodeRegistry(bobPort))
|
||||||
.networkHandler(aliceNetworkHandler)
|
.networkHandler(aliceNetworkHandler)
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography())
|
||||||
.listener(aliceListener)
|
.listener(aliceListener)
|
||||||
.labeler(aliceLabeler)
|
.labeler(aliceLabeler)
|
||||||
.build();
|
.build();
|
||||||
alice.startup();
|
alice.startup();
|
||||||
aliceIdentity = alice.createIdentity(false, DOES_ACK);
|
aliceIdentity = alice.createIdentity(false, DOES_ACK);
|
||||||
|
|
||||||
JdbcConfig bobDB = new JdbcConfig("jdbc:h2:mem:bob;DB_CLOSE_DELAY=-1", "sa", "");
|
JdbcConfig bobDB = new JdbcConfig("jdbc:h2:mem:bob;DB_CLOSE_DELAY=-1", "sa", "");
|
||||||
bob = new BitmessageContext.Builder()
|
bob = new BitmessageContext.Builder()
|
||||||
.addressRepo(new JdbcAddressRepository(bobDB))
|
.addressRepo(new JdbcAddressRepository(bobDB))
|
||||||
.inventory(new JdbcInventory(bobDB))
|
.inventory(new JdbcInventory(bobDB))
|
||||||
.messageRepo(new JdbcMessageRepository(bobDB))
|
.messageRepo(new JdbcMessageRepository(bobDB))
|
||||||
.powRepo(new JdbcProofOfWorkRepository(bobDB))
|
.powRepo(new JdbcProofOfWorkRepository(bobDB))
|
||||||
.port(bobPort)
|
.port(bobPort)
|
||||||
.nodeRegistry(new TestNodeRegistry(alicePort))
|
.nodeRegistry(new TestNodeRegistry(alicePort))
|
||||||
.networkHandler(bobNetworkHandler)
|
.networkHandler(bobNetworkHandler)
|
||||||
.cryptography(new BouncyCryptography())
|
.cryptography(new BouncyCryptography())
|
||||||
.listener(bobListener)
|
.listener(bobListener)
|
||||||
.labeler(new DebugLabeler("Bob"))
|
.labeler(new DebugLabeler("Bob"))
|
||||||
.build();
|
.build();
|
||||||
bob.startup();
|
bob.startup();
|
||||||
bobIdentity = bob.createIdentity(false, DOES_ACK);
|
bobIdentity = bob.createIdentity(false, DOES_ACK);
|
||||||
|
|
||||||
@ -121,7 +122,7 @@ public class SystemTest {
|
|||||||
assertThat(plaintext.getText(), equalTo(originalMessage));
|
assertThat(plaintext.getText(), equalTo(originalMessage));
|
||||||
|
|
||||||
Mockito.verify(aliceLabeler, Mockito.timeout(TimeUnit.MINUTES.toMillis(15)).atLeastOnce())
|
Mockito.verify(aliceLabeler, Mockito.timeout(TimeUnit.MINUTES.toMillis(15)).atLeastOnce())
|
||||||
.markAsAcknowledged(any());
|
.markAsAcknowledged(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout = 30_000)
|
@Test(timeout = 30_000)
|
||||||
|
@ -46,7 +46,7 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
@Override
|
@Override
|
||||||
protected List<Label> findLabels(String where) {
|
protected List<Label> findLabels(String where) {
|
||||||
try (
|
try (
|
||||||
Connection connection = config.getConnection()
|
Connection connection = config.getConnection()
|
||||||
) {
|
) {
|
||||||
return findLabels(connection, where);
|
return findLabels(connection, where);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
@ -76,12 +76,12 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
where = "id IN (SELECT message_id FROM Message_Label WHERE label_id=" + label.getId() + ") AND ";
|
where = "id IN (SELECT message_id FROM Message_Label WHERE label_id=" + label.getId() + ") AND ";
|
||||||
}
|
}
|
||||||
where += "id IN (SELECT message_id FROM Message_Label WHERE label_id IN (" +
|
where += "id IN (SELECT message_id FROM Message_Label WHERE label_id IN (" +
|
||||||
"SELECT id FROM Label WHERE type = '" + Label.Type.UNREAD.name() + "'))";
|
"SELECT id FROM Label WHERE type = '" + Label.Type.UNREAD.name() + "'))";
|
||||||
|
|
||||||
try (
|
try (
|
||||||
Connection connection = config.getConnection();
|
Connection connection = config.getConnection();
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT count(*) FROM Message WHERE " + where)
|
ResultSet rs = stmt.executeQuery("SELECT count(*) FROM Message WHERE " + where)
|
||||||
) {
|
) {
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
return rs.getInt(1);
|
return rs.getInt(1);
|
||||||
@ -96,11 +96,11 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
protected List<Plaintext> find(String where) {
|
protected List<Plaintext> find(String where) {
|
||||||
List<Plaintext> result = new LinkedList<>();
|
List<Plaintext> result = new LinkedList<>();
|
||||||
try (
|
try (
|
||||||
Connection connection = config.getConnection();
|
Connection connection = config.getConnection();
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery(
|
ResultSet rs = stmt.executeQuery(
|
||||||
"SELECT id, iv, type, sender, recipient, data, ack_data, sent, received, initial_hash, status, ttl, retries, next_try " +
|
"SELECT id, iv, type, sender, recipient, data, ack_data, sent, received, initial_hash, status, ttl, retries, next_try " +
|
||||||
"FROM Message WHERE " + where)
|
"FROM Message WHERE " + where)
|
||||||
) {
|
) {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
byte[] iv = rs.getBytes("iv");
|
byte[] iv = rs.getBytes("iv");
|
||||||
@ -120,7 +120,7 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
builder.retries(rs.getInt("retries"));
|
builder.retries(rs.getInt("retries"));
|
||||||
builder.nextTry(rs.getLong("next_try"));
|
builder.nextTry(rs.getLong("next_try"));
|
||||||
builder.labels(findLabels(connection,
|
builder.labels(findLabels(connection,
|
||||||
"id IN (SELECT label_id FROM Message_Label WHERE message_id=" + id + ") ORDER BY ord"));
|
"id IN (SELECT label_id FROM Message_Label WHERE message_id=" + id + ") ORDER BY ord"));
|
||||||
Plaintext message = builder.build();
|
Plaintext message = builder.build();
|
||||||
message.setInitialHash(rs.getBytes("initial_hash"));
|
message.setInitialHash(rs.getBytes("initial_hash"));
|
||||||
result.add(message);
|
result.add(message);
|
||||||
@ -134,8 +134,8 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
private List<Label> findLabels(Connection connection, String where) {
|
private List<Label> findLabels(Connection connection, String where) {
|
||||||
List<Label> result = new ArrayList<>();
|
List<Label> result = new ArrayList<>();
|
||||||
try (
|
try (
|
||||||
Statement stmt = connection.createStatement();
|
Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT id, label, type, color FROM Label WHERE " + where)
|
ResultSet rs = stmt.executeQuery("SELECT id, label, type, color FROM Label WHERE " + where)
|
||||||
) {
|
) {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
result.add(getLabel(rs));
|
result.add(getLabel(rs));
|
||||||
@ -148,7 +148,8 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(Plaintext message) {
|
public void save(Plaintext message) {
|
||||||
safeSenderIfNecessary(message);
|
saveContactIfNecessary(message.getFrom());
|
||||||
|
saveContactIfNecessary(message.getTo());
|
||||||
|
|
||||||
try (Connection connection = config.getConnection()) {
|
try (Connection connection = config.getConnection()) {
|
||||||
try {
|
try {
|
||||||
@ -180,7 +181,7 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
}
|
}
|
||||||
// save new labels
|
// save new labels
|
||||||
try (PreparedStatement ps = connection.prepareStatement("INSERT INTO Message_Label VALUES (" +
|
try (PreparedStatement ps = connection.prepareStatement("INSERT INTO Message_Label VALUES (" +
|
||||||
message.getId() + ", ?)")) {
|
message.getId() + ", ?)")) {
|
||||||
for (Label label : message.getLabels()) {
|
for (Label label : message.getLabels()) {
|
||||||
ps.setLong(1, (Long) label.getId());
|
ps.setLong(1, (Long) label.getId());
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
@ -190,10 +191,10 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
|
|
||||||
private void insert(Connection connection, Plaintext message) throws SQLException, IOException {
|
private void insert(Connection connection, Plaintext message) throws SQLException, IOException {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"INSERT INTO Message (iv, type, sender, recipient, data, ack_data, sent, received, " +
|
"INSERT INTO Message (iv, type, sender, recipient, data, ack_data, sent, received, " +
|
||||||
"status, initial_hash, ttl, retries, next_try) " +
|
"status, initial_hash, ttl, retries, next_try) " +
|
||||||
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
Statement.RETURN_GENERATED_KEYS)
|
Statement.RETURN_GENERATED_KEYS)
|
||||||
) {
|
) {
|
||||||
ps.setBytes(1, message.getInventoryVector() == null ? null : message.getInventoryVector().getHash());
|
ps.setBytes(1, message.getInventoryVector() == null ? null : message.getInventoryVector().getHash());
|
||||||
ps.setString(2, message.getType().name());
|
ps.setString(2, message.getType().name());
|
||||||
@ -220,9 +221,9 @@ public class JdbcMessageRepository extends AbstractMessageRepository implements
|
|||||||
|
|
||||||
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
|
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
|
||||||
try (PreparedStatement ps = connection.prepareStatement(
|
try (PreparedStatement ps = connection.prepareStatement(
|
||||||
"UPDATE Message SET iv=?, type=?, sender=?, recipient=?, data=?, ack_data=?, sent=?, received=?, " +
|
"UPDATE Message SET iv=?, type=?, sender=?, recipient=?, data=?, ack_data=?, sent=?, received=?, " +
|
||||||
"status=?, initial_hash=?, ttl=?, retries=?, next_try=? " +
|
"status=?, initial_hash=?, ttl=?, retries=?, next_try=? " +
|
||||||
"WHERE id=?")) {
|
"WHERE id=?")) {
|
||||||
ps.setBytes(1, message.getInventoryVector() == null ? null : message.getInventoryVector().getHash());
|
ps.setBytes(1, message.getInventoryVector() == null ? null : message.getInventoryVector().getHash());
|
||||||
ps.setString(2, message.getType().name());
|
ps.setString(2, message.getType().name());
|
||||||
ps.setString(3, message.getFrom().getAddress());
|
ps.setString(3, message.getFrom().getAddress());
|
||||||
|
@ -109,6 +109,11 @@ public class JdbcNodeRegistry extends JdbcHelper implements NodeRegistry {
|
|||||||
result.add(Collections.selectRandom(nodes));
|
result.add(Collections.selectRandom(nodes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.isEmpty()) {
|
||||||
|
// There might have been an error resolving domain names due to a missing internet exception.
|
||||||
|
// Try to load the stable nodes again next time.
|
||||||
|
stableNodes = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user