1// +build go1.7
2
3package ini
4
5import (
6	"encoding/json"
7	"io/ioutil"
8	"os"
9	"path/filepath"
10	"strings"
11	"testing"
12)
13
14func TestValidDataFiles(t *testing.T) {
15	const expectedFileSuffix = "_expected"
16	filepath.Walk("./testdata/valid", func(path string, info os.FileInfo, err error) error {
17		if strings.HasSuffix(path, expectedFileSuffix) {
18			return nil
19		}
20
21		if info.IsDir() {
22			return nil
23		}
24
25		f, err := os.Open(path)
26		if err != nil {
27			t.Errorf("%s: unexpected error, %v", path, err)
28		}
29		defer f.Close()
30
31		tree, err := ParseAST(f)
32		if err != nil {
33			t.Errorf("%s: unexpected parse error, %v", path, err)
34		}
35
36		v := NewDefaultVisitor()
37		err = Walk(tree, v)
38		if err != nil {
39			t.Errorf("%s: unexpected walk error, %v", path, err)
40		}
41
42		expectedPath := path + "_expected"
43		e := map[string]interface{}{}
44
45		b, err := ioutil.ReadFile(expectedPath)
46		if err != nil {
47			// ignore files that do not have an expected file
48			return nil
49		}
50
51		err = json.Unmarshal(b, &e)
52		if err != nil {
53			t.Errorf("unexpected error during deserialization, %v", err)
54		}
55
56		for profile, tableIface := range e {
57			p, ok := v.Sections.GetSection(profile)
58			if !ok {
59				t.Fatal("could not find profile " + profile)
60			}
61
62			table := tableIface.(map[string]interface{})
63			for k, v := range table {
64				switch e := v.(type) {
65				case string:
66					a := p.String(k)
67					if e != a {
68						t.Errorf("%s: expected %v, but received %v for profile %v", path, e, a, profile)
69					}
70				case int:
71					a := p.Int(k)
72					if int64(e) != a {
73						t.Errorf("%s: expected %v, but received %v", path, e, a)
74					}
75				case float64:
76					v := p.values[k]
77					if v.Type == IntegerType {
78						a := p.Int(k)
79						if int64(e) != a {
80							t.Errorf("%s: expected %v, but received %v", path, e, a)
81						}
82					} else {
83						a := p.Float64(k)
84						if e != a {
85							t.Errorf("%s: expected %v, but received %v", path, e, a)
86						}
87					}
88				default:
89					t.Errorf("unexpected type: %T", e)
90				}
91			}
92		}
93
94		return nil
95	})
96}
97
98func TestInvalidDataFiles(t *testing.T) {
99	cases := []struct {
100		path               string
101		expectedParseError bool
102		expectedWalkError  bool
103	}{
104		{
105			path:               "./testdata/invalid/bad_syntax_1",
106			expectedParseError: true,
107		},
108		{
109			path:               "./testdata/invalid/bad_syntax_2",
110			expectedParseError: true,
111		},
112		{
113			path:               "./testdata/invalid/incomplete_section_profile",
114			expectedParseError: true,
115		},
116		{
117			path:               "./testdata/invalid/syntax_error_comment",
118			expectedParseError: true,
119		},
120		{
121			path:               "./testdata/invalid/invalid_keys",
122			expectedParseError: true,
123		},
124		{
125			path:               "./testdata/invalid/bad_section_name",
126			expectedParseError: true,
127		},
128	}
129
130	for i, c := range cases {
131		t.Run(c.path, func(t *testing.T) {
132			f, err := os.Open(c.path)
133			if err != nil {
134				t.Errorf("unexpected error, %v", err)
135			}
136			defer f.Close()
137
138			tree, err := ParseAST(f)
139			if err != nil && !c.expectedParseError {
140				t.Errorf("%d: unexpected error, %v", i+1, err)
141			} else if err == nil && c.expectedParseError {
142				t.Errorf("%d: expected error, but received none", i+1)
143			}
144
145			if c.expectedParseError {
146				return
147			}
148
149			v := NewDefaultVisitor()
150			err = Walk(tree, v)
151			if err == nil && c.expectedWalkError {
152				t.Errorf("%d: expected error, but received none", i+1)
153			}
154		})
155	}
156}
157