Migrated everything except
- the Bytes utilities class - it's easier to do in Java as with Kotlin byte + byte = int - the demo project, which I'm not sure I'll migrate. Maybe I'll make a new Kotlin Demo application
This commit is contained in:
@ -17,7 +17,7 @@ dependencies {
|
||||
compile 'org.flywaydb:flyway-core:4.1.2'
|
||||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'com.h2database:h2:1.4.194'
|
||||
testCompile 'org.mockito:mockito-core:2.7.21'
|
||||
testCompile 'com.nhaarman:mockito-kotlin:1.4.0'
|
||||
testCompile project(path: ':core', configuration: 'testArtifacts')
|
||||
testCompile project(':cryptography-bc')
|
||||
}
|
||||
|
@ -1,183 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository;
|
||||
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.payload.Pubkey.Feature.DOES_ACK;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class JdbcAddressRepositoryTest extends TestBase {
|
||||
public static final String CONTACT_A = "BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt";
|
||||
public static final String CONTACT_B = "BM-2cTtkBnb4BUYDndTKun6D9PjtueP2h1bQj";
|
||||
public static final String CONTACT_C = "BM-2cV5f9EpzaYARxtoruSpa6pDoucSf9ZNke";
|
||||
public String IDENTITY_A;
|
||||
public String IDENTITY_B;
|
||||
|
||||
private TestJdbcConfig config;
|
||||
private JdbcAddressRepository repo;
|
||||
|
||||
@Before
|
||||
public void setUp() throws InterruptedException {
|
||||
config = new TestJdbcConfig();
|
||||
config.reset();
|
||||
|
||||
repo = new JdbcAddressRepository(config);
|
||||
|
||||
repo.save(new BitmessageAddress(CONTACT_A));
|
||||
repo.save(new BitmessageAddress(CONTACT_B));
|
||||
repo.save(new BitmessageAddress(CONTACT_C));
|
||||
|
||||
BitmessageAddress identityA = new BitmessageAddress(new PrivateKey(false, 1, 1000, 1000, DOES_ACK));
|
||||
repo.save(identityA);
|
||||
IDENTITY_A = identityA.getAddress();
|
||||
BitmessageAddress identityB = new BitmessageAddress(new PrivateKey(false, 1, 1000, 1000));
|
||||
repo.save(identityB);
|
||||
IDENTITY_B = identityB.getAddress();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindContact() throws Exception {
|
||||
BitmessageAddress address = new BitmessageAddress(CONTACT_A);
|
||||
assertEquals(4, address.getVersion());
|
||||
assertEquals(address, repo.findContact(address.getTag()));
|
||||
assertNull(repo.findIdentity(address.getTag()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindIdentity() throws Exception {
|
||||
BitmessageAddress identity = new BitmessageAddress(IDENTITY_A);
|
||||
assertEquals(4, identity.getVersion());
|
||||
assertNull(repo.findContact(identity.getTag()));
|
||||
|
||||
BitmessageAddress storedIdentity = repo.findIdentity(identity.getTag());
|
||||
assertEquals(identity, storedIdentity);
|
||||
assertTrue(storedIdentity.has(DOES_ACK));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetIdentities() throws Exception {
|
||||
List<BitmessageAddress> identities = repo.getIdentities();
|
||||
assertEquals(2, identities.size());
|
||||
for (BitmessageAddress identity : identities) {
|
||||
assertNotNull(identity.getPrivateKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSubscriptions() throws Exception {
|
||||
addSubscription("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||
addSubscription("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ");
|
||||
addSubscription("BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh");
|
||||
List<BitmessageAddress> subscriptions = repo.getSubscriptions();
|
||||
assertEquals(3, subscriptions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSubscriptionsForVersion() throws Exception {
|
||||
addSubscription("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h");
|
||||
addSubscription("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ");
|
||||
addSubscription("BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh");
|
||||
|
||||
List<BitmessageAddress> subscriptions;
|
||||
|
||||
subscriptions = repo.getSubscriptions(5);
|
||||
assertEquals(1, subscriptions.size());
|
||||
|
||||
subscriptions = repo.getSubscriptions(4);
|
||||
assertEquals(2, subscriptions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetContacts() throws Exception {
|
||||
List<BitmessageAddress> contacts = repo.getContacts();
|
||||
assertEquals(3, contacts.size());
|
||||
for (BitmessageAddress contact : contacts) {
|
||||
assertNull(contact.getPrivateKey());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureNewAddressIsSaved() throws Exception {
|
||||
repo.save(new BitmessageAddress(new PrivateKey(false, 1, 1000, 1000)));
|
||||
List<BitmessageAddress> identities = repo.getIdentities();
|
||||
assertEquals(3, identities.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureExistingAddressIsUpdated() throws Exception {
|
||||
BitmessageAddress address = repo.getAddress(CONTACT_A);
|
||||
address.setAlias("Test-Alias");
|
||||
repo.save(address);
|
||||
address = repo.getAddress(address.getAddress());
|
||||
assertEquals("Test-Alias", address.getAlias());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureExistingKeysAreNotDeleted() {
|
||||
BitmessageAddress address = new BitmessageAddress(IDENTITY_A);
|
||||
address.setAlias("Test");
|
||||
repo.save(address);
|
||||
BitmessageAddress identityA = repo.getAddress(IDENTITY_A);
|
||||
assertNotNull(identityA.getPubkey());
|
||||
assertNotNull(identityA.getPrivateKey());
|
||||
assertEquals("Test", identityA.getAlias());
|
||||
assertFalse(identityA.isChan());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureNewChanIsSavedAndUpdated() {
|
||||
BitmessageAddress chan = BitmessageAddress.chan(1, "test");
|
||||
repo.save(chan);
|
||||
BitmessageAddress address = repo.getAddress(chan.getAddress());
|
||||
assertNotNull(address);
|
||||
assertTrue(address.isChan());
|
||||
|
||||
address.setAlias("Test");
|
||||
repo.save(address);
|
||||
|
||||
address = repo.getAddress(chan.getAddress());
|
||||
assertNotNull(address);
|
||||
assertTrue(address.isChan());
|
||||
assertEquals("Test", address.getAlias());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemove() throws Exception {
|
||||
BitmessageAddress address = repo.getAddress(IDENTITY_A);
|
||||
repo.remove(address);
|
||||
assertNull(repo.getAddress(IDENTITY_A));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAddress() throws Exception {
|
||||
BitmessageAddress address = repo.getAddress(IDENTITY_A);
|
||||
assertNotNull(address);
|
||||
assertNotNull(address.getPrivateKey());
|
||||
}
|
||||
|
||||
private void addSubscription(String address) {
|
||||
BitmessageAddress subscription = new BitmessageAddress(address);
|
||||
subscription.setSubscribed(true);
|
||||
repo.save(subscription);
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository;
|
||||
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.payload.GetPubkey;
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectPayload;
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
|
||||
import ch.dissem.bitmessage.ports.Inventory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.payload.ObjectType.GET_PUBKEY;
|
||||
import static ch.dissem.bitmessage.entity.payload.ObjectType.MSG;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.DAY;
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.now;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class JdbcInventoryTest extends TestBase {
|
||||
private TestJdbcConfig config;
|
||||
private Inventory inventory;
|
||||
|
||||
private InventoryVector inventoryVector1;
|
||||
private InventoryVector inventoryVector2;
|
||||
private InventoryVector inventoryVectorIgnore;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
config = new TestJdbcConfig();
|
||||
config.reset();
|
||||
|
||||
inventory = new JdbcInventory(config);
|
||||
|
||||
ObjectMessage object1 = getObjectMessage(1, 300, getGetPubkey());
|
||||
inventoryVector1 = object1.getInventoryVector();
|
||||
inventory.storeObject(object1);
|
||||
|
||||
ObjectMessage object2 = getObjectMessage(2, 300, getGetPubkey());
|
||||
inventoryVector2 = object2.getInventoryVector();
|
||||
inventory.storeObject(object2);
|
||||
|
||||
ObjectMessage ignore = getObjectMessage(1, -1 * DAY, getGetPubkey());
|
||||
inventoryVectorIgnore = ignore.getInventoryVector();
|
||||
inventory.storeObject(ignore);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInventory() throws Exception {
|
||||
List<InventoryVector> inventoryVectors = inventory.getInventory(1);
|
||||
assertEquals(1, inventoryVectors.size());
|
||||
|
||||
inventoryVectors = inventory.getInventory(2);
|
||||
assertEquals(1, inventoryVectors.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMissing() throws Exception {
|
||||
InventoryVector newIV = getObjectMessage(1, 200, getGetPubkey()).getInventoryVector();
|
||||
List<InventoryVector> offer = new LinkedList<>();
|
||||
offer.add(newIV);
|
||||
offer.add(inventoryVector1);
|
||||
List<InventoryVector> missing = inventory.getMissing(offer, 1, 2);
|
||||
assertEquals(1, missing.size());
|
||||
assertEquals(newIV, missing.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObject() throws Exception {
|
||||
ObjectMessage object = inventory.getObject(inventoryVectorIgnore);
|
||||
assertNotNull(object);
|
||||
assertEquals(1, object.getStream());
|
||||
assertEquals(inventoryVectorIgnore, object.getInventoryVector());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetObjects() throws Exception {
|
||||
List<ObjectMessage> objects = inventory.getObjects(1, 4);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
objects = inventory.getObjects(1, 4, GET_PUBKEY);
|
||||
assertEquals(2, objects.size());
|
||||
|
||||
objects = inventory.getObjects(1, 4, MSG);
|
||||
assertEquals(0, objects.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreObject() throws Exception {
|
||||
ObjectMessage object = getObjectMessage(5, 0, getGetPubkey());
|
||||
inventory.storeObject(object);
|
||||
|
||||
assertNotNull(inventory.getObject(object.getInventoryVector()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testContains() {
|
||||
ObjectMessage object = getObjectMessage(5, 0, getGetPubkey());
|
||||
|
||||
assertFalse(inventory.contains(object));
|
||||
|
||||
inventory.storeObject(object);
|
||||
|
||||
assertTrue(inventory.contains(object));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanup() throws Exception {
|
||||
assertNotNull(inventory.getObject(inventoryVectorIgnore));
|
||||
inventory.cleanup();
|
||||
assertNull(inventory.getObject(inventoryVectorIgnore));
|
||||
}
|
||||
|
||||
private ObjectMessage getObjectMessage(long stream, long TTL, ObjectPayload payload) {
|
||||
return new ObjectMessage.Builder()
|
||||
.nonce(new byte[8])
|
||||
.expiresTime(now() + TTL)
|
||||
.stream(stream)
|
||||
.payload(payload)
|
||||
.build();
|
||||
}
|
||||
|
||||
private GetPubkey getGetPubkey() {
|
||||
return new GetPubkey(new BitmessageAddress("BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"));
|
||||
}
|
||||
}
|
@ -1,352 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository;
|
||||
|
||||
import ch.dissem.bitmessage.BitmessageContext;
|
||||
import ch.dissem.bitmessage.InternalContext;
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress;
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage;
|
||||
import ch.dissem.bitmessage.entity.Plaintext;
|
||||
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding;
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label;
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
|
||||
import ch.dissem.bitmessage.entity.valueobject.extended.Message;
|
||||
import ch.dissem.bitmessage.ports.*;
|
||||
import ch.dissem.bitmessage.utils.TestUtils;
|
||||
import ch.dissem.bitmessage.utils.UnixTime;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static ch.dissem.bitmessage.entity.Plaintext.Type.MSG;
|
||||
import static ch.dissem.bitmessage.entity.payload.Pubkey.Feature.DOES_ACK;
|
||||
import static ch.dissem.bitmessage.utils.Singleton.cryptography;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class JdbcMessageRepositoryTest extends TestBase {
|
||||
private BitmessageAddress contactA;
|
||||
private BitmessageAddress contactB;
|
||||
private BitmessageAddress identity;
|
||||
|
||||
private MessageRepository repo;
|
||||
|
||||
private Label inbox;
|
||||
private Label sent;
|
||||
private Label drafts;
|
||||
private Label unread;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
TestJdbcConfig config = new TestJdbcConfig();
|
||||
config.reset();
|
||||
AddressRepository addressRepo = new JdbcAddressRepository(config);
|
||||
repo = new JdbcMessageRepository(config);
|
||||
new InternalContext(
|
||||
cryptography(),
|
||||
mock(Inventory.class),
|
||||
mock(NodeRegistry.class),
|
||||
mock(NetworkHandler.class),
|
||||
addressRepo,
|
||||
repo,
|
||||
mock(ProofOfWorkRepository.class),
|
||||
mock(ProofOfWorkEngine.class),
|
||||
mock(CustomCommandHandler.class),
|
||||
mock(BitmessageContext.Listener.class),
|
||||
mock(Labeler.class),
|
||||
12345,
|
||||
10, 10
|
||||
);
|
||||
BitmessageAddress tmp = new BitmessageAddress(new PrivateKey(false, 1, 1000, 1000, DOES_ACK));
|
||||
contactA = new BitmessageAddress(tmp.getAddress());
|
||||
contactA.setPubkey(tmp.getPubkey());
|
||||
addressRepo.save(contactA);
|
||||
contactB = new BitmessageAddress("BM-2cTtkBnb4BUYDndTKun6D9PjtueP2h1bQj");
|
||||
addressRepo.save(contactB);
|
||||
|
||||
identity = new BitmessageAddress(new PrivateKey(false, 1, 1000, 1000, DOES_ACK));
|
||||
addressRepo.save(identity);
|
||||
|
||||
inbox = repo.getLabels(Label.Type.INBOX).get(0);
|
||||
sent = repo.getLabels(Label.Type.SENT).get(0);
|
||||
drafts = repo.getLabels(Label.Type.DRAFT).get(0);
|
||||
unread = repo.getLabels(Label.Type.UNREAD).get(0);
|
||||
|
||||
addMessage(contactA, identity, Plaintext.Status.RECEIVED, inbox, unread);
|
||||
addMessage(identity, contactA, Plaintext.Status.DRAFT, drafts);
|
||||
addMessage(identity, contactB, Plaintext.Status.DRAFT, unread);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureLabelsAreRetrieved() throws Exception {
|
||||
List<Label> labels = repo.getLabels();
|
||||
assertEquals(5, labels.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureLabelsCanBeRetrievedByType() throws Exception {
|
||||
List<Label> labels = repo.getLabels(Label.Type.INBOX);
|
||||
assertEquals(1, labels.size());
|
||||
assertEquals("Inbox", labels.get(0).toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureMessagesCanBeFoundByLabel() throws Exception {
|
||||
List<Plaintext> messages = repo.findMessages(inbox);
|
||||
assertEquals(1, messages.size());
|
||||
Plaintext m = messages.get(0);
|
||||
assertEquals(contactA, m.getFrom());
|
||||
assertEquals(identity, m.getTo());
|
||||
assertEquals(Plaintext.Status.RECEIVED, m.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureUnreadMessagesCanBeFoundForAllLabels() {
|
||||
int unread = repo.countUnread(null);
|
||||
assertThat(unread, is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureUnreadMessagesCanBeFoundByLabel() {
|
||||
int unread = repo.countUnread(inbox);
|
||||
assertThat(unread, is(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureMessageCanBeRetrievedByInitialHash() {
|
||||
byte[] initialHash = new byte[64];
|
||||
Plaintext message = repo.findMessages(contactA).get(0);
|
||||
message.setInitialHash(initialHash);
|
||||
repo.save(message);
|
||||
Plaintext other = repo.getMessage(initialHash);
|
||||
assertThat(other, is(message));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureAckMessageCanBeUpdatedAndRetrieved() {
|
||||
byte[] initialHash = new byte[64];
|
||||
Plaintext message = repo.findMessages(contactA).get(0);
|
||||
message.setInitialHash(initialHash);
|
||||
ObjectMessage ackMessage = message.getAckMessage();
|
||||
repo.save(message);
|
||||
Plaintext other = repo.getMessage(initialHash);
|
||||
assertThat(other, is(message));
|
||||
assertThat(other.getAckMessage(), is(ackMessage));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMessagesByStatus() throws Exception {
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.RECEIVED);
|
||||
assertEquals(1, messages.size());
|
||||
Plaintext m = messages.get(0);
|
||||
assertEquals(contactA, m.getFrom());
|
||||
assertEquals(identity, m.getTo());
|
||||
assertEquals(Plaintext.Status.RECEIVED, m.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMessagesByStatusAndRecipient() throws Exception {
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.DRAFT, contactB);
|
||||
assertEquals(1, messages.size());
|
||||
Plaintext m = messages.get(0);
|
||||
assertEquals(identity, m.getFrom());
|
||||
assertEquals(contactB, m.getTo());
|
||||
assertEquals(Plaintext.Status.DRAFT, m.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSave() throws Exception {
|
||||
Plaintext message = new Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(identity)
|
||||
.to(contactA)
|
||||
.message("Subject", "Message")
|
||||
.status(Plaintext.Status.DOING_PROOF_OF_WORK)
|
||||
.build();
|
||||
repo.save(message);
|
||||
|
||||
assertNotNull(message.getId());
|
||||
|
||||
message.addLabels(inbox);
|
||||
repo.save(message);
|
||||
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.DOING_PROOF_OF_WORK);
|
||||
|
||||
assertEquals(1, messages.size());
|
||||
assertNotNull(messages.get(0).getInventoryVector());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdate() throws Exception {
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.DRAFT, contactA);
|
||||
Plaintext message = messages.get(0);
|
||||
message.setInventoryVector(TestUtils.randomInventoryVector());
|
||||
repo.save(message);
|
||||
|
||||
messages = repo.findMessages(Plaintext.Status.DRAFT, contactA);
|
||||
assertEquals(1, messages.size());
|
||||
assertNotNull(messages.get(0).getInventoryVector());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureMessageIsRemoved() throws Exception {
|
||||
Plaintext toRemove = repo.findMessages(Plaintext.Status.DRAFT, contactB).get(0);
|
||||
List<Plaintext> messages = repo.findMessages(Plaintext.Status.DRAFT);
|
||||
assertEquals(2, messages.size());
|
||||
repo.remove(toRemove);
|
||||
messages = repo.findMessages(Plaintext.Status.DRAFT);
|
||||
assertThat(messages, hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureUnacknowledgedMessagesAreFoundForResend() throws Exception {
|
||||
Plaintext message = new Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(identity)
|
||||
.to(contactA)
|
||||
.message("Subject", "Message")
|
||||
.sent(UnixTime.now())
|
||||
.status(Plaintext.Status.SENT)
|
||||
.ttl(2)
|
||||
.build();
|
||||
message.updateNextTry();
|
||||
assertThat(message.getRetries(), is(1));
|
||||
assertThat(message.getNextTry(), greaterThan(UnixTime.now()));
|
||||
assertThat(message.getNextTry(), lessThanOrEqualTo(UnixTime.now() + 2));
|
||||
repo.save(message);
|
||||
Thread.sleep(4100); // somewhat longer than 2*TTL
|
||||
List<Plaintext> messagesToResend = repo.findMessagesToResend();
|
||||
assertThat(messagesToResend, hasSize(1));
|
||||
|
||||
message.updateNextTry();
|
||||
assertThat(message.getRetries(), is(2));
|
||||
assertThat(message.getNextTry(), greaterThan(UnixTime.now()));
|
||||
repo.save(message);
|
||||
messagesToResend = repo.findMessagesToResend();
|
||||
assertThat(messagesToResend, empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureParentsAreSaved() {
|
||||
Plaintext parent = storeConversation();
|
||||
|
||||
List<Plaintext> responses = repo.findResponses(parent);
|
||||
assertThat(responses, hasSize(2));
|
||||
assertThat(responses, hasItem(hasMessage("Re: new test", "Nice!")));
|
||||
assertThat(responses, hasItem(hasMessage("Re: new test", "PS: it did work!")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureConversationCanBeRetrieved() {
|
||||
Plaintext root = storeConversation();
|
||||
List<UUID> conversations = repo.findConversations(inbox);
|
||||
assertThat(conversations, hasSize(2));
|
||||
assertThat(conversations, hasItem(root.getConversationId()));
|
||||
}
|
||||
|
||||
private Plaintext addMessage(BitmessageAddress from, BitmessageAddress to, Plaintext.Status status, Label... labels) {
|
||||
ExtendedEncoding content = new Message.Builder()
|
||||
.subject("Subject")
|
||||
.body("Message")
|
||||
.build();
|
||||
return addMessage(from, to, content, status, labels);
|
||||
}
|
||||
|
||||
private Plaintext addMessage(BitmessageAddress from, BitmessageAddress to,
|
||||
ExtendedEncoding content, Plaintext.Status status, Label... labels) {
|
||||
Plaintext message = new Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(from)
|
||||
.to(to)
|
||||
.message(content)
|
||||
.status(status)
|
||||
.labels(Arrays.asList(labels))
|
||||
.build();
|
||||
repo.save(message);
|
||||
return message;
|
||||
}
|
||||
|
||||
private Plaintext storeConversation() {
|
||||
Plaintext older = addMessage(identity, contactA,
|
||||
new Message.Builder()
|
||||
.subject("hey there")
|
||||
.body("does it work?")
|
||||
.build(),
|
||||
Plaintext.Status.SENT, sent);
|
||||
|
||||
Plaintext root = addMessage(identity, contactA,
|
||||
new Message.Builder()
|
||||
.subject("new test")
|
||||
.body("There's a new test in town!")
|
||||
.build(),
|
||||
Plaintext.Status.SENT, sent);
|
||||
|
||||
addMessage(contactA, identity,
|
||||
new Message.Builder()
|
||||
.subject("Re: new test")
|
||||
.body("Nice!")
|
||||
.addParent(root)
|
||||
.build(),
|
||||
Plaintext.Status.RECEIVED, inbox);
|
||||
|
||||
addMessage(contactA, identity,
|
||||
new Message.Builder()
|
||||
.subject("Re: new test")
|
||||
.body("PS: it did work!")
|
||||
.addParent(root)
|
||||
.addParent(older)
|
||||
.build(),
|
||||
Plaintext.Status.RECEIVED, inbox);
|
||||
|
||||
return repo.getMessage(root.getId());
|
||||
}
|
||||
|
||||
private Matcher<Plaintext> hasMessage(String subject, String body) {
|
||||
return new BaseMatcher<Plaintext>() {
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("Subject: ").appendText(subject);
|
||||
description.appendText(", ");
|
||||
description.appendText("Body: ").appendText(body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object item) {
|
||||
if (item instanceof Plaintext) {
|
||||
Plaintext message = (Plaintext) item;
|
||||
if (subject != null && !subject.equals(message.getSubject())) {
|
||||
return false;
|
||||
}
|
||||
if (body != null && !body.equals(message.getText())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository;
|
||||
|
||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
|
||||
import ch.dissem.bitmessage.ports.NodeRegistry;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static ch.dissem.bitmessage.utils.UnixTime.now;
|
||||
import static org.hamcrest.Matchers.empty;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* Please note that some tests fail if there is no internet connection,
|
||||
* as the initial nodes' IP addresses are determined by DNS lookup.
|
||||
*/
|
||||
public class JdbcNodeRegistryTest extends TestBase {
|
||||
private TestJdbcConfig config;
|
||||
private NodeRegistry registry;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
config = new TestJdbcConfig();
|
||||
config.reset();
|
||||
registry = new JdbcNodeRegistry(config);
|
||||
|
||||
registry.offerAddresses(Arrays.asList(
|
||||
createAddress(1, 8444, 1, now()),
|
||||
createAddress(2, 8444, 1, now()),
|
||||
createAddress(3, 8444, 1, now()),
|
||||
createAddress(4, 8444, 2, now())
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureGetKnownNodesWithoutStreamsYieldsEmpty() {
|
||||
assertThat(registry.getKnownAddresses(10), empty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensurePredefinedNodeIsReturnedWhenDatabaseIsEmpty() throws Exception {
|
||||
config.reset();
|
||||
List<NetworkAddress> knownAddresses = registry.getKnownAddresses(2, 1);
|
||||
assertEquals(1, knownAddresses.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetKnownAddresses() throws Exception {
|
||||
List<NetworkAddress> knownAddresses = registry.getKnownAddresses(2, 1);
|
||||
assertEquals(2, knownAddresses.size());
|
||||
|
||||
knownAddresses = registry.getKnownAddresses(1000, 1);
|
||||
assertEquals(3, knownAddresses.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOfferAddresses() throws Exception {
|
||||
registry.offerAddresses(Arrays.asList(
|
||||
createAddress(1, 8444, 1, now()),
|
||||
createAddress(10, 8444, 1, now()),
|
||||
createAddress(11, 8444, 1, now())
|
||||
));
|
||||
|
||||
List<NetworkAddress> knownAddresses = registry.getKnownAddresses(1000, 1);
|
||||
assertEquals(5, knownAddresses.size());
|
||||
|
||||
registry.offerAddresses(Collections.singletonList(
|
||||
createAddress(1, 8445, 1, now())
|
||||
));
|
||||
|
||||
knownAddresses = registry.getKnownAddresses(1000, 1);
|
||||
assertEquals(6, knownAddresses.size());
|
||||
}
|
||||
|
||||
private NetworkAddress createAddress(int lastByte, int port, long stream, long time) {
|
||||
return new NetworkAddress.Builder()
|
||||
.ipv6(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, lastByte)
|
||||
.port(port)
|
||||
.stream(stream)
|
||||
.time(time)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository
|
||||
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey.Feature.DOES_ACK
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
class JdbcAddressRepositoryTest : TestBase() {
|
||||
private val CONTACT_A = "BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"
|
||||
private val CONTACT_B = "BM-2cTtkBnb4BUYDndTKun6D9PjtueP2h1bQj"
|
||||
private val CONTACT_C = "BM-2cV5f9EpzaYARxtoruSpa6pDoucSf9ZNke"
|
||||
|
||||
private lateinit var IDENTITY_A: String
|
||||
private lateinit var IDENTITY_B: String
|
||||
|
||||
private lateinit var config: TestJdbcConfig
|
||||
private lateinit var repo: JdbcAddressRepository
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
config = TestJdbcConfig()
|
||||
config.reset()
|
||||
|
||||
repo = JdbcAddressRepository(config)
|
||||
|
||||
repo.save(BitmessageAddress(CONTACT_A))
|
||||
repo.save(BitmessageAddress(CONTACT_B))
|
||||
repo.save(BitmessageAddress(CONTACT_C))
|
||||
|
||||
val identityA = BitmessageAddress(PrivateKey(false, 1, 1000, 1000, DOES_ACK))
|
||||
repo.save(identityA)
|
||||
IDENTITY_A = identityA.address
|
||||
val identityB = BitmessageAddress(PrivateKey(false, 1, 1000, 1000))
|
||||
repo.save(identityB)
|
||||
IDENTITY_B = identityB.address
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure contact can be found`() {
|
||||
val address = BitmessageAddress(CONTACT_A)
|
||||
assertEquals(4, address.version)
|
||||
assertEquals(address, repo.findContact(address.tag!!))
|
||||
assertNull(repo.findIdentity(address.tag!!))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure identity can be found`() {
|
||||
val identity = BitmessageAddress(IDENTITY_A)
|
||||
assertEquals(4, identity.version)
|
||||
assertNull(repo.findContact(identity.tag!!))
|
||||
|
||||
val storedIdentity = repo.findIdentity(identity.tag!!)
|
||||
assertEquals(identity, storedIdentity)
|
||||
assertTrue(storedIdentity!!.has(DOES_ACK))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure identities are retrieved`() {
|
||||
val identities = repo.getIdentities()
|
||||
assertEquals(2, identities.size.toLong())
|
||||
for (identity in identities) {
|
||||
assertNotNull(identity.privateKey)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure subscriptions are retrieved`() {
|
||||
addSubscription("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h")
|
||||
addSubscription("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ")
|
||||
addSubscription("BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh")
|
||||
val subscriptions = repo.getSubscriptions()
|
||||
assertEquals(3, subscriptions.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure subscriptions are retrieved for given version`() {
|
||||
addSubscription("BM-2cXxfcSetKnbHJX2Y85rSkaVpsdNUZ5q9h")
|
||||
addSubscription("BM-2D9Vc5rFxxR5vTi53T9gkLfemViHRMVLQZ")
|
||||
addSubscription("BM-2D9QKN4teYRvoq2fyzpiftPh9WP9qggtzh")
|
||||
|
||||
var subscriptions = repo.getSubscriptions(5)
|
||||
|
||||
assertEquals(1, subscriptions.size.toLong())
|
||||
|
||||
subscriptions = repo.getSubscriptions(4)
|
||||
assertEquals(2, subscriptions.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure contacts are retrieved`() {
|
||||
val contacts = repo.getContacts()
|
||||
assertEquals(3, contacts.size.toLong())
|
||||
for (contact in contacts) {
|
||||
assertNull(contact.privateKey)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure new address is saved`() {
|
||||
repo.save(BitmessageAddress(PrivateKey(false, 1, 1000, 1000)))
|
||||
val identities = repo.getIdentities()
|
||||
assertEquals(3, identities.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure existing address is updated`() {
|
||||
var address = repo.getAddress(CONTACT_A)
|
||||
address!!.alias = "Test-Alias"
|
||||
repo.save(address)
|
||||
address = repo.getAddress(address.address)
|
||||
assertEquals("Test-Alias", address!!.alias)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure existing keys are not deleted`() {
|
||||
val address = BitmessageAddress(IDENTITY_A)
|
||||
address.alias = "Test"
|
||||
repo.save(address)
|
||||
val identityA = repo.getAddress(IDENTITY_A)
|
||||
assertNotNull(identityA!!.pubkey)
|
||||
assertNotNull(identityA.privateKey)
|
||||
assertEquals("Test", identityA.alias)
|
||||
assertFalse(identityA.isChan)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure new chan is saved and updated`() {
|
||||
val chan = BitmessageAddress.chan(1, "test")
|
||||
repo.save(chan)
|
||||
var address = repo.getAddress(chan.address)
|
||||
assertNotNull(address)
|
||||
assertTrue(address!!.isChan)
|
||||
|
||||
address.alias = "Test"
|
||||
repo.save(address)
|
||||
|
||||
address = repo.getAddress(chan.address)
|
||||
assertNotNull(address)
|
||||
assertTrue(address!!.isChan)
|
||||
assertEquals("Test", address.alias)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure address is removed`() {
|
||||
val address = repo.getAddress(IDENTITY_A)
|
||||
repo.remove(address!!)
|
||||
assertNull(repo.getAddress(IDENTITY_A))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure address can be retrieved`() {
|
||||
val address = repo.getAddress(IDENTITY_A)
|
||||
assertNotNull(address)
|
||||
assertNotNull(address!!.privateKey)
|
||||
}
|
||||
|
||||
private fun addSubscription(address: String) {
|
||||
val subscription = BitmessageAddress(address)
|
||||
subscription.isSubscribed = true
|
||||
repo.save(subscription)
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository
|
||||
|
||||
import ch.dissem.bitmessage.entity.BitmessageAddress
|
||||
import ch.dissem.bitmessage.entity.ObjectMessage
|
||||
import ch.dissem.bitmessage.entity.payload.GetPubkey
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectPayload
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectType.GET_PUBKEY
|
||||
import ch.dissem.bitmessage.entity.payload.ObjectType.MSG
|
||||
import ch.dissem.bitmessage.entity.valueobject.InventoryVector
|
||||
import ch.dissem.bitmessage.ports.Inventory
|
||||
import ch.dissem.bitmessage.utils.UnixTime.DAY
|
||||
import ch.dissem.bitmessage.utils.UnixTime.now
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
class JdbcInventoryTest : TestBase() {
|
||||
private lateinit var config: TestJdbcConfig
|
||||
private lateinit var inventory: Inventory
|
||||
|
||||
private lateinit var inventoryVector1: InventoryVector
|
||||
private lateinit var inventoryVector2: InventoryVector
|
||||
private lateinit var inventoryVectorIgnore: InventoryVector
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
config = TestJdbcConfig()
|
||||
config.reset()
|
||||
|
||||
inventory = JdbcInventory(config)
|
||||
|
||||
val object1 = getObjectMessage(1, 300, getPubkey)
|
||||
inventoryVector1 = object1.inventoryVector
|
||||
inventory.storeObject(object1)
|
||||
|
||||
val object2 = getObjectMessage(2, 300, getPubkey)
|
||||
inventoryVector2 = object2.inventoryVector
|
||||
inventory.storeObject(object2)
|
||||
|
||||
val ignore = getObjectMessage(1, -1 * DAY, getPubkey)
|
||||
inventoryVectorIgnore = ignore.inventoryVector
|
||||
inventory.storeObject(ignore)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure inventory can be retrieved`() {
|
||||
var inventoryVectors = inventory.getInventory(1)
|
||||
assertEquals(1, inventoryVectors.size.toLong())
|
||||
|
||||
inventoryVectors = inventory.getInventory(2)
|
||||
assertEquals(1, inventoryVectors.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure the IVs of missing objects are returned`() {
|
||||
val newIV = getObjectMessage(1, 200, getPubkey).inventoryVector
|
||||
val offer = LinkedList<InventoryVector>()
|
||||
offer.add(newIV)
|
||||
offer.add(inventoryVector1)
|
||||
val missing = inventory.getMissing(offer, 1, 2)
|
||||
assertEquals(1, missing.size.toLong())
|
||||
assertEquals(newIV, missing[0])
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure single object can be retrieved`() {
|
||||
val `object` = inventory.getObject(inventoryVectorIgnore)
|
||||
assertNotNull(`object`)
|
||||
assertEquals(1, `object`!!.stream)
|
||||
assertEquals(inventoryVectorIgnore, `object`.inventoryVector)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure objects can be retrieved`() {
|
||||
var objects = inventory.getObjects(1, 4)
|
||||
assertEquals(2, objects.size.toLong())
|
||||
|
||||
objects = inventory.getObjects(1, 4, GET_PUBKEY)
|
||||
assertEquals(2, objects.size.toLong())
|
||||
|
||||
objects = inventory.getObjects(1, 4, MSG)
|
||||
assertEquals(0, objects.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure object can be stored`() {
|
||||
val `object` = getObjectMessage(5, 0, getPubkey)
|
||||
inventory.storeObject(`object`)
|
||||
|
||||
assertNotNull(inventory.getObject(`object`.inventoryVector))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure contained objects are recognized`() {
|
||||
val `object` = getObjectMessage(5, 0, getPubkey)
|
||||
|
||||
assertFalse(inventory.contains(`object`))
|
||||
|
||||
inventory.storeObject(`object`)
|
||||
|
||||
assertTrue(inventory.contains(`object`))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure inventory is cleaned up`() {
|
||||
assertNotNull(inventory.getObject(inventoryVectorIgnore))
|
||||
inventory.cleanup()
|
||||
assertNull(inventory.getObject(inventoryVectorIgnore))
|
||||
}
|
||||
|
||||
private fun getObjectMessage(stream: Long, TTL: Long, payload: ObjectPayload): ObjectMessage {
|
||||
return ObjectMessage(
|
||||
nonce = ByteArray(8),
|
||||
expiresTime = now + TTL,
|
||||
stream = stream,
|
||||
payload = payload
|
||||
)
|
||||
}
|
||||
|
||||
private val getPubkey: GetPubkey = GetPubkey(BitmessageAddress("BM-2cW7cD5cDQJDNkE7ibmyTxfvGAmnPqa9Vt"))
|
||||
}
|
@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository
|
||||
|
||||
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.Plaintext.Type.MSG
|
||||
import ch.dissem.bitmessage.entity.payload.Pubkey.Feature.DOES_ACK
|
||||
import ch.dissem.bitmessage.entity.valueobject.ExtendedEncoding
|
||||
import ch.dissem.bitmessage.entity.valueobject.Label
|
||||
import ch.dissem.bitmessage.entity.valueobject.PrivateKey
|
||||
import ch.dissem.bitmessage.entity.valueobject.extended.Message
|
||||
import ch.dissem.bitmessage.ports.MessageRepository
|
||||
import ch.dissem.bitmessage.utils.TestUtils
|
||||
import ch.dissem.bitmessage.utils.TestUtils.mockedInternalContext
|
||||
import ch.dissem.bitmessage.utils.UnixTime
|
||||
import org.hamcrest.BaseMatcher
|
||||
import org.hamcrest.CoreMatchers.`is`
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers.*
|
||||
import org.junit.Assert.*
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
class JdbcMessageRepositoryTest : TestBase() {
|
||||
private lateinit var contactA: BitmessageAddress
|
||||
private lateinit var contactB: BitmessageAddress
|
||||
private lateinit var identity: BitmessageAddress
|
||||
|
||||
private lateinit var repo: MessageRepository
|
||||
|
||||
private lateinit var inbox: Label
|
||||
private lateinit var sent: Label
|
||||
private lateinit var drafts: Label
|
||||
private lateinit var unread: Label
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
val config = TestJdbcConfig()
|
||||
config.reset()
|
||||
val addressRepo = JdbcAddressRepository(config)
|
||||
repo = JdbcMessageRepository(config)
|
||||
mockedInternalContext(
|
||||
cryptography = BouncyCryptography(),
|
||||
addressRepository = addressRepo,
|
||||
messageRepository = repo,
|
||||
port = 12345,
|
||||
connectionTTL = 10,
|
||||
connectionLimit = 10
|
||||
)
|
||||
val tmp = BitmessageAddress(PrivateKey(false, 1, 1000, 1000, DOES_ACK))
|
||||
contactA = BitmessageAddress(tmp.address)
|
||||
contactA.pubkey = tmp.pubkey
|
||||
addressRepo.save(contactA)
|
||||
contactB = BitmessageAddress("BM-2cTtkBnb4BUYDndTKun6D9PjtueP2h1bQj")
|
||||
addressRepo.save(contactB)
|
||||
|
||||
identity = BitmessageAddress(PrivateKey(false, 1, 1000, 1000, DOES_ACK))
|
||||
addressRepo.save(identity)
|
||||
|
||||
inbox = repo.getLabels(Label.Type.INBOX)[0]
|
||||
sent = repo.getLabels(Label.Type.SENT)[0]
|
||||
drafts = repo.getLabels(Label.Type.DRAFT)[0]
|
||||
unread = repo.getLabels(Label.Type.UNREAD)[0]
|
||||
|
||||
addMessage(contactA, identity, Plaintext.Status.RECEIVED, inbox, unread)
|
||||
addMessage(identity, contactA, Plaintext.Status.DRAFT, drafts)
|
||||
addMessage(identity, contactB, Plaintext.Status.DRAFT, unread)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure labels are retrieved`() {
|
||||
val labels = repo.getLabels()
|
||||
assertEquals(5, labels.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure labels can be retrieved by type`() {
|
||||
val labels = repo.getLabels(Label.Type.INBOX)
|
||||
assertEquals(1, labels.size.toLong())
|
||||
assertEquals("Inbox", labels[0].toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure messages can be found by label`() {
|
||||
val messages = repo.findMessages(inbox)
|
||||
assertEquals(1, messages.size.toLong())
|
||||
val m = messages[0]
|
||||
assertEquals(contactA, m.from)
|
||||
assertEquals(identity, m.to)
|
||||
assertEquals(Plaintext.Status.RECEIVED, m.status)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure unread messages can be found for all labels`() {
|
||||
val unread = repo.countUnread(null)
|
||||
assertThat(unread, `is`(2))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure unread messages can be found by label`() {
|
||||
val unread = repo.countUnread(inbox)
|
||||
assertThat(unread, `is`(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure message can be retrieved by initial hash`() {
|
||||
val initialHash = ByteArray(64)
|
||||
val message = repo.findMessages(contactA)[0]
|
||||
message.initialHash = initialHash
|
||||
repo.save(message)
|
||||
val other = repo.getMessage(initialHash)
|
||||
assertThat<Plaintext>(other, `is`(message))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure ack message can be updated and retrieved`() {
|
||||
val initialHash = ByteArray(64)
|
||||
val message = repo.findMessages(contactA)[0]
|
||||
message.initialHash = initialHash
|
||||
val ackMessage = message.ackMessage
|
||||
repo.save(message)
|
||||
val other = repo.getMessage(initialHash)!!
|
||||
assertThat<Plaintext>(other, `is`(message))
|
||||
assertThat<ObjectMessage>(other.ackMessage, `is`<ObjectMessage>(ackMessage))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure messages can be found by status`() {
|
||||
val messages = repo.findMessages(Plaintext.Status.RECEIVED)
|
||||
assertEquals(1, messages.size.toLong())
|
||||
val m = messages[0]
|
||||
assertEquals(contactA, m.from)
|
||||
assertEquals(identity, m.to)
|
||||
assertEquals(Plaintext.Status.RECEIVED, m.status)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure messages can be found by status and recipient`() {
|
||||
val messages = repo.findMessages(Plaintext.Status.DRAFT, contactB)
|
||||
assertEquals(1, messages.size.toLong())
|
||||
val m = messages[0]
|
||||
assertEquals(identity, m.from)
|
||||
assertEquals(contactB, m.to)
|
||||
assertEquals(Plaintext.Status.DRAFT, m.status)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure message can be saved`() {
|
||||
val message = Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(identity)
|
||||
.to(contactA)
|
||||
.message("Subject", "Message")
|
||||
.status(Plaintext.Status.DOING_PROOF_OF_WORK)
|
||||
.build()
|
||||
repo.save(message)
|
||||
|
||||
assertNotNull(message.id)
|
||||
|
||||
message.addLabels(inbox)
|
||||
repo.save(message)
|
||||
|
||||
val messages = repo.findMessages(Plaintext.Status.DOING_PROOF_OF_WORK)
|
||||
|
||||
assertEquals(1, messages.size.toLong())
|
||||
assertNotNull(messages[0].inventoryVector)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure message can be updated`() {
|
||||
var messages = repo.findMessages(Plaintext.Status.DRAFT, contactA)
|
||||
val message = messages[0]
|
||||
message.inventoryVector = TestUtils.randomInventoryVector()
|
||||
repo.save(message)
|
||||
|
||||
messages = repo.findMessages(Plaintext.Status.DRAFT, contactA)
|
||||
assertEquals(1, messages.size.toLong())
|
||||
assertNotNull(messages[0].inventoryVector)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure message is removed`() {
|
||||
val toRemove = repo.findMessages(Plaintext.Status.DRAFT, contactB)[0]
|
||||
var messages = repo.findMessages(Plaintext.Status.DRAFT)
|
||||
assertEquals(2, messages.size.toLong())
|
||||
repo.remove(toRemove)
|
||||
messages = repo.findMessages(Plaintext.Status.DRAFT)
|
||||
assertThat(messages, hasSize<Plaintext>(1))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure unacknowledged messages are found for resend`() {
|
||||
val message = Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(identity)
|
||||
.to(contactA)
|
||||
.message("Subject", "Message")
|
||||
.sent(UnixTime.now)
|
||||
.status(Plaintext.Status.SENT)
|
||||
.ttl(2)
|
||||
.build()
|
||||
message.updateNextTry()
|
||||
assertThat(message.retries, `is`(1))
|
||||
assertThat<Long>(message.nextTry, greaterThan(UnixTime.now))
|
||||
assertThat<Long>(message.nextTry, lessThanOrEqualTo(UnixTime.now + 2))
|
||||
repo.save(message)
|
||||
Thread.sleep(4100) // somewhat longer than 2*TTL
|
||||
var messagesToResend = repo.findMessagesToResend()
|
||||
assertThat(messagesToResend, hasSize<Plaintext>(1))
|
||||
|
||||
message.updateNextTry()
|
||||
assertThat(message.retries, `is`(2))
|
||||
assertThat<Long>(message.nextTry, greaterThan(UnixTime.now))
|
||||
repo.save(message)
|
||||
messagesToResend = repo.findMessagesToResend()
|
||||
assertThat(messagesToResend, empty<Plaintext>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure parents are saved`() {
|
||||
val parent = storeConversation()
|
||||
|
||||
val responses = repo.findResponses(parent)
|
||||
assertThat(responses, hasSize<Plaintext>(2))
|
||||
assertThat(responses, hasItem(hasMessage("Re: new test", "Nice!")))
|
||||
assertThat(responses, hasItem(hasMessage("Re: new test", "PS: it did work!")))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure conversation can be retrieved`() {
|
||||
val root = storeConversation()
|
||||
val conversations = repo.findConversations(inbox)
|
||||
assertThat(conversations, hasSize<UUID>(2))
|
||||
assertThat(conversations, hasItem(root.conversationId))
|
||||
}
|
||||
|
||||
private fun addMessage(from: BitmessageAddress, to: BitmessageAddress, status: Plaintext.Status, vararg labels: Label): Plaintext {
|
||||
val content = Message.Builder()
|
||||
.subject("Subject")
|
||||
.body("Message")
|
||||
.build()
|
||||
return addMessage(from, to, content, status, *labels)
|
||||
}
|
||||
|
||||
private fun addMessage(from: BitmessageAddress, to: BitmessageAddress,
|
||||
content: ExtendedEncoding, status: Plaintext.Status, vararg labels: Label): Plaintext {
|
||||
val message = Plaintext.Builder(MSG)
|
||||
.IV(TestUtils.randomInventoryVector())
|
||||
.from(from)
|
||||
.to(to)
|
||||
.message(content)
|
||||
.status(status)
|
||||
.labels(Arrays.asList(*labels))
|
||||
.build()
|
||||
repo.save(message)
|
||||
return message
|
||||
}
|
||||
|
||||
private fun storeConversation(): Plaintext {
|
||||
val older = addMessage(identity, contactA,
|
||||
Message.Builder()
|
||||
.subject("hey there")
|
||||
.body("does it work?")
|
||||
.build(),
|
||||
Plaintext.Status.SENT, sent)
|
||||
|
||||
val root = addMessage(identity, contactA,
|
||||
Message.Builder()
|
||||
.subject("new test")
|
||||
.body("There's a new test in town!")
|
||||
.build(),
|
||||
Plaintext.Status.SENT, sent)
|
||||
|
||||
addMessage(contactA, identity,
|
||||
Message.Builder()
|
||||
.subject("Re: new test")
|
||||
.body("Nice!")
|
||||
.addParent(root)
|
||||
.build(),
|
||||
Plaintext.Status.RECEIVED, inbox)
|
||||
|
||||
addMessage(contactA, identity,
|
||||
Message.Builder()
|
||||
.subject("Re: new test")
|
||||
.body("PS: it did work!")
|
||||
.addParent(root)
|
||||
.addParent(older)
|
||||
.build(),
|
||||
Plaintext.Status.RECEIVED, inbox)
|
||||
|
||||
return repo.getMessage(root.id!!)
|
||||
}
|
||||
|
||||
private fun hasMessage(subject: String?, body: String?): Matcher<Plaintext> {
|
||||
return object : BaseMatcher<Plaintext>() {
|
||||
override fun describeTo(description: Description) {
|
||||
description.appendText("Subject: ").appendText(subject)
|
||||
description.appendText(", ")
|
||||
description.appendText("Body: ").appendText(body)
|
||||
}
|
||||
|
||||
override fun matches(item: Any): Boolean {
|
||||
if (item is Plaintext) {
|
||||
if (subject != null && subject != item.subject) {
|
||||
return false
|
||||
}
|
||||
if (body != null && body != item.text) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2015 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.repository
|
||||
|
||||
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress
|
||||
import ch.dissem.bitmessage.ports.NodeRegistry
|
||||
import ch.dissem.bitmessage.utils.UnixTime.now
|
||||
import org.hamcrest.Matchers.empty
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Please note that some tests fail if there is no internet connection,
|
||||
* as the initial nodes' IP addresses are determined by DNS lookup.
|
||||
*/
|
||||
class JdbcNodeRegistryTest : TestBase() {
|
||||
private lateinit var config: TestJdbcConfig
|
||||
private lateinit var registry: NodeRegistry
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
config = TestJdbcConfig()
|
||||
config.reset()
|
||||
registry = JdbcNodeRegistry(config)
|
||||
|
||||
registry.offerAddresses(Arrays.asList(
|
||||
createAddress(1, 8444, 1, now),
|
||||
createAddress(2, 8444, 1, now),
|
||||
createAddress(3, 8444, 1, now),
|
||||
createAddress(4, 8444, 2, now)
|
||||
))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure getKnownNodes() without streams yields empty`() {
|
||||
assertThat(registry.getKnownAddresses(10), empty<NetworkAddress>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure predefined node is returned when database is empty`() {
|
||||
config.reset()
|
||||
val knownAddresses = registry.getKnownAddresses(2, 1)
|
||||
assertEquals(1, knownAddresses.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure known addresses are retrieved`() {
|
||||
var knownAddresses = registry.getKnownAddresses(2, 1)
|
||||
assertEquals(2, knownAddresses.size.toLong())
|
||||
|
||||
knownAddresses = registry.getKnownAddresses(1000, 1)
|
||||
assertEquals(3, knownAddresses.size.toLong())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ensure offered addresses are added`() {
|
||||
registry.offerAddresses(Arrays.asList(
|
||||
createAddress(1, 8444, 1, now),
|
||||
createAddress(10, 8444, 1, now),
|
||||
createAddress(11, 8444, 1, now)
|
||||
))
|
||||
|
||||
var knownAddresses = registry.getKnownAddresses(1000, 1)
|
||||
assertEquals(5, knownAddresses.size.toLong())
|
||||
|
||||
registry.offerAddresses(listOf(createAddress(1, 8445, 1, now)))
|
||||
|
||||
knownAddresses = registry.getKnownAddresses(1000, 1)
|
||||
assertEquals(6, knownAddresses.size.toLong())
|
||||
}
|
||||
|
||||
private fun createAddress(lastByte: Int, port: Int, stream: Long, time: Long): NetworkAddress {
|
||||
return NetworkAddress.Builder()
|
||||
.ipv6(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, lastByte)
|
||||
.port(port)
|
||||
.stream(stream)
|
||||
.time(time)
|
||||
.build()
|
||||
}
|
||||
}
|
@ -14,35 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package ch.dissem.bitmessage.repository;
|
||||
package ch.dissem.bitmessage.repository
|
||||
|
||||
import org.h2.tools.Server;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import org.h2.tools.Server
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
/**
|
||||
* JdbcConfig to be used for tests. Uses an in-memory database and adds a useful {@link #reset()} method resetting
|
||||
* JdbcConfig to be used for tests. Uses an in-memory database and adds a useful [.reset] method resetting
|
||||
* the database.
|
||||
*/
|
||||
public class TestJdbcConfig extends JdbcConfig {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TestJdbcConfig.class);
|
||||
class TestJdbcConfig : JdbcConfig("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", null) {
|
||||
|
||||
static {
|
||||
try {
|
||||
Server.createTcpServer().start();
|
||||
} catch (SQLException e) {
|
||||
LOG.error(e.getMessage(), e);
|
||||
fun reset() {
|
||||
flyway.clean()
|
||||
flyway.migrate()
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Server.createTcpServer().start()
|
||||
}
|
||||
}
|
||||
|
||||
public TestJdbcConfig() {
|
||||
super("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", null);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
getFlyway().clean();
|
||||
getFlyway().migrate();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user