static String getAvailableRegions = "<v01:getAvailableRegions />"; static String getAvailableRegionsResponse =
    "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
    + "<soap:Body>\n"
    + "      <ns1:getAvailableRegionsResponse xmlns:ns1=\"http://webservice.api.ultra.neustar.com/v01/\">\n"
    + "          <DirectionalDNSAvailableRegionList xmlns:ns2=\"http://schema.ultraservice.neustar.com/v01/\">\n"
    + "              <ns2:Region TerritoryName=\"Anonymous Proxy\" RegionName=\"Anonymous Proxy (A1)\" RegionID=\"14\" />\n"
    + "              <ns2:Region TerritoryName=\"Antarctica;Bouvet Island;French Southern Territories\" RegionName=\"Antarctica\" RegionID=\"3\" />\n"
    + "          </DirectionalDNSAvailableRegionList>\n"
    + "      </ns1:getAvailableRegionsResponse>\n"
    + "  </soap:Body>\n"
    + "</soap:Envelope>"; static String
    getDirectionalDNSGroupDetails =
    "<v01:getDirectionalDNSGroupDetails><GroupId>AAAAAAAAAAAAAAAA</GroupId></v01:getDirectionalDNSGroupDetails>"; static String getDirectionalDNSGroupDetailsResponseEurope = "<?xml version=\"1.0\"?>\n"
                                                            + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
                                                            + " <soap:Body>\n"
                                                            + "         <ns1:getDirectionalDNSGroupDetailsResponseEurope xmlns:ns1=\"http://webservice.api.ultra.neustar.com/v01/\">\n"
                                                            + "                 <DirectionalDNSGroupDetail xmlns:ns2=\"http://schema.ultraservice.neustar.com/v01/\" GroupName=\"Europe\">\n"
                                                            + "                         <ns2:DirectionalDNSRegion>\n"
                                                            + "                                 <ns2:RegionForNewGroups RegionName=\"Europe\"\n"
                                                            + "                                         TerritoryName=\"Aland Islands;Albania;Andorra;Armenia;Austria;Azerbaijan;Belarus;Belgium;Bosnia-Herzegovina;Bulgaria;Croatia;Czech Republic;Denmark;Estonia;Faroe Islands;Finland;France;Georgia;Germany;Gibraltar;Greece;Guernsey;Hungary;Iceland;Ireland;Isle of Man;Italy;Jersey;Latvia;Liechtenstein;Lithuania;Luxembourg;Macedonia, the former Yugoslav Republic of;Malta;Moldova, Republic of;Monaco;Montenegro;Netherlands;Norway;Poland;Portugal;Romania;San Marino;Serbia;Slovakia;Slovenia;Spain;Svalbard and Jan Mayen;Sweden;Switzerland;Ukraine;Undefined Europe;United Kingdom - England, Northern Ireland, Scotland, Wales;Vatican City\" />\n"
                                                            + "                         </ns2:DirectionalDNSRegion>\n"
                                                            + "                 </DirectionalDNSGroupDetail>\n"
                                                            + "         </ns1:getDirectionalDNSGroupDetailsResponseEurope>\n"
                                                            + " </soap:Body>\n"
                                                            + "</soap:Envelope>"; static String getDirectionalDNSRecordsForGroup =
    format(getDirectionalDNSRecordsForGroupTemplate, "Europe",
           "www.denominator.io.", "denominator.io.", 1); static String getDirectionalDNSRecordsForGroupEuropeIPV6 =
    format(getDirectionalDNSRecordsForGroupTemplate,
           "Europe", "www.denominator.io.", "denominator.io.", 28); static String getDirectionalDNSRecordsForGroupResponseAbsent =
    getDirectionalDNSRecordsForGroupResponseHeader
    + getDirectionalDNSRecordsForGroupResponseFooter; static String getDirectionalDNSRecordsForGroupResponsePresent =
    getDirectionalDNSRecordsForGroupResponseHeader
    + "    <DirectionalDNSRecordDetailList xmlns:ns2=\"http://schema.ultraservice.neustar.com/v01/\" ZoneName=\"denominator.io.\" DName=\"www.denominator.io.\">\n"
    + "      <ns2:DirectionalDNSRecordDetail GeolocationGroupName=\"Europe\" GeolocationGroupId=\"C000000000000001\" TerritoriesCount=\"54\" DirPoolRecordId=\"A000000000000001\">\n"
    + "        <ns2:DirectionalDNSRecord recordType=\"CNAME\" TTL=\"300\" noResponseRecord=\"false\">\n"
    + "          <ns2:InfoValues Info1Value=\"www-000000001.eu-west-1.elb.amazonaws.com.\" />\n"
    + "        </ns2:DirectionalDNSRecord>\n"
    + "      </ns2:DirectionalDNSRecordDetail>\n"
    + "    </DirectionalDNSRecordDetailList>\n"
    + getDirectionalDNSRecordsForGroupResponseFooter; static String getDirectionalDNSRecordsForHost =
    format(getDirectionalDNSRecordsForHostTemplate, "denominator.io.",
           "www.denominator.io.", 0); static String getDirectionalDNSRecordsForHostIPV4 =
    format(getDirectionalDNSRecordsForHostTemplate,
           "denominator.io.", "www.denominator.io.", 1); static String getDirectionalDNSRecordsForHostIPV6 =
    format(getDirectionalDNSRecordsForHostTemplate,
           "denominator.io.", "www.denominator.io.", 28); static String getDirectionalDNSRecordsForHostResponseAbsent =
    getDirectionalDNSRecordsForHostResponseHeader
    + getDirectionalDNSRecordsForHostResponseFooter; static String getDirectionalDNSRecordsForHostResponsePresent =
    getDirectionalDNSRecordsForHostResponseHeader
    + "    <DirectionalDNSRecordDetailList xmlns:ns2=\"http://schema.ultraservice.neustar.com/v01/\" ZoneName=\"denominator.io.\" DName=\"www.denominator.io.\">\n"
    + "      <ns2:DirectionalDNSRecordDetail GeolocationGroupName=\"Europe\" GeolocationGroupId=\"C000000000000001\" TerritoriesCount=\"54\" DirPoolRecordId=\"A000000000000001\">\n"
    + "        <ns2:DirectionalDNSRecord recordType=\"CNAME\" TTL=\"300\" noResponseRecord=\"false\">\n"
    + "          <ns2:InfoValues Info1Value=\"www-000000001.eu-west-1.elb.amazonaws.com.\" />\n"
    + "        </ns2:DirectionalDNSRecord>\n"
    + "      </ns2:DirectionalDNSRecordDetail>\n"
    + "      <ns2:DirectionalDNSRecordDetail GeolocationGroupName=\"US\" GeolocationGroupId=\"C000000000000002\" TerritoriesCount=\"3\" DirPoolRecordId=\"A000000000000002\">\n"
    + "        <ns2:DirectionalDNSRecord recordType=\"CNAME\" TTL=\"300\" noResponseRecord=\"false\">\n"
    + "          <ns2:InfoValues Info1Value=\"www-000000001.us-east-1.elb.amazonaws.com.\" />\n"
    + "        </ns2:DirectionalDNSRecord>\n"
    + "      </ns2:DirectionalDNSRecordDetail>\n"
    + "      <ns2:DirectionalDNSRecordDetail GeolocationGroupName=\"Everywhere Else\" GeolocationGroupId=\"C000000000000003\" TerritoriesCount=\"323\" DirPoolRecordId=\"A000000000000003\">\n"
    + "        <ns2:DirectionalDNSRecord recordType=\"CNAME\" TTL=\"60\" noResponseRecord=\"false\">\n"
    + "          <ns2:InfoValues Info1Value=\"www-000000002.us-east-1.elb.amazonaws.com.\" />\n"
    + "        </ns2:DirectionalDNSRecord>\n"
    + "      </ns2:DirectionalDNSRecordDetail>\n"
    + "    </DirectionalDNSRecordDetailList>\n"
    + getDirectionalDNSRecordsForHostResponseFooter; static String
    getDirectionalPoolsOfZone =
    "<v01:getDirectionalPoolsOfZone><zoneName>denominator.io.</zoneName></v01:getDirectionalPoolsOfZone>"; static String getDirectionalPoolsOfZoneResponsePresent = getDirectionalPoolsOfZoneResponseHeader

                                                         + "      <ns2:DirectionalPoolData dirpoolid=\"D000000000000001\" Zoneid=\"Z000000000000001\" Pooldname=\"www.denominator.io.\" DirPoolType=\"GEOLOCATION\" Description=\"test with ips and cnames\" />\n"
                                                         + "      <ns2:DirectionalPoolData dirpoolid=\"D000000000000002\" Zoneid=\"Z000000000000001\" Pooldname=\"www2.denominator.io.\" DirPoolType=\"SOURCEIP\" Description=\"should filter out as not geo\" />\n"
                                                         + getDirectionalPoolsOfZoneResponseFooter; static String updateDirectionalPoolRecordRegions = format(
    updateDirectionalPoolRecordTemplate,
    "A000000000000001",
    300,
    "www-000000001.eu-west-1.elb.amazonaws.com.",
    "<GeolocationGroupDetails groupName=\"Europe\"><GeolocationGroupDefinitionData regionName=\"Europe\" territoryNames=\"Aland Islands\" /></GeolocationGroupDetails><forceOverlapTransfer>true</forceOverlapTransfer>"); static String updateDirectionalPoolRecordResponse =
    "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
    + "  <soap:Body>\n"
    + "    <ns1:updateDirectionalPoolRecordResponse xmlns:ns1=\"http://webservice.api.ultra.neustar.com/v01/\">\n"
    + "      <result xmlns:ns2=\"http://schema.ultraservice.neustar.com/v01/\">Successful</result>\n"
    + "    </ns1:updateDirectionalPoolRecordResponse>\n"
    + "  </soap:Body>\n"
    + "</soap:Envelope>"; static String
    updateDirectionalPoolRecordTemplate =
    "<v01:updateDirectionalPoolRecord><transactionID /><UpdateDirectionalRecordData directionalPoolRecordId=\"%s\"><DirectionalRecordConfiguration TTL=\"%s\" ><InfoValues Info1Value=\"%s\" /></DirectionalRecordConfiguration>%s</UpdateDirectionalRecordData></v01:updateDirectionalPoolRecord>";
import com.squareup.okhttp.mockwebserver.MockResponse;
import org.junit.Rule;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import denominator.model.ResourceRecordSet;
import denominator.model.profile.Geo;
import denominator.model.rdata.CNAMEData;
import denominator.profile.GeoResourceRecordSetApi;
import static denominator.assertj.ModelAssertions.assertThat;
import static denominator.ultradns.UltraDNSException.DIRECTIONAL_NOT_ENABLED;
import static denominator.ultradns.UltraDNSTest.getAvailableRegions;
import static denominator.ultradns.UltraDNSTest.getAvailableRegionsResponse;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSGroupDetails;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSGroupDetailsResponseEurope;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForGroup;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForGroupEuropeIPV6;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForGroupResponseAbsent;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForGroupResponsePresent;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForHost;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForHostIPV4;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForHostIPV6;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForHostResponseAbsent;
import static denominator.ultradns.UltraDNSTest.getDirectionalDNSRecordsForHostResponsePresent;
import static denominator.ultradns.UltraDNSTest.getDirectionalPoolsOfZone;
import static denominator.ultradns.UltraDNSTest.getDirectionalPoolsOfZoneResponsePresent;
import static denominator.ultradns.UltraDNSTest.updateDirectionalPoolRecordRegions;
import static denominator.ultradns.UltraDNSTest.updateDirectionalPoolRecordResponse;
import static denominator.ultradns.UltraDNSTest.updateDirectionalPoolRecordTemplate;
import static java.lang.String.format;
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000001"));
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000003"));
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000002"));
  }

  @Test
  public void iterateByNameAndTypeWhenPresent() throws Exception {
    server.enqueue(new MockResponse().setBody(getAvailableRegionsResponse));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForHostResponsePresent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForHostResponseAbsent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSGroupDetailsResponseEurope));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSGroupDetailsResponseEverywhereElse));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSGroupDetailsResponseUS));

    GeoResourceRecordSetApi api = server.connect().api().geoRecordSetsInZone("denominator.io.");

    Iterator<ResourceRecordSet<?>>
        iterator =
        api.iterateByNameAndType("www.denominator.io.", "CNAME");
    assertEurope(iterator.next());
    assertEverywhereElse(iterator.next());
    assertUS(iterator.next());
    assertThat(iterator).isEmpty();

    server.assertSoapBody(getAvailableRegions);
    server.assertSoapBody(getDirectionalDNSRecordsForHostIPV4);
    server.assertSoapBody(getDirectionalDNSRecordsForHostIPV6);
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000001"));
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000003"));
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000002"));
  }

  @Test
  public void supportedRegionsCache() throws Exception {
    server.enqueue(new MockResponse().setBody(getAvailableRegionsResponse));

    GeoResourceRecordSetApi api = server.connect().api().geoRecordSetsInZone("denominator.io.");

    assertThat(api.supportedRegions()).hasSize(2);
    api.supportedRegions(); // cached

    server.assertSoapBody(getAvailableRegions);
  }

  @Test
  public void putWhenMatches() throws Exception {
    server.enqueue(new MockResponse().setBody(getAvailableRegionsResponse));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponsePresent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponseAbsent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSGroupDetailsResponseEurope));

    GeoResourceRecordSetApi api = server.connect().api().geoRecordSetsInZone("denominator.io.");

    api.put(europe);

    server.assertSoapBody(getAvailableRegions);
    server.assertSoapBody(getDirectionalDNSRecordsForGroup);
    server.assertSoapBody(getDirectionalDNSRecordsForGroupEuropeIPV6);
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000001"));
  }

  @Test
  public void putWhenRegionsDiffer() throws Exception {
    server.enqueue(new MockResponse().setBody(getAvailableRegionsResponse));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponsePresent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponseAbsent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSGroupDetailsResponseEurope));
    server.enqueue(new MockResponse().setBody(updateDirectionalPoolRecordResponse));

    GeoResourceRecordSetApi api = server.connect().api().geoRecordSetsInZone("denominator.io.");

    ResourceRecordSet<CNAMEData> lessOfEurope = ResourceRecordSet.<CNAMEData>builder()
        .name(europe.name())
        .type(europe.type())
        .qualifier(europe.qualifier())
        .ttl(europe.ttl())
        .addAll(europe.records())
        .geo(Geo.create(new LinkedHashMap<String, Collection<String>>() {
          {
            put("Europe", Arrays.asList("Aland Islands"));
          }
        })).build();
    api.put(lessOfEurope);

    server.assertSoapBody(getAvailableRegions);
    server.assertSoapBody(getDirectionalDNSRecordsForGroup);
    server.assertSoapBody(getDirectionalDNSRecordsForGroupEuropeIPV6);
    server.assertSoapBody(
        getDirectionalDNSGroupDetails.replace("AAAAAAAAAAAAAAAA", "C000000000000001"));
    server.assertSoapBody(updateDirectionalPoolRecordRegions);
  }

  @Test
  public void putWhenTTLDiffers() throws Exception {
    server.enqueue(new MockResponse().setBody(getAvailableRegionsResponse));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponsePresent));
    server.enqueue(new MockResponse().setBody(getDirectionalDNSRecordsForGroupResponseAbsent));
    server.enqueue(new MockResponse().setBody(updateDirectionalPoolRecordResponse));

    GeoResourceRecordSetApi api = server.connect().api().geoRecordSetsInZone("denominator.io.");
    ResourceRecordSet<CNAMEData> lessTTL = ResourceRecordSet.<CNAMEData>builder()
        .name(europe.name())
        .type(europe.type())
        .qualifier(europe.qualifier())
        .ttl(600)
        .addAll(europe.records())
        .geo(europe.geo()).build();
    api.put(lessTTL);

    server.assertSoapBody(getAvailableRegions);
    server.assertSoapBody(getDirectionalDNSRecordsForGroup);
    server.assertSoapBody(getDirectionalDNSRecordsForGroupEuropeIPV6);
    server.assertSoapBody(format(
        updateDirectionalPoolRecordTemplate,