diff --git a/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/LocalDnsHelper.java b/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/LocalDnsHelper.java
index 3175e15f337c..4eca683f1a08 100644
--- a/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/LocalDnsHelper.java
+++ b/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/LocalDnsHelper.java
@@ -54,6 +54,7 @@
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -71,10 +72,11 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
/**
- * A utility to create local Google Cloud DNS mock.
+ * A local Google Cloud DNS mock.
*
*
The mock runs in a separate thread, listening for HTTP requests on the local machine at an
* ephemeral port.
@@ -82,7 +84,7 @@
*
While the mock attempts to simulate the service, there are some differences in the behaviour.
* The mock will accept any project ID and never returns a notFound or another error because of
* project ID. It assumes that all project IDs exist and that the user has all the necessary
- * privileges to manipulate any project. Similarly, the local simulation does not work with any
+ * privileges to manipulate any project. Similarly, the local simulation does not require
* verification of domain name ownership. Any request for creating a managed zone will be approved.
* The mock does not track quota and will allow the user to exceed it. The mock provides only basic
* validation of the DNS data for records of type A and AAAA. It does not validate any other record
@@ -98,12 +100,12 @@ public class LocalDnsHelper {
private static final Random ID_GENERATOR = new Random();
private static final String VERSION = "v1";
private static final String CONTEXT = "/dns/" + VERSION + "/projects";
- private static final Set SUPPORTED_COMPRESSION_ENCODINGS =
- ImmutableSet.of("gzip", "x-gzip");
+ private static final Set SUPPORTED_ENCODINGS = ImmutableSet.of("gzip", "x-gzip");
private static final List TYPES = ImmutableList.of("A", "AAAA", "CNAME", "MX", "NAPTR",
"NS", "PTR", "SOA", "SPF", "SRV", "TXT");
private static final TreeSet FORBIDDEN = Sets.newTreeSet(
ImmutableList.of("google.com.", "com.", "example.com.", "net.", "org."));
+ private static final Pattern ZONE_NAME_RE = Pattern.compile("[a-z][a-z0-9-]*");
static {
try {
@@ -265,12 +267,13 @@ private String toJson(String message) throws IOException {
private class RequestHandler implements HttpHandler {
private Response pickHandler(HttpExchange exchange, CallRegex regex) {
- String path = BASE_CONTEXT.relativize(exchange.getRequestURI()).getPath();
+ URI relative = BASE_CONTEXT.relativize(exchange.getRequestURI());
+ String path = relative.getPath();
String[] tokens = path.split("/");
String projectId = tokens.length > 0 ? tokens[0] : null;
String zoneName = tokens.length > 2 ? tokens[2] : null;
String changeId = tokens.length > 4 ? tokens[4] : null;
- String query = BASE_CONTEXT.relativize(exchange.getRequestURI()).getQuery();
+ String query = relative.getQuery();
switch (regex) {
case CHANGE_GET:
return getChange(projectId, zoneName, changeId, query);
@@ -315,7 +318,8 @@ public void handle(HttpExchange exchange) throws IOException {
}
}
writeResponse(exchange, Error.NOT_FOUND.response(String.format(
- "The url %s does not match any API call.", exchange.getRequestURI())));
+ "The url %s for %s method does not match any API call.",
+ requestMethod, exchange.getRequestURI())));
}
/**
@@ -323,7 +327,6 @@ public void handle(HttpExchange exchange) throws IOException {
*/
private Response handleChangeCreate(HttpExchange exchange, String projectId, String zoneName,
String query) throws IOException {
- String[] fields = OptionParsers.parseGetOptions(query);
String requestBody = decodeContent(exchange.getRequestHeaders(), exchange.getRequestBody());
Change change;
try {
@@ -332,6 +335,7 @@ private Response handleChangeCreate(HttpExchange exchange, String projectId, Str
return Error.REQUIRED.response(
"The 'entity.change' parameter is required but was missing.");
}
+ String[] fields = OptionParsers.parseGetOptions(query);
return createChange(projectId, zoneName, change, fields);
}
@@ -426,7 +430,7 @@ private static String decodeContent(Headers headers, InputStream inputStream) th
try {
if (contentEncoding != null && !contentEncoding.isEmpty()) {
String encoding = contentEncoding.get(0);
- if (SUPPORTED_COMPRESSION_ENCODINGS.contains(encoding)) {
+ if (SUPPORTED_ENCODINGS.contains(encoding)) {
input = new GZIPInputStream(inputStream);
} else if (!"identity".equals(encoding)) {
throw new IOException(
@@ -451,7 +455,7 @@ static Response toListResponse(List serializedObjects, String context, S
responseBody.append("{\"").append(context).append("\": [");
Joiner.on(",").appendTo(responseBody, serializedObjects);
responseBody.append(']');
- // add page token only if exists and is asked for
+ // add page token only if it exists and is asked for
if (pageToken != null && includePageToken) {
responseBody.append(",\"nextPageToken\": \"").append(pageToken).append('"');
}
@@ -506,9 +510,6 @@ static String getUniqueId(Set ids) {
do {
id = Long.toHexString(System.currentTimeMillis())
+ Long.toHexString(Math.abs(ID_GENERATOR.nextLong()));
- if (!ids.contains(id)) {
- return id;
- }
} while (ids.contains(id));
return id;
}
@@ -659,12 +660,10 @@ Response deleteZone(String projectId, String zoneName) {
*/
@VisibleForTesting
Response createZone(String projectId, ManagedZone zone, String... fields) {
- // check if the provided data is valid
Response errorResponse = checkZone(zone);
if (errorResponse != null) {
return errorResponse;
}
- // create a copy of the managed zone in order to avoid side effects
ManagedZone completeZone = new ManagedZone();
completeZone.setName(zone.getName());
completeZone.setDnsName(zone.getDnsName());
@@ -675,9 +674,7 @@ Response createZone(String projectId, ManagedZone zone, String... fields) {
completeZone.setId(BigInteger.valueOf(Math.abs(ID_GENERATOR.nextLong() % Long.MAX_VALUE)));
completeZone.setNameServers(randomNameservers());
ZoneContainer zoneContainer = new ZoneContainer(completeZone);
- // create the default NS and SOA records
zoneContainer.dnsRecords().set(defaultRecords(completeZone));
- // place the zone in the data collection
ProjectContainer projectContainer = findProject(projectId);
ZoneContainer oldValue = projectContainer.zones().putIfAbsent(
completeZone.getName(), zoneContainer);
@@ -685,7 +682,6 @@ Response createZone(String projectId, ManagedZone zone, String... fields) {
return Error.ALREADY_EXISTS.response(String.format(
"The resource 'entity.managedZone' named '%s' already exists", completeZone.getName()));
}
- // now return the desired attributes
ManagedZone result = OptionParsers.extractFields(completeZone, fields);
try {
return new Response(HTTP_OK, jsonFactory.toString(result));
@@ -704,13 +700,11 @@ Response createChange(String projectId, String zoneName, Change change, String..
return Error.NOT_FOUND.response(String.format(
"The 'parameters.managedZone' resource named %s does not exist.", zoneName));
}
- // check that the change to be applied is valid
Response response = checkChange(change, zoneContainer);
if (response != null) {
return response;
}
- // start applying
- Change completeChange = new Change(); // copy to avoid side effects
+ Change completeChange = new Change();
if (change.getAdditions() != null) {
completeChange.setAdditions(ImmutableList.copyOf(change.getAdditions()));
}
@@ -728,11 +722,11 @@ Response createChange(String projectId, String zoneName, Change change, String..
if (index == maxId) {
break;
}
- c.setId(String.valueOf(++index)); // indexing from 1
+ c.setId(String.valueOf(++index));
}
- completeChange.setStatus("pending"); // not finished yet
+ completeChange.setStatus("pending");
completeChange.setStartTime(ISODateTimeFormat.dateTime().withZoneUTC()
- .print(System.currentTimeMillis())); // accepted
+ .print(System.currentTimeMillis()));
invokeChange(projectId, zoneName, completeChange.getId());
Change result = OptionParsers.extractFields(completeChange, fields);
try {
@@ -813,7 +807,6 @@ private void applyExistingChange(String projectId, String zoneName, String chang
copy.put(id, rrset);
}
}
- // make it immutable and replace
boolean success = dnsRecords.compareAndSet(original, ImmutableSortedMap.copyOf(copy));
if (success) {
break; // success if no other thread modified the value in the meantime
@@ -824,7 +817,7 @@ private void applyExistingChange(String projectId, String zoneName, String chang
/**
* Lists zones. Next page token is the last listed zone name and is returned only of there is more
- * to list.
+ * to list and if the user does not exclude nextPageToken from field options.
*/
@VisibleForTesting
Response listZones(String projectId, String query) {
@@ -839,8 +832,8 @@ Response listZones(String projectId, String query) {
String pageToken = (String) options.get("pageToken");
Integer maxResults = options.get("maxResults") == null
? null : Integer.valueOf((String) options.get("maxResults"));
- boolean sizeReached = false; // maximum result size was reached, we should not return more
- boolean hasMorePages = false; // should next page token be included in the response?
+ boolean sizeReached = false;
+ boolean hasMorePages = false;
LinkedList serializedZones = new LinkedList<>();
String lastZoneName = null;
ConcurrentNavigableMap fragment =
@@ -859,20 +852,19 @@ Response listZones(String projectId, String query) {
OptionParsers.extractFields(zone, fields)));
} catch (IOException e) {
return Error.INTERNAL_ERROR.response(String.format(
- "Error when serializing managed zone %s in project %s", zone.getName(),
- projectId));
+ "Error when serializing managed zone %s in project %s", lastZoneName, projectId));
}
}
}
sizeReached = maxResults != null && maxResults.equals(serializedZones.size());
}
boolean includePageToken =
- hasMorePages && (fields == null || ImmutableList.copyOf(fields).contains("nextPageToken"));
+ hasMorePages && (fields == null || Arrays.asList(fields).contains("nextPageToken"));
return toListResponse(serializedZones, "managedZones", lastZoneName, includePageToken);
}
/**
- * Lists DNS records for a zone. Next page token is ID of the last record listed.
+ * Lists DNS records for a zone. Next page token is the ID of the last record listed.
*/
@VisibleForTesting
Response listDnsRecords(String projectId, String zoneName, String query) {
@@ -895,8 +887,8 @@ Response listDnsRecords(String projectId, String zoneName, String query) {
pageToken != null ? dnsRecords.tailMap(pageToken, false) : dnsRecords;
Integer maxResults = options.get("maxResults") == null
? null : Integer.valueOf((String) options.get("maxResults"));
- boolean sizeReached = false; // maximum result size was reached, we should not return more
- boolean hasMorePages = false; // should next page token be included in the response?
+ boolean sizeReached = false;
+ boolean hasMorePages = false;
LinkedList serializedRrsets = new LinkedList<>();
String lastRecordId = null;
for (String recordId : fragment.keySet()) {
@@ -921,12 +913,12 @@ Response listDnsRecords(String projectId, String zoneName, String query) {
sizeReached = maxResults != null && maxResults.equals(serializedRrsets.size());
}
boolean includePageToken =
- hasMorePages && (fields == null || ImmutableList.copyOf(fields).contains("nextPageToken"));
+ hasMorePages && (fields == null || Arrays.asList(fields).contains("nextPageToken"));
return toListResponse(serializedRrsets, "rrsets", lastRecordId, includePageToken);
}
/**
- * Lists changes. Next page token is ID of the last change listed.
+ * Lists changes. Next page token is the ID of the last change listed.
*/
@VisibleForTesting
Response listChanges(String projectId, String zoneName, String query) {
@@ -952,7 +944,7 @@ Response listChanges(String projectId, String zoneName, String query) {
String pageToken = (String) options.get("pageToken");
Integer maxResults = options.get("maxResults") == null
? null : Integer.valueOf((String) options.get("maxResults"));
- // we are not reading sortBy as the only key is the change sequence
+ // as the only supported field is change sequence, we are not reading sortBy
NavigableSet keys;
if ("descending".equals(sortOrder)) {
keys = changes.descendingKeySet();
@@ -968,8 +960,8 @@ Response listChanges(String projectId, String zoneName, String query) {
keys = from != null ? keys.tailSet(from, false) : keys;
NavigableMap fragment =
from != null && changes.containsKey(from) ? changes.tailMap(from, false) : changes;
- boolean sizeReached = false; // maximum result size was reached, we should not return more
- boolean hasMorePages = false; // should next page token be included in the response?
+ boolean sizeReached = false;
+ boolean hasMorePages = false;
LinkedList serializedResults = new LinkedList<>();
String lastChangeId = null;
for (Integer key : keys) {
@@ -986,13 +978,13 @@ Response listChanges(String projectId, String zoneName, String query) {
} catch (IOException e) {
return Error.INTERNAL_ERROR.response(String.format(
"Error when serializing change %s in managed zone %s in project %s",
- change.getId(), zoneName, projectId));
+ lastChangeId, zoneName, projectId));
}
}
sizeReached = maxResults != null && maxResults.equals(serializedResults.size());
}
boolean includePageToken =
- hasMorePages && (fields == null || ImmutableList.copyOf(fields).contains("nextPageToken"));
+ hasMorePages && (fields == null || Arrays.asList(fields).contains("nextPageToken"));
return toListResponse(serializedResults, "changes", lastChangeId, includePageToken);
}
@@ -1019,7 +1011,8 @@ private static Response checkZone(ManagedZone zone) {
} catch (NumberFormatException ex) {
// expected
}
- if (zone.getName().isEmpty()) {
+ if (zone.getName().isEmpty() || zone.getName().length() > 32
+ || !ZONE_NAME_RE.matcher(zone.getName()).matches()) {
return Error.INVALID.response(
String.format("Invalid value for 'entity.managedZone.name': '%s'", zone.getName()));
}
diff --git a/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/OptionParsers.java b/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/OptionParsers.java
index dcebf81350ad..ecd7e8179efe 100644
--- a/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/OptionParsers.java
+++ b/gcloud-java-dns/src/main/java/com/google/gcloud/dns/testing/OptionParsers.java
@@ -163,7 +163,7 @@ static Project extractFields(Project fullProject, String... fields) {
}
static ResourceRecordSet extractFields(ResourceRecordSet fullRecord, String... fields) {
- if (fields == null) {
+ if (fields == null || fields.length == 0) {
return fullRecord;
}
ResourceRecordSet record = new ResourceRecordSet();
@@ -196,7 +196,6 @@ static Map parseListChangesOptions(String query) {
String[] argEntry = arg.split("=");
switch (argEntry[0]) {
case "fields":
- // todo we do not support fragmentation in deletions and additions in the library
String replaced = argEntry[1].replace("changes(", ",").replace(")", ",");
options.put("fields", replaced.split(",")); // empty strings will be ignored
break;
diff --git a/gcloud-java-dns/src/test/java/com/google/gcloud/dns/testing/LocalDnsHelperTest.java b/gcloud-java-dns/src/test/java/com/google/gcloud/dns/testing/LocalDnsHelperTest.java
index 2dfb6c05c27e..59b3a46c1cba 100644
--- a/gcloud-java-dns/src/test/java/com/google/gcloud/dns/testing/LocalDnsHelperTest.java
+++ b/gcloud-java-dns/src/test/java/com/google/gcloud/dns/testing/LocalDnsHelperTest.java
@@ -30,7 +30,6 @@
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Lists;
import com.google.gcloud.dns.DnsException;
import com.google.gcloud.spi.DefaultDnsRpc;
@@ -43,6 +42,7 @@
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -55,8 +55,8 @@ public class LocalDnsHelperTest {
private static final ResourceRecordSet RRSET_KEEP = new ResourceRecordSet();
private static final String PROJECT_ID1 = "2135436541254";
private static final String PROJECT_ID2 = "882248761325";
- private static final String ZONE_NAME1 = "my little zone";
- private static final String ZONE_NAME2 = "another zone name";
+ private static final String ZONE_NAME1 = "my-little-zone";
+ private static final String ZONE_NAME2 = "another-zone-name";
private static final ManagedZone ZONE1 = new ManagedZone();
private static final ManagedZone ZONE2 = new ManagedZone();
private static final String DNS_NAME = "www.example.com.";
@@ -66,8 +66,7 @@ public class LocalDnsHelperTest {
private static final Change CHANGE_COMPLEX = new Change();
private static final LocalDnsHelper LOCAL_DNS_HELPER = LocalDnsHelper.create(0L); // synchronous
private static final Map EMPTY_RPC_OPTIONS = ImmutableMap.of();
- private static final DnsRpc RPC =
- new DefaultDnsRpc(LOCAL_DNS_HELPER.options());
+ private static final DnsRpc RPC = new DefaultDnsRpc(LOCAL_DNS_HELPER.options());
private static final String REAL_PROJECT_ID = LOCAL_DNS_HELPER.options().projectId();
private Map optionsMap;
@@ -104,15 +103,76 @@ public void setUp() {
optionsMap = new HashMap<>();
}
+ @AfterClass
+ public static void after() {
+ LOCAL_DNS_HELPER.stop();
+ }
+
private static void resetProjects() {
for (String project : LOCAL_DNS_HELPER.projects().keySet()) {
LOCAL_DNS_HELPER.projects().remove(project);
}
}
- @AfterClass
- public static void after() {
- LOCAL_DNS_HELPER.stop();
+ private static void assertEqChangesIgnoreStatus(Change expected, Change actual) {
+ assertEquals(expected.getAdditions(), actual.getAdditions());
+ assertEquals(expected.getDeletions(), actual.getDeletions());
+ assertEquals(expected.getId(), actual.getId());
+ assertEquals(expected.getStartTime(), actual.getStartTime());
+ }
+
+ private static void waitUntilComplete(DnsRpc rpc, String zoneName, String changeId) {
+ while (true) {
+ Change change = rpc.getChangeRequest(zoneName, changeId, EMPTY_RPC_OPTIONS);
+ if ("done".equals(change.getStatus())) {
+ return;
+ }
+ try {
+ Thread.sleep(50L);
+ } catch (InterruptedException e) {
+ fail("Thread was interrupted while waiting for change processing.");
+ }
+ }
+ }
+
+ private static void executeCreateAndApplyChangeTest(DnsRpc rpc) {
+ rpc.create(ZONE1, EMPTY_RPC_OPTIONS);
+ assertNull(rpc.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
+ // add
+ Change createdChange = rpc.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS);
+ assertEquals(createdChange.getAdditions(), CHANGE1.getAdditions());
+ assertEquals(createdChange.getDeletions(), CHANGE1.getDeletions());
+ assertNotNull(createdChange.getStartTime());
+ assertEquals("1", createdChange.getId());
+ Change retrievedChange = rpc.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS);
+ assertEqChangesIgnoreStatus(createdChange, retrievedChange);
+ assertNull(rpc.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
+ waitUntilComplete(rpc, ZONE1.getName(), "1"); // necessary for the following to return 409
+ try {
+ rpc.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS);
+ fail();
+ } catch (DnsException ex) {
+ assertEquals(409, ex.code());
+ }
+ assertNotNull(rpc.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
+ assertNull(rpc.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
+ // delete
+ rpc.applyChangeRequest(ZONE1.getName(), CHANGE2, EMPTY_RPC_OPTIONS);
+ assertNotNull(rpc.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
+ assertNotNull(rpc.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
+ waitUntilComplete(rpc, ZONE1.getName(), "2");
+ rpc.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS);
+ waitUntilComplete(rpc, ZONE1.getName(), "3");
+ Iterable results =
+ rpc.listDnsRecords(ZONE1.getName(), EMPTY_RPC_OPTIONS).results();
+ boolean ok = false;
+ for (ResourceRecordSet dnsRecord : results) {
+ if (dnsRecord.getName().equals(RRSET_KEEP.getName())
+ && dnsRecord.getType().equals(RRSET_KEEP.getType())) {
+ ok = true;
+ }
+ }
+ assertTrue(ok);
}
@Test
@@ -121,7 +181,11 @@ public void testCreateZone() {
// check that default records were created
DnsRpc.ListResult listResult
= RPC.listDnsRecords(ZONE1.getName(), EMPTY_RPC_OPTIONS);
- assertEquals(2, Lists.newLinkedList(listResult.results()).size());
+ ImmutableList defaultTypes = ImmutableList.of("SOA", "NS");
+ Iterator iterator = listResult.results().iterator();
+ assertTrue(defaultTypes.contains(iterator.next().getType()));
+ assertTrue(defaultTypes.contains(iterator.next().getType()));
+ assertFalse(iterator.hasNext());
assertEquals(created, LOCAL_DNS_HELPER.findZone(REAL_PROJECT_ID, ZONE1.getName()).zone());
ManagedZone zone = RPC.getZone(ZONE_NAME1, EMPTY_RPC_OPTIONS);
assertEquals(created, zone);
@@ -325,81 +389,17 @@ public void testDeleteZone() {
}
@Test
- public void testCreateAndApplyChangeWithThreads() {
- LocalDnsHelper localDnsThreaded = LocalDnsHelper.create(50L); // using threads here
- localDnsThreaded.createZone(PROJECT_ID1, ZONE1);
- assertNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("1"));
- LocalDnsHelper.Response response =
- localDnsThreaded.createChange(PROJECT_ID1, ZONE_NAME1, CHANGE1); // add
- assertEquals(200, response.code());
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("1"));
- assertNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("2"));
- localDnsThreaded.createChange(PROJECT_ID1, ZONE_NAME1, CHANGE1); // add
- response = localDnsThreaded.createChange(PROJECT_ID1, ZONE_NAME1, CHANGE1); // add
- assertEquals(200, response.code());
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("1"));
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("2"));
- localDnsThreaded.createChange(PROJECT_ID1, ZONE_NAME1, CHANGE2); // delete
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("1"));
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("2"));
- assertNotNull(localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).findChange("3"));
- localDnsThreaded.createChange(PROJECT_ID1, ZONE_NAME1, CHANGE_KEEP);
- // check execution
- Change change = localDnsThreaded.findChange(PROJECT_ID1, ZONE_NAME1, "4");
- for (int i = 0; i < 10 && !change.getStatus().equals("done"); i++) {
- // change has not been finished yet; wait at most 5 seconds
- // it takes 5O ms for the thread to kick in in the first place
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- fail("Test was interrupted");
- }
- }
- assertEquals("done", change.getStatus());
- ImmutableSortedMap list =
- localDnsThreaded.findZone(PROJECT_ID1, ZONE_NAME1).dnsRecords().get();
- assertTrue(list.containsValue(RRSET_KEEP));
- localDnsThreaded.stop();
+ public void testCreateAndApplyChange() {
+ executeCreateAndApplyChangeTest(RPC);
}
@Test
- public void testCreateAndApplyChange() {
- // not using threads
- RPC.create(ZONE1, EMPTY_RPC_OPTIONS);
- assertNull(RPC.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
- // add
- Change createdChange = RPC.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS);
- assertEquals(createdChange.getAdditions(), CHANGE1.getAdditions());
- assertEquals(createdChange.getDeletions(), CHANGE1.getDeletions());
- assertNotNull(createdChange.getStartTime());
- assertEquals("1", createdChange.getId());
- Change retrievedChange = RPC.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS);
- assertEquals(createdChange, retrievedChange);
- assertNull(RPC.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
- try {
- RPC.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS);
- fail();
- } catch (DnsException ex) {
- assertEquals(409, ex.code());
- }
- assertNotNull(RPC.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
- assertNull(RPC.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
- // delete
- RPC.applyChangeRequest(ZONE1.getName(), CHANGE2, EMPTY_RPC_OPTIONS);
- assertNotNull(RPC.getChangeRequest(ZONE1.getName(), "1", EMPTY_RPC_OPTIONS));
- assertNotNull(RPC.getChangeRequest(ZONE1.getName(), "2", EMPTY_RPC_OPTIONS));
- Change last = RPC.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS);
- assertEquals("done", last.getStatus());
- Iterable results =
- RPC.listDnsRecords(ZONE1.getName(), EMPTY_RPC_OPTIONS).results();
- boolean ok = false;
- for (ResourceRecordSet dnsRecord : results) {
- if (dnsRecord.getName().equals(RRSET_KEEP.getName())
- && dnsRecord.getType().equals(RRSET_KEEP.getType())) {
- ok = true;
- }
- }
- assertTrue(ok);
+ public void testCreateAndApplyChangeWithThreads() {
+ LocalDnsHelper localDnsThreaded = LocalDnsHelper.create(50L);
+ localDnsThreaded.start();
+ DnsRpc rpc = new DefaultDnsRpc(localDnsThreaded.options());
+ executeCreateAndApplyChangeTest(rpc);
+ localDnsThreaded.stop();
}
@Test
@@ -580,10 +580,10 @@ public void testListZones() {
}
// ok size
options = new HashMap<>();
- options.put(DnsRpc.Option.PAGE_SIZE, 1);
+ options.put(DnsRpc.Option.PAGE_SIZE, 335);
results = RPC.listZones(options).results();
zones = ImmutableList.copyOf(results);
- assertEquals(1, zones.size());
+ assertEquals(2, zones.size());
// dns name problems
options = new HashMap<>();
options.put(DnsRpc.Option.DNS_NAME, "aaa");
@@ -717,10 +717,6 @@ public void testListDnsRecords() {
assertEquals(400, ex.code());
assertTrue(ex.getMessage().contains("parameters.maxResults"));
}
- options.put(DnsRpc.Option.PAGE_SIZE, 1);
- results = RPC.listDnsRecords(ZONE1.getName(), options).results();
- records = ImmutableList.copyOf(results);
- assertEquals(1, records.size());
options.put(DnsRpc.Option.PAGE_SIZE, 15);
results = RPC.listDnsRecords(ZONE1.getName(), options).results();
records = ImmutableList.copyOf(results);
@@ -768,62 +764,62 @@ public void testListDnsRecords() {
// field options
options = new HashMap<>();
options.put(DnsRpc.Option.FIELDS, "rrsets(name)");
- DnsRpc.ListResult resourceRecordSetListResult =
+ DnsRpc.ListResult listResult =
RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ records = ImmutableList.copyOf(listResult.results());
ResourceRecordSet record = records.get(0);
assertNotNull(record.getName());
assertNull(record.getRrdatas());
assertNull(record.getType());
assertNull(record.getTtl());
- assertNull(resourceRecordSetListResult.pageToken());
+ assertNull(listResult.pageToken());
options.put(DnsRpc.Option.FIELDS, "rrsets(rrdatas)");
- resourceRecordSetListResult = RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ records = ImmutableList.copyOf(listResult.results());
record = records.get(0);
assertNull(record.getName());
assertNotNull(record.getRrdatas());
assertNull(record.getType());
assertNull(record.getTtl());
- assertNull(resourceRecordSetListResult.pageToken());
+ assertNull(listResult.pageToken());
options.put(DnsRpc.Option.FIELDS, "rrsets(ttl)");
- resourceRecordSetListResult = RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ records = ImmutableList.copyOf(listResult.results());
record = records.get(0);
assertNull(record.getName());
assertNull(record.getRrdatas());
assertNull(record.getType());
assertNotNull(record.getTtl());
- assertNull(resourceRecordSetListResult.pageToken());
+ assertNull(listResult.pageToken());
options.put(DnsRpc.Option.FIELDS, "rrsets(type)");
- resourceRecordSetListResult = RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ records = ImmutableList.copyOf(listResult.results());
record = records.get(0);
assertNull(record.getName());
assertNull(record.getRrdatas());
assertNotNull(record.getType());
assertNull(record.getTtl());
- assertNull(resourceRecordSetListResult.pageToken());
+ assertNull(listResult.pageToken());
options.put(DnsRpc.Option.FIELDS, "nextPageToken");
- resourceRecordSetListResult = RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ records = ImmutableList.copyOf(listResult.results());
record = records.get(0);
assertNull(record.getName());
assertNull(record.getRrdatas());
assertNull(record.getType());
assertNull(record.getTtl());
- assertNull(resourceRecordSetListResult.pageToken());
+ assertNull(listResult.pageToken());
options.put(DnsRpc.Option.FIELDS, "nextPageToken,rrsets(name,rrdatas)");
options.put(DnsRpc.Option.PAGE_SIZE, 1);
- resourceRecordSetListResult = RPC.listDnsRecords(ZONE1.getName(), options);
- records = ImmutableList.copyOf(resourceRecordSetListResult.results());
+ listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ records = ImmutableList.copyOf(listResult.results());
assertEquals(1, records.size());
record = records.get(0);
assertNotNull(record.getName());
assertNotNull(record.getRrdatas());
assertNull(record.getType());
assertNull(record.getTtl());
- assertNotNull(resourceRecordSetListResult.pageToken());
+ assertNotNull(listResult.pageToken());
}
@Test
@@ -898,8 +894,7 @@ public void testListChanges() {
options = new HashMap<>();
options.put(DnsRpc.Option.SORTING_ORDER, "descending");
options.put(DnsRpc.Option.FIELDS, "changes(additions)");
- DnsRpc.ListResult changeListResult =
- RPC.listChangeRequests(ZONE1.getName(), options);
+ DnsRpc.ListResult changeListResult = RPC.listChangeRequests(ZONE1.getName(), options);
changes = ImmutableList.copyOf(changeListResult.results());
Change complex = changes.get(0);
assertNotNull(complex.getAdditions());
@@ -968,10 +963,8 @@ public void testDnsRecordPaging() {
RPC.listDnsRecords(ZONE1.getName(), EMPTY_RPC_OPTIONS).results());
Map options = new HashMap<>();
options.put(DnsRpc.Option.PAGE_SIZE, 1);
- DnsRpc.ListResult listResult =
- RPC.listDnsRecords(ZONE1.getName(), options);
- ImmutableList records =
- ImmutableList.copyOf(listResult.results());
+ DnsRpc.ListResult listResult = RPC.listDnsRecords(ZONE1.getName(), options);
+ ImmutableList records = ImmutableList.copyOf(listResult.results());
assertEquals(1, records.size());
assertEquals(complete.get(0), records.get(0));
options.put(DnsRpc.Option.PAGE_TOKEN, listResult.pageToken());
@@ -989,17 +982,17 @@ public void testZonePaging() {
RPC.listZones(EMPTY_RPC_OPTIONS).results());
Map options = new HashMap<>();
options.put(DnsRpc.Option.PAGE_SIZE, 1);
- DnsRpc.ListResult managedZoneListResult = RPC.listZones(options);
- ImmutableList page1 = ImmutableList.copyOf(managedZoneListResult.results());
+ DnsRpc.ListResult listResult = RPC.listZones(options);
+ ImmutableList page1 = ImmutableList.copyOf(listResult.results());
assertEquals(1, page1.size());
assertEquals(complete.get(0), page1.get(0));
- assertEquals(page1.get(0).getName(), managedZoneListResult.pageToken());
- options.put(DnsRpc.Option.PAGE_TOKEN, managedZoneListResult.pageToken());
- managedZoneListResult = RPC.listZones(options);
- ImmutableList page2 = ImmutableList.copyOf(managedZoneListResult.results());
+ assertEquals(page1.get(0).getName(), listResult.pageToken());
+ options.put(DnsRpc.Option.PAGE_TOKEN, listResult.pageToken());
+ listResult = RPC.listZones(options);
+ ImmutableList page2 = ImmutableList.copyOf(listResult.results());
assertEquals(1, page2.size());
assertEquals(complete.get(1), page2.get(0));
- assertNull(managedZoneListResult.pageToken());
+ assertNull(listResult.pageToken());
}
@Test
@@ -1062,9 +1055,30 @@ public void testCreateZoneValidation() {
response = LOCAL_DNS_HELPER.createZone(PROJECT_ID1, copy);
assertEquals(400, response.code());
assertTrue(response.body().contains("entity.managedZone.dnsName"));
- // zone name is a number
+ // zone name does not start with a letter
+ copy = copyZone(minimalZone);
+ copy.setName("1aaaaaa");
+ response = LOCAL_DNS_HELPER.createZone(PROJECT_ID1, copy);
+ assertEquals(400, response.code());
+ assertTrue(response.body().contains("entity.managedZone.name"));
+ assertTrue(response.body().contains("Invalid"));
+ // zone name is too long
+ copy = copyZone(minimalZone);
+ copy.setName("123456aaaa123456aaaa123456aaaa123456aaaa123456aaaa123456aaaa123456aaaa123456aa");
+ response = LOCAL_DNS_HELPER.createZone(PROJECT_ID1, copy);
+ assertEquals(400, response.code());
+ assertTrue(response.body().contains("entity.managedZone.name"));
+ assertTrue(response.body().contains("Invalid"));
+ // zone name contains invalid characters
+ copy = copyZone(minimalZone);
+ copy.setName("x1234AA6aa");
+ response = LOCAL_DNS_HELPER.createZone(PROJECT_ID1, copy);
+ assertEquals(400, response.code());
+ assertTrue(response.body().contains("entity.managedZone.name"));
+ assertTrue(response.body().contains("Invalid"));
+ // zone name contains invalid characters
copy = copyZone(minimalZone);
- copy.setName("123456");
+ copy.setName("x a");
response = LOCAL_DNS_HELPER.createZone(PROJECT_ID1, copy);
assertEquals(400, response.code());
assertTrue(response.body().contains("entity.managedZone.name"));
@@ -1289,7 +1303,7 @@ public void testCheckChange() {
}
@Test
- public void testAdditionsMeetDeletions() {
+ public void testCheckAdditionsDeletions() {
ResourceRecordSet validA = new ResourceRecordSet();
validA.setName(ZONE1.getDnsName());
validA.setType("A");