Home | History | Annotate | Download | only in config
      1 // Copyright 2016 syzkaller project authors. All rights reserved.
      2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
      3 
      4 package config
      5 
      6 import (
      7 	"encoding/json"
      8 	"fmt"
      9 	"reflect"
     10 	"testing"
     11 	"time"
     12 )
     13 
     14 func TestLoad(t *testing.T) {
     15 	type NestedNested struct {
     16 		Ccc int
     17 		Ddd string
     18 	}
     19 	type Nested struct {
     20 		Aaa  int
     21 		Bbb  string
     22 		More NestedNested
     23 	}
     24 	type Config struct {
     25 		Foo int
     26 		Bar string
     27 		Baz string `json:"-"`
     28 		Raw json.RawMessage
     29 		Qux []string
     30 		Box Nested
     31 		Boq *Nested
     32 		Arr []Nested
     33 		T   time.Time
     34 	}
     35 
     36 	tests := []struct {
     37 		input  string
     38 		output Config
     39 		err    string
     40 	}{
     41 		{
     42 			`{"foo": 42}`,
     43 			Config{
     44 				Foo: 42,
     45 			},
     46 			"",
     47 		},
     48 		{
     49 			`{"BAR": "Baz", "foo": 42}`,
     50 			Config{
     51 				Foo: 42,
     52 				Bar: "Baz",
     53 			},
     54 			"",
     55 		},
     56 		{
     57 			`{"foobar": 42}`,
     58 			Config{},
     59 			"unknown field 'foobar' in config",
     60 		},
     61 		{
     62 			`{"foo": 1, "baz": "baz", "bar": "bar"}`,
     63 			Config{},
     64 			"unknown field 'baz' in config",
     65 		},
     66 		{
     67 			`{"foo": 1, "box": {"aaa": 12, "bbb": "bbb"}}`,
     68 			Config{
     69 				Foo: 1,
     70 				Box: Nested{
     71 					Aaa: 12,
     72 					Bbb: "bbb",
     73 				},
     74 			},
     75 			"",
     76 		},
     77 		{
     78 			`{"qux": ["aaa", "bbb"]}`,
     79 			Config{
     80 				Qux: []string{"aaa", "bbb"},
     81 			},
     82 			"",
     83 		},
     84 		{
     85 			`{"box": {"aaa": 12, "ccc": "bbb"}}`,
     86 			Config{},
     87 			"unknown field 'box.ccc' in config",
     88 		},
     89 		{
     90 			`{"foo": 1, "boq": {"aaa": 12, "bbb": "bbb"}}`,
     91 			Config{
     92 				Foo: 1,
     93 				Boq: &Nested{
     94 					Aaa: 12,
     95 					Bbb: "bbb",
     96 				},
     97 			},
     98 			"",
     99 		},
    100 		{
    101 			`{"boq": {"aaa": 12, "ccc": "bbb"}}`,
    102 			Config{},
    103 			"unknown field 'boq.ccc' in config",
    104 		},
    105 
    106 		{
    107 			`{"foo": 1, "arr": []}`,
    108 			Config{
    109 				Foo: 1,
    110 				Arr: []Nested{},
    111 			},
    112 			"",
    113 		},
    114 		{
    115 			`{"foo": 1, "arr": [{"aaa": 12, "bbb": "bbb"}, {"aaa": 13, "bbb": "ccc"}]}`,
    116 			Config{
    117 				Foo: 1,
    118 				Arr: []Nested{
    119 					{
    120 						Aaa: 12,
    121 						Bbb: "bbb",
    122 					},
    123 					{
    124 						Aaa: 13,
    125 						Bbb: "ccc",
    126 					},
    127 				},
    128 			},
    129 			"",
    130 		},
    131 		{
    132 			`{"arr": [{"aaa": 12, "ccc": "bbb"}]}`,
    133 			Config{},
    134 			"unknown field 'arr[0].ccc' in config",
    135 		},
    136 		{
    137 			`{"foo": 1, "boq": {"aaa": 12, "more": {"ccc": 13, "ddd": "ddd"}}}`,
    138 			Config{
    139 				Foo: 1,
    140 				Boq: &Nested{
    141 					Aaa: 12,
    142 					More: NestedNested{
    143 						Ccc: 13,
    144 						Ddd: "ddd",
    145 					},
    146 				},
    147 			},
    148 			"",
    149 		},
    150 		{
    151 			`{"foo": 1, "boq": {"aaa": 12, "more": {"ccc": 13, "eee": "eee"}}}`,
    152 			Config{},
    153 			"unknown field 'boq.more.eee' in config",
    154 		},
    155 		{
    156 			`{"raw": {"zux": 11}}`,
    157 			Config{
    158 				Raw: []byte(`{"zux": 11}`),
    159 			},
    160 			"",
    161 		},
    162 		{
    163 			`{"foo": null, "qux": null}`,
    164 			Config{},
    165 			"",
    166 		},
    167 		{
    168 			`{"t": "2000-01-02T03:04:05Z"}`,
    169 			Config{
    170 				T: time.Date(2000, 1, 2, 3, 4, 5, 0, time.UTC),
    171 			},
    172 			"",
    173 		},
    174 	}
    175 	for i, test := range tests {
    176 		t.Run(fmt.Sprint(i), func(t *testing.T) {
    177 			var cfg Config
    178 			err := LoadData([]byte(test.input), &cfg)
    179 			errStr := ""
    180 			if err != nil {
    181 				errStr = err.Error()
    182 			}
    183 			if test.err != errStr {
    184 				t.Fatalf("bad err: want '%v', got '%v'", test.err, errStr)
    185 			}
    186 			if !reflect.DeepEqual(test.output, cfg) {
    187 				t.Fatalf("bad output: want:\n%#v\n, got:\n%#v", test.output, cfg)
    188 			}
    189 		})
    190 	}
    191 }
    192 
    193 func TestLoadBadType(t *testing.T) {
    194 	want := "config type is not pointer to struct"
    195 	if err := LoadData([]byte("{}"), 1); err == nil || err.Error() != want {
    196 		t.Fatalf("got '%v', want '%v'", err, want)
    197 	}
    198 	i := 0
    199 	if err := LoadData([]byte("{}"), &i); err == nil || err.Error() != want {
    200 		t.Fatalf("got '%v', want '%v'", err, want)
    201 	}
    202 	s := struct{}{}
    203 	if err := LoadData([]byte("{}"), s); err == nil || err.Error() != want {
    204 		t.Fatalf("got '%v', want '%v'", err, want)
    205 	}
    206 }
    207