Merge branch 'name-fixes' into launch

This commit is contained in:
catbref
2020-05-18 10:12:31 +01:00
24 changed files with 1115 additions and 231 deletions

View File

@@ -0,0 +1,38 @@
package org.qortal.test;
import static org.junit.Assert.*;
import static org.qortal.utils.Unicode.*;
import org.junit.Test;
import org.qortal.utils.Unicode;
public class UnicodeTests {
@Test
public void testWhitespace() {
String input = " " + NO_BREAK_SPACE + "test ";
String output = Unicode.normalize(input);
assertEquals("trim & collapse failed", "test", output);
}
@Test
public void testCaseComparison() {
String input1 = " " + NO_BREAK_SPACE + "test ";
String input2 = " " + NO_BREAK_SPACE + "TEST " + ZERO_WIDTH_SPACE;
assertEquals("strings should match", Unicode.sanitize(input1), Unicode.sanitize(input2));
}
@Test
public void testHomoglyph() {
String omicron = "\u03bf";
String input1 = " " + NO_BREAK_SPACE + "toÁst ";
String input2 = " " + NO_BREAK_SPACE + "t" + omicron + "ast " + ZERO_WIDTH_SPACE;
assertEquals("strings should match", Unicode.sanitize(input1), Unicode.sanitize(input2));
}
}

View File

@@ -46,7 +46,7 @@ public class NamesApiTests extends ApiCommon {
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
assertNotNull(this.namesResource.getNamesByAddress(alice.getAddress(), null, null, null));
@@ -61,7 +61,7 @@ public class NamesApiTests extends ApiCommon {
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
assertNotNull(this.namesResource.getName(name));
@@ -76,7 +76,7 @@ public class NamesApiTests extends ApiCommon {
String name = "test-name";
long price = 1_23456789L;
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
// Sell-name

View File

@@ -9,14 +9,13 @@ import org.qortal.repository.Repository;
public class RegisterNameTestTransaction extends TestTransaction {
public static TransactionData randomTransaction(Repository repository, PrivateKeyAccount account, boolean wantValid) throws DataException {
String owner = account.getAddress();
String name = "test name";
if (!wantValid)
name += " " + random.nextInt(1_000_000);
String data = "{ \"key\": \"value\" }";
return new RegisterNameTransactionData(generateBase(account), owner, name, data);
return new RegisterNameTransactionData(generateBase(account), name, data);
}
}

View File

@@ -61,7 +61,7 @@ public class BuySellTests extends Common {
@Test
public void testRegisterName() throws DataException {
// Register-name
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, "{}");
TransactionUtils.signAndMint(repository, transactionData, alice);
String name = transactionData.getName();
@@ -95,7 +95,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", price, nameData.getSalePrice());
// Orphan sell-name
@@ -103,7 +103,7 @@ public class BuySellTests extends Common {
// Check name no longer for sale
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
// Re-process sell-name
@@ -111,7 +111,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", price, nameData.getSalePrice());
// Orphan sell-name and register-name
@@ -133,7 +133,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", price, nameData.getSalePrice());
}
@@ -150,7 +150,7 @@ public class BuySellTests extends Common {
// Check name is no longer for sale
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
// Orphan cancel sell-name
@@ -158,7 +158,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", price, nameData.getSalePrice());
}
@@ -177,7 +177,7 @@ public class BuySellTests extends Common {
// Check name is sold
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
// Orphan buy-name
@@ -185,7 +185,7 @@ public class BuySellTests extends Common {
// Check name is for sale (not sold)
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", price, nameData.getSalePrice());
// Re-process buy-name
@@ -193,7 +193,7 @@ public class BuySellTests extends Common {
// Check name is sold
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
assertEquals(bob.getAddress(), nameData.getOwner());
@@ -202,7 +202,7 @@ public class BuySellTests extends Common {
// Check name no longer for sale
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
assertEquals(alice.getAddress(), nameData.getOwner());
@@ -214,7 +214,7 @@ public class BuySellTests extends Common {
// Check name is sold
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
assertEquals(bob.getAddress(), nameData.getOwner());
}
@@ -233,7 +233,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", newPrice, nameData.getSalePrice());
// Orphan sell-name
@@ -241,7 +241,7 @@ public class BuySellTests extends Common {
// Check name no longer for sale
nameData = repository.getNameRepository().fromName(name);
assertFalse(nameData.getIsForSale());
assertFalse(nameData.isForSale());
// Not concerned about price
// Re-process sell-name
@@ -249,7 +249,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", newPrice, nameData.getSalePrice());
// Orphan sell-name and buy-name
@@ -257,7 +257,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
// Note: original sale price
assertEquals("price incorrect", price, nameData.getSalePrice());
assertEquals(alice.getAddress(), nameData.getOwner());
@@ -273,7 +273,7 @@ public class BuySellTests extends Common {
// Check name is for sale
nameData = repository.getNameRepository().fromName(name);
assertTrue(nameData.getIsForSale());
assertTrue(nameData.isForSale());
assertEquals("price incorrect", newPrice, nameData.getSalePrice());
assertEquals(bob.getAddress(), nameData.getOwner());
}

View File

@@ -8,12 +8,16 @@ import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.data.transaction.RegisterNameTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.data.transaction.UpdateNameTransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.Common;
import org.qortal.test.common.TransactionUtils;
import org.qortal.test.common.transaction.TestTransaction;
import org.qortal.transaction.Transaction;
import org.qortal.transaction.Transaction.ValidationResult;
public class MiscTests extends Common {
@@ -27,9 +31,10 @@ public class MiscTests extends Common {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
String name = "initial-name";
String data = "initial-data";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), alice.getAddress(), name, "{}");
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, data);
TransactionUtils.signAndMint(repository, transactionData, alice);
List<String> recentNames = repository.getNameRepository().getRecentNames(0L);
@@ -39,4 +44,56 @@ public class MiscTests extends Common {
}
}
// test trying to register same name twice
@Test
public void testDuplicateRegisterName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
String data = "{}";
RegisterNameTransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, data);
TransactionUtils.signAndMint(repository, transactionData, alice);
// duplicate
String duplicateName = "TEST-nÁme";
transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), duplicateName, data);
Transaction transaction = Transaction.fromData(repository, transactionData);
transaction.sign(alice);
ValidationResult result = transaction.importAsUnconfirmed();
assertTrue("Transaction should be invalid", ValidationResult.OK != result);
}
}
// test register then trying to update another name to existing name
@Test
public void testUpdateToExistingName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String name = "test-name";
String data = "{}";
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, data);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Register another name that we will later attempt to rename to first name (above)
String otherName = "new-name";
String otherData = "";
transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), otherName, otherData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// we shouldn't be able to update name to existing name
String duplicateName = "TEST-nÁme";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), otherName, duplicateName, otherData);
Transaction transaction = Transaction.fromData(repository, transactionData);
transaction.sign(alice);
ValidationResult result = transaction.importAsUnconfirmed();
assertTrue("Transaction should be invalid", ValidationResult.OK != result);
}
}
}

View File

@@ -0,0 +1,334 @@
package org.qortal.test.naming;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.data.transaction.RegisterNameTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.data.transaction.UpdateNameTransactionData;
import org.qortal.repository.DataException;
import org.qortal.repository.Repository;
import org.qortal.repository.RepositoryManager;
import org.qortal.test.common.BlockUtils;
import org.qortal.test.common.Common;
import org.qortal.test.common.TransactionUtils;
import org.qortal.test.common.transaction.TestTransaction;
public class UpdateTests extends Common {
@Before
public void beforeTest() throws DataException {
Common.useDefaultSettings();
}
@Test
public void testUpdateName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData initialTransactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, initialTransactionData, alice);
String newName = "new-name";
String newData = "";
TransactionData updateTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, newName, newData);
TransactionUtils.signAndMint(repository, updateTransactionData, alice);
// Check old name no longer exists
assertFalse(repository.getNameRepository().nameExists(initialName));
// Check new name exists
assertTrue(repository.getNameRepository().nameExists(newName));
// Check updated timestamp is correct
assertEquals((Long) updateTransactionData.getTimestamp(), repository.getNameRepository().fromName(newName).getUpdated());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check new name no longer exists
assertFalse(repository.getNameRepository().nameExists(newName));
// Check old name exists again
assertTrue(repository.getNameRepository().nameExists(initialName));
// Check updated timestamp is empty
assertNull(repository.getNameRepository().fromName(initialName).getUpdated());
}
}
@Test
public void testUpdateNameSameOwner() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData initialTransactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, initialTransactionData, alice);
String newName = "Initial-Name";
String newData = "";
TransactionData updateTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, newName, newData);
TransactionUtils.signAndMint(repository, updateTransactionData, alice);
// Check old name no longer exists
assertFalse(repository.getNameRepository().nameExists(initialName));
// Check new name exists
assertTrue(repository.getNameRepository().nameExists(newName));
// Check updated timestamp is correct
assertEquals((Long) updateTransactionData.getTimestamp(), repository.getNameRepository().fromName(newName).getUpdated());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check new name no longer exists
assertFalse(repository.getNameRepository().nameExists(newName));
// Check old name exists again
assertTrue(repository.getNameRepository().nameExists(initialName));
// Check updated timestamp is empty
assertNull(repository.getNameRepository().fromName(initialName).getUpdated());
}
}
// Test that reverting using previous UPDATE_NAME works as expected
@Test
public void testDoubleUpdateName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData initialTransactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, initialTransactionData, alice);
String middleName = "middle-name";
String middleData = "";
TransactionData middleTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
TransactionUtils.signAndMint(repository, middleTransactionData, alice);
// Check old name no longer exists
assertFalse(repository.getNameRepository().nameExists(initialName));
// Check new name exists
assertTrue(repository.getNameRepository().nameExists(middleName));
String newestName = "newest-name";
String newestData = "newest-data";
TransactionData newestTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), middleName, newestName, newestData);
TransactionUtils.signAndMint(repository, newestTransactionData, alice);
// Check previous name no longer exists
assertFalse(repository.getNameRepository().nameExists(middleName));
// Check newest name exists
assertTrue(repository.getNameRepository().nameExists(newestName));
// Check updated timestamp is correct
assertEquals((Long) newestTransactionData.getTimestamp(), repository.getNameRepository().fromName(newestName).getUpdated());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check newest name no longer exists
assertFalse(repository.getNameRepository().nameExists(newestName));
// Check previous name exists again
assertTrue(repository.getNameRepository().nameExists(middleName));
// Check updated timestamp is correct
assertEquals((Long) middleTransactionData.getTimestamp(), repository.getNameRepository().fromName(middleName).getUpdated());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check new name no longer exists
assertFalse(repository.getNameRepository().nameExists(middleName));
// Check original name exists again
assertTrue(repository.getNameRepository().nameExists(initialName));
// Check updated timestamp is empty
assertNull(repository.getNameRepository().fromName(initialName).getUpdated());
}
}
// Test that reverting using previous UPDATE_NAME works as expected
@Test
public void testIntermediateUpdateName() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Don't update name, but update data.
// This tests whether reverting a future update/sale can find the correct previous name
String middleName = "";
String middleData = "middle-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check old name still exists
assertTrue(repository.getNameRepository().nameExists(initialName));
String newestName = "newest-name";
String newestData = "newest-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, newestName, newestData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check previous name no longer exists
assertFalse(repository.getNameRepository().nameExists(initialName));
// Check newest name exists
assertTrue(repository.getNameRepository().nameExists(newestName));
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check original name exists again
assertTrue(repository.getNameRepository().nameExists(initialName));
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check original name still exists
assertTrue(repository.getNameRepository().nameExists(initialName));
}
}
@Test
public void testUpdateData() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, transactionData, alice);
String newName = "";
String newData = "new-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, newName, newData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check name still exists
assertTrue(repository.getNameRepository().nameExists(initialName));
// Check data is correct
assertEquals(newData, repository.getNameRepository().fromName(initialName).getData());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check name still exists
assertTrue(repository.getNameRepository().nameExists(initialName));
// Check old data restored
assertEquals(initialData, repository.getNameRepository().fromName(initialName).getData());
}
}
// Test that reverting using previous UPDATE_NAME works as expected
@Test
public void testDoubleUpdateData() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Update data
String middleName = "middle-name";
String middleData = "middle-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check data is correct
assertEquals(middleData, repository.getNameRepository().fromName(middleName).getData());
String newestName = "newest-name";
String newestData = "newest-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), middleName, newestName, newestData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check data is correct
assertEquals(newestData, repository.getNameRepository().fromName(newestName).getData());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check data is correct
assertEquals(middleData, repository.getNameRepository().fromName(middleName).getData());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check data is correct
assertEquals(initialData, repository.getNameRepository().fromName(initialName).getData());
}
}
// Test that reverting using previous UPDATE_NAME works as expected
@Test
public void testIntermediateUpdateData() throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
// Register-name
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
String initialName = "initial-name";
String initialData = "initial-data";
TransactionData transactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), initialName, initialData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Don't update data, but update name.
// This tests whether reverting a future update/sale can find the correct previous data
String middleName = "middle-name";
String middleData = "";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), initialName, middleName, middleData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check data is correct
assertEquals(initialData, repository.getNameRepository().fromName(middleName).getData());
String newestName = "newest-name";
String newestData = "newest-data";
transactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), middleName, newestName, newestData);
TransactionUtils.signAndMint(repository, transactionData, alice);
// Check data is correct
assertEquals(newestData, repository.getNameRepository().fromName(newestName).getData());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check data is correct
assertEquals(initialData, repository.getNameRepository().fromName(middleName).getData());
// orphan and recheck
BlockUtils.orphanLastBlock(repository);
// Check data is correct
assertEquals(initialData, repository.getNameRepository().fromName(initialName).getData());
}
}
}