mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
mv com/google/domain/registry google/registry
This change renames directories in preparation for the great package rename. The repository is now in a broken state because the code itself hasn't been updated. However this should ensure that git correctly preserves history for each file.
This commit is contained in:
parent
a41677aea1
commit
5012893c1d
2396 changed files with 0 additions and 0 deletions
346
javatests/google/registry/testing/TaskQueueHelper.java
Normal file
346
javatests/google/registry/testing/TaskQueueHelper.java
Normal file
|
@ -0,0 +1,346 @@
|
|||
// Copyright 2016 The Domain Registry 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 com.google.domain.registry.testing;
|
||||
|
||||
import static com.google.appengine.tools.development.testing.LocalTaskQueueTestConfig.getLocalTaskQueue;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Predicates.in;
|
||||
import static com.google.common.base.Predicates.not;
|
||||
import static com.google.common.collect.Iterables.getFirst;
|
||||
import static com.google.common.collect.Iterables.transform;
|
||||
import static com.google.common.collect.Multisets.containsOccurrences;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assert_;
|
||||
import static com.google.domain.registry.util.DiffUtils.prettyPrintDeepDiff;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
import com.google.appengine.api.taskqueue.dev.QueueStateInfo;
|
||||
import com.google.appengine.api.taskqueue.dev.QueueStateInfo.HeaderWrapper;
|
||||
import com.google.appengine.api.taskqueue.dev.QueueStateInfo.TaskStateInfo;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableMultiset;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.domain.registry.dns.DnsConstants;
|
||||
|
||||
import org.joda.time.Duration;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/** Static utility functions for testing task queues. */
|
||||
public class TaskQueueHelper {
|
||||
|
||||
/**
|
||||
* Matcher to match against the tasks in the task queue. Fields that aren't set are not compared.
|
||||
*/
|
||||
public static class TaskMatcher implements Predicate<TaskStateInfo> {
|
||||
|
||||
MatchableTaskInfo expected = new MatchableTaskInfo();
|
||||
|
||||
public TaskMatcher taskName(String taskName) {
|
||||
expected.taskName = taskName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher url(String url) {
|
||||
expected.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher method(String method) {
|
||||
expected.method = method;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher payload(String payload) {
|
||||
checkState(
|
||||
expected.params.isEmpty(), "Cannot add a payload to a TaskMatcher with params.");
|
||||
expected.payload = payload;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher tag(String tag) {
|
||||
expected.tag = tag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher header(String name, String value) {
|
||||
// Lowercase for case-insensitive comparison.
|
||||
expected.headers.put(name.toLowerCase(), value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher param(String key, String value) {
|
||||
checkState(
|
||||
expected.payload == null, "Cannot add params to a TaskMatcher with a payload.");
|
||||
expected.params.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TaskMatcher etaDelta(Duration lowerBound, Duration upperBound) {
|
||||
checkState(!lowerBound.isShorterThan(Duration.ZERO), "lowerBound must be non-negative.");
|
||||
checkState(
|
||||
upperBound.isLongerThan(lowerBound), "upperBound must be greater than lowerBound.");
|
||||
expected.etaDeltaLowerBound = lowerBound.getStandardSeconds();
|
||||
expected.etaDeltaUpperBound = upperBound.getStandardSeconds();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if there are not more occurrences in {@code sub} of each of its entries
|
||||
* than there are in {@code super}.
|
||||
*/
|
||||
private static boolean containsEntries(
|
||||
Multimap<?, ?> superMultimap, Multimap<?, ?> subMultimap) {
|
||||
return containsOccurrences(
|
||||
ImmutableMultiset.copyOf(superMultimap.entries()),
|
||||
ImmutableMultiset.copyOf(subMultimap.entries()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the fields set on the current object match the given task info. This is not
|
||||
* quite the same contract as {@link #equals}, since it will ignore null fields.
|
||||
*
|
||||
* <p>Match fails if any headers or params expected on the TaskMatcher are not found on the
|
||||
* TaskStateInfo. Note that the inverse is not true (i.e. there may be extra headers on the
|
||||
* TaskStateInfo).
|
||||
*/
|
||||
@Override
|
||||
public boolean apply(@Nonnull TaskStateInfo info) {
|
||||
MatchableTaskInfo actual = new MatchableTaskInfo(info);
|
||||
return (expected.taskName == null || Objects.equals(expected.taskName, actual.taskName))
|
||||
&& (expected.url == null || Objects.equals(expected.url, actual.url))
|
||||
&& (expected.method == null || Objects.equals(expected.method, actual.method))
|
||||
&& (expected.payload == null || Objects.equals(expected.payload, actual.payload))
|
||||
&& (expected.tag == null || Objects.equals(expected.tag, actual.tag))
|
||||
&& (expected.etaDeltaLowerBound == null
|
||||
|| expected.etaDeltaLowerBound <= actual.etaDelta)
|
||||
&& (expected.etaDeltaUpperBound == null
|
||||
|| expected.etaDeltaUpperBound >= actual.etaDelta)
|
||||
&& containsEntries(actual.params, expected.params)
|
||||
&& containsEntries(actual.headers, expected.headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return Joiner.on('\n')
|
||||
.withKeyValueSeparator(":\n")
|
||||
.join(
|
||||
Maps.transformValues(
|
||||
expected.toMap(),
|
||||
new Function<Object, String>() {
|
||||
@Override
|
||||
public String apply(Object input) {
|
||||
return "\t" + String.valueOf(input).replaceAll("\n", "\n\t");
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the info object for the provided queue name. */
|
||||
public static QueueStateInfo getQueueInfo(String queueName) {
|
||||
return getLocalTaskQueue().getQueueStateInfo().get(queueName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the tasks in the named queue are exactly those with the expected property
|
||||
* values after being transformed with the provided property getter function.
|
||||
*/
|
||||
public static void assertTasksEnqueuedWithProperty(
|
||||
String queueName,
|
||||
Function<TaskStateInfo, String> propertyGetter,
|
||||
String... expectedTaskProperties) throws Exception {
|
||||
// Ordering is irrelevant but duplicates should be considered independently.
|
||||
assertThat(transform(getQueueInfo(queueName).getTaskInfo(), propertyGetter))
|
||||
.containsExactly((Object[]) expectedTaskProperties);
|
||||
}
|
||||
|
||||
/** Ensures that the tasks in the named queue are exactly those with the expected names. */
|
||||
public static void assertTasksEnqueued(String queueName, String... expectedTaskNames)
|
||||
throws Exception {
|
||||
Function<TaskStateInfo, String> nameGetter = new Function<TaskStateInfo, String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String apply(@Nonnull TaskStateInfo taskStateInfo) {
|
||||
return taskStateInfo.getTaskName();
|
||||
}};
|
||||
assertTasksEnqueuedWithProperty(queueName, nameGetter, expectedTaskNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the only tasks in the named queue are exactly those that match the expected
|
||||
* matchers.
|
||||
*/
|
||||
public static void assertTasksEnqueued(String queueName, TaskMatcher... taskMatchers)
|
||||
throws Exception {
|
||||
assertTasksEnqueued(queueName, Arrays.asList(taskMatchers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the only tasks in the named queue are exactly those that match the expected
|
||||
* matchers.
|
||||
*/
|
||||
public static void assertTasksEnqueued(String queueName, List<TaskMatcher> taskMatchers)
|
||||
throws Exception {
|
||||
QueueStateInfo qsi = getQueueInfo(queueName);
|
||||
assertThat(qsi.getTaskInfo()).hasSize(taskMatchers.size());
|
||||
LinkedList<TaskStateInfo> taskInfos = new LinkedList<>(qsi.getTaskInfo());
|
||||
for (final TaskMatcher taskMatcher : taskMatchers) {
|
||||
try {
|
||||
taskInfos.remove(Iterables.find(taskInfos, taskMatcher));
|
||||
} catch (NoSuchElementException e) {
|
||||
final Map<String, Object> taskMatcherMap = taskMatcher.expected.toMap();
|
||||
assert_().fail(
|
||||
"Task not found in queue %s:\n\n%s\n\nPotential candidate match diffs:\n\n%s",
|
||||
queueName,
|
||||
taskMatcher,
|
||||
FluentIterable.from(taskInfos)
|
||||
.transform(new Function<TaskStateInfo, String>() {
|
||||
@Override
|
||||
public String apply(TaskStateInfo input) {
|
||||
return prettyPrintDeepDiff(
|
||||
taskMatcherMap,
|
||||
Maps.filterKeys(
|
||||
new MatchableTaskInfo(input).toMap(),
|
||||
in(taskMatcherMap.keySet())));
|
||||
}})
|
||||
.join(Joiner.on('\n')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Empties the task queue. */
|
||||
public static void clearTaskQueue(String queueName) throws Exception {
|
||||
getLocalTaskQueue().flushQueue(queueName);
|
||||
}
|
||||
|
||||
/** Asserts at least one task exists in {@code queue}. */
|
||||
public static void assertAtLeastOneTaskIsEnqueued(String queue) throws Exception {
|
||||
assertThat(getQueueInfo(queue).getCountTasks()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
/** Ensures that the named queue contains no tasks. */
|
||||
public static void assertNoTasksEnqueued(String queueName) throws Exception {
|
||||
assertThat(getQueueInfo(queueName).getCountTasks()).isEqualTo(0);
|
||||
}
|
||||
|
||||
/** Returns the value for the param on a task info, or empty if it is missing. */
|
||||
private static String getParamFromTaskInfo(TaskStateInfo taskInfo, String paramName) {
|
||||
return getFirst(UriParameters.parse(taskInfo.getBody()).get(paramName), "");
|
||||
}
|
||||
|
||||
/** Ensures that the DNS queue tasks are exactly those for the expected target names. */
|
||||
public static void assertDnsTasksEnqueued(String... expectedTaskTargetNames) throws Exception {
|
||||
assertTasksEnqueuedWithProperty(
|
||||
DnsConstants.DNS_PULL_QUEUE_NAME,
|
||||
new Function<TaskStateInfo, String>() {
|
||||
@Nonnull
|
||||
@Override
|
||||
public String apply(@Nonnull TaskStateInfo taskStateInfo) {
|
||||
return getParamFromTaskInfo(taskStateInfo, DnsConstants.DNS_TARGET_NAME_PARAM);
|
||||
}},
|
||||
expectedTaskTargetNames);
|
||||
}
|
||||
|
||||
/** Ensures that the DNS queue does not contain any tasks. */
|
||||
public static void assertNoDnsTasksEnqueued() throws Exception {
|
||||
assertNoTasksEnqueued(DnsConstants.DNS_PULL_QUEUE_NAME);
|
||||
}
|
||||
|
||||
/** An adapter to clean up a {@link TaskStateInfo} for ease of matching. */
|
||||
private static class MatchableTaskInfo {
|
||||
|
||||
String taskName;
|
||||
String method;
|
||||
String url;
|
||||
String payload;
|
||||
String tag;
|
||||
Double etaDelta;
|
||||
Long etaDeltaLowerBound;
|
||||
Long etaDeltaUpperBound;
|
||||
Multimap<String, String> headers = ArrayListMultimap.create();
|
||||
Multimap<String, String> params = ArrayListMultimap.create();
|
||||
|
||||
MatchableTaskInfo() {}
|
||||
|
||||
MatchableTaskInfo(TaskStateInfo info) {
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(info.getUrl());
|
||||
} catch (java.net.URISyntaxException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
this.taskName = info.getTaskName();
|
||||
this.method = info.getMethod();
|
||||
this.url = uri.getPath();
|
||||
this.payload = info.getBody();
|
||||
this.etaDelta = info.getEtaDelta();
|
||||
if (info.getTagAsBytes() != null) {
|
||||
this.tag = new String(info.getTagAsBytes(), UTF_8);
|
||||
}
|
||||
ImmutableMultimap.Builder<String, String> headerBuilder = ImmutableMultimap.builder();
|
||||
for (HeaderWrapper header : info.getHeaders()) {
|
||||
// Lowercase header name for comparison since HTTP
|
||||
// header names are case-insensitive.
|
||||
headerBuilder.put(header.getKey().toLowerCase(), header.getValue());
|
||||
}
|
||||
this.headers = headerBuilder.build();
|
||||
ImmutableMultimap.Builder<String, String> inputParams = new ImmutableMultimap.Builder<>();
|
||||
String query = uri.getQuery();
|
||||
if (query != null) {
|
||||
inputParams.putAll(UriParameters.parse(query));
|
||||
}
|
||||
if (headers.containsEntry(
|
||||
HttpHeaders.CONTENT_TYPE.toLowerCase(), MediaType.FORM_DATA.toString())) {
|
||||
inputParams.putAll(UriParameters.parse(info.getBody()));
|
||||
}
|
||||
this.params = inputParams.build();
|
||||
}
|
||||
|
||||
public Map<String, Object> toMap() {
|
||||
Map<String, Object> builder = new HashMap<>();
|
||||
builder.put("taskName", taskName);
|
||||
builder.put("url", url);
|
||||
builder.put("method", method);
|
||||
builder.put("headers", headers.asMap());
|
||||
builder.put("params", params.asMap());
|
||||
builder.put("payload", payload);
|
||||
builder.put("tag", tag);
|
||||
builder.put("etaDelta", etaDelta);
|
||||
builder.put("etaDeltaLowerBound", etaDeltaLowerBound);
|
||||
builder.put("etaDeltaUpperBound", etaDeltaUpperBound);
|
||||
return Maps.filterValues(builder, not(in(asList(null, "", Collections.EMPTY_MAP))));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue