Wire in domain transfer custom pricing and add a test

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=142593949
This commit is contained in:
mcilwain 2016-12-20 14:00:09 -08:00 committed by Ben McIlwain
parent f0d2f96c26
commit 720f03cc17
11 changed files with 196 additions and 110 deletions

View file

@ -32,7 +32,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.base.Optional;
@ -45,6 +44,7 @@ import google.registry.flows.FlowModule.ClientId;
import google.registry.flows.FlowModule.Superuser;
import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.domain.DomainPricingLogic.FeesAndCredits;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
import google.registry.model.billing.BillingEvent;
@ -53,8 +53,6 @@ import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeTransferCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
import google.registry.model.domain.flags.FlagsTransferCommandExtension;
@ -125,6 +123,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
@Inject HistoryEntry.Builder historyBuilder;
@Inject Trid trid;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainTransferRequestFlow() {}
@Override
@ -142,12 +141,11 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
verifyTransferAllowed(existingDomain, period, now);
String tld = existingDomain.getTld();
Registry registry = Registry.get(tld);
// The cost of the renewal implied by a transfer.
Money renewCost = getDomainRenewCost(targetId, now, years);
// An optional extension from the client specifying what they think the transfer should cost.
FeeTransferCommandExtension feeTransfer =
eppInput.getSingleExtension(FeeTransferCommandExtension.class);
validateFeeChallenge(targetId, tld, now, feeTransfer, renewCost);
FeesAndCredits feesAndCredits = pricingLogic.getTransferPrice(registry, targetId, now, years);
validateFeeChallenge(targetId, tld, now, feeTransfer, feesAndCredits.getTotalCost());
HistoryEntry historyEntry = buildHistory(period, existingDomain, now);
DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength());
// The new expiration time if there is a server approval.
@ -160,7 +158,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
serverApproveNewExpirationTime,
historyEntry,
existingDomain,
renewCost,
feesAndCredits.getTotalCost(),
years,
now);
// Create the transfer data that represents the pending transfer.
@ -189,7 +187,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
return responseBuilder
.setResultFromCode(SUCCESS_WITH_ACTION_PENDING)
.setResData(createResponse(period, existingDomain, newDomain, now))
.setExtensions(createResponseExtensions(renewCost, feeTransfer))
.setExtensions(createResponseExtensions(feesAndCredits, feeTransfer))
.build();
}
@ -241,7 +239,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry,
DomainResource existingDomain,
Money renewCost,
Money transferCost,
int years,
DateTime now) {
// Create a TransferData for the server-approve case to use for the speculative poll messages.
@ -252,7 +250,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
Registry registry = Registry.get(existingDomain.getTld());
return new ImmutableSet.Builder<TransferServerApproveEntity>()
.add(createTransferBillingEvent(
automaticTransferTime, historyEntry, registry, renewCost, years))
automaticTransferTime, historyEntry, registry, transferCost, years))
.addAll(createOptionalAutorenewCancellation(
automaticTransferTime, historyEntry, existingDomain)
.asSet())
@ -271,13 +269,13 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
DateTime automaticTransferTime,
HistoryEntry historyEntry,
Registry registry,
Money renewCost,
Money transferCost,
int years) {
return new BillingEvent.OneTime.Builder()
.setReason(Reason.TRANSFER)
.setTargetId(targetId)
.setClientId(gainingClientId)
.setCost(renewCost)
.setCost(transferCost)
.setPeriodYears(years)
.setEventTime(automaticTransferTime)
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
@ -388,13 +386,14 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
targetId, newDomain.getTransferData(), approveNowExtendedRegistrationTime);
}
private ImmutableList<FeeTransformResponseExtension> createResponseExtensions(Money renewCost,
FeeTransferCommandExtension feeTransfer) {
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(
FeesAndCredits feesAndCredits, FeeTransferCommandExtension feeTransfer) {
return feeTransfer == null
? ImmutableList.<FeeTransformResponseExtension>of()
: ImmutableList.of(feeTransfer.createResponseBuilder()
.setCurrency(renewCost.getCurrencyUnit())
.setFees(ImmutableList.of(Fee.create(renewCost.getAmount(), FeeType.RENEW)))
.setFees(feesAndCredits.getFees())
.setCredits(feesAndCredits.getCredits())
.setCurrency(feesAndCredits.getCurrency())
.build());
}
}

View file

@ -48,6 +48,14 @@ public abstract class BaseFee extends ImmutableObject {
EAP("Early Access Period, fee expires: %s"),
RENEW("renew"),
RESTORE("restore"),
/**
* A transfer fee.
*
* <p>These are not used by the default system, in which the only fee associated with a transfer
* is the RENEW fee. These exist so that custom pricing logic can create a custom transfer fee
* if desired.
*/
TRANSFER("transfer"),
UPDATE("update"),
CREDIT("%s credit");

View file

@ -42,27 +42,6 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic {
super(eppInput, sessionMetadata);
}
private static BaseFee domainNameToFeeOrCredit(InternetDomainName domainName) {
// The second-level domain should be of the form "description-price", where description is the
// description string of the fee or credit, and price is the price (credit if negative, fee
// otherwise). To make sure this is a valid domain name, don't use any spaces, and limit prices
// to integers. Don't use a two-character description for credits, since it is illegal to have
// both the third and fourth characters of a domain name label be hyphens.
List<String> components =
Splitter.on('-')
.limit(2)
.splitToList(Iterables.getFirst(Splitter.on('.').split(domainName.toString()), ""));
checkArgument(components.size() == 2, "Domain name must be of the form description-price.tld");
int price = Integer.parseInt(components.get(1));
if (price < 0) {
return Credit.create(
new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0))));
} else {
return Fee.create(
new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0))));
}
}
@Override
public FeesAndCredits customizeCreatePrice(CreatePriceParameters priceParameters)
throws EppException {
@ -85,53 +64,68 @@ public class TestDomainPricingCustomLogic extends DomainPricingCustomLogic {
@Override
public FeesAndCredits customizeApplicationUpdatePrice(
ApplicationUpdatePriceParameters priceParameters) throws EppException {
if (priceParameters
return (priceParameters
.domainApplication()
.getFullyQualifiedDomainName()
.startsWith("non-free-update")) {
FeesAndCredits feesAndCredits = priceParameters.feesAndCredits();
List<BaseFee> newFeesAndCredits =
new ImmutableList.Builder<BaseFee>()
.addAll(feesAndCredits.getFeesAndCredits())
.add(Fee.create(BigDecimal.valueOf(100), FeeType.UPDATE))
.build();
return new FeesAndCredits(
feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class));
} else {
return priceParameters.feesAndCredits();
}
.startsWith("non-free-update"))
? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.UPDATE))
: priceParameters.feesAndCredits();
}
@Override
public FeesAndCredits customizeRenewPrice(RenewPriceParameters priceParameters)
throws EppException {
if (priceParameters.domainName().toString().startsWith("costly-renew")) {
FeesAndCredits feesAndCredits = priceParameters.feesAndCredits();
List<BaseFee> newFeesAndCredits =
new ImmutableList.Builder<BaseFee>()
.addAll(feesAndCredits.getFeesAndCredits())
.add(Fee.create(BigDecimal.valueOf(100), FeeType.RENEW))
.build();
return new FeesAndCredits(
feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class));
} else {
return priceParameters.feesAndCredits();
return (priceParameters.domainName().toString().startsWith("costly-renew"))
? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.RENEW))
: priceParameters.feesAndCredits();
}
@Override
public FeesAndCredits customizeTransferPrice(TransferPriceParameters priceParameters)
throws EppException {
return (priceParameters.domainName().toString().startsWith("expensive"))
? addCustomFee(
priceParameters.feesAndCredits(), Fee.create(BigDecimal.valueOf(100), FeeType.TRANSFER))
: priceParameters.feesAndCredits();
}
@Override
public FeesAndCredits customizeUpdatePrice(UpdatePriceParameters priceParameters) {
if (priceParameters.domainName().toString().startsWith("non-free-update")) {
FeesAndCredits feesAndCredits = priceParameters.feesAndCredits();
return (priceParameters.domainName().toString().startsWith("non-free-update"))
? addCustomFee(priceParameters.feesAndCredits(), Fee.create(TEN, FeeType.UPDATE))
: priceParameters.feesAndCredits();
}
private static FeesAndCredits addCustomFee(FeesAndCredits feesAndCredits, BaseFee customFee) {
List<BaseFee> newFeesAndCredits =
new ImmutableList.Builder<BaseFee>()
.addAll(feesAndCredits.getFeesAndCredits())
.add(Fee.create(TEN, FeeType.UPDATE))
.add(customFee)
.build();
return new FeesAndCredits(
feesAndCredits.getCurrency(), toArray(newFeesAndCredits, BaseFee.class));
}
private static BaseFee domainNameToFeeOrCredit(InternetDomainName domainName) {
// The second-level domain should be of the form "description-price", where description is the
// description string of the fee or credit, and price is the price (credit if negative, fee
// otherwise). To make sure this is a valid domain name, don't use any spaces, and limit prices
// to integers. Don't use a two-character description for credits, since it is illegal to have
// both the third and fourth characters of a domain name label be hyphens.
List<String> components =
Splitter.on('-')
.limit(2)
.splitToList(Iterables.getFirst(Splitter.on('.').split(domainName.toString()), ""));
checkArgument(components.size() == 2, "Domain name must be of the form description-price.tld");
int price = Integer.parseInt(components.get(1));
if (price < 0) {
return Credit.create(
new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0))));
} else {
return priceParameters.feesAndCredits();
return Fee.create(
new BigDecimal(price), FeeType.valueOf(Ascii.toUpperCase(components.get(0))));
}
}
}

View file

@ -94,7 +94,7 @@ public class DomainTransferApproveFlowTest
.build());
setClientIdForFlow("TheRegistrar");
createTld("extra");
setupDomainWithPendingTransfer();
setupDomainWithPendingTransfer("example", "tld");
clock.advanceOneMilli();
}
@ -278,7 +278,7 @@ public class DomainTransferApproveFlowTest
.asBuilder()
.setTransferGracePeriodLength(Duration.standardMinutes(10))
.build());
setupDomainWithPendingTransfer("net");
setupDomainWithPendingTransfer("example", "net");
doSuccessfulTest(
"net",
"domain_transfer_approve_net.xml",

View file

@ -53,7 +53,7 @@ public class DomainTransferCancelFlowTest
public void setUp() throws Exception {
setEppInput("domain_transfer_cancel.xml");
setClientIdForFlow("NewRegistrar");
setupDomainWithPendingTransfer();
setupDomainWithPendingTransfer("example", "tld");
}
private void doSuccessfulTest(String commandFilename, String expectedXmlFilename)

View file

@ -106,10 +106,6 @@ public class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
TRANSFER_REQUEST_TIME);
}
protected void setupDomain(String tld) throws Exception {
setupDomain("example", tld);
}
/** Adds a domain with no pending transfer on it. */
protected void setupDomain(String label, String tld) throws Exception {
createTld(tld);
@ -230,14 +226,9 @@ public class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
.hasCurrentSponsorClientId("TheRegistrar");
}
/** Adds a .tld domain that has a pending transfer on it from TheRegistrar to NewRegistrar. */
protected void setupDomainWithPendingTransfer() throws Exception {
setupDomainWithPendingTransfer("tld");
}
/** Adds a domain that has a pending transfer on it from TheRegistrar to NewRegistrar. */
protected void setupDomainWithPendingTransfer(String tld) throws Exception {
setupDomain(tld);
protected void setupDomainWithPendingTransfer(String label, String tld) throws Exception {
setupDomain(label, tld);
domain = persistWithPendingTransfer(domain);
}

View file

@ -42,7 +42,7 @@ public class DomainTransferQueryFlowTest
public void setUp() throws Exception {
setEppInput("domain_transfer_query.xml");
setClientIdForFlow("NewRegistrar");
setupDomainWithPendingTransfer();
setupDomainWithPendingTransfer("example", "tld");
}
private void doSuccessfulTest(

View file

@ -55,7 +55,7 @@ public class DomainTransferRejectFlowTest
public void setUp() throws Exception {
setEppInput("domain_transfer_reject.xml");
setClientIdForFlow("TheRegistrar");
setupDomainWithPendingTransfer();
setupDomainWithPendingTransfer("example", "tld");
clock.advanceOneMilli();
}

View file

@ -18,10 +18,10 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.deleteResource;
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatastoreHelper.getOnlyPollMessage;
import static google.registry.testing.DatastoreHelper.getPollMessages;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.DomainResourceSubject.assertAboutDomains;
import static google.registry.testing.GenericEppResourceSubject.assertAboutEppResources;
@ -33,6 +33,7 @@ import static org.joda.money.CurrencyUnit.EUR;
import static org.joda.money.CurrencyUnit.USD;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
@ -95,8 +96,6 @@ public class DomainTransferRequestFlowTest
public void setUp() throws Exception {
setEppInput("domain_transfer_request.xml");
setClientIdForFlow("NewRegistrar");
setupDomain("tld");
createTld("flags");
}
private void assertTransferRequested(DomainResource domain) throws Exception {
@ -107,7 +106,7 @@ public class DomainTransferRequestFlowTest
.hasTransferRequestClientTrid(getClientTrid()).and()
.hasCurrentSponsorClientId("TheRegistrar").and()
.hasPendingTransferExpirationTime(
clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength())).and()
clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength())).and()
.hasStatusValue(StatusValue.PENDING_TRANSFER);
}
@ -118,7 +117,8 @@ public class DomainTransferRequestFlowTest
}
private void assertTransferApproved(DomainResource domain) {
DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
DateTime afterAutoAck =
clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength());
assertAboutDomains().that(domain)
.hasTransferStatus(TransferStatus.SERVER_APPROVED).and()
.hasCurrentSponsorClientId("NewRegistrar").and()
@ -128,7 +128,8 @@ public class DomainTransferRequestFlowTest
}
private void assertTransferApproved(HostResource host) {
DateTime afterAutoAck = clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
DateTime afterAutoAck =
clock.nowUtc().plus(Registry.get(domain.getTld()).getAutomaticTransferLength());
assertAboutHosts().that(host)
.hasCurrentSponsorClientId("NewRegistrar").and()
.hasLastTransferTime(afterAutoAck).and()
@ -145,6 +146,7 @@ public class DomainTransferRequestFlowTest
String expectedXmlFilename,
DateTime expectedExpirationTime,
Map<String, String> substitutions,
Optional<Money> transferCost,
BillingEvent.Cancellation.Builder... extraExpectedBillingEvents) throws Exception {
setEppInput(commandFilename, substitutions);
ImmutableSet<GracePeriod> originalGracePeriods = domain.getGracePeriods();
@ -153,8 +155,8 @@ public class DomainTransferRequestFlowTest
// For all of the other transfer flow tests, 'now' corresponds to day 3 of the transfer, but
// for the request test we want that same 'now' to be the initial request time, so we shift
// the transfer timeline 3 days later by adjusting the implicit transfer time here.
DateTime implicitTransferTime =
clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength());
Registry registry = Registry.get(domain.getTld());
DateTime implicitTransferTime = clock.nowUtc().plus(registry.getAutomaticTransferLength());
// Setup done; run the test.
assertTransactionalFlow(true);
runFlowAssertResponse(readFile(expectedXmlFilename, substitutions));
@ -183,10 +185,9 @@ public class DomainTransferRequestFlowTest
.setReason(Reason.TRANSFER)
.setTargetId(domain.getFullyQualifiedDomainName())
.setEventTime(implicitTransferTime)
.setBillingTime(
implicitTransferTime.plus(Registry.get("tld").getTransferGracePeriodLength()))
.setBillingTime(implicitTransferTime.plus(registry.getTransferGracePeriodLength()))
.setClientId("NewRegistrar")
.setCost(Money.of(USD, 11).multipliedBy(registrationYears))
.setCost(transferCost.or(Money.of(USD, 11).multipliedBy(registrationYears)))
.setPeriodYears(registrationYears)
.setParent(historyEntryTransferRequest)
.build();
@ -225,8 +226,8 @@ public class DomainTransferRequestFlowTest
GracePeriod.create(
GracePeriodStatus.TRANSFER,
clock.nowUtc()
.plus(Registry.get("tld").getAutomaticTransferLength())
.plus(Registry.get("tld").getTransferGracePeriodLength()),
.plus(registry.getAutomaticTransferLength())
.plus(registry.getTransferGracePeriodLength()),
"NewRegistrar",
null),
transferBillingEvent));
@ -285,8 +286,8 @@ public class DomainTransferRequestFlowTest
.isEqualTo(expectedExpirationTime);
// And after the expected grace time, the grace period should be gone.
DomainResource afterGracePeriod = domain.cloneProjectedAtTime(
clock.nowUtc().plus(Registry.get("tld").getAutomaticTransferLength()).plus(
Registry.get("tld").getTransferGracePeriodLength()));
clock.nowUtc().plus(registry.getAutomaticTransferLength()).plus(
registry.getTransferGracePeriodLength()));
assertThat(afterGracePeriod.getGracePeriods()).isEmpty();
}
@ -300,6 +301,7 @@ public class DomainTransferRequestFlowTest
expectedXmlFilename,
expectedExpirationTime,
ImmutableMap.<String, String>of(),
Optional.<Money>absent(),
extraExpectedBillingEvents);
}
@ -312,7 +314,8 @@ public class DomainTransferRequestFlowTest
commandFilename,
expectedXmlFilename,
domain.getRegistrationExpirationTime().plusYears(1),
substitutions);
substitutions,
Optional.<Money>absent());
}
private void doSuccessfulTest(String commandFilename, String expectedXmlFilename)
@ -349,6 +352,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testDryRun() throws Exception {
setupDomain("example", "tld");
setEppInput("domain_transfer_request.xml");
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
dryRunFlowAssertResponse(readFile("domain_transfer_request_response.xml"));
@ -356,29 +360,34 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_fee_v06() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_06_MAP);
}
@Test
public void testSuccess_fee_v11() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_11_MAP);
}
@Test
public void testSuccess_fee_v12() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee.xml", "domain_transfer_request_response_fee.xml", FEE_12_MAP);
}
@Test
public void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml",
"domain_transfer_request_response_fee.xml",
@ -387,6 +396,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml",
"domain_transfer_request_response_fee.xml",
@ -395,6 +405,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_fee_withDefaultAttributes_v12() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_fee_defaults.xml",
"domain_transfer_request_response_fee.xml",
@ -403,60 +414,70 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_refundableFee_v06() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_06_MAP);
}
@Test
public void testFailure_refundableFee_v11() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_11_MAP);
}
@Test
public void testFailure_refundableFee_v12() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_refundable.xml", FEE_12_MAP);
}
@Test
public void testFailure_gracePeriodFee_v06() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_06_MAP);
}
@Test
public void testFailure_gracePeriodFee_v11() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_11_MAP);
}
@Test
public void testFailure_gracePeriodFee_v12() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_grace_period.xml", FEE_12_MAP);
}
@Test
public void testFailure_appliedFee_v06() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml", FEE_06_MAP);
}
@Test
public void testFailure_appliedFee_v11() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml", FEE_11_MAP);
}
@Test
public void testFailure_appliedFee_v12() throws Exception {
setupDomain("example", "tld");
thrown.expect(UnsupportedFeeAttributeException.class);
doFailingTest("domain_transfer_request_fee_applied.xml", FEE_12_MAP);
}
@Test
public void testSuccess_nonDefaultAutomaticTransferLength() throws Exception {
setupDomain("example", "tld");
persistResource(
Registry.get("tld")
.asBuilder()
@ -469,6 +490,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_nonDefaultTransferGracePeriod() throws Exception {
setupDomain("example", "tld");
persistResource(
Registry.get("tld")
.asBuilder()
@ -479,12 +501,14 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_missingPeriod() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest("domain_transfer_request_missing_period.xml",
"domain_transfer_request_response.xml");
}
@Test
public void testSuccess_cappedExpiration() throws Exception {
setupDomain("example", "tld");
// The current expiration is in 15 months, so requesting 10 years would give 11 years 3 months,
// were it not that we cap at 10 years. (MAX_REGISTRATION_YEARS == 10 and is unlikely to ever
// change; we just use a constant for readability.)
@ -497,13 +521,31 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_domainAuthInfo() throws Exception {
setupDomain("example", "tld");
doSuccessfulTest(
"domain_transfer_request_domain_authinfo.xml",
"domain_transfer_request_response.xml");
}
@Test
public void testSuccess_customLogicFee() throws Exception {
setupDomain("expensive-domain", "foo");
clock.advanceOneMilli();
doSuccessfulTest(
"domain_transfer_request_wildcard.xml",
"domain_transfer_request_response_wildcard.xml",
domain.getRegistrationExpirationTime().plusYears(3),
new ImmutableMap.Builder<String, String>()
.put("DOMAIN", "expensive-domain.foo")
.put("YEARS", "3")
.put("EXDATE", "2004-09-08T22:00:00.0Z")
.build(),
Optional.of(Money.of(USD, 133)));
}
@Test
public void testFailure_notAuthorizedForTld() throws Exception {
setupDomain("example", "tld");
persistResource(
Registrar.loadByClientId("NewRegistrar")
.asBuilder()
@ -515,6 +557,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_autorenewBeforeAutomaticTransfer() throws Exception {
setupDomain("example", "tld");
DomainResource oldResource = persistResource(reloadResourceByForeignKey().asBuilder()
.setRegistrationExpirationTime(clock.nowUtc().plusDays(1).plus(1))
.build());
@ -559,6 +602,7 @@ public class DomainTransferRequestFlowTest
}
private void runWrongCurrencyTest(Map<String, String> substitutions) throws Exception {
setupDomain("example", "tld");
persistResource(
Registry.get("tld")
.asBuilder()
@ -575,33 +619,39 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_wrongCurrency_v06() throws Exception {
setupDomain("example", "tld");
runWrongCurrencyTest(FEE_06_MAP);
}
@Test
public void testFailure_wrongCurrency_v11() throws Exception {
setupDomain("example", "tld");
runWrongCurrencyTest(FEE_11_MAP);
}
@Test
public void testFailure_wrongCurrency_v12() throws Exception {
setupDomain("example", "tld");
runWrongCurrencyTest(FEE_12_MAP);
}
@Test
public void testFailure_feeGivenInWrongScale_v06() throws Exception {
setupDomain("example", "tld");
thrown.expect(CurrencyValueScaleException.class);
doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_06_MAP);
}
@Test
public void testFailure_feeGivenInWrongScale_v11() throws Exception {
setupDomain("example", "tld");
thrown.expect(CurrencyValueScaleException.class);
doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_11_MAP);
}
@Test
public void testFailure_feeGivenInWrongScale_v12() throws Exception {
setupDomain("example", "tld");
thrown.expect(CurrencyValueScaleException.class);
doFailingTest("domain_transfer_request_fee_bad_scale.xml", FEE_12_MAP);
}
@ -619,16 +669,19 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_wrongFeeAmount_v06() throws Exception {
setupDomain("example", "tld");
runWrongFeeAmountTest(FEE_06_MAP);
}
@Test
public void testFailure_wrongFeeAmount_v11() throws Exception {
setupDomain("example", "tld");
runWrongFeeAmountTest(FEE_11_MAP);
}
@Test
public void testFailure_wrongFeeAmount_v12() throws Exception {
setupDomain("example", "tld");
runWrongFeeAmountTest(FEE_12_MAP);
}
@ -651,12 +704,14 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_noAuthInfo() throws Exception {
setupDomain("example", "tld");
thrown.expect(MissingTransferRequestAuthInfoException.class);
doFailingTest("domain_transfer_request_no_authinfo.xml");
}
@Test
public void testFailure_badContactPassword() throws Exception {
setupDomain("example", "tld");
// Change the contact's password so it does not match the password in the file.
contact = persistResource(
contact.asBuilder()
@ -668,6 +723,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_badContactRepoId() throws Exception {
setupDomain("example", "tld");
// Set the contact to a different ROID, but don't persist it; this is just so the substitution
// code above will write the wrong ROID into the file.
contact = contact.asBuilder().setRepoId("DEADBEEF_TLD-ROID").build();
@ -677,36 +733,42 @@ public class DomainTransferRequestFlowTest
@Test
public void testSuccess_clientApproved() throws Exception {
setupDomain("example", "tld");
changeTransferStatus(TransferStatus.CLIENT_APPROVED);
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_clientRejected() throws Exception {
setupDomain("example", "tld");
changeTransferStatus(TransferStatus.CLIENT_REJECTED);
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_clientCancelled() throws Exception {
setupDomain("example", "tld");
changeTransferStatus(TransferStatus.CLIENT_CANCELLED);
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_serverApproved() throws Exception {
setupDomain("example", "tld");
changeTransferStatus(TransferStatus.SERVER_APPROVED);
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testSuccess_serverCancelled() throws Exception {
setupDomain("example", "tld");
changeTransferStatus(TransferStatus.SERVER_CANCELLED);
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test
public void testFailure_pending() throws Exception {
setupDomain("example", "tld");
domain = persistResource(domain.asBuilder()
.setTransferData(domain.getTransferData().asBuilder()
.setTransferStatus(TransferStatus.PENDING)
@ -719,6 +781,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_badDomainPassword() throws Exception {
setupDomain("example", "tld");
// Change the domain's password so it does not match the password in the file.
domain = persistResource(domain.asBuilder()
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("badpassword")))
@ -729,6 +792,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_sponsoringClient() throws Exception {
setupDomain("example", "tld");
setClientIdForFlow("TheRegistrar");
thrown.expect(ObjectAlreadySponsoredException.class);
doFailingTest("domain_transfer_request.xml");
@ -736,6 +800,7 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_deletedDomain() throws Exception {
setupDomain("example", "tld");
domain = persistResource(
domain.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
thrown.expect(
@ -746,7 +811,10 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_invalidDomain() throws Exception {
setEppInput("domain_transfer_request_wildcard.xml", ImmutableMap.of("DOMAIN", "--invalid"));
setupDomain("example", "tld");
setEppInput(
"domain_transfer_request_wildcard.xml",
ImmutableMap.of("YEARS", "1", "DOMAIN", "--invalid", "EXDATE", "2002-09-08T22:00:00.0Z"));
eppLoader.replaceAll("JD1234-REP", contact.getRepoId());
assertTransactionalFlow(true);
thrown.expect(ResourceDoesNotExistException.class, "(--invalid)");
@ -755,21 +823,24 @@ public class DomainTransferRequestFlowTest
@Test
public void testFailure_nonexistentDomain() throws Exception {
deleteResource(domain);
createTld("tld");
contact = persistActiveContact("jd1234");
thrown.expect(
ResourceDoesNotExistException.class,
String.format("(%s)", getUniqueIdFromCommand()));
String.format("(%s)", "example.tld"));
doFailingTest("domain_transfer_request.xml");
}
@Test
public void testFailure_periodInMonths() throws Exception {
setupDomain("example", "tld");
thrown.expect(BadPeriodUnitException.class);
doFailingTest("domain_transfer_request_months.xml");
}
@Test
public void testFailure_pendingDelete() throws Exception {
setupDomain("example", "tld");
domain = persistResource(
domain.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build());
thrown.expect(ResourceStatusProhibitsOperationException.class);

View file

@ -0,0 +1,23 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1001">
<msg>Command completed successfully; action pending</msg>
</result>
<resData>
<domain:trnData
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN%</domain:name>
<domain:trStatus>pending</domain:trStatus>
<domain:reID>NewRegistrar</domain:reID>
<domain:reDate>2000-06-09T22:00:00.0Z</domain:reDate>
<domain:acID>TheRegistrar</domain:acID>
<domain:acDate>2000-06-14T22:00:00.0Z</domain:acDate>
<domain:exDate>%EXDATE%</domain:exDate>
</domain:trnData>
</resData>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>

View file

@ -4,7 +4,7 @@
<domain:transfer
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>%DOMAIN%</domain:name>
<domain:period unit="y">1</domain:period>
<domain:period unit="y">%YEARS%</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
</domain:authInfo>