Convert AllocationToken-related classes to tm() (#909)

* Convert AllocationToken-related classes to tm()

For the most part this is a fairly simple converstion -- changing Key
references to VKey references, using JPA transactions when necessary,
and using the TransactionManager interface. There's a bit of cleanup too
in related code
This commit is contained in:
gbrodman 2020-12-21 15:56:49 -05:00 committed by GitHub
parent 6e2bbd1a7e
commit e550c94cbc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 201 additions and 178 deletions

View file

@ -15,14 +15,13 @@
package google.registry.flows.domain.token; package google.registry.flows.domain.token;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException; import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.EppException.AuthorizationErrorException; import google.registry.flows.EppException.AuthorizationErrorException;
@ -153,14 +152,15 @@ public class AllocationTokenFlowUtils {
// See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1 // See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1
throw new InvalidAllocationTokenException(); throw new InvalidAllocationTokenException();
} }
AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now(); Optional<AllocationToken> maybeTokenEntity =
if (tokenEntity == null) { tm().maybeLoad(VKey.create(AllocationToken.class, token));
if (maybeTokenEntity.isEmpty()) {
throw new InvalidAllocationTokenException(); throw new InvalidAllocationTokenException();
} }
if (tokenEntity.isRedeemed()) { if (maybeTokenEntity.get().isRedeemed()) {
throw new AlreadyRedeemedAllocationTokenException(); throw new AlreadyRedeemedAllocationTokenException();
} }
return tokenEntity; return maybeTokenEntity.get();
} }
// Note: exception messages should be <= 32 characters long for domain check results // Note: exception messages should be <= 32 characters long for domain check results

View file

@ -67,7 +67,6 @@ public class Spec11RegistrarThreatMatchesParser {
if (!gcsUtils.existsAndNotEmpty(spec11ReportFilename)) { if (!gcsUtils.existsAndNotEmpty(spec11ReportFilename)) {
return ImmutableSet.of(); return ImmutableSet.of();
} }
ImmutableSet.Builder<RegistrarThreatMatches> builder = ImmutableSet.builder();
try (InputStream in = gcsUtils.openInputStream(spec11ReportFilename); try (InputStream in = gcsUtils.openInputStream(spec11ReportFilename);
InputStreamReader isr = new InputStreamReader(in, UTF_8)) { InputStreamReader isr = new InputStreamReader(in, UTF_8)) {
// Skip the header at line 0 // Skip the header at line 0

View file

@ -14,19 +14,19 @@
package google.registry.tools; package google.registry.tools;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Iterables.partition; import static com.google.common.collect.Iterables.partition;
import static com.google.common.collect.Streams.stream; import static com.google.common.collect.Streams.stream;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.persistence.VKey;
import java.util.List; import java.util.List;
/** /**
@ -48,7 +48,7 @@ final class DeleteAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
private static final int BATCH_SIZE = 20; private static final int BATCH_SIZE = 20;
private static final Joiner JOINER = Joiner.on(", "); private static final Joiner JOINER = Joiner.on(", ");
private ImmutableSet<Key<AllocationToken>> tokensToDelete; private ImmutableSet<VKey<AllocationToken>> tokensToDelete;
@Override @Override
public void init() { public void init() {
@ -71,26 +71,24 @@ final class DeleteAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
} }
/** Deletes a (filtered) batch of AllocationTokens and returns how many were deleted. */ /** Deletes a (filtered) batch of AllocationTokens and returns how many were deleted. */
private long deleteBatch(List<Key<AllocationToken>> batch) { private long deleteBatch(List<VKey<AllocationToken>> batch) {
// Load the tokens in the same transaction as they are deleted to verify they weren't redeemed // Load the tokens in the same transaction as they are deleted to verify they weren't redeemed
// since the query ran. This also filters out per-domain tokens if they're not to be deleted. // since the query ran. This also filters out per-domain tokens if they're not to be deleted.
ImmutableSet<AllocationToken> tokensToDelete = ImmutableSet<VKey<AllocationToken>> tokensToDelete =
ofy().load().keys(batch).values().stream() tm().load(batch).values().stream()
.filter(t -> withDomains || !t.getDomainName().isPresent()) .filter(t -> withDomains || t.getDomainName().isEmpty())
.filter(t -> SINGLE_USE.equals(t.getTokenType())) .filter(t -> SINGLE_USE.equals(t.getTokenType()))
.filter(t -> !t.isRedeemed()) .filter(t -> !t.isRedeemed())
.map(AllocationToken::createVKey)
.collect(toImmutableSet()); .collect(toImmutableSet());
if (!dryRun) { if (!dryRun) {
ofy().delete().entities(tokensToDelete); tm().delete(tokensToDelete);
} }
System.out.printf( System.out.printf(
"%s tokens: %s\n", "%s tokens: %s\n",
dryRun ? "Would delete" : "Deleted", dryRun ? "Would delete" : "Deleted",
JOINER.join( JOINER.join(
tokensToDelete.stream() tokensToDelete.stream().map(VKey::getSqlKey).sorted().collect(toImmutableList())));
.map(AllocationToken::getToken)
.sorted()
.collect(toImmutableSet())));
return tokensToDelete.size(); return tokensToDelete.size();
} }
} }

View file

@ -20,8 +20,8 @@ import static com.google.common.collect.Queues.newArrayDeque;
import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.difference;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH; import static google.registry.util.StringGenerator.DEFAULT_PASSWORD_LENGTH;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@ -38,10 +38,10 @@ import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import com.google.common.io.Files; import com.google.common.io.Files;
import com.googlecode.objectify.Key;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.domain.token.AllocationToken.TokenType; import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.persistence.VKey;
import google.registry.tools.params.TransitionListParameter.TokenStatusTransitions; import google.registry.tools.params.TransitionListParameter.TokenStatusTransitions;
import google.registry.util.CollectionUtils; import google.registry.util.CollectionUtils;
import google.registry.util.NonFinalForTesting; import google.registry.util.NonFinalForTesting;
@ -258,8 +258,13 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
@VisibleForTesting @VisibleForTesting
int saveTokens(final ImmutableSet<AllocationToken> tokens) { int saveTokens(final ImmutableSet<AllocationToken> tokens) {
Collection<AllocationToken> savedTokens = Collection<AllocationToken> savedTokens;
dryRun ? tokens : tm().transact(() -> ofy().save().entities(tokens).now().values()); if (dryRun) {
savedTokens = tokens;
} else {
transactIfJpaTm(() -> tm().transact(() -> tm().putAll(tokens)));
savedTokens = tm().transact(() -> tm().loadAll(tokens));
}
savedTokens.forEach( savedTokens.forEach(
t -> System.out.println(SKIP_NULLS.join(t.getDomainName().orElse(null), t.getToken()))); t -> System.out.println(SKIP_NULLS.join(t.getDomainName().orElse(null), t.getToken())));
return savedTokens.size(); return savedTokens.size();
@ -282,12 +287,14 @@ class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
} }
private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) { private ImmutableSet<String> getExistingTokenStrings(ImmutableSet<String> candidates) {
ImmutableSet<Key<AllocationToken>> existingTokenKeys = ImmutableSet<VKey<AllocationToken>> existingTokenKeys =
candidates.stream() candidates.stream()
.map(input -> Key.create(AllocationToken.class, input)) .map(input -> VKey.create(AllocationToken.class, input))
.collect(toImmutableSet()); .collect(toImmutableSet());
return ofy().load().keys(existingTokenKeys).values().stream() return transactIfJpaTm(
() ->
tm().load(existingTokenKeys).values().stream()
.map(AllocationToken::getToken) .map(AllocationToken::getToken)
.collect(toImmutableSet()); .collect(toImmutableSet()));
} }
} }

View file

@ -15,7 +15,6 @@
package google.registry.tools; package google.registry.tools;
import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
@ -26,6 +25,7 @@ import com.google.common.collect.Lists;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.persistence.VKey;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -45,22 +45,26 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
public void run() { public void run() {
ImmutableMap.Builder<String, AllocationToken> builder = new ImmutableMap.Builder<>(); ImmutableMap.Builder<String, AllocationToken> builder = new ImmutableMap.Builder<>();
for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) { for (List<String> tokens : Lists.partition(mainParameters, BATCH_SIZE)) {
ImmutableList<Key<AllocationToken>> tokenKeys = ImmutableList<VKey<AllocationToken>> tokenKeys =
tokens.stream().map(t -> Key.create(AllocationToken.class, t)).collect(toImmutableList()); tokens.stream()
ofy().load().keys(tokenKeys).forEach((k, v) -> builder.put(k.getName(), v)); .map(t -> VKey.create(AllocationToken.class, t))
.collect(toImmutableList());
tm().load(tokenKeys).forEach((k, v) -> builder.put(k.getSqlKey().toString(), v));
} }
ImmutableMap<String, AllocationToken> loadedTokens = builder.build(); ImmutableMap<String, AllocationToken> loadedTokens = builder.build();
ImmutableMap<Key<DomainBase>, DomainBase> domains = loadRedeemedDomains(loadedTokens.values()); ImmutableMap<VKey<DomainBase>, DomainBase> domains = loadRedeemedDomains(loadedTokens.values());
for (String token : mainParameters) { for (String token : mainParameters) {
if (loadedTokens.containsKey(token)) { if (loadedTokens.containsKey(token)) {
AllocationToken loadedToken = loadedTokens.get(token); AllocationToken loadedToken = loadedTokens.get(token);
System.out.println(loadedToken.toString()); System.out.println(loadedToken.toString());
if (!loadedToken.getRedemptionHistoryEntry().isPresent()) { if (loadedToken.getRedemptionHistoryEntry().isEmpty()) {
System.out.printf("Token %s was not redeemed.\n", token); System.out.printf("Token %s was not redeemed.\n", token);
} else { } else {
Key<DomainBase> domainOfyKey =
loadedToken.getRedemptionHistoryEntry().get().getOfyKey().getParent();
DomainBase domain = DomainBase domain =
domains.get(loadedToken.getRedemptionHistoryEntry().get().getOfyKey().getParent()); domains.get(VKey.create(DomainBase.class, domainOfyKey.getName(), domainOfyKey));
if (domain == null) { if (domain == null) {
System.out.printf("ERROR: Token %s was redeemed but domain can't be loaded.\n", token); System.out.printf("ERROR: Token %s was redeemed but domain can't be loaded.\n", token);
} else { } else {
@ -76,19 +80,23 @@ final class GetAllocationTokenCommand implements CommandWithRemoteApi {
} }
} }
private static ImmutableMap<Key<DomainBase>, DomainBase> loadRedeemedDomains( @SuppressWarnings("unchecked")
private static ImmutableMap<VKey<DomainBase>, DomainBase> loadRedeemedDomains(
Collection<AllocationToken> tokens) { Collection<AllocationToken> tokens) {
ImmutableList<Key<DomainBase>> domainKeys = ImmutableList<VKey<DomainBase>> domainKeys =
tokens.stream() tokens.stream()
.map(AllocationToken::getRedemptionHistoryEntry) .map(AllocationToken::getRedemptionHistoryEntry)
.filter(Optional::isPresent) .filter(Optional::isPresent)
.map(Optional::get) .map(Optional::get)
.map(key -> tm().load(key)) .map(key -> tm().load(key))
.map(he -> (Key<DomainBase>) he.getParent()) .map(he -> (Key<DomainBase>) he.getParent())
.map(key -> VKey.create(DomainBase.class, key.getName(), key))
.collect(toImmutableList()); .collect(toImmutableList());
ImmutableMap.Builder<Key<DomainBase>, DomainBase> domainsBuilder = new ImmutableMap.Builder<>(); ImmutableMap.Builder<VKey<DomainBase>, DomainBase> domainsBuilder =
for (List<Key<DomainBase>> keys : Lists.partition(domainKeys, BATCH_SIZE)) { new ImmutableMap.Builder<>();
domainsBuilder.putAll(ofy().load().keys(keys)); for (List<VKey<DomainBase>> keys : Lists.partition(domainKeys, BATCH_SIZE)) {
tm().load(ImmutableList.copyOf(keys))
.forEach((k, v) -> domainsBuilder.put((VKey<DomainBase>) k, v));
} }
return domainsBuilder.build(); return domainsBuilder.build();
} }

View file

@ -18,8 +18,8 @@ import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Iterables.partition; import static com.google.common.collect.Iterables.partition;
import static com.google.common.collect.Streams.stream; import static com.google.common.collect.Streams.stream;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
@ -105,13 +105,17 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
} }
tokensToSave = tokensToSave =
ofy().load().keys(getTokenKeys()).values().stream() transactIfJpaTm(
() ->
tm().load(getTokenKeys()).values().stream()
.collect(toImmutableMap(Function.identity(), this::updateToken)) .collect(toImmutableMap(Function.identity(), this::updateToken))
.entrySet() .entrySet()
.stream() .stream()
.filter(entry -> !entry.getKey().equals(entry.getValue())) // only update changed tokens .filter(
entry ->
!entry.getKey().equals(entry.getValue())) // only update changed tokens
.map(Map.Entry::getValue) .map(Map.Entry::getValue)
.collect(toImmutableSet()); .collect(toImmutableSet()));
} }
@Override @Override
@ -123,7 +127,7 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
protected String execute() { protected String execute() {
long numUpdated = long numUpdated =
stream(partition(tokensToSave, BATCH_SIZE)) stream(partition(tokensToSave, BATCH_SIZE))
.mapToLong(batch -> tm().transact(() -> saveBatch(batch))) .mapToLong(batch -> tm().transact(() -> saveBatch(ImmutableList.copyOf(batch))))
.sum(); .sum();
return String.format("Updated %d tokens in total.", numUpdated); return String.format("Updated %d tokens in total.", numUpdated);
} }
@ -141,9 +145,9 @@ final class UpdateAllocationTokensCommand extends UpdateOrDeleteAllocationTokens
return builder.build(); return builder.build();
} }
private long saveBatch(List<AllocationToken> batch) { private long saveBatch(ImmutableList<AllocationToken> batch) {
if (!dryRun) { if (!dryRun) {
ofy().save().entities(batch); tm().putAll(batch);
} }
System.out.printf( System.out.printf(
"%s tokens: %s\n", "%s tokens: %s\n",

View file

@ -15,13 +15,15 @@
package google.registry.tools; package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.persistence.VKey;
import java.util.List; import java.util.List;
/** Shared base class for commands to update or delete allocation tokens. */ /** Shared base class for commands to update or delete allocation tokens. */
@ -47,19 +49,28 @@ abstract class UpdateOrDeleteAllocationTokensCommand extends ConfirmingCommand
description = "Do not actually update or delete the tokens; defaults to false") description = "Do not actually update or delete the tokens; defaults to false")
protected boolean dryRun; protected boolean dryRun;
protected ImmutableSet<Key<AllocationToken>> getTokenKeys() { protected ImmutableSet<VKey<AllocationToken>> getTokenKeys() {
checkArgument( checkArgument(
tokens == null ^ prefix == null, tokens == null ^ prefix == null,
"Must provide one of --tokens or --prefix, not both / neither"); "Must provide one of --tokens or --prefix, not both / neither");
if (tokens != null) { if (tokens != null) {
return tokens.stream() ImmutableSet<VKey<AllocationToken>> keys =
.map(token -> Key.create(AllocationToken.class, token)) tokens.stream()
.map(token -> VKey.create(AllocationToken.class, token))
.collect(toImmutableSet()); .collect(toImmutableSet());
ImmutableSet<VKey<AllocationToken>> nonexistentKeys =
transactIfJpaTm(
() -> keys.stream().filter(key -> !tm().exists(key)).collect(toImmutableSet()));
checkState(nonexistentKeys.isEmpty(), "Tokens with keys %s did not exist.", nonexistentKeys);
return keys;
} else { } else {
checkArgument(!prefix.isEmpty(), "Provided prefix should not be blank"); checkArgument(!prefix.isEmpty(), "Provided prefix should not be blank");
return ofy().load().type(AllocationToken.class).keys().list().stream() return transactIfJpaTm(
.filter(key -> key.getName().startsWith(prefix)) () ->
.collect(toImmutableSet()); tm().loadAll(AllocationToken.class).stream()
.filter(token -> token.getToken().startsWith(prefix))
.map(AllocationToken::createVKey)
.collect(toImmutableSet()));
} }
} }
} }

View file

@ -16,15 +16,14 @@ package google.registry.model.domain.token;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat; import static com.google.common.truth.Truth8.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.CANCELLED; import static google.registry.model.domain.token.AllocationToken.TokenStatus.CANCELLED;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.ENDED; import static google.registry.model.domain.token.AllocationToken.TokenStatus.ENDED;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED; import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED;
import static google.registry.model.domain.token.AllocationToken.TokenStatus.VALID; import static google.registry.model.domain.token.AllocationToken.TokenStatus.VALID;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistResource;
@ -40,12 +39,14 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.domain.token.AllocationToken.TokenType; import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import google.registry.testing.TestOfyOnly;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link AllocationToken}. */ /** Unit tests for {@link AllocationToken}. */
@DualDatabaseTest
public class AllocationTokenTest extends EntityTestCase { public class AllocationTokenTest extends EntityTestCase {
public AllocationTokenTest() { public AllocationTokenTest() {
@ -57,7 +58,7 @@ public class AllocationTokenTest extends EntityTestCase {
createTld("foo"); createTld("foo");
} }
@Test @TestOfyAndSql
void testPersistence() { void testPersistence() {
AllocationToken unlimitedUseToken = AllocationToken unlimitedUseToken =
persistResource( persistResource(
@ -77,7 +78,7 @@ public class AllocationTokenTest extends EntityTestCase {
.put(DateTime.now(UTC).plusWeeks(8), TokenStatus.ENDED) .put(DateTime.now(UTC).plusWeeks(8), TokenStatus.ENDED)
.build()) .build())
.build()); .build());
assertThat(ofy().load().entity(unlimitedUseToken).now()).isEqualTo(unlimitedUseToken); assertThat(transactIfJpaTm(() -> tm().load(unlimitedUseToken))).isEqualTo(unlimitedUseToken);
DomainBase domain = persistActiveDomain("example.foo"); DomainBase domain = persistActiveDomain("example.foo");
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1); Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1);
@ -90,32 +91,10 @@ public class AllocationTokenTest extends EntityTestCase {
.setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z")) .setCreationTimeForTest(DateTime.parse("2010-11-12T05:00:00Z"))
.setTokenType(SINGLE_USE) .setTokenType(SINGLE_USE)
.build()); .build());
assertThat(ofy().load().entity(singleUseToken).now()).isEqualTo(singleUseToken); assertThat(transactIfJpaTm(() -> tm().load(singleUseToken))).isEqualTo(singleUseToken);
jpaTm()
.transact(
() -> {
jpaTm().insert(unlimitedUseToken);
jpaTm().insert(singleUseToken);
});
jpaTm()
.transact(
() -> {
assertAboutImmutableObjects()
.that(jpaTm().load(VKey.createSql(AllocationToken.class, "abc123Unlimited")))
.isEqualExceptFields(
unlimitedUseToken,
"creationTime",
"updateTimestamp",
"redemptionHistoryEntry");
assertAboutImmutableObjects()
.that(jpaTm().load(VKey.createSql(AllocationToken.class, "abc123Single")))
.isEqualExceptFields(
singleUseToken, "creationTime", "updateTimestamp", "redemptionHistoryEntry");
});
} }
@Test @TestOfyOnly
void testIndexing() throws Exception { void testIndexing() throws Exception {
DomainBase domain = persistActiveDomain("blahdomain.foo"); DomainBase domain = persistActiveDomain("blahdomain.foo");
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1); Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1);
@ -133,7 +112,7 @@ public class AllocationTokenTest extends EntityTestCase {
"domainName"); "domainName");
} }
@Test @TestOfyAndSql
void testCreationTime_autoPopulates() { void testCreationTime_autoPopulates() {
AllocationToken tokenBeforePersisting = AllocationToken tokenBeforePersisting =
new AllocationToken.Builder().setToken("abc123").setTokenType(SINGLE_USE).build(); new AllocationToken.Builder().setToken("abc123").setTokenType(SINGLE_USE).build();
@ -142,7 +121,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(tokenAfterPersisting.getCreationTime()).hasValue(fakeClock.nowUtc()); assertThat(tokenAfterPersisting.getCreationTime()).hasValue(fakeClock.nowUtc());
} }
@Test @TestOfyAndSql
void testSetCreationTime_cantCallMoreThanOnce() { void testSetCreationTime_cantCallMoreThanOnce() {
AllocationToken.Builder builder = AllocationToken.Builder builder =
new AllocationToken.Builder() new AllocationToken.Builder()
@ -156,7 +135,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Creation time can only be set once"); assertThat(thrown).hasMessageThat().isEqualTo("Creation time can only be set once");
} }
@Test @TestOfyAndSql
void testSetToken_cantCallMoreThanOnce() { void testSetToken_cantCallMoreThanOnce() {
AllocationToken.Builder builder = new AllocationToken.Builder().setToken("foobar"); AllocationToken.Builder builder = new AllocationToken.Builder().setToken("foobar");
IllegalStateException thrown = IllegalStateException thrown =
@ -164,7 +143,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Token can only be set once"); assertThat(thrown).hasMessageThat().isEqualTo("Token can only be set once");
} }
@Test @TestOfyAndSql
void testSetTokenType_cantCallMoreThanOnce() { void testSetTokenType_cantCallMoreThanOnce() {
AllocationToken.Builder builder = AllocationToken.Builder builder =
new AllocationToken.Builder().setTokenType(TokenType.UNLIMITED_USE); new AllocationToken.Builder().setTokenType(TokenType.UNLIMITED_USE);
@ -173,7 +152,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Token type can only be set once"); assertThat(thrown).hasMessageThat().isEqualTo("Token type can only be set once");
} }
@Test @TestOfyAndSql
void testBuild_DomainNameWithLessThanTwoParts() { void testBuild_DomainNameWithLessThanTwoParts() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -191,7 +170,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example"); assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example");
} }
@Test @TestOfyAndSql
void testBuild_invalidTld() { void testBuild_invalidTld() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -209,7 +188,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example.nosuchtld"); assertThat(thrown).hasMessageThat().isEqualTo("Invalid domain name: example.nosuchtld");
} }
@Test @TestOfyAndSql
void testBuild_domainNameOnlyOnSingleUse() { void testBuild_domainNameOnlyOnSingleUse() {
AllocationToken.Builder builder = AllocationToken.Builder builder =
new AllocationToken.Builder() new AllocationToken.Builder()
@ -222,7 +201,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Domain name can only be specified for SINGLE_USE tokens"); .isEqualTo("Domain name can only be specified for SINGLE_USE tokens");
} }
@Test @TestOfyAndSql
void testBuild_redemptionHistoryEntryOnlyInSingleUse() { void testBuild_redemptionHistoryEntryOnlyInSingleUse() {
DomainBase domain = persistActiveDomain("blahdomain.foo"); DomainBase domain = persistActiveDomain("blahdomain.foo");
Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1); Key<HistoryEntry> historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 1);
@ -237,7 +216,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Redemption history entry can only be specified for SINGLE_USE tokens"); .isEqualTo("Redemption history entry can only be specified for SINGLE_USE tokens");
} }
@Test @TestOfyAndSql
void testSetTransitions_notStartOfTime() { void testSetTransitions_notStartOfTime() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -255,7 +234,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("tokenStatusTransitions map must start at START_OF_TIME."); .isEqualTo("tokenStatusTransitions map must start at START_OF_TIME.");
} }
@Test @TestOfyAndSql
void testSetTransitions_badInitialValue() { void testSetTransitions_badInitialValue() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -272,14 +251,14 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("tokenStatusTransitions must start with NOT_STARTED"); .isEqualTo("tokenStatusTransitions must start with NOT_STARTED");
} }
@Test @TestOfyAndSql
void testSetTransitions_invalidInitialTransitions() { void testSetTransitions_invalidInitialTransitions() {
// NOT_STARTED can only go to VALID or CANCELLED // NOT_STARTED can only go to VALID or CANCELLED
assertBadInitialTransition(NOT_STARTED); assertBadInitialTransition(NOT_STARTED);
assertBadInitialTransition(ENDED); assertBadInitialTransition(ENDED);
} }
@Test @TestOfyAndSql
void testSetTransitions_badTransitionsFromValid() { void testSetTransitions_badTransitionsFromValid() {
// VALID can only go to ENDED or CANCELLED // VALID can only go to ENDED or CANCELLED
assertBadTransition( assertBadTransition(
@ -300,14 +279,14 @@ public class AllocationTokenTest extends EntityTestCase {
NOT_STARTED); NOT_STARTED);
} }
@Test @TestOfyAndSql
void testSetTransitions_terminalTransitions() { void testSetTransitions_terminalTransitions() {
// both ENDED and CANCELLED are terminal // both ENDED and CANCELLED are terminal
assertTerminal(ENDED); assertTerminal(ENDED);
assertTerminal(CANCELLED); assertTerminal(CANCELLED);
} }
@Test @TestOfyAndSql
void testSetDiscountFractionTooHigh() { void testSetDiscountFractionTooHigh() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -318,7 +297,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Discount fraction must be between 0 and 1 inclusive"); .isEqualTo("Discount fraction must be between 0 and 1 inclusive");
} }
@Test @TestOfyAndSql
void testSetDiscountFractionTooLow() { void testSetDiscountFractionTooLow() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -329,7 +308,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Discount fraction must be between 0 and 1 inclusive"); .isEqualTo("Discount fraction must be between 0 and 1 inclusive");
} }
@Test @TestOfyAndSql
void testSetDiscountYearsTooHigh() { void testSetDiscountYearsTooHigh() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -340,7 +319,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Discount years must be between 1 and 10 inclusive"); .isEqualTo("Discount years must be between 1 and 10 inclusive");
} }
@Test @TestOfyAndSql
void testSetDiscountYearsTooLow() { void testSetDiscountYearsTooLow() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -351,7 +330,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Discount years must be between 1 and 10 inclusive"); .isEqualTo("Discount years must be between 1 and 10 inclusive");
} }
@Test @TestOfyAndSql
void testBuild_noTokenType() { void testBuild_noTokenType() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -360,7 +339,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Token type must be specified"); assertThat(thrown).hasMessageThat().isEqualTo("Token type must be specified");
} }
@Test @TestOfyAndSql
void testBuild_noToken() { void testBuild_noToken() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -369,7 +348,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Token must not be null or empty"); assertThat(thrown).hasMessageThat().isEqualTo("Token must not be null or empty");
} }
@Test @TestOfyAndSql
void testBuild_emptyToken() { void testBuild_emptyToken() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -378,7 +357,7 @@ public class AllocationTokenTest extends EntityTestCase {
assertThat(thrown).hasMessageThat().isEqualTo("Token must not be blank"); assertThat(thrown).hasMessageThat().isEqualTo("Token must not be blank");
} }
@Test @TestOfyAndSql
void testBuild_discountPremiumsRequiresDiscountFraction() { void testBuild_discountPremiumsRequiresDiscountFraction() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -394,7 +373,7 @@ public class AllocationTokenTest extends EntityTestCase {
.isEqualTo("Discount premiums can only be specified along with a discount fraction"); .isEqualTo("Discount premiums can only be specified along with a discount fraction");
} }
@Test @TestOfyAndSql
void testBuild_discountYearsRequiresDiscountFraction() { void testBuild_discountYearsRequiresDiscountFraction() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(

View file

@ -18,6 +18,8 @@ import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.toArray; import static com.google.common.collect.Iterables.toArray;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
@ -185,7 +187,7 @@ public abstract class CommandTestCase<C extends Command> {
/** Reloads the given resource from Datastore. */ /** Reloads the given resource from Datastore. */
<T> T reloadResource(T resource) { <T> T reloadResource(T resource) {
return ofy().load().entity(resource).now(); return transactIfJpaTm(() -> tm().load(resource));
} }
/** Returns count of all poll messages in Datastore. */ /** Returns count of all poll messages in Datastore. */

View file

@ -16,23 +16,28 @@ package google.registry.tools;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static google.registry.testing.DatabaseHelper.createTlds; import static google.registry.testing.DatabaseHelper.createTlds;
import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistResource;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenType; import google.registry.model.domain.token.AllocationToken.TokenType;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import java.util.Collection; import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import java.util.Arrays;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link DeleteAllocationTokensCommand}. */ /** Unit tests for {@link DeleteAllocationTokensCommand}. */
@DualDatabaseTest
class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocationTokensCommand> { class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocationTokensCommand> {
private AllocationToken preRed1; private AllocationToken preRed1;
@ -53,38 +58,38 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
othrNot = persistToken("asdgfho7HASDS", null, false); othrNot = persistToken("asdgfho7HASDS", null, false);
} }
@Test @TestOfyAndSql
void test_deleteOnlyUnredeemedTokensWithPrefix() throws Exception { void test_deleteOnlyUnredeemedTokensWithPrefix() throws Exception {
runCommandForced("--prefix", "prefix"); runCommandForced("--prefix", "prefix");
assertThat(reloadTokens(preNot1, preNot2)).isEmpty(); assertNonexistent(preNot1, preNot2);
assertThat(reloadTokens(preRed1, preRed2, othrRed, othrNot)) assertThat(reloadTokens(preRed1, preRed2, othrRed, othrNot))
.containsExactly(preRed1, preRed2, othrRed, othrNot); .containsExactly(preRed1, preRed2, othrRed, othrNot);
} }
@Test @TestOfyAndSql
void test_deleteSingleAllocationToken() throws Exception { void test_deleteSingleAllocationToken() throws Exception {
runCommandForced("--prefix", "asdgfho7HASDS"); runCommandForced("--prefix", "asdgfho7HASDS");
assertThat(reloadTokens(othrNot)).isEmpty(); assertNonexistent(othrNot);
assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed)) assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed))
.containsExactly(preRed1, preRed2, preNot1, preNot2, othrRed); .containsExactly(preRed1, preRed2, preNot1, preNot2, othrRed);
} }
@Test @TestOfyAndSql
void test_deleteParticularTokens() throws Exception { void test_deleteParticularTokens() throws Exception {
runCommandForced("--tokens", "prefix2978204,asdgfho7HASDS"); runCommandForced("--tokens", "prefix2978204,asdgfho7HASDS");
assertThat(reloadTokens(preNot1, othrNot)).isEmpty(); assertNonexistent(preNot1, othrNot);
assertThat(reloadTokens(preRed1, preRed2, preNot2, othrRed)) assertThat(reloadTokens(preRed1, preRed2, preNot2, othrRed))
.containsExactly(preRed1, preRed2, preNot2, othrRed); .containsExactly(preRed1, preRed2, preNot2, othrRed);
} }
@Test @TestOfyAndSql
void test_deleteTokensWithNonExistentPrefix_doesNothing() throws Exception { void test_deleteTokensWithNonExistentPrefix_doesNothing() throws Exception {
runCommandForced("--prefix", "nonexistent"); runCommandForced("--prefix", "nonexistent");
assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot)) assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot))
.containsExactly(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot); .containsExactly(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot);
} }
@Test @TestOfyAndSql
void test_dryRun_deletesNothing() throws Exception { void test_dryRun_deletesNothing() throws Exception {
runCommandForced("--prefix", "prefix", "--dry_run"); runCommandForced("--prefix", "prefix", "--dry_run");
assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot)) assertThat(reloadTokens(preRed1, preRed2, preNot1, preNot2, othrRed, othrNot))
@ -92,27 +97,27 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
assertInStdout("Would delete tokens: prefix2978204, prefix8ZZZhs8"); assertInStdout("Would delete tokens: prefix2978204, prefix8ZZZhs8");
} }
@Test @TestOfyAndSql
void test_defaultOptions_doesntDeletePerDomainTokens() throws Exception { void test_defaultOptions_doesntDeletePerDomainTokens() throws Exception {
AllocationToken preDom1 = persistToken("prefixasdfg897as", "foo.bar", false); AllocationToken preDom1 = persistToken("prefixasdfg897as", "foo.bar", false);
AllocationToken preDom2 = persistToken("prefix98HAZXadbn", "foo.bar", true); AllocationToken preDom2 = persistToken("prefix98HAZXadbn", "foo.bar", true);
runCommandForced("--prefix", "prefix"); runCommandForced("--prefix", "prefix");
assertThat(reloadTokens(preNot1, preNot2)).isEmpty(); assertNonexistent(preNot1, preNot2);
assertThat(reloadTokens(preRed1, preRed2, preDom1, preDom2, othrRed, othrNot)) assertThat(reloadTokens(preRed1, preRed2, preDom1, preDom2, othrRed, othrNot))
.containsExactly(preRed1, preRed2, preDom1, preDom2, othrRed, othrNot); .containsExactly(preRed1, preRed2, preDom1, preDom2, othrRed, othrNot);
} }
@Test @TestOfyAndSql
void test_withDomains_doesDeletePerDomainTokens() throws Exception { void test_withDomains_doesDeletePerDomainTokens() throws Exception {
AllocationToken preDom1 = persistToken("prefixasdfg897as", "foo.bar", false); AllocationToken preDom1 = persistToken("prefixasdfg897as", "foo.bar", false);
AllocationToken preDom2 = persistToken("prefix98HAZXadbn", "foo.bar", true); AllocationToken preDom2 = persistToken("prefix98HAZXadbn", "foo.bar", true);
runCommandForced("--prefix", "prefix", "--with_domains"); runCommandForced("--prefix", "prefix", "--with_domains");
assertThat(reloadTokens(preNot1, preNot2, preDom1)).isEmpty(); assertNonexistent(preNot1, preNot2, preDom1);
assertThat(reloadTokens(preRed1, preRed2, preDom2, othrRed, othrNot)) assertThat(reloadTokens(preRed1, preRed2, preDom2, othrRed, othrNot))
.containsExactly(preRed1, preRed2, preDom2, othrRed, othrNot); .containsExactly(preRed1, preRed2, preDom2, othrRed, othrNot);
} }
@Test @TestOfyAndSql
void testSkipUnlimitedUseTokens() throws Exception { void testSkipUnlimitedUseTokens() throws Exception {
AllocationToken unlimitedUseToken = AllocationToken unlimitedUseToken =
persistResource( persistResource(
@ -124,17 +129,18 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
assertThat(reloadTokens(unlimitedUseToken)).containsExactly(unlimitedUseToken); assertThat(reloadTokens(unlimitedUseToken)).containsExactly(unlimitedUseToken);
} }
@Test @TestOfyAndSql
void test_batching() throws Exception { void test_batching() throws Exception {
for (int i = 0; i < 50; i++) { for (int i = 0; i < 50; i++) {
persistToken(String.format("batch%2d", i), null, i % 2 == 0); persistToken(String.format("batch%2d", i), null, i % 2 == 0);
} }
assertThat(ofy().load().type(AllocationToken.class).count()).isEqualTo(56); assertThat(transactIfJpaTm(() -> tm().loadAll(AllocationToken.class).size())).isEqualTo(56);
runCommandForced("--prefix", "batch"); runCommandForced("--prefix", "batch");
assertThat(ofy().load().type(AllocationToken.class).count()).isEqualTo(56 - 25); assertThat(transactIfJpaTm(() -> tm().loadAll(AllocationToken.class).size()))
.isEqualTo(56 - 25);
} }
@Test @TestOfyAndSql
void test_prefixIsRequired() { void test_prefixIsRequired() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, this::runCommandForced); assertThrows(IllegalArgumentException.class, this::runCommandForced);
@ -143,7 +149,7 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
.isEqualTo("Must provide one of --tokens or --prefix, not both / neither"); .isEqualTo("Must provide one of --tokens or --prefix, not both / neither");
} }
@Test @TestOfyAndSql
void testFailure_bothPrefixAndTokens() { void testFailure_bothPrefixAndTokens() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -154,7 +160,7 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
.isEqualTo("Must provide one of --tokens or --prefix, not both / neither"); .isEqualTo("Must provide one of --tokens or --prefix, not both / neither");
} }
@Test @TestOfyAndSql
void testFailure_emptyPrefix() { void testFailure_emptyPrefix() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--prefix", "")); assertThrows(IllegalArgumentException.class, () -> runCommandForced("--prefix", ""));
@ -177,7 +183,11 @@ class DeleteAllocationTokensCommandTest extends CommandTestCase<DeleteAllocation
return persistResource(builder.build()); return persistResource(builder.build());
} }
private static Collection<AllocationToken> reloadTokens(AllocationToken... tokens) { private static ImmutableList<AllocationToken> reloadTokens(AllocationToken... tokens) {
return ofy().load().entities(tokens).values(); return transactIfJpaTm(() -> tm().loadAll(ImmutableSet.copyOf(tokens)));
}
private static void assertNonexistent(AllocationToken... tokens) {
Arrays.stream(tokens).forEach(t -> transactIfJpaTm(() -> assertThat(tm().exists(t)).isFalse()));
} }
} }

View file

@ -17,7 +17,8 @@ package google.registry.tools;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE; import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static google.registry.testing.DatabaseHelper.assertAllocationTokens; import static google.registry.testing.DatabaseHelper.assertAllocationTokens;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DatabaseHelper.persistResource;
@ -43,8 +44,10 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.testing.DeterministicStringGenerator; import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.DeterministicStringGenerator.Rule; import google.registry.testing.DeterministicStringGenerator.Rule;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.FakeClock; import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper; import google.registry.testing.FakeSleeper;
import google.registry.testing.TestOfyAndSql;
import google.registry.util.Retrier; import google.registry.util.Retrier;
import google.registry.util.StringGenerator.Alphabets; import google.registry.util.StringGenerator.Alphabets;
import java.io.File; import java.io.File;
@ -52,10 +55,10 @@ import java.util.Collection;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers; import org.mockito.ArgumentMatchers;
/** Unit tests for {@link GenerateAllocationTokensCommand}. */ /** Unit tests for {@link GenerateAllocationTokensCommand}. */
@DualDatabaseTest
class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAllocationTokensCommand> { class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAllocationTokensCommand> {
@BeforeEach @BeforeEach
@ -65,14 +68,14 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
new Retrier(new FakeSleeper(new FakeClock(DateTime.parse("2000-01-01TZ"))), 3); new Retrier(new FakeSleeper(new FakeClock(DateTime.parse("2000-01-01TZ"))), 3);
} }
@Test @TestOfyAndSql
void testSuccess_oneToken() throws Exception { void testSuccess_oneToken() throws Exception {
runCommand("--prefix", "blah", "--number", "1", "--length", "9"); runCommand("--prefix", "blah", "--number", "1", "--length", "9");
assertAllocationTokens(createToken("blah123456789", null, null)); assertAllocationTokens(createToken("blah123456789", null, null));
assertInStdout("blah123456789"); assertInStdout("blah123456789");
} }
@Test @TestOfyAndSql
void testSuccess_threeTokens() throws Exception { void testSuccess_threeTokens() throws Exception {
runCommand("--prefix", "foo", "--number", "3", "--length", "10"); runCommand("--prefix", "foo", "--number", "3", "--length", "10");
assertAllocationTokens( assertAllocationTokens(
@ -82,14 +85,14 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
assertInStdout("foo123456789A\nfooBCDEFGHJKL\nfooMNPQRSTUVW"); assertInStdout("foo123456789A\nfooBCDEFGHJKL\nfooMNPQRSTUVW");
} }
@Test @TestOfyAndSql
void testSuccess_defaults() throws Exception { void testSuccess_defaults() throws Exception {
runCommand("--number", "1"); runCommand("--number", "1");
assertAllocationTokens(createToken("123456789ABCDEFG", null, null)); assertAllocationTokens(createToken("123456789ABCDEFG", null, null));
assertInStdout("123456789ABCDEFG"); assertInStdout("123456789ABCDEFG");
} }
@Test @TestOfyAndSql
void testSuccess_retry() throws Exception { void testSuccess_retry() throws Exception {
command = spy(command); command = spy(command);
RemoteApiException fakeException = new RemoteApiException("foo", "foo", "foo", new Exception()); RemoteApiException fakeException = new RemoteApiException("foo", "foo", "foo", new Exception());
@ -104,7 +107,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
verify(command, times(3)).saveTokens(ArgumentMatchers.any()); verify(command, times(3)).saveTokens(ArgumentMatchers.any());
} }
@Test @TestOfyAndSql
void testSuccess_tokenCollision() throws Exception { void testSuccess_tokenCollision() throws Exception {
AllocationToken existingToken = AllocationToken existingToken =
persistResource( persistResource(
@ -117,24 +120,24 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
assertInStdout("DEADBEEFDEFGHJKLMNPQ"); assertInStdout("DEADBEEFDEFGHJKLMNPQ");
} }
@Test @TestOfyAndSql
void testSuccess_dryRun_outputsButDoesntSave() throws Exception { void testSuccess_dryRun_outputsButDoesntSave() throws Exception {
runCommand("--prefix", "foo", "--number", "2", "--length", "10", "--dry_run"); runCommand("--prefix", "foo", "--number", "2", "--length", "10", "--dry_run");
assertAllocationTokens(); assertAllocationTokens();
assertInStdout("foo123456789A\nfooBCDEFGHJKL"); assertInStdout("foo123456789A\nfooBCDEFGHJKL");
} }
@Test @TestOfyAndSql
void testSuccess_largeNumberOfTokens() throws Exception { void testSuccess_largeNumberOfTokens() throws Exception {
command.stringGenerator = command.stringGenerator =
new DeterministicStringGenerator(Alphabets.BASE_58, Rule.PREPEND_COUNTER); new DeterministicStringGenerator(Alphabets.BASE_58, Rule.PREPEND_COUNTER);
runCommand("--prefix", "ooo", "--number", "100", "--length", "16"); runCommand("--prefix", "ooo", "--number", "100", "--length", "16");
// The deterministic string generator makes it too much hassle to assert about each token, so // The deterministic string generator makes it too much hassle to assert about each token, so
// just assert total number. // just assert total number.
assertThat(ofy().load().type(AllocationToken.class).count()).isEqualTo(100); assertThat(transactIfJpaTm(() -> tm().loadAll(AllocationToken.class).size())).isEqualTo(100);
} }
@Test @TestOfyAndSql
void testSuccess_domainNames() throws Exception { void testSuccess_domainNames() throws Exception {
createTld("tld"); createTld("tld");
File domainNamesFile = tmpDir.resolve("domain_names.txt").toFile(); File domainNamesFile = tmpDir.resolve("domain_names.txt").toFile();
@ -148,7 +151,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
"foo1.tld,123456789ABCDEFG\nboo2.tld,HJKLMNPQRSTUVWXY\nbaz9.tld,Zabcdefghijkmnop"); "foo1.tld,123456789ABCDEFG\nboo2.tld,HJKLMNPQRSTUVWXY\nbaz9.tld,Zabcdefghijkmnop");
} }
@Test @TestOfyAndSql
void testSuccess_promotionToken() throws Exception { void testSuccess_promotionToken() throws Exception {
DateTime promoStart = DateTime.now(UTC); DateTime promoStart = DateTime.now(UTC);
DateTime promoEnd = promoStart.plusMonths(1); DateTime promoEnd = promoStart.plusMonths(1);
@ -182,24 +185,24 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.build()); .build());
} }
@Test @TestOfyAndSql
void testSuccess_specifyTokens() throws Exception { void testSuccess_specifyTokens() throws Exception {
runCommand("--tokens", "foobar,foobaz"); runCommand("--tokens", "foobar,foobaz");
assertAllocationTokens(createToken("foobar", null, null), createToken("foobaz", null, null)); assertAllocationTokens(createToken("foobar", null, null), createToken("foobaz", null, null));
assertInStdout("foobar", "foobaz"); assertInStdout("foobar", "foobaz");
} }
@Test @TestOfyAndSql
void testSuccess_specifyManyTokens() throws Exception { void testSuccess_specifyManyTokens() throws Exception {
command.stringGenerator = command.stringGenerator =
new DeterministicStringGenerator(Alphabets.BASE_58, Rule.PREPEND_COUNTER); new DeterministicStringGenerator(Alphabets.BASE_58, Rule.PREPEND_COUNTER);
Collection<String> sampleTokens = command.stringGenerator.createStrings(13, 100); Collection<String> sampleTokens = command.stringGenerator.createStrings(13, 100);
runCommand("--tokens", Joiner.on(",").join(sampleTokens)); runCommand("--tokens", Joiner.on(",").join(sampleTokens));
assertInStdout(Iterables.toArray(sampleTokens, String.class)); assertInStdout(Iterables.toArray(sampleTokens, String.class));
assertThat(ofy().load().type(AllocationToken.class).count()).isEqualTo(100); assertThat(transactIfJpaTm(() -> tm().loadAll(AllocationToken.class).size())).isEqualTo(100);
} }
@Test @TestOfyAndSql
void testFailure_mustSpecifyNumberOfTokensOrDomainsFile() { void testFailure_mustSpecifyNumberOfTokensOrDomainsFile() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommand("--prefix", "FEET")); assertThrows(IllegalArgumentException.class, () -> runCommand("--prefix", "FEET"));
@ -208,7 +211,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'"); .isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'");
} }
@Test @TestOfyAndSql
void testFailure_mustNotSpecifyBothNumberOfTokensAndDomainsFile() { void testFailure_mustNotSpecifyBothNumberOfTokensAndDomainsFile() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -223,7 +226,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'"); .isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'");
} }
@Test @TestOfyAndSql
void testFailure_mustNotSpecifyBothNumberOfTokensAndTokenStrings() { void testFailure_mustNotSpecifyBothNumberOfTokensAndTokenStrings() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -238,7 +241,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'"); .isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'");
} }
@Test @TestOfyAndSql
void testFailure_mustNotSpecifyBothTokenStringsAndDomainsFile() { void testFailure_mustNotSpecifyBothTokenStringsAndDomainsFile() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -253,7 +256,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'"); .isEqualTo("Must specify exactly one of '--number', '--domain_names_file', and '--tokens'");
} }
@Test @TestOfyAndSql
void testFailure_specifiesAlreadyExistingToken() throws Exception { void testFailure_specifiesAlreadyExistingToken() throws Exception {
runCommand("--tokens", "foobar"); runCommand("--tokens", "foobar");
beforeEachCommandTestCase(); // reset the command variables beforeEachCommandTestCase(); // reset the command variables
@ -264,7 +267,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Cannot create specified tokens; the following tokens already exist: [foobar]"); .isEqualTo("Cannot create specified tokens; the following tokens already exist: [foobar]");
} }
@Test @TestOfyAndSql
void testFailure_invalidTokenType() { void testFailure_invalidTokenType() {
ParameterException thrown = ParameterException thrown =
assertThrows( assertThrows(
@ -275,7 +278,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isEqualTo("Invalid value for -t parameter. Allowed values:[SINGLE_USE, UNLIMITED_USE]"); .isEqualTo("Invalid value for -t parameter. Allowed values:[SINGLE_USE, UNLIMITED_USE]");
} }
@Test @TestOfyAndSql
void testFailure_invalidTokenStatusTransition() { void testFailure_invalidTokenStatusTransition() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -290,7 +293,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
.isInstanceOf(IllegalArgumentException.class); .isInstanceOf(IllegalArgumentException.class);
} }
@Test @TestOfyAndSql
void testFailure_lengthOfZero() { void testFailure_lengthOfZero() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -302,7 +305,7 @@ class GenerateAllocationTokensCommandTest extends CommandTestCase<GenerateAlloca
"Token length should not be 0. To generate exact tokens, use the --tokens parameter."); "Token length should not be 0. To generate exact tokens, use the --tokens parameter.");
} }
@Test @TestOfyAndSql
void testFailure_unlimitedUseMustHaveTransitions() { void testFailure_unlimitedUseMustHaveTransitions() {
assertThat( assertThat(
assertThrows( assertThrows(

View file

@ -30,12 +30,14 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.ImmutableSortedMap;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
@DualDatabaseTest
class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocationTokensCommand> { class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocationTokensCommand> {
@Test @TestOfyAndSql
void testUpdateTlds_setTlds() throws Exception { void testUpdateTlds_setTlds() throws Exception {
AllocationToken token = AllocationToken token =
persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("toRemove")).build()); persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("toRemove")).build());
@ -43,7 +45,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(token).getAllowedTlds()).containsExactly("tld", "example"); assertThat(reloadResource(token).getAllowedTlds()).containsExactly("tld", "example");
} }
@Test @TestOfyAndSql
void testUpdateTlds_clearTlds() throws Exception { void testUpdateTlds_clearTlds() throws Exception {
AllocationToken token = AllocationToken token =
persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("toRemove")).build()); persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("toRemove")).build());
@ -51,7 +53,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(token).getAllowedTlds()).isEmpty(); assertThat(reloadResource(token).getAllowedTlds()).isEmpty();
} }
@Test @TestOfyAndSql
void testUpdateClientIds_setClientIds() throws Exception { void testUpdateClientIds_setClientIds() throws Exception {
AllocationToken token = AllocationToken token =
persistResource( persistResource(
@ -61,7 +63,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
.containsExactly("clientone", "clienttwo"); .containsExactly("clientone", "clienttwo");
} }
@Test @TestOfyAndSql
void testUpdateClientIds_clearClientIds() throws Exception { void testUpdateClientIds_clearClientIds() throws Exception {
AllocationToken token = AllocationToken token =
persistResource( persistResource(
@ -70,14 +72,14 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(token).getAllowedRegistrarIds()).isEmpty(); assertThat(reloadResource(token).getAllowedRegistrarIds()).isEmpty();
} }
@Test @TestOfyAndSql
void testUpdateDiscountFraction() throws Exception { void testUpdateDiscountFraction() throws Exception {
AllocationToken token = persistResource(builderWithPromo().setDiscountFraction(0.5).build()); AllocationToken token = persistResource(builderWithPromo().setDiscountFraction(0.5).build());
runCommandForced("--prefix", "token", "--discount_fraction", "0.15"); runCommandForced("--prefix", "token", "--discount_fraction", "0.15");
assertThat(reloadResource(token).getDiscountFraction()).isEqualTo(0.15); assertThat(reloadResource(token).getDiscountFraction()).isEqualTo(0.15);
} }
@Test @TestOfyAndSql
void testUpdateDiscountPremiums() throws Exception { void testUpdateDiscountPremiums() throws Exception {
AllocationToken token = AllocationToken token =
persistResource( persistResource(
@ -88,14 +90,14 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(token).shouldDiscountPremiums()).isFalse(); assertThat(reloadResource(token).shouldDiscountPremiums()).isFalse();
} }
@Test @TestOfyAndSql
void testUpdateDiscountYears() throws Exception { void testUpdateDiscountYears() throws Exception {
AllocationToken token = persistResource(builderWithPromo().setDiscountFraction(0.5).build()); AllocationToken token = persistResource(builderWithPromo().setDiscountFraction(0.5).build());
runCommandForced("--prefix", "token", "--discount_years", "4"); runCommandForced("--prefix", "token", "--discount_years", "4");
assertThat(reloadResource(token).getDiscountYears()).isEqualTo(4); assertThat(reloadResource(token).getDiscountYears()).isEqualTo(4);
} }
@Test @TestOfyAndSql
void testUpdateStatusTransitions() throws Exception { void testUpdateStatusTransitions() throws Exception {
DateTime now = DateTime.now(UTC); DateTime now = DateTime.now(UTC);
AllocationToken token = persistResource(builderWithPromo().build()); AllocationToken token = persistResource(builderWithPromo().build());
@ -110,7 +112,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
.containsExactly(START_OF_TIME, NOT_STARTED, now.minusDays(1), VALID, now, CANCELLED); .containsExactly(START_OF_TIME, NOT_STARTED, now.minusDays(1), VALID, now, CANCELLED);
} }
@Test @TestOfyAndSql
void testUpdateStatusTransitions_badTransitions() { void testUpdateStatusTransitions_badTransitions() {
DateTime now = DateTime.now(UTC); DateTime now = DateTime.now(UTC);
persistResource(builderWithPromo().build()); persistResource(builderWithPromo().build());
@ -130,7 +132,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
.isEqualTo("tokenStatusTransitions map cannot transition from NOT_STARTED to ENDED."); .isEqualTo("tokenStatusTransitions map cannot transition from NOT_STARTED to ENDED.");
} }
@Test @TestOfyAndSql
void testUpdate_onlyWithPrefix() throws Exception { void testUpdate_onlyWithPrefix() throws Exception {
AllocationToken token = AllocationToken token =
persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("tld")).build()); persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("tld")).build());
@ -146,7 +148,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(otherToken).getAllowedTlds()).isEmpty(); assertThat(reloadResource(otherToken).getAllowedTlds()).isEmpty();
} }
@Test @TestOfyAndSql
void testUpdate_onlyTokensProvided() throws Exception { void testUpdate_onlyTokensProvided() throws Exception {
AllocationToken firstToken = AllocationToken firstToken =
persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("tld")).build()); persistResource(builderWithPromo().setAllowedTlds(ImmutableSet.of("tld")).build());
@ -170,7 +172,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloadResource(thirdToken).getAllowedTlds()).isEmpty(); assertThat(reloadResource(thirdToken).getAllowedTlds()).isEmpty();
} }
@Test @TestOfyAndSql
void testDoNothing() throws Exception { void testDoNothing() throws Exception {
AllocationToken token = AllocationToken token =
persistResource( persistResource(
@ -186,7 +188,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
assertThat(reloaded.getDiscountFraction()).isEqualTo(token.getDiscountFraction()); assertThat(reloaded.getDiscountFraction()).isEqualTo(token.getDiscountFraction());
} }
@Test @TestOfyAndSql
void testFailure_bothTokensAndPrefix() { void testFailure_bothTokensAndPrefix() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -196,7 +198,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
.isEqualTo("Must provide one of --tokens or --prefix, not both / neither"); .isEqualTo("Must provide one of --tokens or --prefix, not both / neither");
} }
@Test @TestOfyAndSql
void testFailure_neitherTokensNorPrefix() { void testFailure_neitherTokensNorPrefix() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -205,7 +207,7 @@ class UpdateAllocationTokensCommandTest extends CommandTestCase<UpdateAllocation
.isEqualTo("Must provide one of --tokens or --prefix, not both / neither"); .isEqualTo("Must provide one of --tokens or --prefix, not both / neither");
} }
@Test @TestOfyAndSql
void testFailure_emptyPrefix() { void testFailure_emptyPrefix() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> runCommandForced("--prefix", "")); assertThrows(IllegalArgumentException.class, () -> runCommandForced("--prefix", ""));