forked from Qortal/qortal
Fix some minor group-related bugs
Incorrect column names when saving a group ban. Missing column in LeaveGroupTransactions. More stringent validity checks in group-kick, group-ban and remove-group-admin. Added loads more tests to cover group actions.
This commit is contained in:
parent
ec1954bae1
commit
448e984995
@ -530,7 +530,7 @@ public class HSQLDBDatabaseUpdates {
|
||||
|
||||
// Leave group
|
||||
stmt.execute("CREATE TABLE LeaveGroupTransactions (signature Signature, leaver QortalPublicKey NOT NULL, group_id GroupID NOT NULL, "
|
||||
+ "member_reference Signature, admin_reference Signature, " + TRANSACTION_KEYS + ")");
|
||||
+ "member_reference Signature, admin_reference Signature, previous_group_id GroupID, " + TRANSACTION_KEYS + ")");
|
||||
|
||||
// Kick from group
|
||||
stmt.execute("CREATE TABLE GroupKickTransactions (signature Signature, admin QortalPublicKey NOT NULL, "
|
||||
@ -618,6 +618,11 @@ public class HSQLDBDatabaseUpdates {
|
||||
stmt.execute("CREATE TABLE PublicizeTransactions (signature Signature, nonce INT NOT NULL, " + TRANSACTION_KEYS + ")");
|
||||
break;
|
||||
|
||||
case 20:
|
||||
// XXX Bug-fix, but remove when we build new genesis
|
||||
stmt.execute("ALTER TABLE LeaveGroupTransactions ADD COLUMN IF NOT EXISTS previous_group_id GroupID");
|
||||
break;
|
||||
|
||||
default:
|
||||
// nothing to do
|
||||
return false;
|
||||
|
@ -828,7 +828,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
|
||||
HSQLDBSaver saveHelper = new HSQLDBSaver("GroupBans");
|
||||
|
||||
saveHelper.bind("group_id", groupBanData.getGroupId()).bind("offender", groupBanData.getOffender()).bind("admin", groupBanData.getAdmin())
|
||||
.bind("banned", groupBanData.getBanned()).bind("reason", groupBanData.getReason()).bind("expiry", groupBanData.getExpiry())
|
||||
.bind("banned_when", groupBanData.getBanned()).bind("reason", groupBanData.getReason()).bind("expires_when", groupBanData.getExpiry())
|
||||
.bind("reference", groupBanData.getReference());
|
||||
|
||||
try {
|
||||
|
@ -72,7 +72,11 @@ public class GroupBanTransaction extends Transaction {
|
||||
|
||||
Account offender = getOffender();
|
||||
|
||||
// Can't ban another admin unless the group owner
|
||||
// Can't ban group owner
|
||||
if (offender.getAddress().equals(groupData.getOwner()))
|
||||
return ValidationResult.INVALID_GROUP_OWNER;
|
||||
|
||||
// Can't ban another admin unless admin is the group owner
|
||||
if (!admin.getAddress().equals(groupData.getOwner()) && this.repository.getGroupRepository().adminExists(groupId, offender.getAddress()))
|
||||
return ValidationResult.INVALID_GROUP_OWNER;
|
||||
|
||||
|
@ -74,7 +74,11 @@ public class GroupKickTransaction extends Transaction {
|
||||
if (!groupRepository.joinRequestExists(groupId, member.getAddress()) && !groupRepository.memberExists(groupId, member.getAddress()))
|
||||
return ValidationResult.NOT_GROUP_MEMBER;
|
||||
|
||||
// Can't kick another admin unless the group owner
|
||||
// Can't kick group owner
|
||||
if (member.getAddress().equals(groupData.getOwner()))
|
||||
return ValidationResult.INVALID_GROUP_OWNER;
|
||||
|
||||
// Can't kick another admin unless kicker is the group owner
|
||||
if (!admin.getAddress().equals(groupData.getOwner()) && groupRepository.adminExists(groupId, member.getAddress()))
|
||||
return ValidationResult.INVALID_GROUP_OWNER;
|
||||
|
||||
|
@ -76,6 +76,10 @@ public class RemoveGroupAdminTransaction extends Transaction {
|
||||
if (!this.repository.getGroupRepository().adminExists(groupId, admin.getAddress()))
|
||||
return ValidationResult.NOT_GROUP_ADMIN;
|
||||
|
||||
// Check admin is not group owner
|
||||
if (admin.getAddress().equals(groupData.getOwner()))
|
||||
return ValidationResult.INVALID_GROUP_OWNER;
|
||||
|
||||
// Check creator has enough funds
|
||||
if (owner.getConfirmedBalance(Asset.QORT) < this.removeGroupAdminTransactionData.getFee())
|
||||
return ValidationResult.NO_BALANCE;
|
||||
|
@ -257,11 +257,11 @@ public class AccountRefCacheTests extends Common {
|
||||
|
||||
// generate new payment from Alice to new account
|
||||
TransactionData paymentData1 = new PaymentTransactionData(TestTransaction.generateBase(alice), newbie.getAddress(), amount);
|
||||
TransactionUtils.signAsUnconfirmed(repository, paymentData1, alice); // updates paymentData1's signature
|
||||
TransactionUtils.signAndImportValid(repository, paymentData1, alice); // updates paymentData1's signature
|
||||
|
||||
// generate another payment from Alice to new account
|
||||
TransactionData paymentData2 = new PaymentTransactionData(TestTransaction.generateBase(alice), newbie.getAddress(), amount);
|
||||
TransactionUtils.signAsUnconfirmed(repository, paymentData2, alice); // updates paymentData2's signature
|
||||
TransactionUtils.signAndImportValid(repository, paymentData2, alice); // updates paymentData2's signature
|
||||
|
||||
// mint block containing payments (uses cache)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
@ -313,7 +313,7 @@ public class TransferPrivsTests extends Common {
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, senderAccount.getPublicKey(), fee, null);
|
||||
TransactionData transactionData = new TransferPrivsTransactionData(baseTransactionData, recipientAccount.getAddress());
|
||||
|
||||
TransactionUtils.signAsUnconfirmed(repository, transactionData, senderAccount);
|
||||
TransactionUtils.signAndImportValid(repository, transactionData, senderAccount);
|
||||
BlockMinter.mintTestingBlock(repository, mintingAccount);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@ -17,8 +18,25 @@ import org.qortal.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class TransactionUtils {
|
||||
|
||||
/** Signs transaction using given account and imports into unconfirmed pile. */
|
||||
public static void signAsUnconfirmed(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
/** Signs transaction using given account and attempts to import into unconfirmed pile, returning validation result. */
|
||||
public static ValidationResult signAndImport(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(signingAccount);
|
||||
|
||||
// Add to unconfirmed
|
||||
assertTrue("Transaction's signature should be valid", transaction.isSignatureValid());
|
||||
|
||||
// We might need to wait until transaction's timestamp is valid for the block we're about to mint
|
||||
try {
|
||||
Thread.sleep(1L);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
|
||||
return transaction.importAsUnconfirmed();
|
||||
}
|
||||
|
||||
/** Signs transaction using given account and imports into unconfirmed pile, checking transaction is valid. */
|
||||
public static void signAndImportValid(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(signingAccount);
|
||||
|
||||
@ -37,7 +55,7 @@ public class TransactionUtils {
|
||||
|
||||
/** Signs transaction using given account and mints a new block.<br> See {@link BlockUtils#mintBlock(Repository)} */
|
||||
public static void signAndMint(Repository repository, TransactionData transactionData, PrivateKeyAccount signingAccount) throws DataException {
|
||||
signAsUnconfirmed(repository, transactionData, signingAccount);
|
||||
signAndImportValid(repository, transactionData, signingAccount);
|
||||
|
||||
// Mint block
|
||||
BlockUtils.mintBlock(repository);
|
||||
@ -58,4 +76,13 @@ public class TransactionUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static void deleteUnconfirmedTransactions(Repository repository) throws DataException {
|
||||
List<TransactionData> unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
|
||||
|
||||
for (TransactionData transactionData : unconfirmedTransactions)
|
||||
repository.getTransactionRepository().delete(transactionData);
|
||||
|
||||
repository.saveChanges();
|
||||
}
|
||||
|
||||
}
|
||||
|
352
src/test/java/org/qortal/test/group/AdminTests.java
Normal file
352
src/test/java/org/qortal/test/group/AdminTests.java
Normal file
@ -0,0 +1,352 @@
|
||||
package org.qortal.test.group;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.data.transaction.AddGroupAdminTransactionData;
|
||||
import org.qortal.data.transaction.CancelGroupBanTransactionData;
|
||||
import org.qortal.data.transaction.CreateGroupTransactionData;
|
||||
import org.qortal.data.transaction.GroupBanTransactionData;
|
||||
import org.qortal.data.transaction.GroupKickTransactionData;
|
||||
import org.qortal.data.transaction.JoinGroupTransactionData;
|
||||
import org.qortal.group.Group.ApprovalThreshold;
|
||||
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;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class AdminTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupKickMember() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to kick Bob
|
||||
ValidationResult result = groupKick(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to kick Bob
|
||||
result = groupKick(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupKickAdmin() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Promote Bob to admin
|
||||
addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to kick Bob
|
||||
ValidationResult result = groupKick(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob now an admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice (owner) try to kick herself!
|
||||
result = groupKick(repository, alice, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Have Bob try to kick Alice (owner)
|
||||
result = groupKick(repository, bob, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupBanMember() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to cancel non-existent Bob ban
|
||||
ValidationResult result = cancelGroupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Attempt to ban Bob
|
||||
result = groupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block (Bob ban)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed group-ban transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Bob to join
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to ban Bob
|
||||
result = groupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Cancel Bob's ban
|
||||
result = cancelGroupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block (Bob join)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed join-group transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Orphan last block (Cancel Bob ban)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed cancel-ban transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block (Bob ban)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed group-ban transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGroupBanAdmin() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Bob to join
|
||||
ValidationResult result = joinGroup(repository, bob, groupId);
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Promote Bob to admin
|
||||
addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to ban Bob
|
||||
result = groupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Cancel Bob's ban
|
||||
result = cancelGroupBan(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block (Bob join)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed join-group transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Orphan last block (Cancel Bob ban)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed cancel-ban transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Bob attempts to rejoin
|
||||
result = joinGroup(repository, bob, groupId);
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block (Bob ban)
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
// Delete unconfirmed group-ban transaction
|
||||
TransactionUtils.deleteUnconfirmedTransactions(repository);
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice (owner) try to ban herself!
|
||||
result = groupBan(repository, alice, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Have Bob try to ban Alice (owner)
|
||||
result = groupBan(repository, bob, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
private Integer createGroup(Repository repository, PrivateKeyAccount owner, String groupName, boolean isOpen) throws DataException {
|
||||
String description = groupName + " (description)";
|
||||
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(owner), groupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
TransactionUtils.signAndMint(repository, transactionData, owner);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
|
||||
private ValidationResult joinGroup(Repository repository, PrivateKeyAccount joiner, int groupId) throws DataException {
|
||||
JoinGroupTransactionData transactionData = new JoinGroupTransactionData(TestTransaction.generateBase(joiner), groupId);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, joiner);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ValidationResult groupKick(Repository repository, PrivateKeyAccount admin, int groupId, String member) throws DataException {
|
||||
GroupKickTransactionData transactionData = new GroupKickTransactionData(TestTransaction.generateBase(admin), groupId, member, "testing");
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, admin);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ValidationResult groupBan(Repository repository, PrivateKeyAccount admin, int groupId, String member) throws DataException {
|
||||
GroupBanTransactionData transactionData = new GroupBanTransactionData(TestTransaction.generateBase(admin), groupId, member, "testing", 0);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, admin);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ValidationResult cancelGroupBan(Repository repository, PrivateKeyAccount admin, int groupId, String member) throws DataException {
|
||||
CancelGroupBanTransactionData transactionData = new CancelGroupBanTransactionData(TestTransaction.generateBase(admin), groupId, member);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, admin);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addGroupAdmin(Repository repository, PrivateKeyAccount owner, int groupId, String member) throws DataException {
|
||||
AddGroupAdminTransactionData transactionData = new AddGroupAdminTransactionData(TestTransaction.generateBase(owner), groupId, member);
|
||||
TransactionUtils.signAndMint(repository, transactionData, owner);
|
||||
}
|
||||
|
||||
private boolean isMember(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().memberExists(groupId, address);
|
||||
}
|
||||
|
||||
private boolean isAdmin(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().adminExists(groupId, address);
|
||||
}
|
||||
|
||||
}
|
@ -1,20 +1,23 @@
|
||||
package org.qortal.test.group;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.data.transaction.CreateGroupTransactionData;
|
||||
import org.qortal.data.transaction.GroupInviteTransactionData;
|
||||
import org.qortal.data.transaction.JoinGroupTransactionData;
|
||||
import org.qortal.data.transaction.LeaveGroupTransactionData;
|
||||
import org.qortal.group.Group.ApprovalThreshold;
|
||||
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;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class MiscTests extends Common {
|
||||
@ -32,28 +35,184 @@ public class MiscTests extends Common {
|
||||
@Test
|
||||
public void testCreateGroupWithExistingName() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Register-name
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String groupName = "test-group";
|
||||
String description = "test group";
|
||||
|
||||
final boolean isOpen = false;
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.PCT40;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(alice), groupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||
// Create group
|
||||
createGroup(repository, alice, "test-group", false);
|
||||
|
||||
// duplicate
|
||||
String duplicateGroupName = "TEST-gr0up";
|
||||
transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(alice), duplicateGroupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
Transaction transaction = Transaction.fromData(repository, transactionData);
|
||||
transaction.sign(alice);
|
||||
String description = duplicateGroupName + " (description)";
|
||||
|
||||
ValidationResult result = transaction.importAsUnconfirmed();
|
||||
boolean isOpen = false;
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(alice), duplicateGroupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, alice);
|
||||
assertTrue("Transaction should be invalid", ValidationResult.OK != result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinOpenGroup() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinClosedGroup() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "closed-group", false);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob still not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice 'invite' Bob to confirm membership
|
||||
groupInvite(repository, alice, groupId, bob.getAddress(), 0); // non-expiring invite
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJoinGroupViaInvite() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "closed-group", false);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice 'invite' Bob to join
|
||||
groupInvite(repository, alice, groupId, bob.getAddress(), 0); // non-expiring invite
|
||||
|
||||
// Confirm Bob still not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob uses invite to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLeaveGroup() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Confirm Bob is not a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Bob leaves
|
||||
leaveGroup(repository, bob, groupId);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob now a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob no longer a member
|
||||
assertFalse(isMember(repository, bob.getAddress(), groupId));
|
||||
}
|
||||
}
|
||||
|
||||
private Integer createGroup(Repository repository, PrivateKeyAccount owner, String groupName, boolean isOpen) throws DataException {
|
||||
String description = groupName + " (description)";
|
||||
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(owner), groupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
TransactionUtils.signAndMint(repository, transactionData, owner);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
|
||||
private void joinGroup(Repository repository, PrivateKeyAccount joiner, int groupId) throws DataException {
|
||||
JoinGroupTransactionData transactionData = new JoinGroupTransactionData(TestTransaction.generateBase(joiner), groupId);
|
||||
TransactionUtils.signAndMint(repository, transactionData, joiner);
|
||||
}
|
||||
|
||||
private void groupInvite(Repository repository, PrivateKeyAccount admin, int groupId, String invitee, int timeToLive) throws DataException {
|
||||
GroupInviteTransactionData transactionData = new GroupInviteTransactionData(TestTransaction.generateBase(admin), groupId, invitee, timeToLive);
|
||||
TransactionUtils.signAndMint(repository, transactionData, admin);
|
||||
}
|
||||
|
||||
private void leaveGroup(Repository repository, PrivateKeyAccount leaver, int groupId) throws DataException {
|
||||
LeaveGroupTransactionData transactionData = new LeaveGroupTransactionData(TestTransaction.generateBase(leaver), groupId);
|
||||
TransactionUtils.signAndMint(repository, transactionData, leaver);
|
||||
}
|
||||
|
||||
private boolean isMember(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().memberExists(groupId, address);
|
||||
}
|
||||
|
||||
}
|
||||
|
187
src/test/java/org/qortal/test/group/OwnerTests.java
Normal file
187
src/test/java/org/qortal/test/group/OwnerTests.java
Normal file
@ -0,0 +1,187 @@
|
||||
package org.qortal.test.group;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.account.PrivateKeyAccount;
|
||||
import org.qortal.data.transaction.AddGroupAdminTransactionData;
|
||||
import org.qortal.data.transaction.CreateGroupTransactionData;
|
||||
import org.qortal.data.transaction.JoinGroupTransactionData;
|
||||
import org.qortal.data.transaction.RemoveGroupAdminTransactionData;
|
||||
import org.qortal.group.Group.ApprovalThreshold;
|
||||
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;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
|
||||
public class OwnerTests extends Common {
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAdmin() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Attempt to promote non-member
|
||||
ValidationResult result = addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Promote Bob to admin
|
||||
addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to re-promote admin
|
||||
result = addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob no longer an admin
|
||||
assertFalse(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Confirm Bob is still a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice try to promote herself
|
||||
result = addGroupAdmin(repository, alice, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAdmin() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
PrivateKeyAccount bob = Common.getTestAccount(repository, "bob");
|
||||
|
||||
// Create group
|
||||
int groupId = createGroup(repository, alice, "open-group", true);
|
||||
|
||||
// Attempt to demote non-member
|
||||
ValidationResult result = removeGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Bob to join
|
||||
joinGroup(repository, bob, groupId);
|
||||
|
||||
// Attempt to demote non-admin member
|
||||
result = removeGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Promote Bob to admin
|
||||
addGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Attempt to demote admin
|
||||
result = removeGroupAdmin(repository, alice, groupId, bob.getAddress());
|
||||
// Should be OK
|
||||
assertEquals(ValidationResult.OK, result);
|
||||
|
||||
// Confirm Bob no longer an admin
|
||||
assertFalse(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Confirm Bob is still a member
|
||||
assertTrue(isMember(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Orphan last block
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Confirm Bob is now admin
|
||||
assertTrue(isAdmin(repository, bob.getAddress(), groupId));
|
||||
|
||||
// Have Alice (owner) try to demote herself
|
||||
result = removeGroupAdmin(repository, alice, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
|
||||
// Have Bob try to demote Alice (owner)
|
||||
result = removeGroupAdmin(repository, bob, groupId, alice.getAddress());
|
||||
// Should NOT be OK
|
||||
assertNotSame(ValidationResult.OK, result);
|
||||
}
|
||||
}
|
||||
|
||||
private Integer createGroup(Repository repository, PrivateKeyAccount owner, String groupName, boolean isOpen) throws DataException {
|
||||
String description = groupName + " (description)";
|
||||
|
||||
ApprovalThreshold approvalThreshold = ApprovalThreshold.ONE;
|
||||
int minimumBlockDelay = 10;
|
||||
int maximumBlockDelay = 1440;
|
||||
|
||||
CreateGroupTransactionData transactionData = new CreateGroupTransactionData(TestTransaction.generateBase(owner), groupName, description, isOpen, approvalThreshold, minimumBlockDelay, maximumBlockDelay);
|
||||
TransactionUtils.signAndMint(repository, transactionData, owner);
|
||||
|
||||
return repository.getGroupRepository().fromGroupName(groupName).getGroupId();
|
||||
}
|
||||
|
||||
private ValidationResult joinGroup(Repository repository, PrivateKeyAccount joiner, int groupId) throws DataException {
|
||||
JoinGroupTransactionData transactionData = new JoinGroupTransactionData(TestTransaction.generateBase(joiner), groupId);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, joiner);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ValidationResult addGroupAdmin(Repository repository, PrivateKeyAccount owner, int groupId, String member) throws DataException {
|
||||
AddGroupAdminTransactionData transactionData = new AddGroupAdminTransactionData(TestTransaction.generateBase(owner), groupId, member);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, owner);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private ValidationResult removeGroupAdmin(Repository repository, PrivateKeyAccount owner, int groupId, String member) throws DataException {
|
||||
RemoveGroupAdminTransactionData transactionData = new RemoveGroupAdminTransactionData(TestTransaction.generateBase(owner), groupId, member);
|
||||
ValidationResult result = TransactionUtils.signAndImport(repository, transactionData, owner);
|
||||
|
||||
if (result == ValidationResult.OK)
|
||||
BlockUtils.mintBlock(repository);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isMember(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().memberExists(groupId, address);
|
||||
}
|
||||
|
||||
private boolean isAdmin(Repository repository, String address, int groupId) throws DataException {
|
||||
return repository.getGroupRepository().adminExists(groupId, address);
|
||||
}
|
||||
|
||||
}
|
@ -86,7 +86,7 @@ public class DisagreementTests extends Common {
|
||||
|
||||
// Cancel reward-share
|
||||
TransactionData cancelRewardShareTransactionData = AccountUtils.createRewardShare(repository, "alice", "bob", CANCEL_SHARE_PERCENT);
|
||||
TransactionUtils.signAsUnconfirmed(repository, cancelRewardShareTransactionData, signingAccount);
|
||||
TransactionUtils.signAndImportValid(repository, cancelRewardShareTransactionData, signingAccount);
|
||||
BlockMinter.mintTestingBlockRetainingTimestamps(repository, mintingAccount);
|
||||
|
||||
// Confirm reward-share no longer exists in repository
|
||||
|
Loading…
Reference in New Issue
Block a user