...
1
2
3
4
5
6
7 package main
8
9 import (
10 "bytes"
11 "flag"
12 "fmt"
13 "go/format"
14 "log"
15 "os"
16 "path/filepath"
17 "strconv"
18 "strings"
19 "text/template"
20 "time"
21 )
22
23 type invalid struct {
24 Name string
25 Input string
26 }
27
28 type valid struct {
29 Name string
30 Input string
31 JsonRef string
32 }
33
34 type testsCollection struct {
35 Ref string
36 Timestamp string
37 Invalid []invalid
38 Valid []valid
39 Count int
40 }
41
42 const srcTemplate = "// Generated by tomltestgen for toml-test ref {{.Ref}} on {{.Timestamp}}\n" +
43 "package toml_test\n" +
44 " import (\n" +
45 " \"testing\"\n" +
46 ")\n" +
47
48 "{{range .Invalid}}\n" +
49 "func TestTOMLTest_Invalid_{{.Name}}(t *testing.T) {\n" +
50 " input := {{.Input|gostr}}\n" +
51 " testgenInvalid(t, input)\n" +
52 "}\n" +
53 "{{end}}\n" +
54 "\n" +
55 "{{range .Valid}}\n" +
56 "func TestTOMLTest_Valid_{{.Name}}(t *testing.T) {\n" +
57 " input := {{.Input|gostr}}\n" +
58 " jsonRef := {{.JsonRef|gostr}}\n" +
59 " testgenValid(t, input, jsonRef)\n" +
60 "}\n" +
61 "{{end}}\n"
62
63 func kebabToCamel(kebab string) string {
64 camel := ""
65 nextUpper := true
66 for _, c := range kebab {
67 if nextUpper {
68 camel += strings.ToUpper(string(c))
69 nextUpper = false
70 } else if c == '-' {
71 nextUpper = true
72 } else if c == '/' {
73 nextUpper = true
74 camel += "_"
75 } else {
76 camel += string(c)
77 }
78 }
79 return camel
80 }
81
82 func templateGoStr(input string) string {
83 return strconv.Quote(input)
84 }
85
86 var (
87 ref = flag.String("r", "master", "git reference")
88 out = flag.String("o", "", "output file")
89 )
90
91 func usage() {
92 _, _ = fmt.Fprintf(os.Stderr, "usage: tomltestgen [flags]\n")
93 flag.PrintDefaults()
94 }
95
96 func main() {
97 flag.Usage = usage
98 flag.Parse()
99
100 collection := testsCollection{
101 Ref: *ref,
102 Timestamp: time.Now().Format(time.RFC3339),
103 }
104
105 dirContent, _ := filepath.Glob("tests/invalid/**/*.toml")
106 for _, f := range dirContent {
107 filename := strings.TrimPrefix(f, "tests/valid/")
108 name := kebabToCamel(strings.TrimSuffix(filename, ".toml"))
109
110 log.Printf("> [%s] %s\n", "invalid", name)
111
112 tomlContent, err := os.ReadFile(f)
113 if err != nil {
114 fmt.Printf("failed to read test file: %s\n", err)
115 os.Exit(1)
116 }
117
118 collection.Invalid = append(collection.Invalid, invalid{
119 Name: name,
120 Input: string(tomlContent),
121 })
122 collection.Count++
123 }
124
125 dirContent, _ = filepath.Glob("tests/valid/**/*.toml")
126 for _, f := range dirContent {
127 filename := strings.TrimPrefix(f, "tests/valid/")
128 name := kebabToCamel(strings.TrimSuffix(filename, ".toml"))
129
130 log.Printf("> [%s] %s\n", "valid", name)
131
132 tomlContent, err := os.ReadFile(f)
133 if err != nil {
134 fmt.Printf("failed reading test file: %s\n", err)
135 os.Exit(1)
136 }
137
138 filename = strings.TrimSuffix(f, ".toml")
139 jsonContent, err := os.ReadFile(filename + ".json")
140 if err != nil {
141 fmt.Printf("failed reading validation json: %s\n", err)
142 os.Exit(1)
143 }
144
145 collection.Valid = append(collection.Valid, valid{
146 Name: name,
147 Input: string(tomlContent),
148 JsonRef: string(jsonContent),
149 })
150 collection.Count++
151 }
152
153 log.Printf("Collected %d tests from toml-test\n", collection.Count)
154
155 funcMap := template.FuncMap{
156 "gostr": templateGoStr,
157 }
158 t := template.Must(template.New("src").Funcs(funcMap).Parse(srcTemplate))
159 buf := new(bytes.Buffer)
160 err := t.Execute(buf, collection)
161 if err != nil {
162 panic(err)
163 }
164 outputBytes, err := format.Source(buf.Bytes())
165 if err != nil {
166 panic(err)
167 }
168
169 if *out == "" {
170 fmt.Println(string(outputBytes))
171 return
172 }
173
174 err = os.WriteFile(*out, outputBytes, 0o644)
175 if err != nil {
176 panic(err)
177 }
178 }
179
View as plain text