1package generator
2
3import (
4	"bytes"
5	"fmt"
6	"go/format"
7	"testing"
8	"text/template"
9
10	"github.com/stretchr/testify/assert"
11	"github.com/stretchr/testify/require"
12)
13
14func TestYAMLParsing(t *testing.T) {
15	heuristics, err := parseYaml("test_files/heuristics.yml")
16
17	require.NoError(t, err)
18	assert.NotNil(t, heuristics)
19
20	// extensions
21	require.NotNil(t, heuristics.Disambiguations)
22	assert.Equal(t, 4, len(heuristics.Disambiguations))
23	assert.Equal(t, 2, len(heuristics.Disambiguations[0].Extensions))
24
25	rules := heuristics.Disambiguations[0].Rules
26	assert.Equal(t, 2, len(rules))
27	require.Equal(t, "Objective-C", rules[0].Languages[0])
28	assert.Equal(t, 1, len(rules[0].Pattern))
29
30	rules = heuristics.Disambiguations[1].Rules
31	assert.Equal(t, 3, len(rules))
32	require.Equal(t, "Forth", rules[0].Languages[0])
33	require.Equal(t, 2, len(rules[0].Pattern))
34
35	rules = heuristics.Disambiguations[2].Rules
36	assert.Equal(t, 3, len(rules))
37	require.Equal(t, "Unix Assembly", rules[1].Languages[0])
38	require.NotNil(t, rules[1].And)
39	assert.Equal(t, 2, len(rules[1].And))
40	require.NotNil(t, rules[1].And[0].NegativePattern)
41	assert.Equal(t, "np", rules[1].And[0].NegativePattern)
42
43	rules = heuristics.Disambiguations[3].Rules
44	assert.Equal(t, 1, len(rules))
45	assert.Equal(t, "Linux Kernel Module", rules[0].Languages[0])
46	assert.Equal(t, "AMPL", rules[0].Languages[1])
47
48	// named_patterns
49	require.NotNil(t, heuristics.NamedPatterns)
50	assert.Equal(t, 2, len(heuristics.NamedPatterns))
51	assert.Equal(t, 1, len(heuristics.NamedPatterns["fortran"]))
52	assert.Equal(t, 2, len(heuristics.NamedPatterns["cpp"]))
53}
54
55func TestSingleRuleLoading(t *testing.T) {
56	namedPatterns := map[string]StringArray{"cpp": []string{"cpp_ptrn1", "cpp_ptrn2"}}
57	rules := []*Rule{
58		&Rule{Languages: []string{"a"}, Patterns: Patterns{NamedPattern: "cpp"}},
59		&Rule{Languages: []string{"b"}, And: []*Rule{}},
60	}
61
62	// named_pattern case
63	langPattern := loadRule(namedPatterns, rules[0])
64	require.Equal(t, "a", langPattern.Langs[0])
65	assert.NotEmpty(t, langPattern.Pattern)
66
67	// and case
68	langPattern = loadRule(namedPatterns, rules[1])
69	require.Equal(t, "b", langPattern.Langs[0])
70}
71
72func TestLoadingAllHeuristics(t *testing.T) {
73	parsedYaml, err := parseYaml("test_files/heuristics.yml")
74	require.NoError(t, err)
75
76	hs, err := loadHeuristics(parsedYaml)
77
78	// grep -Eo "extensions:\ (.*)" internal/code-generator/generator/test_files/heuristics.yml
79	assert.Equal(t, 5, len(hs))
80}
81
82func TestLoadingHeuristicsForSameExt(t *testing.T) {
83	parsedYaml := &Heuristics{
84		Disambiguations: []*Disambiguation{
85			&Disambiguation{
86				Extensions: []string{".a", ".b"},
87				Rules:      []*Rule{&Rule{Languages: []string{"A"}}},
88			},
89			&Disambiguation{
90				Extensions: []string{".b"},
91				Rules:      []*Rule{&Rule{Languages: []string{"B"}}},
92			},
93		},
94	}
95
96	_, err := loadHeuristics(parsedYaml)
97	require.Error(t, err)
98}
99
100func TestTemplateMatcherVars(t *testing.T) {
101	parsed, err := parseYaml("test_files/heuristics.yml")
102	require.NoError(t, err)
103
104	heuristics, err := loadHeuristics(parsed)
105	require.NoError(t, err)
106
107	// render a tmpl
108	const contentTmpl = "../assets/content.go.tmpl"
109	tmpl, err := template.New("content.go.tmpl").Funcs(template.FuncMap{
110		"stringVal": func(val string) string {
111			return fmt.Sprintf("`%s`", val)
112		},
113	}).ParseFiles(contentTmpl)
114	require.NoError(t, err)
115
116	buf := bytes.NewBuffer(nil)
117	err = tmpl.Execute(buf, heuristics)
118	require.NoError(t, err, fmt.Sprintf("%+v", tmpl))
119	require.NotEmpty(t, buf)
120
121	// TODO(bzz) add more advanced test using go/ast package, to verify the
122	// strucutre of generated code:
123	//  - check key literal exists in map for each extension:
124
125	src, err := format.Source(buf.Bytes())
126	require.NoError(t, err, "\n%s\n", string(src))
127}
128