github.com/teknogeek/dnscontrol@v0.2.8/integrationTest/integration_test.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"testing"
     6  
     7  	"fmt"
     8  
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/StackExchange/dnscontrol/models"
    13  	"github.com/StackExchange/dnscontrol/pkg/nameservers"
    14  	"github.com/StackExchange/dnscontrol/providers"
    15  	_ "github.com/StackExchange/dnscontrol/providers/_all"
    16  	"github.com/StackExchange/dnscontrol/providers/config"
    17  	"github.com/miekg/dns/dnsutil"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  var providerToRun = flag.String("provider", "", "Provider to run")
    22  var startIdx = flag.Int("start", 0, "Test number to begin with")
    23  var endIdx = flag.Int("end", 0, "Test index to stop after")
    24  var verbose = flag.Bool("verbose", false, "Print corrections as you run them")
    25  
    26  func init() {
    27  	flag.Parse()
    28  }
    29  
    30  func getProvider(t *testing.T) (providers.DNSServiceProvider, string, map[int]bool) {
    31  	if *providerToRun == "" {
    32  		t.Log("No provider specified with -provider")
    33  		return nil, "", nil
    34  	}
    35  	jsons, err := config.LoadProviderConfigs("providers.json")
    36  	if err != nil {
    37  		t.Fatalf("Error loading provider configs: %s", err)
    38  	}
    39  	fails := map[int]bool{}
    40  	for name, cfg := range jsons {
    41  		if *providerToRun != name {
    42  			continue
    43  		}
    44  		provider, err := providers.CreateDNSProvider(name, cfg, nil)
    45  		if err != nil {
    46  			t.Fatal(err)
    47  		}
    48  		if f := cfg["knownFailures"]; f != "" {
    49  			for _, s := range strings.Split(f, ",") {
    50  				i, err := strconv.Atoi(s)
    51  				if err != nil {
    52  					t.Fatal(err)
    53  				}
    54  				fails[i] = true
    55  			}
    56  		}
    57  		return provider, cfg["domain"], fails
    58  	}
    59  	t.Fatalf("Provider %s not found", *providerToRun)
    60  	return nil, "", nil
    61  }
    62  
    63  func TestDNSProviders(t *testing.T) {
    64  	provider, domain, fails := getProvider(t)
    65  	if provider == nil {
    66  		return
    67  	}
    68  	t.Run(fmt.Sprintf("%s", domain), func(t *testing.T) {
    69  		runTests(t, provider, domain, fails)
    70  	})
    71  
    72  }
    73  
    74  func getDomainConfigWithNameservers(t *testing.T, prv providers.DNSServiceProvider, domainName string) *models.DomainConfig {
    75  	dc := &models.DomainConfig{
    76  		Name: domainName,
    77  	}
    78  	// fix up nameservers
    79  	ns, err := prv.GetNameservers(domainName)
    80  	if err != nil {
    81  		t.Fatal("Failed getting nameservers", err)
    82  	}
    83  	dc.Nameservers = ns
    84  	nameservers.AddNSRecords(dc)
    85  	return dc
    86  }
    87  
    88  func runTests(t *testing.T, prv providers.DNSServiceProvider, domainName string, knownFailures map[int]bool) {
    89  	dc := getDomainConfigWithNameservers(t, prv, domainName)
    90  	// run tests one at a time
    91  	end := *endIdx
    92  	tests := makeTests(t)
    93  	if end == 0 || end >= len(tests) {
    94  		end = len(tests) - 1
    95  	}
    96  	for i := *startIdx; i <= end; i++ {
    97  		tst := tests[i]
    98  		if t.Failed() {
    99  			break
   100  		}
   101  		t.Run(fmt.Sprintf("%d: %s", i, tst.Desc), func(t *testing.T) {
   102  			skipVal := false
   103  			if knownFailures[i] {
   104  				t.Log("SKIPPING VALIDATION FOR KNOWN FAILURE CASE")
   105  				skipVal = true
   106  			}
   107  			dom, _ := dc.Copy()
   108  			for _, r := range tst.Records {
   109  				rc := models.RecordConfig(*r)
   110  				if strings.Contains(rc.GetTargetField(), "**current-domain**") {
   111  					rc.SetTarget(strings.Replace(rc.GetTargetField(), "**current-domain**", domainName, 1) + ".")
   112  				}
   113  				if strings.Contains(rc.GetLabelFQDN(), "**current-domain**") {
   114  					rc.SetLabelFromFQDN(strings.Replace(rc.GetLabelFQDN(), "**current-domain**", domainName, 1), domainName)
   115  				}
   116  				dom.Records = append(dom.Records, &rc)
   117  			}
   118  			dom.IgnoredLabels = tst.IgnoredLabels
   119  			models.PostProcessRecords(dom.Records)
   120  			dom2, _ := dom.Copy()
   121  			// get corrections for first time
   122  			corrections, err := prv.GetDomainCorrections(dom)
   123  			if err != nil {
   124  				t.Fatal(errors.Wrap(err, "runTests"))
   125  			}
   126  			if !skipVal && i != *startIdx && len(corrections) == 0 {
   127  				if tst.Desc != "Empty" {
   128  					// There are "no corrections" if the last test was programmatically
   129  					// skipped.  We detect this (possibly inaccurately) by checking to
   130  					// see if .Desc is "Empty".
   131  					t.Fatalf("Expect changes for all tests, but got none")
   132  				}
   133  			}
   134  			for _, c := range corrections {
   135  				if *verbose {
   136  					t.Log(c.Msg)
   137  				}
   138  				err = c.F()
   139  				if !skipVal && err != nil {
   140  					t.Fatal(err)
   141  				}
   142  			}
   143  			// run a second time and expect zero corrections
   144  			corrections, err = prv.GetDomainCorrections(dom2)
   145  			if err != nil {
   146  				t.Fatal(err)
   147  			}
   148  			if !skipVal && len(corrections) != 0 {
   149  				t.Logf("Expected 0 corrections on second run, but found %d.", len(corrections))
   150  				for i, c := range corrections {
   151  					t.Logf("#%d: %s", i, c.Msg)
   152  				}
   153  				t.FailNow()
   154  			}
   155  		})
   156  	}
   157  }
   158  
   159  func TestDualProviders(t *testing.T) {
   160  	p, domain, _ := getProvider(t)
   161  	if p == nil {
   162  		return
   163  	}
   164  	dc := getDomainConfigWithNameservers(t, p, domain)
   165  	// clear everything
   166  	run := func() {
   167  		dom, _ := dc.Copy()
   168  		cs, err := p.GetDomainCorrections(dom)
   169  		if err != nil {
   170  			t.Fatal(err)
   171  		}
   172  		for i, c := range cs {
   173  			t.Logf("#%d: %s", i+1, c.Msg)
   174  			if err = c.F(); err != nil {
   175  				t.Fatal(err)
   176  			}
   177  		}
   178  	}
   179  	t.Log("Clearing everything")
   180  	run()
   181  	// add bogus nameservers
   182  	dc.Records = []*models.RecordConfig{}
   183  	dc.Nameservers = append(dc.Nameservers, models.StringsToNameservers([]string{"ns1.otherdomain.tld", "ns2.otherdomain.tld"})...)
   184  	nameservers.AddNSRecords(dc)
   185  	t.Log("Adding nameservers from another provider")
   186  	run()
   187  	// run again to make sure no corrections
   188  	t.Log("Running again to ensure stability")
   189  	cs, err := p.GetDomainCorrections(dc)
   190  	if err != nil {
   191  		t.Fatal(err)
   192  	}
   193  	if len(cs) != 0 {
   194  		t.Logf("Expect no corrections on second run, but found %d.", len(cs))
   195  		for i, c := range cs {
   196  			t.Logf("#%d: %s", i, c.Msg)
   197  		}
   198  		t.FailNow()
   199  	}
   200  }
   201  
   202  type TestCase struct {
   203  	Desc          string
   204  	Records       []*rec
   205  	IgnoredLabels []string
   206  }
   207  
   208  type rec models.RecordConfig
   209  
   210  func (r *rec) GetLabel() string {
   211  	return r.Name
   212  }
   213  
   214  func (r *rec) SetLabel(label, domain string) {
   215  	r.Name = label
   216  	r.NameFQDN = dnsutil.AddOrigin(label, "**current-domain**")
   217  }
   218  
   219  func (r *rec) SetTarget(target string) {
   220  	r.Target = target
   221  }
   222  
   223  func a(name, target string) *rec {
   224  	return makeRec(name, target, "A")
   225  }
   226  
   227  func cname(name, target string) *rec {
   228  	return makeRec(name, target, "CNAME")
   229  }
   230  
   231  func alias(name, target string) *rec {
   232  	return makeRec(name, target, "ALIAS")
   233  }
   234  
   235  func r53alias(name, aliasType, target string) *rec {
   236  	r := makeRec(name, target, "R53_ALIAS")
   237  	r.R53Alias = map[string]string{
   238  		"type": aliasType,
   239  	}
   240  	return r
   241  }
   242  
   243  func ns(name, target string) *rec {
   244  	return makeRec(name, target, "NS")
   245  }
   246  
   247  func mx(name string, prio uint16, target string) *rec {
   248  	r := makeRec(name, target, "MX")
   249  	r.MxPreference = prio
   250  	return r
   251  }
   252  
   253  func ptr(name, target string) *rec {
   254  	return makeRec(name, target, "PTR")
   255  }
   256  
   257  func srv(name string, priority, weight, port uint16, target string) *rec {
   258  	r := makeRec(name, target, "SRV")
   259  	r.SrvPriority = priority
   260  	r.SrvWeight = weight
   261  	r.SrvPort = port
   262  	return r
   263  }
   264  
   265  func txt(name, target string) *rec {
   266  	// FYI: This must match the algorithm in pkg/js/helpers.js TXT.
   267  	r := makeRec(name, target, "TXT")
   268  	r.TxtStrings = []string{target}
   269  	return r
   270  }
   271  
   272  func txtmulti(name string, target []string) *rec {
   273  	// FYI: This must match the algorithm in pkg/js/helpers.js TXT.
   274  	r := makeRec(name, target[0], "TXT")
   275  	r.TxtStrings = target
   276  	return r
   277  }
   278  
   279  func caa(name string, tag string, flag uint8, target string) *rec {
   280  	r := makeRec(name, target, "CAA")
   281  	r.CaaFlag = flag
   282  	r.CaaTag = tag
   283  	return r
   284  }
   285  
   286  func tlsa(name string, usage, selector, matchingtype uint8, target string) *rec {
   287  	r := makeRec(name, target, "TLSA")
   288  	r.TlsaUsage = usage
   289  	r.TlsaSelector = selector
   290  	r.TlsaMatchingType = matchingtype
   291  	return r
   292  }
   293  
   294  func ignore(name string) *rec {
   295  	r := &rec{
   296  		Type: "IGNORE",
   297  	}
   298  	r.SetLabel(name, "**current-domain**")
   299  	return r
   300  }
   301  
   302  func makeRec(name, target, typ string) *rec {
   303  	r := &rec{
   304  		Type: typ,
   305  		TTL:  300,
   306  	}
   307  	r.SetLabel(name, "**current-domain**")
   308  	r.SetTarget(target)
   309  	return r
   310  }
   311  
   312  func (r *rec) ttl(t uint32) *rec {
   313  	r.TTL = t
   314  	return r
   315  }
   316  
   317  func tc(desc string, recs ...*rec) *TestCase {
   318  	var records []*rec
   319  	var ignored []string
   320  	for _, r := range recs {
   321  		if r.Type == "IGNORE" {
   322  			ignored = append(ignored, r.GetLabel())
   323  		} else {
   324  			records = append(records, r)
   325  		}
   326  	}
   327  	return &TestCase{
   328  		Desc:          desc,
   329  		Records:       records,
   330  		IgnoredLabels: ignored,
   331  	}
   332  }
   333  
   334  func manyA(namePattern, target string, n int) []*rec {
   335  	recs := []*rec{}
   336  	for i := 0; i < n; i++ {
   337  		recs = append(recs, makeRec(fmt.Sprintf(namePattern, i), target, "A"))
   338  	}
   339  	return recs
   340  }
   341  
   342  func makeTests(t *testing.T) []*TestCase {
   343  	// ALWAYS ADD TO BOTTOM OF LIST. Order and indexes matter.
   344  	tests := []*TestCase{
   345  		// A
   346  		tc("Empty"),
   347  		tc("Create an A record", a("@", "1.1.1.1")),
   348  		tc("Change it", a("@", "1.2.3.4")),
   349  		tc("Add another", a("@", "1.2.3.4"), a("www", "1.2.3.4")),
   350  		tc("Add another(same name)", a("@", "1.2.3.4"), a("www", "1.2.3.4"), a("www", "5.6.7.8")),
   351  		tc("Change a ttl", a("@", "1.2.3.4").ttl(1000), a("www", "1.2.3.4"), a("www", "5.6.7.8")),
   352  		tc("Change single target from set", a("@", "1.2.3.4").ttl(1000), a("www", "2.2.2.2"), a("www", "5.6.7.8")),
   353  		tc("Change all ttls", a("@", "1.2.3.4").ttl(500), a("www", "2.2.2.2").ttl(400), a("www", "5.6.7.8").ttl(400)),
   354  		tc("Delete one", a("@", "1.2.3.4").ttl(500), a("www", "5.6.7.8").ttl(400)),
   355  		tc("Add back and change ttl", a("www", "5.6.7.8").ttl(700), a("www", "1.2.3.4").ttl(700)),
   356  		tc("Change targets and ttls", a("www", "1.1.1.1"), a("www", "2.2.2.2")),
   357  		tc("Create wildcard", a("*", "1.2.3.4"), a("www", "1.1.1.1")),
   358  		tc("Delete wildcard", a("www", "1.1.1.1")),
   359  
   360  		// CNAMES
   361  		tc("Empty"),
   362  		tc("Create a CNAME", cname("foo", "google.com.")),
   363  		tc("Change it", cname("foo", "google2.com.")),
   364  		tc("Change to A record", a("foo", "1.2.3.4")),
   365  		tc("Change back to CNAME", cname("foo", "google.com.")),
   366  		tc("Record pointing to @", cname("foo", "**current-domain**")),
   367  
   368  		// NS
   369  		tc("Empty"),
   370  		tc("NS for subdomain", ns("xyz", "ns2.foo.com.")),
   371  		tc("Dual NS for subdomain", ns("xyz", "ns2.foo.com."), ns("xyz", "ns1.foo.com.")),
   372  		tc("NS Record pointing to @", ns("foo", "**current-domain**")),
   373  
   374  		// IDNAs
   375  		tc("Empty"),
   376  		tc("Internationalized name", a("ööö", "1.2.3.4")),
   377  		tc("Change IDN", a("ööö", "2.2.2.2")),
   378  		tc("Internationalized CNAME Target", cname("a", "ööö.com.")),
   379  		tc("IDN CNAME AND Target", cname("öoö", "ööö.企业.")),
   380  
   381  		// MX
   382  		tc("Empty"),
   383  		tc("MX record", mx("@", 5, "foo.com.")),
   384  		tc("Second MX record, same prio", mx("@", 5, "foo.com."), mx("@", 5, "foo2.com.")),
   385  		tc("3 MX", mx("@", 5, "foo.com."), mx("@", 5, "foo2.com."), mx("@", 15, "foo3.com.")),
   386  		tc("Delete one", mx("@", 5, "foo2.com."), mx("@", 15, "foo3.com.")),
   387  		tc("Change to other name", mx("@", 5, "foo2.com."), mx("mail", 15, "foo3.com.")),
   388  		tc("Change Preference", mx("@", 7, "foo2.com."), mx("mail", 15, "foo3.com.")),
   389  		tc("Record pointing to @", mx("foo", 8, "**current-domain**")),
   390  	}
   391  
   392  	// PTR
   393  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUsePTR) {
   394  		t.Log("Skipping PTR Tests because provider does not support them")
   395  	} else {
   396  		tests = append(tests, tc("Empty"),
   397  			tc("Create PTR record", ptr("4", "foo.com.")),
   398  			tc("Modify PTR record", ptr("4", "bar.com.")),
   399  		)
   400  	}
   401  
   402  	// ALIAS
   403  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseAlias) {
   404  		t.Log("Skipping ALIAS Tests because provider does not support them")
   405  	} else {
   406  		tests = append(tests, tc("Empty"),
   407  			tc("ALIAS at root", alias("@", "foo.com.")),
   408  			tc("change it", alias("@", "foo2.com.")),
   409  			tc("ALIAS at subdomain", alias("test", "foo.com.")),
   410  		)
   411  	}
   412  
   413  	// SRV
   414  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseSRV) {
   415  		t.Log("Skipping SRV Tests because provider does not support them")
   416  	} else {
   417  		tests = append(tests, tc("Empty"),
   418  			tc("SRV record", srv("_sip._tcp", 5, 6, 7, "foo.com.")),
   419  			tc("Second SRV record, same prio", srv("_sip._tcp", 5, 6, 7, "foo.com."), srv("_sip._tcp", 5, 60, 70, "foo2.com.")),
   420  			tc("3 SRV", srv("_sip._tcp", 5, 6, 7, "foo.com."), srv("_sip._tcp", 5, 60, 70, "foo2.com."), srv("_sip._tcp", 15, 65, 75, "foo3.com.")),
   421  			tc("Delete one", srv("_sip._tcp", 5, 6, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo3.com.")),
   422  			tc("Change Target", srv("_sip._tcp", 5, 6, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
   423  			tc("Change Priority", srv("_sip._tcp", 52, 6, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
   424  			tc("Change Weight", srv("_sip._tcp", 52, 62, 7, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
   425  			tc("Change Port", srv("_sip._tcp", 52, 62, 72, "foo.com."), srv("_sip._tcp", 15, 65, 75, "foo4.com.")),
   426  		)
   427  	}
   428  
   429  	// CAA
   430  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseCAA) {
   431  		t.Log("Skipping CAA Tests because provider does not support them")
   432  	} else {
   433  		tests = append(tests, tc("Empty"),
   434  			tc("CAA record", caa("@", "issue", 0, "letsencrypt.org")),
   435  			tc("CAA change tag", caa("@", "issuewild", 0, "letsencrypt.org")),
   436  			tc("CAA change target", caa("@", "issuewild", 0, "example.com")),
   437  			tc("CAA change flag", caa("@", "issuewild", 128, "example.com")),
   438  			tc("CAA many records", caa("@", "issue", 0, "letsencrypt.org"), caa("@", "issuewild", 0, ";"), caa("@", "iodef", 128, "mailto:test@example.com")),
   439  			tc("CAA delete", caa("@", "issue", 0, "letsencrypt.org")),
   440  		)
   441  	}
   442  
   443  	// TLSA
   444  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseTLSA) {
   445  		t.Log("Skipping TLSA Tests because provider does not support them")
   446  	} else {
   447  		sha256hash := strings.Repeat("0123456789abcdef", 4)
   448  		sha512hash := strings.Repeat("0123456789abcdef", 8)
   449  		reversedSha512 := strings.Repeat("fedcba9876543210", 8)
   450  		tests = append(tests, tc("Empty"),
   451  			tc("TLSA record", tlsa("_443._tcp", 3, 1, 1, sha256hash)),
   452  			tc("TLSA change usage", tlsa("_443._tcp", 2, 1, 1, sha256hash)),
   453  			tc("TLSA change selector", tlsa("_443._tcp", 2, 0, 1, sha256hash)),
   454  			tc("TLSA change matchingtype", tlsa("_443._tcp", 2, 0, 2, sha512hash)),
   455  			tc("TLSA change certificate", tlsa("_443._tcp", 2, 0, 2, reversedSha512)),
   456  		)
   457  	}
   458  
   459  	// Case
   460  	tests = append(tests, tc("Empty"),
   461  		tc("Empty"),
   462  		tc("Create CAPS", mx("BAR", 5, "BAR.com.")),
   463  		tc("Downcase label", mx("bar", 5, "BAR.com."), a("decoy", "1.1.1.1")),
   464  		tc("Downcase target", mx("bar", 5, "bar.com."), a("decoy", "2.2.2.2")),
   465  		tc("Upcase both", mx("BAR", 5, "BAR.COM."), a("decoy", "3.3.3.3")),
   466  		// The decoys are required so that there is at least one actual change in each tc.
   467  	)
   468  
   469  	// Test large zonefiles.
   470  	// Mostly to test paging. Many providers page at 100
   471  	// Known page sizes:
   472  	//  - gandi: 100
   473  	skip := map[string]bool{
   474  		"NS1": true, // ns1 free acct only allows 50 records
   475  	}
   476  	if skip[*providerToRun] {
   477  		t.Log("Skipping Large record count Tests because provider does not support them")
   478  	} else {
   479  		tests = append(tests, tc("Empty"),
   480  			tc("99 records", manyA("rec%04d", "1.2.3.4", 99)...),
   481  			tc("100 records", manyA("rec%04d", "1.2.3.4", 100)...),
   482  			tc("101 records", manyA("rec%04d", "1.2.3.4", 101)...),
   483  		)
   484  	}
   485  
   486  	// NB(tlim): To temporarily skip most of the tests, insert a line like this:
   487  	//tests = nil
   488  
   489  	// TXT (single)
   490  	tests = append(tests, tc("Empty"),
   491  		tc("Empty"),
   492  		tc("Create a TXT", txt("foo", "simple")),
   493  		tc("Change a TXT", txt("foo", "changed")),
   494  		tc("Empty"),
   495  		tc("Create a TXT with spaces", txt("foo", "with spaces")),
   496  		tc("Change a TXT with spaces", txt("foo", "with whitespace")),
   497  		tc("Create 1 TXT as array", txtmulti("foo", []string{"simple"})),
   498  		tc("Empty"),
   499  		tc("Create a 255-byte TXT", txt("foo", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")),
   500  	)
   501  
   502  	// TXTMulti
   503  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseTXTMulti) {
   504  		t.Log("Skipping TXTMulti Tests because provider does not support them")
   505  	} else {
   506  		tests = append(tests,
   507  			tc("Empty"),
   508  			tc("Create TXTMulti 1",
   509  				txtmulti("foo1", []string{"simple"}),
   510  			),
   511  			tc("Create TXTMulti 2",
   512  				txtmulti("foo1", []string{"simple"}),
   513  				txtmulti("foo2", []string{"one", "two"}),
   514  			),
   515  			tc("Create TXTMulti 3",
   516  				txtmulti("foo1", []string{"simple"}),
   517  				txtmulti("foo2", []string{"one", "two"}),
   518  				txtmulti("foo3", []string{"eh", "bee", "cee"}),
   519  			),
   520  			tc("Create TXTMulti with quotes",
   521  				txtmulti("foo1", []string{"simple"}),
   522  				txtmulti("foo2", []string{"o\"ne", "tw\"o"}),
   523  				txtmulti("foo3", []string{"eh", "bee", "cee"}),
   524  			),
   525  			tc("Change TXTMulti",
   526  				txtmulti("foo1", []string{"dimple"}),
   527  				txtmulti("foo2", []string{"fun", "two"}),
   528  				txtmulti("foo3", []string{"eh", "bzz", "cee"}),
   529  			),
   530  			tc("Empty"),
   531  			tc("3x255-byte TXTMulti",
   532  				txtmulti("foo3", []string{"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY", "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"}),
   533  			),
   534  			tc("Empty"),
   535  		)
   536  	}
   537  
   538  	// ignored records
   539  	tests = append(tests,
   540  		tc("Empty"),
   541  		tc("Create some records", txt("foo", "simple"), a("foo", "1.2.3.4")),
   542  		tc("Add a new record - ignoring foo", a("bar", "1.2.3.4"), ignore("foo")),
   543  	)
   544  
   545  	// R53_ALIAS
   546  	if !providers.ProviderHasCabability(*providerToRun, providers.CanUseRoute53Alias) {
   547  		t.Log("Skipping Route53 ALIAS Tests because provider does not support them")
   548  	} else {
   549  		tests = append(tests, tc("Empty"),
   550  			tc("create dependent records", a("foo", "1.2.3.4"), a("quux", "2.3.4.5")),
   551  			tc("ALIAS to A record in same zone", a("foo", "1.2.3.4"), a("quux", "2.3.4.5"), r53alias("bar", "A", "foo.**current-domain**")),
   552  			tc("change it", a("foo", "1.2.3.4"), a("quux", "2.3.4.5"), r53alias("bar", "A", "quux.**current-domain**")),
   553  		)
   554  	}
   555  
   556  	// Empty last
   557  	tc("Empty")
   558  	return tests
   559  }