From 1be9ccccc0678c913bf117e22682fdb0d9284c69 Mon Sep 17 00:00:00 2001 From: Martin Derka Date: Thu, 3 Mar 2016 10:22:52 -0800 Subject: [PATCH] Refactored change test. Fixed docs and formatting. Addressed remaining codacy issues. Added missing fails. --- .../gcloud/dns/testing/LocalDnsHelper.java | 77 +++--- .../gcloud/dns/testing/OptionParsers.java | 3 +- .../dns/testing/LocalDnsHelperTest.java | 258 ++++++++++-------- 3 files changed, 173 insertions(+), 165 deletions(-) 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..489b935d7e50 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); @@ -136,6 +200,7 @@ public void testCreateZone() { // create zone twice try { RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + fail("Zone already exists."); } catch (DnsException ex) { // expected assertEquals(409, ex.code()); @@ -325,81 +390,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 @@ -434,6 +435,7 @@ public void testCreateChange() { // non-existent zone try { RPC.applyChangeRequest(ZONE_NAME1, CHANGE1, EMPTY_RPC_OPTIONS); + fail("Zone was not created yet."); } catch (DnsException ex) { assertEquals(404, ex.code()); } @@ -580,10 +582,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 +719,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 +766,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 +896,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 +965,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 +984,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 +1057,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 +1305,7 @@ public void testCheckChange() { } @Test - public void testAdditionsMeetDeletions() { + public void testCheckAdditionsDeletions() { ResourceRecordSet validA = new ResourceRecordSet(); validA.setName(ZONE1.getDnsName()); validA.setType("A");