github.com/anuvu/tyk@v2.9.0-beta9-dl-apic+incompatible/cli/linter/linter_test.go (about)

     1  package linter
     2  
     3  import (
     4  	"encoding/json"
     5  	"io/ioutil"
     6  	"os"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/TykTechnologies/tyk/config"
    11  )
    12  
    13  func TestMain(m *testing.M) {
    14  	// Use the root package, as that's where the directories and
    15  	// files required to run the gateway are.
    16  	os.Chdir("../..")
    17  	os.Exit(m.Run())
    18  }
    19  
    20  // onDefaults overlays src as a JSON string on top of the default config
    21  // as a JSON. This can be useful to change the default config in ways
    22  // that would not be possible via the config.Config struct, such as
    23  // using invalid types or adding extra fields.
    24  func onDefaults(src string) string {
    25  	conf := map[string]interface{}{}
    26  	defBytes, _ := json.Marshal(config.Default)
    27  	json.Unmarshal(defBytes, &conf)
    28  	json.Unmarshal([]byte(src), &conf)
    29  	resBytes, _ := json.Marshal(conf)
    30  	return string(resBytes)
    31  }
    32  
    33  var tests = []struct {
    34  	name string
    35  	in   string
    36  	want interface{}
    37  }{
    38  	{
    39  		"InvalidJSON", `{`,
    40  		"unexpected EOF",
    41  	},
    42  	{
    43  		"WrongType", `{"enable_jsvm": 3}`,
    44  		"cannot unmarshal number into Go struct field Config.enable_jsvm of type bool",
    45  	},
    46  	{
    47  		"FieldTypo", `{"enable_jsvmm": true}`,
    48  		"Additional property enable_jsvmm is not allowed",
    49  	},
    50  	{"Empty", `{}`, nil},
    51  	{"Default", onDefaults(`{}`), nil},
    52  	{"OldMonitor", `{"Monitor": {}}`, nil},
    53  	{"NullObject", `{"event_handlers": null}`, nil},
    54  	{
    55  		"MissingPath", `{"app_path": "missing-path"}`,
    56  		"app_path: Path does not exist or is not accessible",
    57  	},
    58  	{
    59  		"ExtraPort", `{"listen_address": "foo.com:8080"}`,
    60  		"listen_address: Address should be a host without port",
    61  	},
    62  	{
    63  		"BadHost", `{"storage": {"host": "::::"}}`,
    64  		"storage.host: Address should be a host without port",
    65  	},
    66  	{
    67  		"BadLogLevel", `{"log_level": "catastrophic"}`,
    68  		`log_level: log_level must be one of the following: "", "debug", "info", "warn", "error"`,
    69  	},
    70  	{
    71  		"BadStorageType", `{"storage": {"type": "cd-rom"}}`,
    72  		`storage.type: storage.type must be one of the following: "", "redis"`,
    73  	},
    74  	{
    75  		"BadPolicySource", `{"policies": {"policy_source": "internet"}}`,
    76  		`policies.policy_source: policies.policy_source must be one of the following: "", "service", "rpc"`,
    77  	},
    78  	{
    79  		"MalformedDnsCacheEntry", `{"dns_cache": { "enabled": true, "tttl": 10} }`,
    80  		`tttl: Additional property tttl is not allowed`,
    81  	},
    82  	{
    83  		"BadDnsCacheTTL", `{"dns_cache": { "enabled": false, "ttl": -2 } }`,
    84  		`dns_cache.ttl: Must be greater than or equal to -1`,
    85  	},
    86  	{
    87  		"ExtraDnsCacheCheckInterval", `{"dns_cache": { "enabled": true, "ttl": -1, "check_interval": 2500 } }`,
    88  		`check_interval: Additional property check_interval is not allowed`,
    89  	},
    90  	{
    91  		"InvalidDnsCacheMultipleIPsHandleStrategy", `{"dns_cache": { "enabled": true, "ttl": 1, "multiple_ips_handle_strategy": "true" } }`,
    92  		`dns_cache.multiple_ips_handle_strategy: dns_cache.multiple_ips_handle_strategy must be one of the following: "pick_first", "random", "no_cache"`,
    93  	},
    94  }
    95  
    96  func allContains(got, want []string) bool {
    97  	if len(want) != len(got) {
    98  		return false
    99  	}
   100  	for i := range want {
   101  		if !strings.Contains(got[i], want[i]) {
   102  			return false
   103  		}
   104  	}
   105  	return true
   106  }
   107  
   108  func TestLint(t *testing.T) {
   109  	for _, tc := range tests {
   110  		t.Run(tc.name, func(t *testing.T) {
   111  			f, err := ioutil.TempFile("", "tyk-lint")
   112  			if err != nil {
   113  				t.Fatal(err)
   114  			}
   115  			if _, err := f.WriteString(tc.in); err != nil {
   116  				t.Fatal(err)
   117  			}
   118  			f.Close()
   119  
   120  			confSchema, err := ioutil.ReadFile("cli/linter/schema.json")
   121  			if err != nil {
   122  				t.Fatal(err)
   123  			}
   124  
   125  			_, got, err := Run(string(confSchema), []string{f.Name()})
   126  			if err != nil {
   127  				got = []string{err.Error()}
   128  			}
   129  			want := []string{}
   130  			switch x := tc.want.(type) {
   131  			case nil:
   132  			case string:
   133  				want = []string{x}
   134  			case []string:
   135  				want = x
   136  			default:
   137  				t.Fatalf("unexpected want type: %T\n", x)
   138  			}
   139  			if !allContains(got, want) {
   140  				t.Fatalf("want:\n%s\ngot:\n%s",
   141  					strings.Join(want, "\n"),
   142  					strings.Join(got, "\n"))
   143  			}
   144  		})
   145  	}
   146  }