1
0
mirror of https://github.com/google/nomulus synced 2026-07-14 20:12:19 +00:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Michael Muller 8a045aedd0 Disambiguate naming of VKey.create() overloads (#513)
* Disambiguate naming of VKey.create() overloads

It was discovered in the course of trying to convert the larger codebase
to VKey.create() calls that method overloading isn't a very effective
discriminator in cases where "Object" is one of the distinguishing
argument types:-)

Convert the two specialized create() methods to createOfy() and
createSql() so that (at least in the former case) we'll get a
compile-time error if we aim to create a VKey for an Ofy key from an
object of the incorrect type.
2020-03-12 16:13:12 -04:00
gbrodman 560bec1e83 Add a RelockDomainAction for future auto-relocks (#485)
* Add a RelockAction and reference to relocks in RegistryLocks

* Respond to CR

- refactor the request param exception logging a bit
- don't log an error if the domain was already locked, just skip

* Save a relock for all locks (if possible)

* derp

* Long -> long + remove unnecessary transact

* semantic merge conflict woo

* fix another semantic merge conflict
2020-03-12 16:02:27 -04:00
Lai Jiang 3e7ea75b6f Use cs.opensource.google for code search (#512)
* Use cs.opensource.google for code search

* Change logo size

* Make texts in the table center-aligned
2020-03-12 14:06:04 -04:00
Weimin Yu 6ed7e00b00 Update SqlIntegrationTestSuite (#510)
* Update SqlIntegrationTestSuite

Edited Javadoc to emphasize that suite members should be DAO tests.

Removed functional tests from the suite. They do not benefit much
from running against different schemas when the entities they use
are already covered by DAO tests.

Added DomainBaseSqlTest to the suite, which tests DomainBase.
2020-03-11 14:11:53 -04:00
Michael Muller 6e1231233e Create a nom_build wrapper script (#508)
* Create a nom_build wrapper script

nom_build is a wrapper around ./gradlew.  It's purpose is to help us
deal with properties.  The main problem that it is trying to solve is
that when properties are specified using -P, we don't get an error if
the property we specify isn't correct.  As a result, a user or a build
agent can launch a build with unintended parameters.

nom_build consolidates all of the properties that we define into a
python script where the properties are translated to flags (actual
gradlew flags are also proxied).  It also generates the property file
and warns the user if the current properties file is out of sync with
the script and includes documentation on each of the properties.
2020-03-10 16:32:14 -04:00
Shicong Huang 3098048fdb Enable Cloud SQL when Datastore is enabled for unit test (#502)
* Enable Cloud SQL when Datastore is enabled for unit test

* Add explanation for why add a ETA field in GenerateEscrowDepositCommand

* Fix line length

* Ignore membershipt test but bring back test suite

* Fix tiny issue
2020-03-10 12:26:25 -04:00
gbrodman f2846fc914 Gray out the password field for admins (#506)
* Gray out the password field for admins

We don't check it for admins since it's not necessary, so ignore it

* Remove the field entirely
2020-03-10 11:30:20 -04:00
gbrodman 499237ac57 Listen to the user hitting enter in the lock/unlock modal input fields (#505)
* Listen to the user hitting enter in the lock/unlock modal input fields

Listen to both, just in case one or the other is disabled

* Don't require that the element exist
2020-03-10 11:22:57 -04:00
Weimin Yu 6bd50421bc Fix broken builds when Maven Central is used (#509)
* Fix broken builds when Maven Central is used

Gradle 6.2.1 apparently introduces a behavior change wrt boolean
expression: empty string used to eval to false, but now evals to
true.

Pre Gradle 6.2.1, root project's Gradle properties apparently were
not set to buildSrc. Now they are passed on to buildSrc -- mavenUrl
in buildSrc changes from null to "".

Both changes break the project when mavenUrl and/or pluginsUrl are
not set on command line.

Also added junit.jupiter-api as testCompile dependencies to projects.
This is a directly used dependency, whose absence causes a Lint
warning.
2020-03-10 11:21:03 -04:00
sarahcaseybot dbdd2b4491 Add Lock dual write (#496)
* Add Lock dual write

* wrap calls in DB transaction
2020-03-09 11:13:46 -04:00
221 changed files with 2040 additions and 1117 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
# Nomulus
| Internal Build | FOSS Build | LGTM | License | Code Search |
|----------------|------------|------|---------|-------------|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/internal/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[![Build Status for the open source build](https://storage.googleapis.com/domain-registry-kokoro/foss/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Source Graph](https://sourcegraph.com/.assets/img/sourcegraph-light-head-logo.svg)](https://sourcegraph.com/github.com/google/nomulus)|
|:--------------:|:----------:|:----:|:-------:|:-----------:|
|[![Build Status for Google Registry internal build](https://storage.googleapis.com/domain-registry-kokoro/internal/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/internal/index.html)|[![Build Status for the open source build](https://storage.googleapis.com/domain-registry-kokoro/foss/build.svg)](https://storage.googleapis.com/domain-registry-kokoro/foss/index.html)|[![Total alerts](https://img.shields.io/lgtm/alerts/g/google/nomulus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/google/nomulus/alerts/)|[![License for this repo](https://img.shields.io/github/license/google/nomulus.svg)](https://github.com/google/nomulus/blob/master/LICENSE)|[![Link to Code Search](https://www.gstatic.com/devopsconsole/images/oss/favicons/oss-32x32.png)](https://cs.opensource.google/nomulus/nomulus)|
![Nomulus logo](./nomulus-logo.png)
+3 -3
View File
@@ -169,10 +169,10 @@ allprojects {
if (project.name == 'services') return
repositories {
if (rootProject.mavenUrl) {
if (!mavenUrl.isEmpty()) {
maven {
println "Java dependencies: Using repo $pluginsUrl..."
url rootProject.mavenUrl
println "Java dependencies: Using repo ${mavenUrl}..."
url mavenUrl
}
} else {
println "Java dependencies: Using Maven Central..."
+6 -3
View File
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import static com.google.common.base.Strings.isNullOrEmpty;
buildscript {
if (project.enableDependencyLocking.toBoolean()) {
// Lock buildscript dependencies.
@@ -40,13 +42,13 @@ if (rootProject.enableDependencyLocking.toBoolean()) {
}
repositories {
if (project.ext.properties.mavenUrl == null) {
println "Plugin dependencies: Using Maven central..."
if (isNullOrEmpty(project.ext.properties.mavenUrl)) {
println "Java dependencies: Using Maven central..."
mavenCentral()
google()
} else {
maven {
println "Plugin dependencies: Using repo ${mavenUrl}..."
println "Java dependencies: Using repo ${mavenUrl}..."
url mavenUrl
}
}
@@ -82,6 +84,7 @@ dependencies {
testCompile deps['com.google.truth:truth']
testCompile deps['com.google.truth.extensions:truth-java8-extension']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
testCompile deps['org.mockito:mockito-core']
+1
View File
@@ -62,6 +62,7 @@ dependencies {
testingCompile deps['io.github.java-diff-utils:java-diff-utils']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
}
+327
View File
@@ -0,0 +1,327 @@
# Copyright 2020 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Script to generate dr-build and the properties file.
"""
import argparse
import attr
import io
import os
import subprocess
import sys
from typing import List, Union
@attr.s(auto_attribs=True)
class Property:
name : str = ''
desc : str = ''
default : str = ''
constraints : type = str
def validate(self, value: str):
"""Verify that "value" is appropriate for the property."""
if type is bool:
if value not in ('true', 'false'):
raise ValidationError('value of {self.name} must be "true" or '
'"false".')
@attr.s(auto_attribs=True)
class GradleFlag:
flags : Union[str, List[str]]
desc : str
has_arg : bool = False
PROPERTIES_HEADER = """\
# This file defines properties used by the gradle build. It must be kept in
# sync with config/nom_build.py.
#
# To regenerate, run config/nom_build.py --generate-gradle-properties
#
# To view property descriptions (which are command line flags for
# nom_build), run config/nom_build.py --help.
#
# DO NOT EDIT THIS FILE BY HAND
org.gradle.jvmargs=-Xmx1024m
"""
# Define all of our special gradle properties here.
PROPERTIES = [
Property('mavenUrl',
'URL to use for the main maven repository (defaults to maven '
'central). This can be http(s) or a "gcs" repo.'),
Property('pluginsUrl',
'URL to use for the gradle plugins repository (defaults to maven '
'central, see also mavenUrl'),
Property('uploaderDestination',
'Location to upload test reports to. Normally this should be a '
'GCS url (see also uploaderCredentialsFile)'),
Property('uploaderCredentialsFile',
'json credentials file to use to upload test reports.'),
Property('uploaderMultithreadedUpload',
'Whether to enable multithread upload.'),
Property('verboseTestOutput',
'If true, show all test output in near-realtime.',
'false',
bool),
Property('flowDocsFile',
'Output filename for the flowDocsTool command.'),
Property('enableDependencyLocking',
'Enables dependency locking.',
'true',
bool),
Property('enableCrossReferencing',
'generate metadata during java compile (used for kythe source '
'reference generation).',
'false'),
Property('testFilter',
'Comma separated list of test patterns, if specified run only '
'these.'),
Property('environment', 'GAE Environment for deployment and staging.'),
# Cloud SQL properties
Property('dbServer',
'A registry environment name (e.g., "alpha") or a host[:port] '
'string'),
Property('dbName',
'Database name to use in connection.',
'postgres'),
Property('dbUser', 'Database user name for use in connection'),
Property('dbPassword', 'Database password for use in connection'),
Property('publish_repo',
'Maven repository that hosts the Cloud SQL schema jar and the '
'registry server test jars. Such jars are needed for '
'server/schema integration tests. Please refer to <a '
'href="./integration/README.md">integration project</a> for more '
'information.'),
Property('schema_version',
'The nomulus version tag of the schema for use in a database'
'integration test.'),
Property('nomulus_version',
'The version of nomulus to test against in a database '
'integration test.'),
]
GRADLE_FLAGS = [
GradleFlag(['-a', '--no-rebuild'],
'Do not rebuild project dependencies.'),
GradleFlag(['-b', '--build-file'], 'Specify the build file.', True),
GradleFlag(['--build-cache'],
'Enables the Gradle build cache. Gradle will try to reuse '
'outputs from previous builds.'),
GradleFlag(['-c', '--settings-file'], 'Specify the settings file.', True),
GradleFlag(['--configure-on-demand'],
'Configure necessary projects only. Gradle will attempt to '
'reduce configuration time for large multi-project builds. '
'[incubating]'),
GradleFlag(['--console'],
'Specifies which type of console output to generate. Values '
"are 'plain', 'auto' (default), 'rich' or 'verbose'.",
True),
GradleFlag(['--continue'], 'Continue task execution after a task failure.'),
GradleFlag(['-D', '--system-prop'],
'Set system property of the JVM (e.g. -Dmyprop=myvalue).',
True),
GradleFlag(['-d', '--debug'],
'Log in debug mode (includes normal stacktrace).'),
GradleFlag(['--daemon'],
'Uses the Gradle Daemon to run the build. Starts the Daemon '
'if not running.'),
GradleFlag(['--foreground'], 'Starts the Gradle Daemon in the foreground.'),
GradleFlag(['-g', '--gradle-user-home'],
'Specifies the gradle user home directory.',
True),
GradleFlag(['-I', '--init-script'], 'Specify an initialization script.',
True),
GradleFlag(['-i', '--info'], 'Set log level to info.'),
GradleFlag(['--include-build'],
'Include the specified build in the composite.',
True),
GradleFlag(['-m', '--dry-run'],
'Run the builds with all task actions disabled.'),
GradleFlag(['--max-workers'],
'Configure the number of concurrent workers Gradle is '
'allowed to use.',
True),
GradleFlag(['--no-build-cache'], 'Disables the Gradle build cache.'),
GradleFlag(['--no-configure-on-demand'],
'Disables the use of configuration on demand. [incubating]'),
GradleFlag(['--no-daemon'],
'Do not use the Gradle daemon to run the build. Useful '
'occasionally if you have configured Gradle to always run '
'with the daemon by default.'),
GradleFlag(['--no-parallel'],
'Disables parallel execution to build projects.'),
GradleFlag(['--no-scan'],
'Disables the creation of a build scan. For more information '
'about build scans, please visit '
'https://gradle.com/build-scans.'),
GradleFlag(['--offline'],
'Execute the build without accessing network resources.'),
GradleFlag(['-P', '--project-prop'],
'Set project property for the build script (e.g. '
'-Pmyprop=myvalue).',
True),
GradleFlag(['-p', '--project-dir'],
'Specifies the start directory for Gradle. Defaults to '
'current directory.'),
GradleFlag(['--parallel'],
'Build projects in parallel. Gradle will attempt to '
'determine the optimal number of executor threads to use.'),
GradleFlag(['--priority'],
'Specifies the scheduling priority for the Gradle daemon and '
"all processes launched by it. Values are 'normal' (default) "
"or 'low' [incubating]",
True),
GradleFlag(['--profile'],
'Profile build execution time and generates a report in the '
'<build_dir>/reports/profile directory.'),
GradleFlag(['--project-cache-dir'],
'Specify the project-specific cache directory. Defaults to '
'.gradle in the root project directory.',
True),
GradleFlag(['-q', '--quiet'], 'Log errors only.'),
GradleFlag(['--refresh-dependencies'], 'Refresh the state of dependencies.'),
GradleFlag(['--rerun-tasks'], 'Ignore previously cached task results.'),
GradleFlag(['-S', '--full-stacktrace'],
'Print out the full (very verbose) stacktrace for all '
'exceptions.'),
GradleFlag(['-s', '--stacktrace'],
'Print out the stacktrace for all exceptions.'),
GradleFlag(['--scan'],
'Creates a build scan. Gradle will emit a warning if the '
'build scan plugin has not been applied. '
'(https://gradle.com/build-scans)'),
GradleFlag(['--status'],
'Shows status of running and recently stopped Gradle '
'Daemon(s).'),
GradleFlag(['--stop'], 'Stops the Gradle Daemon if it is running.'),
GradleFlag(['-t', '--continuous'],
'Enables continuous build. Gradle does not exit and will '
're-execute tasks when task file inputs change.'),
GradleFlag(['--update-locks'],
'Perform a partial update of the dependency lock, letting '
'passed in module notations change version. [incubating]'),
GradleFlag(['-v', '--version'], 'Print version info.'),
GradleFlag(['-w', '--warn'], 'Set log level to warn.'),
GradleFlag(['--warning-mode'],
'Specifies which mode of warnings to generate. Values are '
"'all', 'fail', 'summary'(default) or 'none'",
True),
GradleFlag(['--write-locks'],
'Persists dependency resolution for locked configurations, '
'ignoring existing locking information if it exists '
'[incubating]'),
GradleFlag(['-x', '--exclude-task'],
'Specify a task to be excluded from execution.',
True),
]
def generate_gradle_properties() -> str:
"""Returns the expected contents of gradle.properties."""
out = io.StringIO()
out.write(PROPERTIES_HEADER)
for prop in PROPERTIES:
out.write(f'{prop.name}={prop.default}\n')
return out.getvalue()
def get_root() -> str:
"""Returns the root of the nomulus build tree."""
cur_dir = os.getcwd()
if not os.path.exists(os.path.join(cur_dir, '.git')) or \
not os.path.exists(os.path.join(cur_dir, 'core')) or \
not os.path.exists(os.path.join(cur_dir, 'gradle.properties')):
raise Exception('You must run this script from the root directory')
return cur_dir
def main(args):
parser = argparse.ArgumentParser('nom_build')
for prop in PROPERTIES:
parser.add_argument('--' + prop.name, default=prop.default,
help=prop.desc)
# Add Gradle flags. We set 'dest' to the first flag to get a name that is
# predictable for getattr (even though it will have a leading '-' and thus
# we can't use normal python attribute syntax to get it).
for flag in GRADLE_FLAGS:
if flag.has_arg:
parser.add_argument(*flag.flags, dest=flag.flags[0],
help=flag.desc)
else:
parser.add_argument(*flag.flags, dest=flag.flags[0],
help=flag.desc,
action='store_true')
# Add a flag to regenerate the gradle properties file.
parser.add_argument('--generate-gradle-properties',
help='Regenerate the gradle.properties file. This '
'file must be regenerated when changes are made to '
'config/nom_build.py, and should not be updated by '
'hand.',
action='store_true')
# Consume the remaining non-flag arguments.
parser.add_argument('non_flag_args', nargs='*')
# Parse command line arguments. Note that this exits the program and
# prints usage if either of the help options (-h, --help) are specified.
args = parser.parse_args(args)
gradle_properties = generate_gradle_properties()
root = get_root()
# If we're regenerating properties, do so and exit.
if args.generate_gradle_properties:
with open(f'{root}/gradle.properties', 'w') as dst:
dst.write(gradle_properties)
return
# Verify that the gradle properties file is what we expect it to be.
with open(f'{root}/gradle.properties') as src:
if src.read() != gradle_properties:
print('\033[33mWARNING:\033[0m Gradle properties out of sync '
'with nom_build. Run with --generate-gradle-properties '
'to regenerate.')
# Add properties to the gradle argument list.
gradle_command = [f'{root}/gradlew']
for prop in PROPERTIES:
arg_val = getattr(args, prop.name)
if arg_val != prop.default:
prop.validate(arg_val)
gradle_command.extend(['-P', f'{prop.name}={arg_val}'])
# Add Gradle flags to the gradle argument list.
for flag in GRADLE_FLAGS:
arg_val = getattr(args, flag.flags[0])
if arg_val:
gradle_command.append(flag.flags[-1])
if flag.has_arg:
gradle_command.append(arg_val)
# Add the non-flag args (we exclude the first, which is the command name
# itself) and run.
gradle_command.extend(args.non_flag_args[1:])
subprocess.call(gradle_command)
if __name__ == '__main__':
main(sys.argv)
+109
View File
@@ -0,0 +1,109 @@
# Copyright 2020 The Nomulus Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import io
import os
import unittest
from unittest import mock
import nom_build
import subprocess
FAKE_PROPERTIES = [
nom_build.Property('foo', 'help text'),
nom_build.Property('bar', 'more text', 'true', bool),
]
FAKE_PROP_CONTENTS = nom_build.PROPERTIES_HEADER + 'foo=\nbar=true\n'
PROPERTIES_FILENAME = '/tmp/rootdir/gradle.properties'
GRADLEW = '/tmp/rootdir/gradlew'
class FileFake(io.StringIO):
"""File fake that writes file contents to the dictionary on close."""
def __init__(self, contents_dict, filename):
self.dict = contents_dict
self.filename = filename
super(FileFake, self).__init__()
def close(self):
self.dict[self.filename] = self.getvalue()
super(FileFake, self).close()
class MyTest(unittest.TestCase):
def open_fake(self, filename, action='r'):
if action == 'r':
return io.StringIO(self.file_contents.get(filename, ''))
elif action == 'w':
result = self.file_contents[filename] = (
FileFake(self.file_contents, filename))
return result
else:
raise Exception(f'Unexpected action {action}')
def print_fake(self, data):
self.printed.append(data)
def setUp(self):
self.addCleanup(mock.patch.stopall)
self.exists_mock = mock.patch.object(os.path, 'exists').start()
self.getcwd_mock = mock.patch.object(os, 'getcwd').start()
self.getcwd_mock.return_value = '/tmp/rootdir'
self.open_mock = (
mock.patch.object(nom_build, 'open', self.open_fake).start())
self.print_mock = (
mock.patch.object(nom_build, 'print', self.print_fake).start())
self.call_mock = mock.patch.object(subprocess, 'call').start()
self.file_contents = {
# Prefil with the actual file contents.
PROPERTIES_FILENAME: nom_build.generate_gradle_properties()
}
self.printed = []
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
def test_property_generation(self):
self.assertEqual(nom_build.generate_gradle_properties(),
FAKE_PROP_CONTENTS)
@mock.patch.object(nom_build, 'PROPERTIES', FAKE_PROPERTIES)
def test_property_file_write(self):
nom_build.main(['nom_build', '--generate-gradle-properties'])
self.assertEqual(self.file_contents[PROPERTIES_FILENAME],
FAKE_PROP_CONTENTS)
def test_property_file_incorrect(self):
self.file_contents[PROPERTIES_FILENAME] = 'bad contents'
nom_build.main(['nom_build'])
self.assertIn('', self.printed[0])
def test_no_args(self):
nom_build.main(['nom_build'])
self.assertEqual(self.printed, [])
self.call_mock.assert_called_with([GRADLEW])
def test_property_calls(self):
nom_build.main(['nom_build', '--testFilter=foo'])
self.call_mock.assert_called_with([GRADLEW, '-P', 'testFilter=foo'])
def test_gradle_flags(self):
nom_build.main(['nom_build', '-d', '-b', 'foo'])
self.call_mock.assert_called_with([GRADLEW, '--build-file', 'foo',
'--debug'])
unittest.main()
Binary file not shown.
+3 -1
View File
@@ -300,6 +300,7 @@ dependencies {
testCompile deps['org.hamcrest:hamcrest-library']
compile deps['org.hibernate:hibernate-hikaricp']
testCompile deps['junit:junit']
testCompile deps['org.junit.jupiter:junit-jupiter-api']
testCompile deps['org.junit.jupiter:junit-jupiter-engine']
testCompile deps['org.junit.vintage:junit-vintage-engine']
testCompile deps['org.mockito:mockito-core']
@@ -869,7 +870,8 @@ test {
// Don't run any tests from this task, all testing gets done in the
// FilteringTest tasks.
exclude "**"
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest)
// TODO(weiminyu): Remove dependency on sqlIntegrationTest
}.dependsOn(fragileTest, outcastTest, standardTest, registryToolIntegrationTest, sqlIntegrationTest)
createUberJar('nomulus', 'nomulus', 'google.registry.tools.RegistryTool')
@@ -21,6 +21,7 @@ import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_DELETE;
import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_HOST_RENAME;
import static google.registry.request.RequestParameters.extractLongParameter;
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
@@ -40,9 +41,7 @@ import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
/**
* Dagger module for injecting common settings for batch actions.
*/
/** Dagger module for injecting common settings for batch actions. */
@Module
public class BatchModule {
@@ -94,6 +93,12 @@ public class BatchModule {
return extractSetOfDatetimeParameters(req, PARAM_RESAVE_TIMES);
}
@Provides
@Parameter("oldUnlockRevisionId")
static long provideOldUnlockRevisionId(HttpServletRequest req) {
return extractLongParameter(req, "oldUnlockRevisionId");
}
@Provides
@Named(QUEUE_ASYNC_ACTIONS)
static Queue provideAsyncActionsPushQueue() {
@@ -0,0 +1,167 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.request.Action.Method.POST;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.model.domain.DomainBase;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.registry.RegistryLockDao;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.schema.domain.RegistryLock;
import google.registry.tools.DomainLockUtils;
import google.registry.util.DateTimeUtils;
import javax.inject.Inject;
/**
* Task that relocks a previously-Registry-Locked domain after some predetermined period of time.
*/
@Action(
service = Action.Service.BACKEND,
path = RelockDomainAction.PATH,
method = POST,
automaticallyPrintOk = true,
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
public class RelockDomainAction implements Runnable {
public static final String PATH = "/_dr/task/relockDomain";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final long oldUnlockRevisionId;
private final DomainLockUtils domainLockUtils;
private final Response response;
@Inject
public RelockDomainAction(
@Parameter("oldUnlockRevisionId") long oldUnlockRevisionId,
DomainLockUtils domainLockUtils,
Response response) {
this.oldUnlockRevisionId = oldUnlockRevisionId;
this.domainLockUtils = domainLockUtils;
this.response = response;
}
@Override
public void run() {
jpaTm().transact(this::relockDomain);
}
private void relockDomain() {
RegistryLock oldLock;
try {
oldLock =
RegistryLockDao.getByRevisionId(oldUnlockRevisionId)
.orElseThrow(
() ->
new IllegalArgumentException(
String.format("Unknown revision ID %d", oldUnlockRevisionId)));
DomainBase domain =
ofy()
.load()
.type(DomainBase.class)
.id(oldLock.getRepoId())
.now()
.cloneProjectedAtTime(jpaTm().getTransactionTime());
if (domain.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES)
|| oldLock.getRelock() != null) {
// The domain was manually locked, so we shouldn't worry about relocking
String message =
String.format(
"Domain %s is already manually relocked, skipping automated relock.",
domain.getFullyQualifiedDomainName());
logger.atInfo().log(message);
// SC_NO_CONTENT (204) skips retry -- see the comment below
response.setStatus(SC_NO_CONTENT);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(message);
return;
}
verifyDomainAndLockState(oldLock, domain);
} catch (Throwable t) {
/* If there's a bad verification code or the domain is in a bad state, we won't want to retry.
* AppEngine will retry on non-2xx error codes, so we return SC_NO_CONTENT (204) to avoid it.
*
* See https://cloud.google.com/appengine/docs/standard/java/taskqueue/push/retrying-tasks
* for more details on retry behavior. */
logger.atWarning().withCause(t).log(
"Exception when attempting to relock domain with old revision ID %d.",
oldUnlockRevisionId);
response.setStatus(SC_NO_CONTENT);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
return;
}
applyRelock(oldLock);
}
private void applyRelock(RegistryLock oldLock) {
try {
domainLockUtils.administrativelyApplyLock(
oldLock.getDomainName(),
oldLock.getRegistrarId(),
oldLock.getRegistrarPocId(),
oldLock.isSuperuser());
logger.atInfo().log("Relocked domain %s.", oldLock.getDomainName());
response.setStatus(SC_OK);
} catch (Throwable t) {
// Any errors that occur here are unexpected, so we should retry. Return a non-2xx
// error code to get AppEngine to retry
logger.atSevere().withCause(t).log(
"Exception when attempting to relock domain %s.", oldLock.getDomainName());
response.setStatus(SC_INTERNAL_SERVER_ERROR);
response.setContentType(MediaType.PLAIN_TEXT_UTF_8);
response.setPayload(String.format("Relock failed: %s", t.getMessage()));
}
}
private void verifyDomainAndLockState(RegistryLock oldLock, DomainBase domain) {
// Domain shouldn't be deleted or have a pending transfer/delete
String domainName = domain.getFullyQualifiedDomainName();
checkArgument(
!DateTimeUtils.isAtOrAfter(jpaTm().getTransactionTime(), domain.getDeletionTime()),
"Domain %s has been deleted",
domainName);
ImmutableSet<StatusValue> statusValues = domain.getStatusValues();
checkArgument(
!statusValues.contains(StatusValue.PENDING_DELETE),
"Domain %s has a pending delete",
domainName);
checkArgument(
!statusValues.contains(StatusValue.PENDING_TRANSFER),
"Domain %s has a pending transfer",
domainName);
checkArgument(
domain.getCurrentSponsorClientId().equals(oldLock.getRegistrarId()),
"Domain %s has been transferred from registrar %s to registrar %s since the unlock",
domainName,
oldLock.getRegistrarId(),
domain.getCurrentSponsorClientId());
}
}
@@ -25,6 +25,12 @@ import javax.persistence.EntityManager;
/** Data access object for {@link google.registry.schema.domain.RegistryLock}. */
public final class RegistryLockDao {
/** Returns the {@link RegistryLock} referred to by this revision ID, or empty if none exists. */
public static Optional<RegistryLock> getByRevisionId(long revisionId) {
jpaTm().assertInTransaction();
return Optional.ofNullable(jpaTm().getEntityManager().find(RegistryLock.class, revisionId));
}
/** Returns the most recent version of the {@link RegistryLock} referred to by the code. */
public static Optional<RegistryLock> getByVerificationCode(String verificationCode) {
jpaTm().assertInTransaction();
@@ -84,7 +90,29 @@ public final class RegistryLockDao {
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.lockCompletionTimestamp IS NOT NULL ORDER BY lock.revisionId"
+ " lock.lockCompletionTimestamp IS NOT NULL AND"
+ " lock.unlockCompletionTimestamp IS NULL ORDER BY lock.revisionId"
+ " DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
.setMaxResults(1)
.getResultStream()
.findFirst();
}
/**
* Returns the most recent verified unlock for a given domain specified by repo ID.
*
* <p>Returns empty if no unlock has ever been finalized for this domain. This is different from
* {@link #getMostRecentByRepoId(String)} in that it only returns verified unlocks.
*/
public static Optional<RegistryLock> getMostRecentVerifiedUnlockByRepoId(String repoId) {
jpaTm().assertInTransaction();
return jpaTm()
.getEntityManager()
.createQuery(
"SELECT lock FROM RegistryLock lock WHERE lock.repoId = :repoId AND"
+ " lock.unlockCompletionTimestamp IS NOT NULL ORDER BY lock.revisionId"
+ " DESC",
RegistryLock.class)
.setParameter("repoId", repoId)
@@ -16,6 +16,7 @@ package google.registry.model.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
@@ -28,6 +29,7 @@ import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.schema.server.LockDao;
import google.registry.util.RequestStatusChecker;
import google.registry.util.RequestStatusCheckerImpl;
import java.io.Serializable;
@@ -177,8 +179,7 @@ public class Lock extends ImmutableObject implements Serializable {
// access to resources like GCS that can't be transactionally rolled back. Therefore, the lock
// must be definitively acquired before it is used, even when called inside another transaction.
AcquireResult acquireResult =
tm()
.transactNew(
tm().transactNew(
() -> {
DateTime now = tm().getTransactionTime();
@@ -207,6 +208,31 @@ public class Lock extends ImmutableObject implements Serializable {
// contention) and
// don't need to be backed up.
ofy().saveWithoutBackup().entity(newLock);
// create and save the lock to Cloud SQL
try {
jpaTm()
.transact(
() -> {
google.registry.schema.server.Lock cloudSqlLock =
google.registry.schema.server.Lock.create(
resourceName,
Optional.ofNullable(tld).orElse("GLOBAL"),
requestStatusChecker.getLogId(),
now,
leaseLength);
// cloudSqlLock should not already exist in Cloud SQL, but call delete
// just in case
// TODO: Remove this delete once dual read is added
LockDao.delete(
resourceName, Optional.ofNullable(tld).orElse("GLOBAL"));
LockDao.saveNew(cloudSqlLock);
});
} catch (Exception e) {
logger.atSevere().withCause(e).log(
"Error saving lock to Cloud SQL: %s", newLock);
}
return AcquireResult.create(now, lock, newLock, lockState);
});
@@ -218,8 +244,7 @@ public class Lock extends ImmutableObject implements Serializable {
/** Release the lock. */
public void release() {
// Just use the default clock because we aren't actually doing anything that will use the clock.
tm()
.transact(
tm().transact(
() -> {
// To release a lock, check that no one else has already obtained it and if not
// delete it. If the lock in Datastore was different then this lock is gone already;
@@ -231,6 +256,19 @@ public class Lock extends ImmutableObject implements Serializable {
// lock.
logger.atInfo().log("Deleting lock: %s", lockId);
ofy().deleteWithoutBackup().entity(Lock.this);
// Remove the lock from Cloud SQL
try {
jpaTm()
.transact(
() ->
LockDao.delete(
resourceName, Optional.ofNullable(tld).orElse("GLOBAL")));
} catch (Exception e) {
logger.atSevere().withCause(e).log(
"Error deleting lock from Cloud SQL: %s", loadedLock);
}
lockMetrics.recordRelease(
resourceName, tld, new Duration(acquiredTime, tm().getTransactionTime()));
} else {
@@ -26,6 +26,7 @@ import google.registry.batch.DeleteLoadTestDataAction;
import google.registry.batch.DeleteProberDataAction;
import google.registry.batch.ExpandRecurringBillingEventsAction;
import google.registry.batch.RefreshDnsOnHostRenameAction;
import google.registry.batch.RelockDomainAction;
import google.registry.batch.ResaveAllEppResourcesAction;
import google.registry.batch.ResaveEntityAction;
import google.registry.cron.CommitLogFanoutAction;
@@ -140,6 +141,7 @@ interface BackendRequestComponent {
RdeReporter rdeReporter();
RefreshDnsAction refreshDnsAction();
RefreshDnsOnHostRenameAction refreshDnsOnHostRenameAction();
RelockDomainAction relockDomainAction();
ResaveAllEppResourcesAction resaveAllEppResourcesAction();
ResaveEntityAction resaveEntityAction();
SyncGroupMembersAction syncGroupMembersAction();
@@ -43,11 +43,11 @@ public class VKey<T> extends ImmutableObject {
return new VKey(kind, ofyKey, primaryKey);
}
public static <T> VKey<T> create(Class<? extends T> kind, Object primaryKey) {
public static <T> VKey<T> createSql(Class<? extends T> kind, Object primaryKey) {
return new VKey(kind, null, primaryKey);
}
public static <T> VKey<T> create(
public static <T> VKey<T> createOfy(
Class<? extends T> kind, com.googlecode.objectify.Key<T> ofyKey) {
return new VKey(kind, ofyKey, null);
}
@@ -193,8 +193,7 @@ public class PublishSpec11ReportAction implements Runnable {
// Group by email address then flat-map all of the ThreatMatch objects together
return ImmutableMap.copyOf(
Maps.transformValues(
Multimaps.index(registrarThreatMatches, RegistrarThreatMatches::clientId)
.asMap(),
Multimaps.index(registrarThreatMatches, RegistrarThreatMatches::clientId).asMap(),
registrarThreatMatchesCollection ->
registrarThreatMatchesCollection.stream()
.flatMap(matches -> matches.threatMatches().stream())
@@ -44,11 +44,11 @@ public final class RequestParameters {
* method to yield the following results:
*
* <ul>
* <li>/foo?bar=hello → hello
* <li>/foo?bar=hello&bar=there → hello
* <li>/foo?bar= → 400 error (empty)
* <li>/foo?bar=&bar=there → 400 error (empty)
* <li>/foo → 400 error (absent)
* <li>/foo?bar=hello → hello
* <li>/foo?bar=hello&bar=there → hello
* <li>/foo?bar= → 400 error (empty)
* <li>/foo?bar=&bar=there → 400 error (empty)
* <li>/foo → 400 error (absent)
* </ul>
*
* @throws BadRequestException if request parameter is absent or empty
@@ -88,10 +88,27 @@ public final class RequestParameters {
* @throws BadRequestException if request parameter is absent, empty, or not a valid integer
*/
public static int extractIntParameter(HttpServletRequest req, String name) {
String stringParam = req.getParameter(name);
try {
return Integer.parseInt(nullToEmpty(req.getParameter(name)));
return Integer.parseInt(nullToEmpty(stringParam));
} catch (NumberFormatException e) {
throw new BadRequestException("Expected integer: " + name);
throw new BadRequestException(
String.format("Expected int for parameter %s but received %s", name, stringParam));
}
}
/**
* Returns first GET or POST parameter associated with {@code name} as a long.
*
* @throws BadRequestException if request parameter is absent, empty, or not a valid long
*/
public static long extractLongParameter(HttpServletRequest req, String name) {
String stringParam = req.getParameter(name);
try {
return Long.parseLong(nullToEmpty(stringParam));
} catch (NumberFormatException e) {
throw new BadRequestException(
String.format("Expected long for parameter %s but received %s", name, stringParam));
}
}
@@ -126,9 +143,7 @@ public final class RequestParameters {
if (parameter == null || parameter.isEmpty()) {
return ImmutableSet.of();
}
return Splitter.on(',')
.splitToList(parameter)
.stream()
return Splitter.on(',').splitToList(parameter).stream()
.filter(s -> !s.isEmpty())
.collect(toImmutableSet());
}
@@ -160,8 +175,8 @@ public final class RequestParameters {
* @throws BadRequestException if request parameter named {@code name} is absent, empty, or not
* equal to any of the values in {@code enumClass}
*/
public static <C extends Enum<C>>
C extractEnumParameter(HttpServletRequest req, Class<C> enumClass, String name) {
public static <C extends Enum<C>> C extractEnumParameter(
HttpServletRequest req, Class<C> enumClass, String name) {
return getEnumValue(enumClass, extractRequiredParameter(req, name), name);
}
@@ -216,9 +231,9 @@ public final class RequestParameters {
}
/**
* Returns first request parameter associated with {@code name} parsed as an
* <a href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ},
* {@code 2000-01-01T16:20:00Z}.
* Returns first request parameter associated with {@code name} parsed as an <a
* href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ}, {@code
* 2000-01-01T16:20:00Z}.
*
* @throws BadRequestException if request parameter named {@code name} is absent, empty, or could
* not be parsed as an ISO 8601 timestamp
@@ -233,9 +248,9 @@ public final class RequestParameters {
}
/**
* Returns first request parameter associated with {@code name} parsed as an
* <a href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ},
* {@code 2000-01-01T16:20:00Z}.
* Returns first request parameter associated with {@code name} parsed as an <a
* href="https://goo.gl/pk5Q2k">ISO 8601</a> timestamp, e.g. {@code 1984-12-18TZ}, {@code
* 2000-01-01T16:20:00Z}.
*
* @throws BadRequestException if request parameter is present but not a valid {@link DateTime}.
*/
@@ -262,8 +277,7 @@ public final class RequestParameters {
public static ImmutableSet<DateTime> extractSetOfDatetimeParameters(
HttpServletRequest req, String name) {
try {
return extractSetOfParameters(req, name)
.stream()
return extractSetOfParameters(req, name).stream()
.filter(not(String::isEmpty))
.map(DateTime::parse)
.collect(toImmutableSet());
@@ -28,10 +28,13 @@ import java.time.ZonedDateTime;
import java.util.Optional;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.joda.time.DateTime;
@@ -123,6 +126,11 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
@Column(nullable = false)
private boolean isSuperuser;
/** The lock that undoes this lock, if this lock has been unlocked and the domain locked again. */
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "relockRevisionId", referencedColumnName = "revisionId")
private RegistryLock relock;
/** Time that this entity was last updated. */
private UpdateAutoTimestamp lastUpdateTimestamp;
@@ -179,6 +187,16 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
return revisionId;
}
/**
* The lock that undoes this lock, if this lock has been unlocked and the domain locked again.
*
* <p>Note: this is lazily loaded, so it may not be initialized if referenced outside of the
* transaction in which this lock is loaded.
*/
public RegistryLock getRelock() {
return relock;
}
public boolean isLocked() {
return lockCompletionTimestamp != null && unlockCompletionTimestamp == null;
}
@@ -266,5 +284,10 @@ public final class RegistryLock extends ImmutableObject implements Buildable {
getInstance().isSuperuser = isSuperuser;
return this;
}
public Builder setRelock(RegistryLock relock) {
getInstance().relock = relock;
return this;
}
}
}
@@ -51,26 +51,29 @@ public class LockDao {
* else empty.
*/
public static Optional<Lock> load(String resourceName) {
checkArgumentNotNull(resourceName, "The resource name of the lock to load cannot be null");
return Optional.ofNullable(
jpaTm()
.transact(
() ->
jpaTm().getEntityManager().find(Lock.class, new LockId(resourceName, GLOBAL))));
return load(resourceName, GLOBAL);
}
/**
* Deletes the given {@link Lock} object from Cloud SQL. This method is idempotent and will simply
* return if the lock has already been deleted.
* Deletes the {@link Lock} object with the given resourceName and tld from Cloud SQL. This method
* is idempotent and will simply return if the lock has already been deleted.
*/
public static void delete(Lock lock) {
public static void delete(String resourceName, String tld) {
jpaTm()
.transact(
() -> {
Optional<Lock> loadedLock = load(lock.resourceName, lock.tld);
Optional<Lock> loadedLock = load(resourceName, tld);
if (loadedLock.isPresent()) {
jpaTm().getEntityManager().remove(loadedLock.get());
}
});
}
/**
* Deletes the global {@link Lock} object with the given resourceName from Cloud SQL. This method
* is idempotent and will simply return if the lock has already been deleted.
*/
public static void delete(String resourceName) {
delete(resourceName, GLOBAL);
}
}
@@ -106,6 +106,7 @@ public final class DomainLockUtils {
RegistryLock newLock =
RegistryLockDao.save(lock.asBuilder().setLockCompletionTimestamp(now).build());
setAsRelock(newLock);
tm().transact(() -> applyLockStatuses(newLock, now));
return newLock;
});
@@ -149,13 +150,14 @@ public final class DomainLockUtils {
.transact(
() -> {
DateTime now = jpaTm().getTransactionTime();
RegistryLock result =
RegistryLock newLock =
RegistryLockDao.save(
createLockBuilder(domainName, registrarId, registrarPocId, isAdmin)
.setLockCompletionTimestamp(now)
.build());
tm().transact(() -> applyLockStatuses(result, now));
return result;
tm().transact(() -> applyLockStatuses(newLock, now));
setAsRelock(newLock);
return newLock;
});
}
@@ -179,6 +181,16 @@ public final class DomainLockUtils {
});
}
private void setAsRelock(RegistryLock newLock) {
jpaTm()
.transact(
() ->
RegistryLockDao.getMostRecentVerifiedUnlockByRepoId(newLock.getRepoId())
.ifPresent(
oldLock ->
RegistryLockDao.save(oldLock.asBuilder().setRelock(newLock).build())));
}
private RegistryLock.Builder createLockBuilder(
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
DateTime now = jpaTm().getTransactionTime();
@@ -28,11 +28,13 @@ import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.common.annotations.VisibleForTesting;
import google.registry.model.rde.RdeMode;
import google.registry.rde.RdeStagingAction;
import google.registry.tools.params.DateTimeParameter;
import google.registry.util.AppEngineServiceUtils;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
@@ -75,7 +77,16 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
private String outdir;
@Inject AppEngineServiceUtils appEngineServiceUtils;
@Inject @Named("rde-report") Queue queue;
@Inject
@Named("rde-report")
Queue queue;
// ETA is a required property for TaskOptions but we let the service to set it when submitting the
// task to the task queue. However, the local test service doesn't do that for us during the unit
// test, so we add this field here to let the unit test be able to inject the ETA to pass the
// test.
@VisibleForTesting Optional<Long> maybeEtaMillis = Optional.empty();
@Override
public void run() {
@@ -115,6 +126,9 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
if (revision != null) {
opts = opts.param(PARAM_REVISION, String.valueOf(revision));
}
if (maybeEtaMillis.isPresent()) {
opts = opts.etaMillis(maybeEtaMillis.get());
}
queue.add(opts);
}
}
@@ -45,6 +45,7 @@ registry.registrar.RegistryLock = function(console, resource) {
goog.inherits(registry.registrar.RegistryLock, registry.ResourceComponent);
registry.registrar.RegistryLock.prototype.runAfterRender = function(objArgs) {
this.isAdmin = objArgs.isAdmin;
this.clientId = objArgs.clientId;
this.xsrfToken = objArgs.xsrfToken;
@@ -91,7 +92,7 @@ registry.registrar.RegistryLock.prototype.fillLocksPage_ = function(e) {
lockEnabledForContact: locksDetails.lockEnabledForContact});
if (locksDetails.lockEnabledForContact) {
// Listen to the lock-domain 'submit' button click as well as the enter key
// Listen to the lock-domain 'submit' button click
var lockButton = goog.dom.getRequiredElement('button-lock-domain');
goog.events.listen(lockButton, goog.events.EventType.CLICK, this.onLockDomain_, false, this);
// For all unlock buttons, listen and perform the unlock action if they're clicked
@@ -114,7 +115,8 @@ registry.registrar.RegistryLock.prototype.showModal_ = function(targetElement, d
var parentElement = targetElement.parentElement;
// attach the modal to the parent element so focus remains correct if the user closes the modal
var modalElement = goog.soy.renderAsElement(
registry.soy.registrar.registrylock.confirmModal, {domain: domain, isLock: isLock});
registry.soy.registrar.registrylock.confirmModal,
{domain: domain, isLock: isLock, isAdmin: this.isAdmin});
parentElement.prepend(modalElement);
if (domain == null) {
goog.dom.getRequiredElement('domain-lock-input-value').focus();
@@ -129,12 +131,29 @@ registry.registrar.RegistryLock.prototype.showModal_ = function(targetElement, d
false,
this);
// Listen to the "submit" click and also the user hitting enter
goog.events.listen(
goog.dom.getRequiredElement('domain-lock-submit'),
goog.events.EventType.CLICK,
e => this.lockOrUnlockDomain_(isLock, e),
false,
this);
[goog.dom.getElement('domain-lock-password'),
goog.dom.getElement('domain-lock-input-value')].forEach(elem => {
if (elem != null) {
goog.events.listen(
elem,
goog.events.EventType.KEYPRESS,
e => {
if (e.keyCode === goog.events.KeyCodes.ENTER) {
this.lockOrUnlockDomain_(isLock, e);
}
},
false,
this);
}
});
}
/**
@@ -106,6 +106,7 @@
/** Modal that confirms that the user wishes to lock/unlock a domain. */
{template .confirmModal}
{@param isLock: bool}
{@param isAdmin: bool}
{@param? domain: string|null}
<div id="lock-confirm-modal" class="{css('lock-confirm-modal')}">
<div class="modal-content">
@@ -117,9 +118,11 @@
value="{$domain}" disabled
{/if}>
<br>
<label for="domain-lock-password">Registry lock password: </label>
<input type="password" id="domain-lock-password">
<br>
{if not $isAdmin}
<label for="domain-lock-password">Registry lock password: </label>
<input type="password" id="domain-lock-password">
<br>
{/if}
<div id="modal-error-message" hidden class="{css('kd-errormessage')}"></div>
<div class="{css('buttons-div')}">
<button id="domain-lock-cancel" class="{css('kd-button')}">Cancel</button>
@@ -46,10 +46,8 @@ public class CommitLogCheckpointActionTest {
private static final String QUEUE_NAME = "export-commits";
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
CommitLogCheckpointStrategy strategy = mock(CommitLogCheckpointStrategy.class);
@@ -47,9 +47,7 @@ import org.junit.runners.JUnit4;
public class CommitLogCheckpointStrategyTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -50,9 +50,7 @@ import org.junit.runners.JUnit4;
public class ExportCommitLogDiffActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
/** Local GCS service available for testing. */
private final GcsService gcsService = GcsServiceFactory.createGcsService();
@@ -62,9 +62,7 @@ public class GcsDiffFileListerTest {
private final TestLogHandler logHandler = new TestLogHandler();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void before() throws Exception {
@@ -71,9 +71,7 @@ public class RestoreCommitLogsActionTest {
final GcsService gcsService = createGcsService();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void init() {
@@ -61,7 +61,7 @@ public class AsyncTaskEnqueuerTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final InjectRule inject = new InjectRule();
@@ -0,0 +1,176 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.batch;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE;
import static google.registry.model.eppcommon.StatusValue.PENDING_TRANSFER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveHost;
import static google.registry.testing.DatastoreHelper.persistDomainAsDeleted;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.getMostRecentVerifiedRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCode;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import com.google.common.collect.ImmutableSet;
import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.DeterministicStringGenerator;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import google.registry.testing.UserInfo;
import google.registry.tools.DomainLockUtils;
import google.registry.util.StringGenerator.Alphabets;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link RelockDomainAction}. */
@RunWith(JUnit4.class)
public class RelockDomainActionTest {
private static final String DOMAIN_NAME = "example.tld";
private static final String CLIENT_ID = "TheRegistrar";
private static final String POC_ID = "marla.singer@example.com";
private final FakeResponse response = new FakeResponse();
private final FakeClock clock = new FakeClock();
private final DomainLockUtils domainLockUtils =
new DomainLockUtils(new DeterministicStringGenerator(Alphabets.BASE_58));
@Rule
public final AppEngineRule appEngineRule =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withUserService(UserInfo.create(POC_ID, "12345"))
.build();
private DomainBase domain;
private RegistryLock oldLock;
private RelockDomainAction action;
@Before
public void setup() {
createTlds("tld", "net");
HostResource host = persistActiveHost("ns1.example.net");
domain = persistResource(newDomainBase(DOMAIN_NAME, host));
oldLock = domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, POC_ID, false);
assertThat(reloadDomain(domain).getStatusValues())
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
oldLock = domainLockUtils.administrativelyApplyUnlock(DOMAIN_NAME, CLIENT_ID, false);
assertThat(reloadDomain(domain).getStatusValues()).containsNoneIn(REGISTRY_LOCK_STATUSES);
action = createAction(oldLock.getRevisionId());
}
@Test
public void testLock() {
action.run();
assertThat(reloadDomain(domain).getStatusValues())
.containsAtLeastElementsIn(REGISTRY_LOCK_STATUSES);
// the old lock should have a reference to the relock
RegistryLock newLock = getMostRecentVerifiedRegistryLockByRepoId(domain.getRepoId()).get();
assertThat(getRegistryLockByVerificationCode(oldLock.getVerificationCode()).get().getRelock())
.isEqualTo(newLock);
}
@Test
public void testFailure_unknownCode() {
action = createAction(12128675309L);
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload()).isEqualTo("Relock failed: Unknown revision ID 12128675309");
}
@Test
public void testFailure_pendingDelete() {
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of(PENDING_DELETE)).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has a pending delete", DOMAIN_NAME));
}
@Test
public void testFailure_pendingTransfer() {
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of(PENDING_TRANSFER)).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has a pending transfer", DOMAIN_NAME));
}
@Test
public void testFailure_domainAlreadyLocked() {
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, null, true);
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Domain example.tld is already manually relocked, skipping automated relock.");
}
@Test
public void testFailure_domainDeleted() {
persistDomainAsDeleted(domain, clock.nowUtc());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(String.format("Relock failed: Domain %s has been deleted", DOMAIN_NAME));
}
@Test
public void testFailure_domainTransferred() {
persistResource(domain.asBuilder().setPersistedCurrentSponsorClientId("NewRegistrar").build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo(
String.format(
"Relock failed: Domain %s has been transferred from registrar %s to registrar "
+ "%s since the unlock",
DOMAIN_NAME, CLIENT_ID, "NewRegistrar"));
}
@Test
public void testFailure_relockAlreadySet() {
RegistryLock newLock =
domainLockUtils.administrativelyApplyLock(DOMAIN_NAME, CLIENT_ID, null, true);
saveRegistryLock(oldLock.asBuilder().setRelock(newLock).build());
// Save the domain without the lock statuses so that we pass that check in the action
persistResource(domain.asBuilder().setStatusValues(ImmutableSet.of()).build());
action.run();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Domain example.tld is already manually relocked, skipping automated relock.");
}
private DomainBase reloadDomain(DomainBase domain) {
return ofy().load().entity(domain).now();
}
private RelockDomainAction createAction(Long oldUnlockRevisionId) {
return new RelockDomainAction(oldUnlockRevisionId, domainLockUtils, response);
}
}
@@ -70,7 +70,7 @@ public class ResaveEntityActionTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final InjectRule inject = new InjectRule();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@@ -39,17 +39,20 @@ public class CommitLogFanoutActionTest {
private static final String QUEUE = "the-queue";
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
@Test
public void testSuccess() {
@@ -54,17 +54,20 @@ public class TldFanoutActionTest {
private final FakeResponse response = new FakeResponse();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>the-queue</name>",
" <rate>1/s</rate>",
" </queue>",
"</queue-entries>"))
.build();
private static ImmutableListMultimap<String, String> getParamsMap(String... keysAndValues) {
ImmutableListMultimap.Builder<String, String> params = new ImmutableListMultimap.Builder<>();
@@ -46,10 +46,8 @@ import org.junit.runners.JUnit4;
public final class DnsInjectionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -35,10 +35,9 @@ import org.junit.runners.JUnit4;
public class DnsQueueTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private DnsQueue dnsQueue;
private final FakeClock clock = new FakeClock(DateTime.parse("2010-01-01T10:00:00Z"));
@@ -55,10 +55,8 @@ import org.junit.runners.JUnit4;
public class PublishDnsUpdatesActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -73,22 +73,25 @@ public class ReadDnsQueueActionTest {
private FakeClock clock = new FakeClock(DateTime.parse("3000-01-01TZ"));
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue(Joiner.on('\n').join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>dns-publish</name>",
" <rate>1/s</rate>",
" </queue>",
" <queue>",
" <name>dns-pull</name>",
" <mode>pull</mode>",
" </queue>",
"</queue-entries>"))
.withClock(clock)
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql()
.withTaskQueue(
Joiner.on('\n')
.join(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
"<queue-entries>",
" <queue>",
" <name>dns-publish</name>",
" <rate>1/s</rate>",
" </queue>",
" <queue>",
" <name>dns-pull</name>",
" <mode>pull</mode>",
" </queue>",
"</queue-entries>"))
.withClock(clock)
.build();
@Before
public void before() {
@@ -42,7 +42,7 @@ public class RefreshDnsActionTest {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final FakeClock clock = new FakeClock();
@@ -69,7 +69,9 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class CloudDnsWriterTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
private static final Inet4Address IPv4 = (Inet4Address) InetAddresses.forString("127.0.0.1");
@@ -76,7 +76,7 @@ public class DnsUpdateWriterTest {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final InjectRule inject = new InjectRule();
@@ -62,10 +62,9 @@ import org.junit.runners.JUnit4;
public class BigqueryPollJobActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private static final String PROJECT_ID = "project_id";
private static final String JOB_ID = "job_id";
private static final String CHAINED_QUEUE_NAME = UpdateSnapshotViewAction.QUEUE;
@@ -59,7 +59,8 @@ public class ExportPremiumTermsActionTest {
private static final String EXPECTED_FILE_CONTENT =
DISCLAIMER_WITH_NEWLINE + "0,USD 549.00\n" + "2048,USD 549.00\n";
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private final DriveConnection driveConnection = mock(DriveConnection.class);
private final Response response = mock(Response.class);
@@ -48,7 +48,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class ExportReservedTermsActionTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private final DriveConnection driveConnection = mock(DriveConnection.class);
private final Response response = mock(Response.class);
@@ -32,9 +32,7 @@ import org.junit.runners.JUnit4;
public class ExportUtilsTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void test_exportReservedTerms() {
@@ -60,9 +60,7 @@ import org.junit.runners.JUnit4;
public class SyncGroupMembersActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -40,10 +40,8 @@ import org.junit.runners.JUnit4;
public class SyncRegistrarsSheetActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
private final FakeResponse response = new FakeResponse();
private final SyncRegistrarsSheet syncRegistrarsSheet = mock(SyncRegistrarsSheet.class);
@@ -58,7 +58,9 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class SyncRegistrarsSheetTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Rule public final InjectRule inject = new InjectRule();
@@ -56,7 +56,9 @@ public class CheckApiActionTest {
private static final DateTime START_TIME = DateTime.parse("2000-01-01T00:00:00.0Z");
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Mock private CheckApiMetrics checkApiMetrics;
@@ -48,10 +48,8 @@ import org.junit.runners.JUnit4;
public class EppCommitLogsTest extends ShardableTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -66,7 +66,10 @@ import org.mockito.junit.MockitoRule;
@RunWith(JUnit4.class)
public class EppControllerTest extends ShardableTestCase {
@Rule public AppEngineRule appEngineRule = new AppEngineRule.Builder().withDatastore().build();
@Rule
public AppEngineRule appEngineRule =
new AppEngineRule.Builder().withDatastoreAndCloudSql().build();
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
@Mock SessionMetadata sessionMetadata;
@@ -32,10 +32,8 @@ import org.junit.runners.JUnit4;
public class EppLifecycleContactTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testContactLifecycle() throws Exception {
@@ -64,7 +64,7 @@ public class EppLifecycleDomainTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Before
public void initTld() {
@@ -39,10 +39,8 @@ import org.junit.runners.JUnit4;
public class EppLifecycleHostTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testLifecycle() throws Exception {
@@ -30,7 +30,7 @@ public class EppLifecycleLoginTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastore().withTaskQueue().build();
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Test
public void testLoginAndLogout_recordsEppMetric() throws Exception {
@@ -30,9 +30,7 @@ import org.junit.runners.JUnit4;
public class EppLoggedOutTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testHello() throws Exception {
@@ -33,7 +33,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class EppLoginTlsTest extends EppTestCase {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
void setClientCertificateHash(String clientCertificateHash) {
setTransportCredentials(
@@ -26,9 +26,7 @@ import org.junit.runners.JUnit4;
public class EppXxeAttackTest extends EppTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testRemoteXmlExternalEntity() throws Exception {
@@ -48,9 +48,7 @@ import org.junit.runners.JUnit4;
public class ExtensionManagerTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testDuplicateExtensionsForbidden() {
@@ -83,10 +83,8 @@ public abstract class FlowTestCase<F extends Flow> extends ShardableTestCase {
public enum UserPrivileges { NORMAL, SUPERUSER }
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -38,7 +38,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class TlsCredentialsTest extends ShardableTestCase {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testProvideClientCertificateHash() {
@@ -63,7 +63,8 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
private final AllocationTokenFlowUtils flowUtils =
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void initTest() {
@@ -35,7 +35,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class HostFlowUtilsTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void test_validExternalHostName_validates() throws Exception {
@@ -37,7 +37,8 @@ public class KmsKeyringTest {
@Rule public final BouncyCastleProviderRule bouncy = new BouncyCastleProviderRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private KmsKeyring keyring;
@@ -36,7 +36,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class KmsUpdaterTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule public final BouncyCastleProviderRule bouncy = new BouncyCastleProviderRule();
@@ -62,7 +62,8 @@ public class ChildEntityInputTest {
private static final DateTime now = DateTime.now(DateTimeZone.UTC);
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
DomainBase domainA;
DomainBase domainB;
HistoryEntry domainHistoryEntryA;
@@ -48,7 +48,7 @@ public final class CommitLogManifestInputTest {
private static final DateTime DATE_TIME_NEW2 = DateTime.parse("2017-12-19T12:00Z");
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testInputOlderThan_allFound() throws Exception {
@@ -56,7 +56,8 @@ public class EppResourceInputsTest {
private static final double EPSILON = 0.0001;
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@SuppressWarnings("unchecked")
private <T> T serializeAndDeserialize(T obj) throws Exception {
try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
@@ -35,9 +35,7 @@ import org.junit.runners.JUnit4;
public class CreateAutoTimestampTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
/** Timestamped class. */
@Entity
@@ -49,19 +49,17 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public abstract class EntityTestCase {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
@Rule
public InjectRule inject = new InjectRule();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withClock(fakeClock).build();
protected FakeClock clock = new FakeClock(DateTime.now(UTC));
@Rule public InjectRule inject = new InjectRule();
@Before
public void injectClock() {
inject.setStaticField(Ofy.class, "clock", clock);
inject.setStaticField(Ofy.class, "clock", fakeClock);
}
// Helper method to find private fields including inherited ones.
@@ -77,17 +75,17 @@ public abstract class EntityTestCase {
}
/** Verify that fields are either indexed or not, depending on the parameter. */
private void verifyIndexingHelper(
Object obj,
boolean indexed,
Collection<String> fieldPaths) throws Exception {
outer: for (String fieldPath : fieldPaths) {
private void verifyIndexingHelper(Object obj, boolean indexed, Collection<String> fieldPaths)
throws Exception {
outer:
for (String fieldPath : fieldPaths) {
// Walk the field path and grab the value referred to on the object using reflection.
Object fieldValue = obj;
for (String fieldName : Splitter.on('.').split(fieldPath)) {
if (fieldValue == null) {
throw new RuntimeException(String.format("field '%s' not found on %s",
fieldPath, obj.getClass().getSimpleName()));
throw new RuntimeException(
String.format(
"field '%s' not found on %s", fieldPath, obj.getClass().getSimpleName()));
}
Field field = getField(fieldValue.getClass(), fieldName);
field.setAccessible(true);
@@ -149,14 +147,14 @@ public abstract class EntityTestCase {
// because verifyIndexingHelper knows how to descend into collections.
if (Collection.class.isAssignableFrom(fieldClass)) {
Type inner = ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
fieldClass = inner instanceof ParameterizedType
? (Class<?>) ((ParameterizedType) inner).getRawType()
: (Class<?>) inner;
fieldClass =
inner instanceof ParameterizedType
? (Class<?>) ((ParameterizedType) inner).getRawType()
: (Class<?>) inner;
}
// Descend into persisted ImmutableObject classes, but not anything else.
if (ImmutableObject.class.isAssignableFrom(fieldClass)) {
getAllPotentiallyIndexedFieldPaths(fieldClass)
.stream()
getAllPotentiallyIndexedFieldPaths(fieldClass).stream()
.map(subfield -> field.getName() + "." + subfield)
.distinct()
.forEachOrdered(fields::add);
@@ -46,7 +46,7 @@ public class EppResourceTest extends EntityTestCase {
persistResource(originalContact.asBuilder().setEmailAddress("different@fake.lol").build());
assertThat(EppResource.loadCached(ImmutableList.of(Key.create(originalContact))))
.containsExactly(Key.create(originalContact), originalContact);
assertThat(loadByForeignKey(ContactResource.class, "contact123", clock.nowUtc()))
assertThat(loadByForeignKey(ContactResource.class, "contact123", fakeClock.nowUtc()))
.hasValue(modifiedContact);
}
@@ -57,10 +57,10 @@ public class EppResourceTest extends EntityTestCase {
.containsExactly(Key.create(originalHost), originalHost);
HostResource modifiedHost =
persistResource(
originalHost.asBuilder().setLastTransferTime(clock.nowUtc().minusDays(60)).build());
originalHost.asBuilder().setLastTransferTime(fakeClock.nowUtc().minusDays(60)).build());
assertThat(EppResource.loadCached(ImmutableList.of(Key.create(originalHost))))
.containsExactly(Key.create(originalHost), originalHost);
assertThat(loadByForeignKey(HostResource.class, "ns1.example.com", clock.nowUtc()))
assertThat(loadByForeignKey(HostResource.class, "ns1.example.com", fakeClock.nowUtc()))
.hasValue(modifiedHost);
}
}
@@ -41,10 +41,8 @@ import org.junit.runners.JUnit4;
public class EppResourceUtilsTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.withTaskQueue()
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withTaskQueue().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -50,9 +50,7 @@ import org.junit.runners.JUnit4;
public class ImmutableObjectTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Before
public void register() {
@@ -49,7 +49,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class OteAccountBuilderTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testGetRegistrarToTldMap() {
@@ -26,7 +26,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public final class OteStatsTest {
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testSuccess_allPass() throws Exception {
@@ -30,7 +30,7 @@ import org.junit.runners.JUnit4;
public class SchemaVersionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testGoldenSchemaFile() {
@@ -35,9 +35,7 @@ import org.junit.runners.JUnit4;
public class UpdateAutoTimestampTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
/** Timestamped class. */
@Entity
@@ -29,27 +29,23 @@ import static org.junit.Assert.assertThrows;
import google.registry.model.EntityTestCase;
import google.registry.model.domain.DomainBase;
import google.registry.model.registry.Registry;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.schema.cursor.CursorDao;
import google.registry.testing.FakeClock;
import org.joda.time.DateTime;
import org.junit.Rule;
import org.junit.Before;
import org.junit.Test;
/** Unit tests for {@link Cursor}. */
public class CursorTest extends EntityTestCase {
private final FakeClock fakeClock = new FakeClock(DateTime.parse("2010-10-17TZ"));
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule();
@Before
public void setUp() {
fakeClock.setTo(DateTime.parse("2010-10-17TZ"));
}
@Test
public void testSuccess_persistScopedCursor() {
createTld("tld");
clock.advanceOneMilli();
this.fakeClock.advanceOneMilli();
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
Cursor cursor = Cursor.create(RDE_UPLOAD, time, Registry.get("tld"));
CursorDao.saveCursor(cursor, "tld");
@@ -85,7 +81,7 @@ public class CursorTest extends EntityTestCase {
@Test
public void testFailure_invalidScopeOnCreate() {
createTld("tld");
clock.advanceOneMilli();
this.fakeClock.advanceOneMilli();
final DateTime time = DateTime.parse("2012-07-12T03:30:00.000Z");
final DomainBase domain = persistActiveDomain("notaregistry.tld");
IllegalArgumentException thrown =
@@ -30,9 +30,7 @@ import org.junit.runners.JUnit4;
public class GaeUserIdConverterTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@After
public void verifyNoLingeringEntities() {
@@ -32,9 +32,7 @@ import org.junit.runners.JUnit4;
public class ContactCommandTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private void doXmlRoundtripTest(String inputFilename) throws Exception {
EppLoader eppLoader = new EppLoader(this, inputFilename);
@@ -48,81 +48,89 @@ public class ContactResourceTest extends EntityTestCase {
public void setUp() {
createTld("foobar");
// Set up a new persisted ContactResource entity.
contactResource = persistResource(cloneAndSetAutoTimestamps(
new ContactResource.Builder()
.setContactId("contact_id")
.setRepoId("1-FOOBAR")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateClientId("another registrar")
.setLastTransferTime(clock.nowUtc())
.setPersistedCurrentSponsorClientId("a third registrar")
.setLocalizedPostalInfo(new PostalInfo.Builder()
.setType(Type.LOCALIZED)
.setAddress(new ContactAddress.Builder()
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
.setCity("New York")
.setState("NY")
.setZip("10011")
.setCountryCode("US")
.build())
.build())
.setInternationalizedPostalInfo(new PostalInfo.Builder()
.setType(Type.INTERNATIONALIZED)
.setAddress(new ContactAddress.Builder()
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
.setCity("New York")
.setState("NY")
.setZip("10011")
.setCountryCode("US")
.build())
.build())
.setVoiceNumber(new ContactPhoneNumber.Builder()
.setPhoneNumber("867-5309")
.build())
.setFaxNumber(new ContactPhoneNumber.Builder()
.setPhoneNumber("867-5309")
.setExtension("1000")
.build())
.setEmailAddress("jenny@example.com")
.setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("passw0rd")))
.setDisclose(new Disclose.Builder()
.setVoice(new PresenceMarker())
.setEmail(new PresenceMarker())
.setFax(new PresenceMarker())
.setFlag(true)
.setAddrs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.setNames(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.setOrgs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.build())
.setStatusValues(ImmutableSet.of(StatusValue.OK))
.setTransferData(new TransferData.Builder()
.setGainingClientId("gaining")
.setLosingClientId("losing")
.setPendingTransferExpirationTime(clock.nowUtc())
.setServerApproveEntities(
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1)))
.setTransferRequestTime(clock.nowUtc())
.setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
.build())
.build()));
contactResource =
persistResource(
cloneAndSetAutoTimestamps(
new ContactResource.Builder()
.setContactId("contact_id")
.setRepoId("1-FOOBAR")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(fakeClock.nowUtc())
.setLastEppUpdateClientId("another registrar")
.setLastTransferTime(fakeClock.nowUtc())
.setPersistedCurrentSponsorClientId("a third registrar")
.setLocalizedPostalInfo(
new PostalInfo.Builder()
.setType(Type.LOCALIZED)
.setAddress(
new ContactAddress.Builder()
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
.setCity("New York")
.setState("NY")
.setZip("10011")
.setCountryCode("US")
.build())
.build())
.setInternationalizedPostalInfo(
new PostalInfo.Builder()
.setType(Type.INTERNATIONALIZED)
.setAddress(
new ContactAddress.Builder()
.setStreet(ImmutableList.of("111 8th Ave", "4th Floor"))
.setCity("New York")
.setState("NY")
.setZip("10011")
.setCountryCode("US")
.build())
.build())
.setVoiceNumber(
new ContactPhoneNumber.Builder().setPhoneNumber("867-5309").build())
.setFaxNumber(
new ContactPhoneNumber.Builder()
.setPhoneNumber("867-5309")
.setExtension("1000")
.build())
.setEmailAddress("jenny@example.com")
.setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("passw0rd")))
.setDisclose(
new Disclose.Builder()
.setVoice(new PresenceMarker())
.setEmail(new PresenceMarker())
.setFax(new PresenceMarker())
.setFlag(true)
.setAddrs(
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.setNames(
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.setOrgs(
ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED)))
.build())
.setStatusValues(ImmutableSet.of(StatusValue.OK))
.setTransferData(
new TransferData.Builder()
.setGainingClientId("gaining")
.setLosingClientId("losing")
.setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities(
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1)))
.setTransferRequestTime(fakeClock.nowUtc())
.setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
.build())
.build()));
}
@Test
public void testPersistence() {
assertThat(
loadByForeignKey(ContactResource.class, contactResource.getForeignKey(), clock.nowUtc()))
loadByForeignKey(
ContactResource.class, contactResource.getForeignKey(), fakeClock.nowUtc()))
.hasValue(contactResource);
}
@Test
public void testIndexing() throws Exception {
verifyIndexing(
contactResource,
"deletionTime",
"currentSponsorClientId",
"searchName");
verifyIndexing(contactResource, "deletionTime", "currentSponsorClientId", "searchName");
}
@Test
@@ -131,27 +139,30 @@ public class ContactResourceTest extends EntityTestCase {
assertThat(new ContactResource.Builder().setContactId("").build().getContactId()).isNull();
assertThat(new ContactResource.Builder().setContactId(" ").build().getContactId()).isNotNull();
// Nested ImmutableObjects should also be fixed
assertThat(new ContactResource.Builder()
.setInternationalizedPostalInfo(new PostalInfo.Builder()
.setType(Type.INTERNATIONALIZED)
.setName(null)
.build())
.build()
.getInternationalizedPostalInfo().getName()).isNull();
assertThat(new ContactResource.Builder()
.setInternationalizedPostalInfo(new PostalInfo.Builder()
.setType(Type.INTERNATIONALIZED)
.setName("")
.build())
.build()
.getInternationalizedPostalInfo().getName()).isNull();
assertThat(new ContactResource.Builder()
.setInternationalizedPostalInfo(new PostalInfo.Builder()
.setType(Type.INTERNATIONALIZED)
.setName(" ")
.build())
.build()
.getInternationalizedPostalInfo().getName()).isNotNull();
assertThat(
new ContactResource.Builder()
.setInternationalizedPostalInfo(
new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName(null).build())
.build()
.getInternationalizedPostalInfo()
.getName())
.isNull();
assertThat(
new ContactResource.Builder()
.setInternationalizedPostalInfo(
new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName("").build())
.build()
.getInternationalizedPostalInfo()
.getName())
.isNull();
assertThat(
new ContactResource.Builder()
.setInternationalizedPostalInfo(
new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName(" ").build())
.build()
.getInternationalizedPostalInfo()
.getName())
.isNotNull();
}
@Test
@@ -170,32 +181,39 @@ public class ContactResourceTest extends EntityTestCase {
.hasExactlyStatusValues(StatusValue.OK);
// If there are other status values, OK should be suppressed.
assertAboutContacts()
.that(new ContactResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
.build())
.that(
new ContactResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
.build())
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
// When OK is suppressed, it should be removed even if it was originally there.
assertAboutContacts()
.that(new ContactResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
.build())
.that(
new ContactResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
.build())
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
}
@Test
public void testExpiredTransfer() {
ContactResource afterTransfer = contactResource.asBuilder()
.setTransferData(contactResource.getTransferData().asBuilder()
.setTransferStatus(TransferStatus.PENDING)
.setPendingTransferExpirationTime(clock.nowUtc().plusDays(1))
.setGainingClientId("winner")
.build())
.build()
.cloneProjectedAtTime(clock.nowUtc().plusDays(1));
assertThat(afterTransfer.getTransferData().getTransferStatus()).isEqualTo(
TransferStatus.SERVER_APPROVED);
ContactResource afterTransfer =
contactResource
.asBuilder()
.setTransferData(
contactResource
.getTransferData()
.asBuilder()
.setTransferStatus(TransferStatus.PENDING)
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1))
.setGainingClientId("winner")
.build())
.build()
.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(1));
assertThat(afterTransfer.getTransferData().getTransferStatus())
.isEqualTo(TransferStatus.SERVER_APPROVED);
assertThat(afterTransfer.getCurrentSponsorClientId()).isEqualTo("winner");
assertThat(afterTransfer.getLastTransferTime()).isEqualTo(clock.nowUtc().plusDays(1));
assertThat(afterTransfer.getLastTransferTime()).isEqualTo(fakeClock.nowUtc().plusDays(1));
}
@Test
@@ -27,11 +27,8 @@ import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -40,10 +37,6 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class DomainBaseSqlTest extends EntityTestCase {
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().buildIntegrationWithCoverageRule();
DomainBase domain;
Key<ContactResource> contactKey;
Key<ContactResource> contact2Key;
@@ -58,9 +51,9 @@ public class DomainBaseSqlTest extends EntityTestCase {
.setFullyQualifiedDomainName("example.com")
.setRepoId("4-COM")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateTime(fakeClock.nowUtc())
.setLastEppUpdateClientId("AnotherRegistrar")
.setLastTransferTime(clock.nowUtc())
.setLastTransferTime(fakeClock.nowUtc())
.setStatusValues(
ImmutableSet.of(
StatusValue.CLIENT_DELETE_PROHIBITED,
@@ -73,7 +66,7 @@ public class DomainBaseSqlTest extends EntityTestCase {
.setContacts(ImmutableSet.of(DesignatedContact.create(Type.ADMIN, contact2Key)))
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
.setPersistedCurrentSponsorClientId("losing")
.setRegistrationExpirationTime(clock.nowUtc().plusYears(1))
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
.setLaunchNotice(
@@ -108,9 +108,9 @@ public class DomainBaseTest extends EntityTestCase {
.setFullyQualifiedDomainName("example.com")
.setRepoId("4-COM")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateTime(fakeClock.nowUtc())
.setLastEppUpdateClientId("AnotherRegistrar")
.setLastTransferTime(clock.nowUtc())
.setLastTransferTime(fakeClock.nowUtc())
.setStatusValues(
ImmutableSet.of(
StatusValue.CLIENT_DELETE_PROHIBITED,
@@ -124,7 +124,7 @@ public class DomainBaseTest extends EntityTestCase {
.setNameservers(ImmutableSet.of(hostKey))
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
.setPersistedCurrentSponsorClientId("losing")
.setRegistrationExpirationTime(clock.nowUtc().plusYears(1))
.setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1))
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
.setDsData(
ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
@@ -134,13 +134,13 @@ public class DomainBaseTest extends EntityTestCase {
new TransferData.Builder()
.setGainingClientId("gaining")
.setLosingClientId("losing")
.setPendingTransferExpirationTime(clock.nowUtc())
.setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities(
ImmutableSet.of(oneTimeBillKey, recurringBillKey, autorenewPollKey))
.setServerApproveBillingEvent(oneTimeBillKey)
.setServerApproveAutorenewEvent(recurringBillKey)
.setServerApproveAutorenewPollMessage(autorenewPollKey)
.setTransferRequestTime(clock.nowUtc().plusDays(1))
.setTransferRequestTime(fakeClock.nowUtc().plusDays(1))
.setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
.build())
@@ -150,13 +150,16 @@ public class DomainBaseTest extends EntityTestCase {
.setSmdId("smdid")
.addGracePeriod(
GracePeriod.create(
GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "registrar", null))
GracePeriodStatus.ADD,
fakeClock.nowUtc().plusDays(1),
"registrar",
null))
.build()));
}
@Test
public void testPersistence() {
assertThat(loadByForeignKey(DomainBase.class, domain.getForeignKey(), clock.nowUtc()))
assertThat(loadByForeignKey(DomainBase.class, domain.getForeignKey(), fakeClock.nowUtc()))
.hasValue(domain);
}
@@ -323,7 +326,7 @@ public class DomainBaseTest extends EntityTestCase {
assertThat(domain.getTransferData().getTransferStatus())
.isEqualTo(TransferStatus.SERVER_APPROVED);
assertThat(domain.getCurrentSponsorClientId()).isEqualTo("winner");
assertThat(domain.getLastTransferTime()).isEqualTo(clock.nowUtc().plusDays(1));
assertThat(domain.getLastTransferTime()).isEqualTo(fakeClock.nowUtc().plusDays(1));
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime);
assertThat(domain.getAutorenewBillingEvent()).isEqualTo(newAutorenewEvent);
}
@@ -336,9 +339,9 @@ public class DomainBaseTest extends EntityTestCase {
.setReason(Reason.TRANSFER)
.setClientId("winner")
.setTargetId("example.com")
.setEventTime(clock.nowUtc())
.setEventTime(fakeClock.nowUtc())
.setBillingTime(
clock
fakeClock
.nowUtc()
.plusDays(1)
.plus(Registry.get("com").getTransferGracePeriodLength()))
@@ -355,8 +358,8 @@ public class DomainBaseTest extends EntityTestCase {
.getTransferData()
.asBuilder()
.setTransferStatus(TransferStatus.PENDING)
.setTransferRequestTime(clock.nowUtc().minusDays(4))
.setPendingTransferExpirationTime(clock.nowUtc().plusDays(1))
.setTransferRequestTime(fakeClock.nowUtc().minusDays(4))
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1))
.setGainingClientId("winner")
.setServerApproveBillingEvent(Key.create(transferBillingEvent))
.setServerApproveEntities(ImmutableSet.of(Key.create(transferBillingEvent)))
@@ -365,9 +368,9 @@ public class DomainBaseTest extends EntityTestCase {
// Okay for billing event to be null since the point of this grace period is just
// to check that the transfer will clear all existing grace periods.
GracePeriod.create(
GracePeriodStatus.ADD, clock.nowUtc().plusDays(100), "foo", null))
GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(100), "foo", null))
.build();
DomainBase afterTransfer = domain.cloneProjectedAtTime(clock.nowUtc().plusDays(1));
DomainBase afterTransfer = domain.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(1));
DateTime newExpirationTime = oldExpirationTime.plusYears(1);
Key<BillingEvent.Recurring> serverApproveAutorenewEvent =
domain.getTransferData().getServerApproveAutorenewEvent();
@@ -376,20 +379,26 @@ public class DomainBaseTest extends EntityTestCase {
.containsExactly(
GracePeriod.create(
GracePeriodStatus.TRANSFER,
clock.nowUtc().plusDays(1).plus(Registry.get("com").getTransferGracePeriodLength()),
fakeClock
.nowUtc()
.plusDays(1)
.plus(Registry.get("com").getTransferGracePeriodLength()),
"winner",
Key.create(transferBillingEvent)));
// If we project after the grace period expires all should be the same except the grace period.
DomainBase afterGracePeriod =
domain.cloneProjectedAtTime(
clock.nowUtc().plusDays(2).plus(Registry.get("com").getTransferGracePeriodLength()));
fakeClock
.nowUtc()
.plusDays(2)
.plus(Registry.get("com").getTransferGracePeriodLength()));
assertTransferred(afterGracePeriod, newExpirationTime, serverApproveAutorenewEvent);
assertThat(afterGracePeriod.getGracePeriods()).isEmpty();
}
@Test
public void testExpiredTransfer() {
doExpiredTransferTest(clock.nowUtc().plusMonths(1));
doExpiredTransferTest(fakeClock.nowUtc().plusMonths(1));
}
@Test
@@ -397,7 +406,7 @@ public class DomainBaseTest extends EntityTestCase {
// Since transfer swallows a preceding autorenew, this should be identical to the regular
// transfer case (and specifically, the new expiration and grace periods will be the same as if
// there was no autorenew).
doExpiredTransferTest(clock.nowUtc().minusDays(1));
doExpiredTransferTest(fakeClock.nowUtc().minusDays(1));
}
private void setupPendingTransferDomain(
@@ -421,7 +430,7 @@ public class DomainBaseTest extends EntityTestCase {
@Test
public void testEppLastUpdateTimeAndClientId_autoRenewBeforeTransferSuccess() {
DateTime now = clock.nowUtc();
DateTime now = fakeClock.nowUtc();
DateTime transferRequestDateTime = now.plusDays(1);
DateTime autorenewDateTime = now.plusDays(3);
DateTime transferSuccessDateTime = now.plusDays(5);
@@ -440,7 +449,7 @@ public class DomainBaseTest extends EntityTestCase {
@Test
public void testEppLastUpdateTimeAndClientId_autoRenewAfterTransferSuccess() {
DateTime now = clock.nowUtc();
DateTime now = fakeClock.nowUtc();
DateTime transferRequestDateTime = now.plusDays(1);
DateTime autorenewDateTime = now.plusDays(3);
DateTime transferSuccessDateTime = now.plusDays(5);
@@ -470,7 +479,7 @@ public class DomainBaseTest extends EntityTestCase {
@Test
public void testEppLastUpdateTimeAndClientId_isSetCorrectlyWithNullPreviousValue() {
DateTime now = clock.nowUtc();
DateTime now = fakeClock.nowUtc();
DateTime autorenewDateTime = now.plusDays(3);
setupUnmodifiedDomain(autorenewDateTime);
@@ -487,12 +496,12 @@ public class DomainBaseTest extends EntityTestCase {
public void testStackedGracePeriods() {
ImmutableList<GracePeriod> gracePeriods =
ImmutableList.of(
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(2), "bar", null),
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
GracePeriod.create(GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(2), "bar", null),
GracePeriod.create(GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(1), "baz", null));
domain = domain.asBuilder().setGracePeriods(ImmutableSet.copyOf(gracePeriods)).build();
for (int i = 1; i < 3; ++i) {
assertThat(domain.cloneProjectedAtTime(clock.nowUtc().plusDays(i)).getGracePeriods())
assertThat(domain.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(i)).getGracePeriods())
.containsExactlyElementsIn(Iterables.limit(gracePeriods, 3 - i));
}
}
@@ -501,12 +510,14 @@ public class DomainBaseTest extends EntityTestCase {
public void testGracePeriodsByType() {
ImmutableSet<GracePeriod> addGracePeriods =
ImmutableSet.of(
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(GracePeriodStatus.ADD, clock.nowUtc().plusDays(1), "baz", null));
GracePeriod.create(GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(GracePeriodStatus.ADD, fakeClock.nowUtc().plusDays(1), "baz", null));
ImmutableSet<GracePeriod> renewGracePeriods =
ImmutableSet.of(
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(GracePeriodStatus.RENEW, clock.nowUtc().plusDays(1), "baz", null));
GracePeriod.create(
GracePeriodStatus.RENEW, fakeClock.nowUtc().plusDays(3), "foo", null),
GracePeriod.create(
GracePeriodStatus.RENEW, fakeClock.nowUtc().plusDays(1), "baz", null));
domain =
domain
.asBuilder()
@@ -82,7 +82,7 @@ public class DomainCommandTest extends ResourceCommandTestCase {
persistActiveContact("jd1234");
DomainCommand.Create create =
(DomainCommand.Create) loadEppResourceCommand("domain_create.xml");
create.cloneAndLinkReferences(clock.nowUtc());
create.cloneAndLinkReferences(fakeClock.nowUtc());
}
@Test
@@ -90,7 +90,7 @@ public class DomainCommandTest extends ResourceCommandTestCase {
// This EPP command wouldn't be allowed for policy reasons, but should clone-and-link fine.
DomainCommand.Create create =
(DomainCommand.Create) loadEppResourceCommand("domain_create_empty.xml");
create.cloneAndLinkReferences(clock.nowUtc());
create.cloneAndLinkReferences(fakeClock.nowUtc());
}
@Test
@@ -100,7 +100,7 @@ public class DomainCommandTest extends ResourceCommandTestCase {
DomainCommand.Create create =
(DomainCommand.Create)
loadEppResourceCommand("domain_create_missing_non_registrant_contacts.xml");
create.cloneAndLinkReferences(clock.nowUtc());
create.cloneAndLinkReferences(fakeClock.nowUtc());
}
@Test
@@ -132,7 +132,7 @@ public class DomainCommandTest extends ResourceCommandTestCase {
persistActiveContact("sh8013");
DomainCommand.Update update =
(DomainCommand.Update) loadEppResourceCommand("domain_update.xml");
update.cloneAndLinkReferences(clock.nowUtc());
update.cloneAndLinkReferences(fakeClock.nowUtc());
}
@Test
@@ -140,7 +140,7 @@ public class DomainCommandTest extends ResourceCommandTestCase {
// This EPP command wouldn't be allowed for policy reasons, but should clone-and-link fine.
DomainCommand.Update update =
(DomainCommand.Update) loadEppResourceCommand("domain_update_empty.xml");
update.cloneAndLinkReferences(clock.nowUtc());
update.cloneAndLinkReferences(fakeClock.nowUtc());
}
@Test
@@ -39,9 +39,11 @@ import org.junit.runners.JUnit4;
public class GracePeriodTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore() // Needed to be able to construct Keys.
.build();
public final AppEngineRule appEngine =
AppEngineRule.builder()
.withDatastoreAndCloudSql() // Needed to be able to construct Keys.
.build();
private final DateTime now = DateTime.now(UTC);
private BillingEvent.OneTime onetime;
@@ -102,7 +102,7 @@ public class AllocationTokenTest extends EntityTestCase {
new AllocationToken.Builder().setToken("abc123").setTokenType(SINGLE_USE).build();
assertThat(tokenBeforePersisting.getCreationTime()).isEmpty();
AllocationToken tokenAfterPersisting = persistResource(tokenBeforePersisting);
assertThat(tokenAfterPersisting.getCreationTime()).hasValue(clock.nowUtc());
assertThat(tokenAfterPersisting.getCreationTime()).hasValue(fakeClock.nowUtc());
}
@Test
@@ -41,7 +41,7 @@ import org.junit.Test;
/** Unit tests for {@link HostResource}. */
public class HostResourceTest extends EntityTestCase {
final DateTime day3 = clock.nowUtc();
final DateTime day3 = fakeClock.nowUtc();
final DateTime day2 = day3.minusDays(1);
final DateTime day1 = day2.minusDays(1);
@@ -61,10 +61,10 @@ public class HostResourceTest extends EntityTestCase {
new TransferData.Builder()
.setGainingClientId("gaining")
.setLosingClientId("losing")
.setPendingTransferExpirationTime(clock.nowUtc())
.setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities(
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1)))
.setTransferRequestTime(clock.nowUtc())
.setTransferRequestTime(fakeClock.nowUtc())
.setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
.build())
@@ -76,9 +76,9 @@ public class HostResourceTest extends EntityTestCase {
.setRepoId("DEADBEEF-COM")
.setFullyQualifiedHostName("ns1.example.com")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateTime(fakeClock.nowUtc())
.setLastEppUpdateClientId("another registrar")
.setLastTransferTime(clock.nowUtc())
.setLastTransferTime(fakeClock.nowUtc())
.setInetAddresses(ImmutableSet.of(InetAddresses.forString("127.0.0.1")))
.setStatusValues(ImmutableSet.of(StatusValue.OK))
.setSuperordinateDomain(Key.create(domain))
@@ -87,7 +87,7 @@ public class HostResourceTest extends EntityTestCase {
@Test
public void testPersistence() {
assertThat(loadByForeignKey(HostResource.class, host.getForeignKey(), clock.nowUtc()))
assertThat(loadByForeignKey(HostResource.class, host.getForeignKey(), fakeClock.nowUtc()))
.hasValue(host);
}
@@ -106,15 +106,24 @@ public class HostResourceTest extends EntityTestCase {
@Test
public void testEmptyStringsBecomeNull() {
assertThat(new HostResource.Builder().setPersistedCurrentSponsorClientId(null).build()
.getPersistedCurrentSponsorClientId())
.isNull();
assertThat(new HostResource.Builder().setPersistedCurrentSponsorClientId("").build()
.getPersistedCurrentSponsorClientId())
.isNull();
assertThat(new HostResource.Builder().setPersistedCurrentSponsorClientId(" ").build()
.getPersistedCurrentSponsorClientId())
.isNotNull();
assertThat(
new HostResource.Builder()
.setPersistedCurrentSponsorClientId(null)
.build()
.getPersistedCurrentSponsorClientId())
.isNull();
assertThat(
new HostResource.Builder()
.setPersistedCurrentSponsorClientId("")
.build()
.getPersistedCurrentSponsorClientId())
.isNull();
assertThat(
new HostResource.Builder()
.setPersistedCurrentSponsorClientId(" ")
.build()
.getPersistedCurrentSponsorClientId())
.isNotNull();
}
@Test
@@ -138,15 +147,17 @@ public class HostResourceTest extends EntityTestCase {
.hasExactlyStatusValues(StatusValue.OK);
// If there are other status values, OK should be suppressed.
assertAboutHosts()
.that(new HostResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
.build())
.that(
new HostResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_HOLD))
.build())
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
// When OK is suppressed, it should be removed even if it was originally there.
assertAboutHosts()
.that(new HostResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
.build())
.that(
new HostResource.Builder()
.setStatusValues(ImmutableSet.of(StatusValue.OK, StatusValue.CLIENT_HOLD))
.build())
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
}
@@ -181,10 +192,7 @@ public class HostResourceTest extends EntityTestCase {
@Test
public void testComputeLastTransferTime_hostNeverSwitchedDomains_domainWasNeverTransferred() {
domain = domain.asBuilder().setLastTransferTime(null).build();
host = host.asBuilder()
.setLastTransferTime(null)
.setLastSuperordinateChange(null)
.build();
host = host.asBuilder().setLastTransferTime(null).setLastSuperordinateChange(null).build();
assertThat(host.computeLastTransferTime(domain)).isNull();
}
@@ -194,11 +202,12 @@ public class HostResourceTest extends EntityTestCase {
// Domain was transferred on Day 2.
// Host was always subordinate to domain (and was created before the transfer).
domain = domain.asBuilder().setLastTransferTime(day2).build();
host = host.asBuilder()
.setCreationTimeForTest(day1)
.setLastTransferTime(null)
.setLastSuperordinateChange(null)
.build();
host =
host.asBuilder()
.setCreationTimeForTest(day1)
.setLastTransferTime(null)
.setLastSuperordinateChange(null)
.build();
assertThat(host.computeLastTransferTime(domain)).isEqualTo(day2);
}
@@ -215,7 +224,7 @@ public class HostResourceTest extends EntityTestCase {
.setRepoId("DEADBEEF-COM")
.setFullyQualifiedHostName("ns1.example.com")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateTime(fakeClock.nowUtc())
.setLastEppUpdateClientId("another registrar")
.setInetAddresses(ImmutableSet.of(InetAddresses.forString("127.0.0.1")))
.setStatusValues(ImmutableSet.of(StatusValue.OK))
@@ -230,10 +239,7 @@ public class HostResourceTest extends EntityTestCase {
// Host was made subordinate to domain on Day 2.
// Domain was never transferred.
domain = domain.asBuilder().setLastTransferTime(null).build();
host = host.asBuilder()
.setLastTransferTime(day1)
.setLastSuperordinateChange(day2)
.build();
host = host.asBuilder().setLastTransferTime(day1).setLastSuperordinateChange(day2).build();
assertThat(host.computeLastTransferTime(domain)).isEqualTo(day1);
}
@@ -243,10 +249,7 @@ public class HostResourceTest extends EntityTestCase {
// Domain was transferred on Day 2.
// Host was made subordinate to domain on Day 3.
domain = domain.asBuilder().setLastTransferTime(day2).build();
host = host.asBuilder()
.setLastTransferTime(day1)
.setLastSuperordinateChange(day3)
.build();
host = host.asBuilder().setLastTransferTime(day1).setLastSuperordinateChange(day3).build();
assertThat(host.computeLastTransferTime(domain)).isEqualTo(day1);
}
@@ -256,10 +259,7 @@ public class HostResourceTest extends EntityTestCase {
// Host was made subordinate to domain on Day 2.
// Domain was transferred on Day 3.
domain = domain.asBuilder().setLastTransferTime(day3).build();
host = host.asBuilder()
.setLastTransferTime(day1)
.setLastSuperordinateChange(day2)
.build();
host = host.asBuilder().setLastTransferTime(day1).setLastSuperordinateChange(day2).build();
assertThat(host.computeLastTransferTime(domain)).isEqualTo(day3);
}
}
@@ -55,7 +55,7 @@ public class ForeignKeyIndexTest extends EntityTestCase {
// Persist a host and implicitly persist a ForeignKeyIndex for it.
HostResource host = persistActiveHost("ns1.example.com");
ForeignKeyIndex<HostResource> fki =
ForeignKeyIndex.load(HostResource.class, "ns1.example.com", clock.nowUtc());
ForeignKeyIndex.load(HostResource.class, "ns1.example.com", fakeClock.nowUtc());
assertThat(ofy().load().key(fki.getResourceKey()).now()).isEqualTo(host);
assertThat(fki.getDeletionTime()).isEqualTo(END_OF_TIME);
}
@@ -65,62 +65,64 @@ public class ForeignKeyIndexTest extends EntityTestCase {
// Persist a host and implicitly persist a ForeignKeyIndex for it.
persistActiveHost("ns1.example.com");
verifyIndexing(
ForeignKeyIndex.load(HostResource.class, "ns1.example.com", clock.nowUtc()),
ForeignKeyIndex.load(HostResource.class, "ns1.example.com", fakeClock.nowUtc()),
"deletionTime");
}
@Test
public void testLoadForNonexistentForeignKey_returnsNull() {
assertThat(ForeignKeyIndex.load(HostResource.class, "ns1.example.com", clock.nowUtc()))
assertThat(ForeignKeyIndex.load(HostResource.class, "ns1.example.com", fakeClock.nowUtc()))
.isNull();
}
@Test
public void testLoadForDeletedForeignKey_returnsNull() {
HostResource host = persistActiveHost("ns1.example.com");
persistResource(ForeignKeyIndex.create(host, clock.nowUtc().minusDays(1)));
assertThat(ForeignKeyIndex.load(HostResource.class, "ns1.example.com", clock.nowUtc()))
persistResource(ForeignKeyIndex.create(host, fakeClock.nowUtc().minusDays(1)));
assertThat(ForeignKeyIndex.load(HostResource.class, "ns1.example.com", fakeClock.nowUtc()))
.isNull();
}
@Test
public void testLoad_newerKeyHasBeenSoftDeleted() {
HostResource host1 = persistActiveHost("ns1.example.com");
clock.advanceOneMilli();
fakeClock.advanceOneMilli();
ForeignKeyHostIndex fki = new ForeignKeyHostIndex();
fki.foreignKey = "ns1.example.com";
fki.topReference = Key.create(host1);
fki.deletionTime = clock.nowUtc();
fki.deletionTime = fakeClock.nowUtc();
persistResource(fki);
assertThat(ForeignKeyIndex.load(
HostResource.class, "ns1.example.com", clock.nowUtc())).isNull();
assertThat(ForeignKeyIndex.load(HostResource.class, "ns1.example.com", fakeClock.nowUtc()))
.isNull();
}
@Test
public void testBatchLoad_skipsDeletedAndNonexistent() {
persistActiveHost("ns1.example.com");
HostResource host = persistActiveHost("ns2.example.com");
persistResource(ForeignKeyIndex.create(host, clock.nowUtc().minusDays(1)));
assertThat(ForeignKeyIndex.load(
HostResource.class,
ImmutableList.of("ns1.example.com", "ns2.example.com", "ns3.example.com"),
clock.nowUtc()).keySet())
.containsExactly("ns1.example.com");
persistResource(ForeignKeyIndex.create(host, fakeClock.nowUtc().minusDays(1)));
assertThat(
ForeignKeyIndex.load(
HostResource.class,
ImmutableList.of("ns1.example.com", "ns2.example.com", "ns3.example.com"),
fakeClock.nowUtc())
.keySet())
.containsExactly("ns1.example.com");
}
@Test
public void testDeadCodeThatDeletedScrapCommandsReference() {
persistActiveHost("omg");
assertThat(ForeignKeyIndex.load(HostResource.class, "omg", clock.nowUtc()).getForeignKey())
assertThat(ForeignKeyIndex.load(HostResource.class, "omg", fakeClock.nowUtc()).getForeignKey())
.isEqualTo("omg");
}
private ForeignKeyIndex<HostResource> loadHostFki(String hostname) {
return ForeignKeyIndex.load(HostResource.class, hostname, clock.nowUtc());
return ForeignKeyIndex.load(HostResource.class, hostname, fakeClock.nowUtc());
}
private ForeignKeyIndex<ContactResource> loadContactFki(String contactId) {
return ForeignKeyIndex.load(ContactResource.class, contactId, clock.nowUtc());
return ForeignKeyIndex.load(ContactResource.class, contactId, fakeClock.nowUtc());
}
@Test
@@ -129,17 +131,17 @@ public class ForeignKeyIndexTest extends EntityTestCase {
ForeignKeyIndex.loadCached(
HostResource.class,
ImmutableList.of("ns5.example.com", "ns6.example.com"),
clock.nowUtc()))
fakeClock.nowUtc()))
.isEmpty();
persistActiveHost("ns4.example.com");
persistActiveHost("ns5.example.com");
persistActiveHost("ns6.example.com");
clock.advanceOneMilli();
fakeClock.advanceOneMilli();
assertThat(
ForeignKeyIndex.loadCached(
HostResource.class,
ImmutableList.of("ns6.example.com", "ns5.example.com", "ns4.example.com"),
clock.nowUtc()))
fakeClock.nowUtc()))
.containsExactly("ns4.example.com", loadHostFki("ns4.example.com"));
}
@@ -151,7 +153,7 @@ public class ForeignKeyIndexTest extends EntityTestCase {
ForeignKeyIndex.loadCached(
HostResource.class,
ImmutableList.of("ns1.example.com", "ns2.example.com"),
clock.nowUtc()))
fakeClock.nowUtc()))
.containsExactly(
"ns1.example.com",
loadHostFki("ns1.example.com"),
@@ -164,7 +166,7 @@ public class ForeignKeyIndexTest extends EntityTestCase {
ForeignKeyIndex.loadCached(
HostResource.class,
ImmutableList.of("ns3.example.com", "ns2.example.com", "ns1.example.com"),
clock.nowUtc()))
fakeClock.nowUtc()))
.containsExactly(
"ns1.example.com", loadHostFki("ns1.example.com"),
"ns2.example.com", loadHostFki("ns2.example.com"),
@@ -175,34 +177,34 @@ public class ForeignKeyIndexTest extends EntityTestCase {
public void test_loadCached_doesntSeeHostChangesWhileCacheIsValid() {
HostResource originalHost = persistActiveHost("ns1.example.com");
ForeignKeyIndex<HostResource> originalFki = loadHostFki("ns1.example.com");
clock.advanceOneMilli();
fakeClock.advanceOneMilli();
assertThat(
ForeignKeyIndex.loadCached(
HostResource.class, ImmutableList.of("ns1.example.com"), clock.nowUtc()))
HostResource.class, ImmutableList.of("ns1.example.com"), fakeClock.nowUtc()))
.containsExactly("ns1.example.com", originalFki);
HostResource modifiedHost =
persistResource(
originalHost.asBuilder().setPersistedCurrentSponsorClientId("OtherRegistrar").build());
clock.advanceOneMilli();
fakeClock.advanceOneMilli();
ForeignKeyIndex<HostResource> newFki = loadHostFki("ns1.example.com");
assertThat(newFki).isNotEqualTo(originalFki);
assertThat(loadByForeignKey(HostResource.class, "ns1.example.com", clock.nowUtc()))
assertThat(loadByForeignKey(HostResource.class, "ns1.example.com", fakeClock.nowUtc()))
.hasValue(modifiedHost);
assertThat(
ForeignKeyIndex.loadCached(
HostResource.class, ImmutableList.of("ns1.example.com"), clock.nowUtc()))
HostResource.class, ImmutableList.of("ns1.example.com"), fakeClock.nowUtc()))
.containsExactly("ns1.example.com", originalFki);
}
@Test
public void test_loadCached_filtersOutSoftDeletedHosts() {
persistActiveHost("ns1.example.com");
persistDeletedHost("ns2.example.com", clock.nowUtc().minusDays(1));
persistDeletedHost("ns2.example.com", fakeClock.nowUtc().minusDays(1));
assertThat(
ForeignKeyIndex.loadCached(
HostResource.class,
ImmutableList.of("ns1.example.com", "ns2.example.com"),
clock.nowUtc()))
fakeClock.nowUtc()))
.containsExactly("ns1.example.com", loadHostFki("ns1.example.com"));
}
@@ -211,24 +213,24 @@ public class ForeignKeyIndexTest extends EntityTestCase {
persistActiveContact("contactid1");
ForeignKeyIndex<ContactResource> fki1 = loadContactFki("contactid1");
assertThat(
ForeignKeyIndex.loadCached(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
clock.nowUtc()))
ForeignKeyIndex.loadCached(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
fakeClock.nowUtc()))
.containsExactly("contactid1", fki1);
persistActiveContact("contactid2");
deleteResource(fki1);
assertThat(
ForeignKeyIndex.loadCached(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
clock.nowUtc()))
ForeignKeyIndex.loadCached(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
fakeClock.nowUtc()))
.containsExactly("contactid1", fki1);
assertThat(
ForeignKeyIndex.load(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
clock.nowUtc()))
ForeignKeyIndex.load(
ContactResource.class,
ImmutableList.of("contactid1", "contactid2"),
fakeClock.nowUtc()))
.containsExactly("contactid2", loadContactFki("contactid2"));
}
}
@@ -38,9 +38,7 @@ import org.junit.runners.JUnit4;
public class CommitLogBucketTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -32,9 +32,7 @@ import org.junit.runners.JUnit4;
public class CommitLogCheckpointTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private static final DateTime T1 = START_OF_TIME;
private static final DateTime T2 = START_OF_TIME.plusMillis(1);
@@ -39,9 +39,7 @@ import org.junit.runners.JUnit4;
public class CommitLogMutationTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private static final DateTime NOW = DateTime.now(DateTimeZone.UTC);
@@ -25,9 +25,7 @@ import org.junit.runners.JUnit4;
public class ObjectifyServiceTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void test_initOfy_canBeCalledTwice() {
@@ -47,9 +47,7 @@ import org.junit.runners.JUnit4;
public class OfyCommitLogTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public final InjectRule inject = new InjectRule();
@@ -63,9 +63,7 @@ import org.junit.runners.JUnit4;
public class OfyTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
/** An entity to use in save and delete tests. */
private HistoryEntry someObject;
@@ -46,9 +46,7 @@ import org.junit.runners.JUnit4;
public class PollMessageExternalKeyConverterTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Rule
public InjectRule inject = new InjectRule();
@@ -36,57 +36,62 @@ public class PollMessageTest extends EntityTestCase {
@Before
public void setUp() {
createTld("foobar");
historyEntry = persistResource(new HistoryEntry.Builder()
.setParent(persistActiveDomain("foo.foobar"))
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(Period.create(1, Period.Unit.YEARS))
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
.setModificationTime(clock.nowUtc())
.setClientId("foo")
.setTrid(Trid.create("ABC-123", "server-trid"))
.setBySuperuser(false)
.setReason("reason")
.setRequestedByRegistrar(false)
.build());
historyEntry =
persistResource(
new HistoryEntry.Builder()
.setParent(persistActiveDomain("foo.foobar"))
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(Period.create(1, Period.Unit.YEARS))
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
.setModificationTime(fakeClock.nowUtc())
.setClientId("foo")
.setTrid(Trid.create("ABC-123", "server-trid"))
.setBySuperuser(false)
.setReason("reason")
.setRequestedByRegistrar(false)
.build());
}
@Test
public void testPersistenceOneTime() {
PollMessage.OneTime pollMessage = persistResource(
new PollMessage.OneTime.Builder()
.setClientId("TheRegistrar")
.setEventTime(clock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.build());
PollMessage.OneTime pollMessage =
persistResource(
new PollMessage.OneTime.Builder()
.setClientId("TheRegistrar")
.setEventTime(fakeClock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.build());
assertThat(ofy().load().entity(pollMessage).now()).isEqualTo(pollMessage);
}
@Test
public void testPersistenceAutorenew() {
PollMessage.Autorenew pollMessage = persistResource(
new PollMessage.Autorenew.Builder()
.setClientId("TheRegistrar")
.setEventTime(clock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.setAutorenewEndTime(clock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build());
PollMessage.Autorenew pollMessage =
persistResource(
new PollMessage.Autorenew.Builder()
.setClientId("TheRegistrar")
.setEventTime(fakeClock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build());
assertThat(ofy().load().entity(pollMessage).now()).isEqualTo(pollMessage);
}
@Test
public void testIndexingAutorenew() throws Exception {
PollMessage.Autorenew pollMessage = persistResource(
new PollMessage.Autorenew.Builder()
.setClientId("TheRegistrar")
.setEventTime(clock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.setAutorenewEndTime(clock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build());
PollMessage.Autorenew pollMessage =
persistResource(
new PollMessage.Autorenew.Builder()
.setClientId("TheRegistrar")
.setEventTime(fakeClock.nowUtc())
.setMsg("Test poll message")
.setParent(historyEntry)
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build());
verifyIndexing(pollMessage);
}
}
@@ -35,7 +35,8 @@ import org.junit.runners.JUnit4;
public class RdeRevisionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testGetNextRevision_objectDoesntExist_returnsZero() {
assertThat(getNextRevision("torment", DateTime.parse("1984-12-18TZ"), FULL))
@@ -66,7 +66,7 @@ public class RegistrarTest extends EntityTestCase {
.setAllowedTlds(ImmutableSet.of("xn--q9jyb4c"))
.setWhoisServer("whois.example.com")
.setBlockPremiumNames(true)
.setClientCertificate(SAMPLE_CERT, clock.nowUtc())
.setClientCertificate(SAMPLE_CERT, fakeClock.nowUtc())
.setIpAddressWhitelist(
ImmutableList.of(
CidrAddressBlock.create("192.168.1.1/31"),
@@ -128,10 +128,14 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testPersistence() {
assertThat(registrar).isEqualTo(ofy().load().type(Registrar.class)
.parent(EntityGroupRoot.getCrossTldKey())
.id(registrar.getClientId())
.now());
assertThat(registrar)
.isEqualTo(
ofy()
.load()
.type(Registrar.class)
.parent(EntityGroupRoot.getCrossTldKey())
.id(registrar.getClientId())
.now());
}
@Test
@@ -186,12 +190,10 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testSetCertificateHash_alsoSetsHash() {
registrar = registrar.asBuilder().setClientCertificate(null, clock.nowUtc()).build();
clock.advanceOneMilli();
registrar = registrar.asBuilder()
.setClientCertificate(SAMPLE_CERT, clock.nowUtc())
.build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(clock.nowUtc());
registrar = registrar.asBuilder().setClientCertificate(null, fakeClock.nowUtc()).build();
fakeClock.advanceOneMilli();
registrar = registrar.asBuilder().setClientCertificate(SAMPLE_CERT, fakeClock.nowUtc()).build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(fakeClock.nowUtc());
assertThat(registrar.getClientCertificate()).isEqualTo(SAMPLE_CERT);
assertThat(registrar.getClientCertificateHash()).isEqualTo(SAMPLE_CERT_HASH);
}
@@ -199,44 +201,43 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testDeleteCertificateHash_alsoDeletesHash() {
assertThat(registrar.getClientCertificateHash()).isNotNull();
clock.advanceOneMilli();
registrar = registrar.asBuilder()
.setClientCertificate(null, clock.nowUtc())
.build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(clock.nowUtc());
fakeClock.advanceOneMilli();
registrar = registrar.asBuilder().setClientCertificate(null, fakeClock.nowUtc()).build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(fakeClock.nowUtc());
assertThat(registrar.getClientCertificate()).isNull();
assertThat(registrar.getClientCertificateHash()).isNull();
}
@Test
public void testSetFailoverCertificateHash_alsoSetsHash() {
clock.advanceOneMilli();
registrar = registrar.asBuilder()
.setFailoverClientCertificate(SAMPLE_CERT2, clock.nowUtc())
.build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(clock.nowUtc());
fakeClock.advanceOneMilli();
registrar =
registrar
.asBuilder()
.setFailoverClientCertificate(SAMPLE_CERT2, fakeClock.nowUtc())
.build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(fakeClock.nowUtc());
assertThat(registrar.getFailoverClientCertificate()).isEqualTo(SAMPLE_CERT2);
assertThat(registrar.getFailoverClientCertificateHash()).isEqualTo(SAMPLE_CERT2_HASH);
}
@Test
public void testDeleteFailoverCertificateHash_alsoDeletesHash() {
registrar = registrar.asBuilder()
.setFailoverClientCertificate(SAMPLE_CERT, clock.nowUtc())
.build();
registrar =
registrar.asBuilder().setFailoverClientCertificate(SAMPLE_CERT, fakeClock.nowUtc()).build();
assertThat(registrar.getFailoverClientCertificateHash()).isNotNull();
clock.advanceOneMilli();
registrar = registrar.asBuilder()
.setFailoverClientCertificate(null, clock.nowUtc())
.build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(clock.nowUtc());
fakeClock.advanceOneMilli();
registrar =
registrar.asBuilder().setFailoverClientCertificate(null, fakeClock.nowUtc()).build();
assertThat(registrar.getLastCertificateUpdateTime()).isEqualTo(fakeClock.nowUtc());
assertThat(registrar.getFailoverClientCertificate()).isNull();
assertThat(registrar.getFailoverClientCertificateHash()).isNull();
}
@Test
public void testSuccess_clearingIanaAndBillingIds() {
registrar.asBuilder()
registrar
.asBuilder()
.setType(Type.TEST)
.setIanaIdentifier(null)
.setBillingIdentifier(null)
@@ -244,10 +245,8 @@ public class RegistrarTest extends EntityTestCase {
}
@Test
public void testSuccess_clearingBillingAccountMap() {
registrar = registrar.asBuilder()
.setBillingAccountMap(null)
.build();
public void testSuccess_clearingBillingAccountMap() {
registrar = registrar.asBuilder().setBillingAccountMap(null).build();
assertThat(registrar.getBillingAccountMap()).isEmpty();
}
@@ -422,7 +421,8 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testSuccess_setAllowedTlds() {
assertThat(
registrar.asBuilder()
registrar
.asBuilder()
.setAllowedTlds(ImmutableSet.of("xn--q9jyb4c"))
.build()
.getAllowedTlds())
@@ -432,7 +432,8 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testSuccess_setAllowedTldsUncached() {
assertThat(
registrar.asBuilder()
registrar
.asBuilder()
.setAllowedTldsUncached(ImmutableSet.of("xn--q9jyb4c"))
.build()
.getAllowedTlds())
@@ -455,9 +456,12 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testFailure_driveFolderId_asFullUrl() {
String driveFolderId =
"https://drive.google.com/drive/folders/1j3v7RZkU25DjbTx2-Q93H04zKOBau89M";
IllegalArgumentException thrown =
assertThrows(IllegalArgumentException.class, () -> registrar.asBuilder().setDriveFolderId(
"https://drive.google.com/drive/folders/1j3v7RZkU25DjbTx2-Q93H04zKOBau89M"));
assertThrows(
IllegalArgumentException.class,
() -> registrar.asBuilder().setDriveFolderId(driveFolderId));
assertThat(thrown).hasMessageThat().isEqualTo("Drive folder ID must not be a full URL");
}
@@ -483,9 +487,7 @@ public class RegistrarTest extends EntityTestCase {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class, () -> registrar.asBuilder().setEmailAddress(""));
assertThat(thrown)
.hasMessageThat()
.isEqualTo("Provided email is not a valid email address");
assertThat(thrown).hasMessageThat().isEqualTo("Provided email is not a valid email address");
}
@Test
@@ -512,9 +514,7 @@ public class RegistrarTest extends EntityTestCase {
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class, () -> registrar.asBuilder().setEmailAddress(""));
assertThat(thrown)
.hasMessageThat()
.isEqualTo("Provided email is not a valid email address");
assertThat(thrown).hasMessageThat().isEqualTo("Provided email is not a valid email address");
}
@Test
@@ -568,8 +568,7 @@ public class RegistrarTest extends EntityTestCase {
@Test
public void testLoadByClientIdCached_isTransactionless() {
tm()
.transact(
tm().transact(
() -> {
assertThat(Registrar.loadByClientIdCached("registrar")).isPresent();
// Load something as a control to make sure we are seeing loaded keys in the session
@@ -34,7 +34,7 @@ import org.junit.runners.JUnit4;
public class RegistriesTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
private void initTestTlds() {
createTlds("foo", "a.b.c"); // Test a multipart tld.
@@ -18,14 +18,14 @@ import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.testing.SqlHelper.getMostRecentRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.getMostRecentUnlockedRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.getMostRecentVerifiedRegistryLockByRepoId;
import static google.registry.testing.SqlHelper.getRegistryLockByRevisionId;
import static google.registry.testing.SqlHelper.getRegistryLockByVerificationCode;
import static google.registry.testing.SqlHelper.getRegistryLocksByRegistrarId;
import static google.registry.testing.SqlHelper.saveRegistryLock;
import static org.junit.Assert.assertThrows;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import google.registry.schema.domain.RegistryLock;
import google.registry.testing.AppEngineRule;
import google.registry.testing.FakeClock;
@@ -41,11 +41,9 @@ public final class RegistryLockDaoTest {
private final FakeClock fakeClock = new FakeClock();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageRule();
public final AppEngineRule appEngine =
AppEngineRule.builder().withDatastoreAndCloudSql().withClock(fakeClock).build();
@Test
public void testSaveAndLoad_success() {
@@ -125,6 +123,20 @@ public final class RegistryLockDaoTest {
assertThat(getRegistryLockByVerificationCode("hi").isPresent()).isFalse();
}
@Test
public void testByRevisionId_valid() {
RegistryLock lock = saveRegistryLock(createLock());
RegistryLock otherLock = getRegistryLockByRevisionId(lock.getRevisionId()).get();
// can't do direct comparison due to update time
assertThat(lock.getDomainName()).isEqualTo(otherLock.getDomainName());
assertThat(lock.getVerificationCode()).isEqualTo(otherLock.getVerificationCode());
}
@Test
public void testByRevisionId_invalid() {
assertThat(getRegistryLockByRevisionId(8675309L).isPresent()).isFalse();
}
@Test
public void testLoad_lockedDomains_byRegistrarId() {
RegistryLock lock = createLock();
@@ -196,6 +208,30 @@ public final class RegistryLockDaoTest {
assertThat(mostRecent.isPresent()).isFalse();
}
@Test
public void testLoad_verifiedUnlock_byRepoId() {
RegistryLock lock =
saveRegistryLock(
createLock()
.asBuilder()
.setLockCompletionTimestamp(fakeClock.nowUtc())
.setUnlockRequestTimestamp(fakeClock.nowUtc())
.setUnlockCompletionTimestamp(fakeClock.nowUtc())
.build());
Optional<RegistryLock> mostRecent = getMostRecentUnlockedRegistryLockByRepoId(lock.getRepoId());
assertThat(mostRecent.get().getRevisionId()).isEqualTo(lock.getRevisionId());
}
@Test
public void testLoad_verifiedUnlock_empty() {
RegistryLock completedLock =
createLock().asBuilder().setLockCompletionTimestamp(fakeClock.nowUtc()).build();
saveRegistryLock(completedLock);
assertThat(getMostRecentUnlockedRegistryLockByRepoId(completedLock.getRepoId()).isPresent())
.isFalse();
}
private RegistryLock createLock() {
return new RegistryLock.Builder()
.setRepoId("repoId")
@@ -112,30 +112,24 @@ public class RegistryTest extends EntityTestCase {
@Test
public void testSettingNumDnsPublishShards() {
Registry registry =
Registry.get("tld").asBuilder().setNumDnsPublishLocks(2).build();
Registry registry = Registry.get("tld").asBuilder().setNumDnsPublishLocks(2).build();
assertThat(registry.getNumDnsPublishLocks()).isEqualTo(2);
}
@Test
public void testSetReservedList_doesntMutateExistingRegistry() {
ReservedList rl15 = persistReservedList(
"tld-reserved15",
"potato,FULLY_BLOCKED",
"phone,FULLY_BLOCKED");
ReservedList rl16 = persistReservedList(
"tld-reserved16",
"port,FULLY_BLOCKED",
"manteau,FULLY_BLOCKED");
ReservedList rl15 =
persistReservedList("tld-reserved15", "potato,FULLY_BLOCKED", "phone,FULLY_BLOCKED");
ReservedList rl16 =
persistReservedList("tld-reserved16", "port,FULLY_BLOCKED", "manteau,FULLY_BLOCKED");
Registry registry1 =
newRegistry("propter", "PROPTER")
.asBuilder()
.setReservedLists(ImmutableSet.of(rl15))
.build();
assertThat(registry1.getReservedLists()).hasSize(1);
Registry registry2 = registry1.asBuilder()
.setReservedLists(ImmutableSet.of(rl15, rl16))
.build();
Registry registry2 =
registry1.asBuilder().setReservedLists(ImmutableSet.of(rl15, rl16)).build();
assertThat(registry1.getReservedLists()).hasSize(1);
assertThat(registry2.getReservedLists()).hasSize(2);
}
@@ -162,16 +156,12 @@ public class RegistryTest extends EntityTestCase {
@Test
public void testSetReservedLists() {
ReservedList rl5 = persistReservedList(
"tld-reserved5",
"lol,FULLY_BLOCKED",
"cat,FULLY_BLOCKED");
ReservedList rl6 = persistReservedList(
"tld-reserved6",
"hammock,FULLY_BLOCKED",
"mouse,FULLY_BLOCKED");
Registry r = Registry.get("tld")
.asBuilder().setReservedLists(ImmutableSet.of(rl5, rl6)).build();
ReservedList rl5 =
persistReservedList("tld-reserved5", "lol,FULLY_BLOCKED", "cat,FULLY_BLOCKED");
ReservedList rl6 =
persistReservedList("tld-reserved6", "hammock,FULLY_BLOCKED", "mouse,FULLY_BLOCKED");
Registry r =
Registry.get("tld").asBuilder().setReservedLists(ImmutableSet.of(rl5, rl6)).build();
assertThat(r.getReservedLists().stream().map(Key::getName))
.containsExactly("tld-reserved5", "tld-reserved6");
r = Registry.get("tld").asBuilder().setReservedLists(ImmutableSet.of()).build();
@@ -180,19 +170,13 @@ public class RegistryTest extends EntityTestCase {
@Test
public void testSetReservedListsByName() {
persistReservedList(
"tld-reserved24",
"lol,FULLY_BLOCKED",
"cat,FULLY_BLOCKED");
persistReservedList(
"tld-reserved25",
"mit,FULLY_BLOCKED",
"tim,FULLY_BLOCKED");
Registry r = Registry
.get("tld")
.asBuilder()
.setReservedListsByName(ImmutableSet.of("tld-reserved24", "tld-reserved25"))
.build();
persistReservedList("tld-reserved24", "lol,FULLY_BLOCKED", "cat,FULLY_BLOCKED");
persistReservedList("tld-reserved25", "mit,FULLY_BLOCKED", "tim,FULLY_BLOCKED");
Registry r =
Registry.get("tld")
.asBuilder()
.setReservedListsByName(ImmutableSet.of("tld-reserved24", "tld-reserved25"))
.build();
assertThat(r.getReservedLists().stream().map(Key::getName))
.containsExactly("tld-reserved24", "tld-reserved25");
r = Registry.get("tld").asBuilder().setReservedListsByName(ImmutableSet.of()).build();
@@ -232,9 +216,11 @@ public class RegistryTest extends EntityTestCase {
@Test
public void testPdtLooksLikeGa() {
Registry registry = Registry.get("tld").asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, TldState.PDT))
.build();
Registry registry =
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(ImmutableSortedMap.of(START_OF_TIME, TldState.PDT))
.build();
assertThat(registry.getTldState(START_OF_TIME)).isEqualTo(GENERAL_AVAILABILITY);
}
@@ -246,71 +232,83 @@ public class RegistryTest extends EntityTestCase {
.setTldStateTransitions(
ImmutableSortedMap.<DateTime, TldState>naturalOrder()
.put(START_OF_TIME, PREDELEGATION)
.put(clock.nowUtc().plusMonths(1), START_DATE_SUNRISE)
.put(clock.nowUtc().plusMonths(2), QUIET_PERIOD)
.put(clock.nowUtc().plusMonths(3), GENERAL_AVAILABILITY)
.put(fakeClock.nowUtc().plusMonths(1), START_DATE_SUNRISE)
.put(fakeClock.nowUtc().plusMonths(2), QUIET_PERIOD)
.put(fakeClock.nowUtc().plusMonths(3), GENERAL_AVAILABILITY)
.build())
.build();
assertThat(registry.getTldState(clock.nowUtc())).isEqualTo(PREDELEGATION);
assertThat(registry.getTldState(clock.nowUtc().plusMillis(1))).isEqualTo(PREDELEGATION);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(1).minusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc())).isEqualTo(PREDELEGATION);
assertThat(registry.getTldState(fakeClock.nowUtc().plusMillis(1))).isEqualTo(PREDELEGATION);
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(1).minusMillis(1)))
.isEqualTo(PREDELEGATION);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(1))).isEqualTo(START_DATE_SUNRISE);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(1).plusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(1)))
.isEqualTo(START_DATE_SUNRISE);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(2).minusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(1).plusMillis(1)))
.isEqualTo(START_DATE_SUNRISE);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(2))).isEqualTo(QUIET_PERIOD);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(2).plusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(2).minusMillis(1)))
.isEqualTo(START_DATE_SUNRISE);
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(2))).isEqualTo(QUIET_PERIOD);
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(2).plusMillis(1)))
.isEqualTo(QUIET_PERIOD);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(3).minusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(3).minusMillis(1)))
.isEqualTo(QUIET_PERIOD);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(3))).isEqualTo(GENERAL_AVAILABILITY);
assertThat(registry.getTldState(clock.nowUtc().plusMonths(3).plusMillis(1)))
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(3)))
.isEqualTo(GENERAL_AVAILABILITY);
assertThat(registry.getTldState(fakeClock.nowUtc().plusMonths(3).plusMillis(1)))
.isEqualTo(GENERAL_AVAILABILITY);
assertThat(registry.getTldState(END_OF_TIME)).isEqualTo(GENERAL_AVAILABILITY);
}
@Test
public void testQuietPeriodCanAppearMultipleTimesAnywhere() {
Registry.get("tld").asBuilder()
.setTldStateTransitions(ImmutableSortedMap.<DateTime, TldState>naturalOrder()
.put(START_OF_TIME, PREDELEGATION)
.put(clock.nowUtc().plusMonths(1), QUIET_PERIOD)
.put(clock.nowUtc().plusMonths(2), START_DATE_SUNRISE)
.put(clock.nowUtc().plusMonths(3), QUIET_PERIOD)
.put(clock.nowUtc().plusMonths(6), GENERAL_AVAILABILITY)
.build())
Registry.get("tld")
.asBuilder()
.setTldStateTransitions(
ImmutableSortedMap.<DateTime, TldState>naturalOrder()
.put(START_OF_TIME, PREDELEGATION)
.put(fakeClock.nowUtc().plusMonths(1), QUIET_PERIOD)
.put(fakeClock.nowUtc().plusMonths(2), START_DATE_SUNRISE)
.put(fakeClock.nowUtc().plusMonths(3), QUIET_PERIOD)
.put(fakeClock.nowUtc().plusMonths(6), GENERAL_AVAILABILITY)
.build())
.build();
}
@Test
public void testRenewBillingCostTransitionTimes() {
Registry registry = Registry.get("tld").asBuilder()
.setRenewBillingCostTransitions(ImmutableSortedMap.of(
START_OF_TIME, Money.of(USD, 8),
clock.nowUtc(), Money.of(USD, 1),
clock.nowUtc().plusMonths(1), Money.of(USD, 2),
clock.nowUtc().plusMonths(2), Money.of(USD, 3))).build();
Registry registry =
Registry.get("tld")
.asBuilder()
.setRenewBillingCostTransitions(
ImmutableSortedMap.of(
START_OF_TIME,
Money.of(USD, 8),
fakeClock.nowUtc(),
Money.of(USD, 1),
fakeClock.nowUtc().plusMonths(1),
Money.of(USD, 2),
fakeClock.nowUtc().plusMonths(2),
Money.of(USD, 3)))
.build();
assertThat(registry.getStandardRenewCost(START_OF_TIME)).isEqualTo(Money.of(USD, 8));
assertThat(registry.getStandardRenewCost(clock.nowUtc().minusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().minusMillis(1)))
.isEqualTo(Money.of(USD, 8));
assertThat(registry.getStandardRenewCost(clock.nowUtc())).isEqualTo(Money.of(USD, 1));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 1));
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMillis(1)))
.isEqualTo(Money.of(USD, 1));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(1).minusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(1).minusMillis(1)))
.isEqualTo(Money.of(USD, 1));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(1)))
.isEqualTo(Money.of(USD, 2));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(1).plusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(1).plusMillis(1)))
.isEqualTo(Money.of(USD, 2));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(2).minusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(2).minusMillis(1)))
.isEqualTo(Money.of(USD, 2));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(2)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(2)))
.isEqualTo(Money.of(USD, 3));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(2).plusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(2).plusMillis(1)))
.isEqualTo(Money.of(USD, 3));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMonths(3).minusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMonths(3).minusMillis(1)))
.isEqualTo(Money.of(USD, 3));
assertThat(registry.getStandardRenewCost(END_OF_TIME)).isEqualTo(Money.of(USD, 3));
}
@@ -320,10 +318,10 @@ public class RegistryTest extends EntityTestCase {
Registry registry = Registry.get("tld");
// The default value of 11 is set in createTld().
assertThat(registry.getStandardRenewCost(START_OF_TIME)).isEqualTo(Money.of(USD, 11));
assertThat(registry.getStandardRenewCost(clock.nowUtc().minusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().minusMillis(1)))
.isEqualTo(Money.of(USD, 11));
assertThat(registry.getStandardRenewCost(clock.nowUtc())).isEqualTo(Money.of(USD, 11));
assertThat(registry.getStandardRenewCost(clock.nowUtc().plusMillis(1)))
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc())).isEqualTo(Money.of(USD, 11));
assertThat(registry.getStandardRenewCost(fakeClock.nowUtc().plusMillis(1)))
.isEqualTo(Money.of(USD, 11));
assertThat(registry.getStandardRenewCost(END_OF_TIME)).isEqualTo(Money.of(USD, 11));
}
@@ -371,8 +369,8 @@ public class RegistryTest extends EntityTestCase {
.asBuilder()
.setTldStateTransitions(
ImmutableSortedMap.of(
clock.nowUtc(), GENERAL_AVAILABILITY,
clock.nowUtc().plusMonths(1), START_DATE_SUNRISE))
fakeClock.nowUtc(), GENERAL_AVAILABILITY,
fakeClock.nowUtc().plusMonths(1), START_DATE_SUNRISE))
.build());
}
@@ -385,8 +383,8 @@ public class RegistryTest extends EntityTestCase {
.asBuilder()
.setTldStateTransitions(
ImmutableSortedMap.of(
clock.nowUtc(), START_DATE_SUNRISE,
clock.nowUtc().plusMonths(1), START_DATE_SUNRISE))
fakeClock.nowUtc(), START_DATE_SUNRISE,
fakeClock.nowUtc().plusMonths(1), START_DATE_SUNRISE))
.build());
}
@@ -511,26 +509,29 @@ public class RegistryTest extends EntityTestCase {
@Test
public void testEapFee_undefined() {
assertThat(Registry.get("tld").getEapFeeFor(clock.nowUtc()).getCost())
assertThat(Registry.get("tld").getEapFeeFor(fakeClock.nowUtc()).getCost())
.isEqualTo(BigDecimal.ZERO.setScale(2, ROUND_UNNECESSARY));
}
@Test
public void testEapFee_specified() {
DateTime a = clock.nowUtc().minusDays(1);
DateTime b = clock.nowUtc().plusDays(1);
DateTime a = fakeClock.nowUtc().minusDays(1);
DateTime b = fakeClock.nowUtc().plusDays(1);
Registry registry =
Registry.get("tld").asBuilder().setEapFeeSchedule(
ImmutableSortedMap.of(
START_OF_TIME, Money.of(USD, 0),
a, Money.of(USD, 100),
b, Money.of(USD, 50))).build();
Registry.get("tld")
.asBuilder()
.setEapFeeSchedule(
ImmutableSortedMap.of(
START_OF_TIME, Money.of(USD, 0),
a, Money.of(USD, 100),
b, Money.of(USD, 50)))
.build();
assertThat(registry.getEapFeeFor(clock.nowUtc()).getCost())
assertThat(registry.getEapFeeFor(fakeClock.nowUtc()).getCost())
.isEqualTo(new BigDecimal("100.00"));
assertThat(registry.getEapFeeFor(clock.nowUtc().minusDays(2)).getCost())
assertThat(registry.getEapFeeFor(fakeClock.nowUtc().minusDays(2)).getCost())
.isEqualTo(BigDecimal.ZERO.setScale(2, ROUND_UNNECESSARY));
assertThat(registry.getEapFeeFor(clock.nowUtc().plusDays(2)).getCost())
assertThat(registry.getEapFeeFor(fakeClock.nowUtc().plusDays(2)).getCost())
.isEqualTo(new BigDecimal("50.00"));
}
@@ -36,7 +36,8 @@ public class GenrulePremiumListTest {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private static final String LISTS_DIRECTORY = "google/registry/config/files/premium/";
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
@Test
public void testParse_allPremiumLists() throws Exception {

Some files were not shown because too many files have changed in this diff Show More