github.com/StackExchange/dnscontrol/v4@v4.11.0/pkg/js/js_test.go (about)

     1  package js
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"testing"
    10  	"unicode"
    11  
    12  	"github.com/StackExchange/dnscontrol/v4/pkg/normalize"
    13  	"github.com/StackExchange/dnscontrol/v4/pkg/prettyzone"
    14  	"github.com/StackExchange/dnscontrol/v4/providers"
    15  	_ "github.com/StackExchange/dnscontrol/v4/providers/_all"
    16  	testifyrequire "github.com/stretchr/testify/require"
    17  )
    18  
    19  const (
    20  	testDir  = "pkg/js/parse_tests"
    21  	errorDir = "pkg/js/error_tests"
    22  )
    23  
    24  func init() {
    25  	os.Chdir("../..") // go up a directory so we helpers.js is in a consistent place.
    26  }
    27  
    28  func TestParsedFiles(t *testing.T) {
    29  	files, err := os.ReadDir(testDir)
    30  	if err != nil {
    31  		t.Fatal(err)
    32  	}
    33  	for _, f := range files {
    34  		name := f.Name()
    35  
    36  		// run all js files that start with a number. Skip others.
    37  		if filepath.Ext(name) != ".js" || !unicode.IsNumber(rune(name[0])) {
    38  			continue
    39  		}
    40  		t.Run(name, func(t *testing.T) {
    41  			var err error
    42  
    43  			// Compile the .js file:
    44  			conf, err := ExecuteJavaScript(string(filepath.Join(testDir, name)), true, nil)
    45  			if err != nil {
    46  				t.Fatal(err)
    47  			}
    48  			// for _, dc := range conf.Domains {
    49  			// 	normalize.UpdateNameSplitHorizon(dc)
    50  			// }
    51  
    52  			// Initialize any DNS providers mentioned.
    53  			for _, dProv := range conf.DNSProviders {
    54  				var pcfg = map[string]string{}
    55  
    56  				if dProv.Type == "-" {
    57  					// Pretend any "look up provider type in creds.json" results
    58  					// in a provider type that actually exists.
    59  					dProv.Type = "CLOUDFLAREAPI"
    60  				}
    61  
    62  				// Fake out any provider's validation tests.
    63  				switch dProv.Type {
    64  				case "CLOUDFLAREAPI":
    65  					pcfg["apitoken"] = "fake"
    66  				default:
    67  				}
    68  				_, err := providers.CreateDNSProvider(dProv.Type, pcfg, nil)
    69  				if err != nil {
    70  					t.Fatal(err)
    71  				}
    72  			}
    73  
    74  			// Test the JS compiled as expected (compare to the .json file)
    75  			actualJSON, err := json.MarshalIndent(conf, "", "  ")
    76  			if err != nil {
    77  				t.Fatal(err)
    78  			}
    79  			testName := name[:len(name)-3]
    80  			expectedFile := filepath.Join(testDir, testName+".json")
    81  			expectedJSON, err := os.ReadFile(expectedFile)
    82  			if err != nil {
    83  				t.Fatal(err)
    84  			}
    85  			es := string(expectedJSON)
    86  			as := string(actualJSON)
    87  			_, _ = es, as
    88  			// When debugging, leave behind the actual result:
    89  			//os.WriteFile(expectedFile+".ACTUAL", []byte(as), 0644)
    90  			testifyrequire.JSONEqf(t, es, as, "EXPECTING %q = \n```\n%s\n```", expectedFile, as)
    91  
    92  			// For each domain, if there is a zone file, test against it:
    93  
    94  			errs := normalize.ValidateAndNormalizeConfig(conf)
    95  			if len(errs) != 0 {
    96  				t.Fatal(errs[0])
    97  			}
    98  
    99  			var dCount int
   100  			for _, dc := range conf.Domains {
   101  				zoneFile := filepath.Join(testDir, testName, dc.Name+".zone")
   102  				expectedZone, err := os.ReadFile(zoneFile)
   103  				if err != nil {
   104  					continue
   105  				}
   106  				dCount++
   107  
   108  				// Generate the zonefile
   109  				var buf bytes.Buffer
   110  				err = prettyzone.WriteZoneFileRC(&buf, dc.Records, dc.Name, 300, nil)
   111  				if err != nil {
   112  					t.Fatal(err)
   113  				}
   114  				actualZone := buf.String()
   115  
   116  				es := string(expectedZone)
   117  				as := actualZone
   118  				if es != as {
   119  					// On failure, leave behind the .ACTUAL file.
   120  					os.WriteFile(zoneFile+".ACTUAL", []byte(actualZone), 0644)
   121  				}
   122  				testifyrequire.Equal(t, es, as, "EXPECTING %q =\n```\n%s```", zoneFile, as)
   123  			}
   124  			if dCount > 0 && (len(conf.Domains) != dCount) {
   125  				t.Fatal(fmt.Errorf("only %d of %d domains in %q have zonefiles", dCount, len(conf.Domains), name))
   126  			}
   127  
   128  		})
   129  
   130  	}
   131  }
   132  
   133  func TestErrors(t *testing.T) {
   134  	tests := []struct{ desc, text string }{
   135  		{"old dsp style", `D("foo.com","reg","dsp")`},
   136  		{"MX no priority", `D("foo.com","reg",MX("@","test."))`},
   137  		{"MX reversed", `D("foo.com","reg",MX("@","test.", 5))`},
   138  		{"CF_REDIRECT With comma", `D("foo.com","reg",CF_REDIRECT("foo.com,","baaa"))`},
   139  		{"CF_TEMP_REDIRECT With comma", `D("foo.com","reg",CF_TEMP_REDIRECT("foo.com","baa,a"))`},
   140  		{"CF_WORKER_ROUTE With comma", `D("foo.com","reg",CF_WORKER_ROUTE("foo.com","baa,a"))`},
   141  		{"Bad cidr", `D(reverse("foo.com"), "reg")`},
   142  		{"Dup domains", `D("example.org", "reg"); D("example.org", "reg")`},
   143  		{"Bad NAMESERVER", `D("example.com","reg", NAMESERVER("@","ns1.foo.com."))`},
   144  	}
   145  	for _, tst := range tests {
   146  		t.Run(tst.desc, func(t *testing.T) {
   147  			if _, err := ExecuteJavaScript(tst.text, true, nil); err == nil {
   148  				t.Fatal("Expected error but found none")
   149  			}
   150  		})
   151  
   152  	}
   153  }