4b0673344a2262138ce2659c5df65279cb1cac52
[govpp.git] / cmd / binapi-generator / generate_test.go
1 // Copyright (c) 2017 Cisco and/or its affiliates.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at:
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package main
16
17 import (
18         "bufio"
19         "bytes"
20         "os"
21         "testing"
22
23         . "github.com/onsi/gomega"
24 )
25
26 func TestGetInputFiles(t *testing.T) {
27         RegisterTestingT(t)
28         result, err := getInputFiles("testdata")
29         Expect(err).ShouldNot(HaveOccurred())
30         Expect(result).To(HaveLen(3))
31         for _, file := range result {
32                 Expect(file).To(BeAnExistingFile())
33         }
34 }
35
36 func TestGetInputFilesError(t *testing.T) {
37         RegisterTestingT(t)
38         result, err := getInputFiles("nonexisting_directory")
39         Expect(err).Should(HaveOccurred())
40         Expect(result).To(BeNil())
41 }
42
43 func TestGenerateFromFile(t *testing.T) {
44         RegisterTestingT(t)
45         outDir := "test_output_directory"
46         // remove directory created during test
47         defer os.RemoveAll(outDir)
48         err := generateFromFile("testdata/acl.api.json", outDir)
49         Expect(err).ShouldNot(HaveOccurred())
50         fileInfo, err := os.Stat(outDir + "/acl/acl.ba.go")
51         Expect(err).ShouldNot(HaveOccurred())
52         Expect(fileInfo.IsDir()).To(BeFalse())
53         Expect(fileInfo.Name()).To(BeEquivalentTo("acl.ba.go"))
54 }
55
56 func TestGenerateFromFileInputError(t *testing.T) {
57         RegisterTestingT(t)
58         outDir := "test_output_directory"
59         err := generateFromFile("testdata/nonexisting.json", outDir)
60         Expect(err).Should(HaveOccurred())
61         Expect(err.Error()).To(ContainSubstring("invalid input file name"))
62 }
63
64 func TestGenerateFromFileReadJsonError(t *testing.T) {
65         RegisterTestingT(t)
66         outDir := "test_output_directory"
67         err := generateFromFile("testdata/input-read-json-error.json", outDir)
68         Expect(err).Should(HaveOccurred())
69         Expect(err.Error()).To(ContainSubstring("invalid input file name"))
70 }
71
72 func TestGenerateFromFileGeneratePackageError(t *testing.T) {
73         RegisterTestingT(t)
74         outDir := "test_output_directory"
75         // generate package throws panic, recover after it
76         defer func() {
77                 if recovery := recover(); recovery != nil {
78                         t.Logf("Recovered from panic: %v", recovery)
79                 }
80                 os.RemoveAll(outDir)
81         }()
82         err := generateFromFile("testdata/input-generate-error.json", outDir)
83         Expect(err).Should(HaveOccurred())
84 }
85
86 func TestGetContext(t *testing.T) {
87         RegisterTestingT(t)
88         outDir := "test_output_directory"
89         result, err := getContext("testdata/af_packet.api.json", outDir)
90         Expect(err).ShouldNot(HaveOccurred())
91         Expect(result).ToNot(BeNil())
92         Expect(result.outputFile).To(BeEquivalentTo(outDir + "/af_packet/af_packet.ba.go"))
93 }
94
95 func TestGetContextNoJsonFile(t *testing.T) {
96         RegisterTestingT(t)
97         outDir := "test_output_directory"
98         result, err := getContext("testdata/input.txt", outDir)
99         Expect(err).Should(HaveOccurred())
100         Expect(err.Error()).To(ContainSubstring("invalid input file name"))
101         Expect(result).To(BeNil())
102 }
103
104 func TestGetContextInterfaceJson(t *testing.T) {
105         RegisterTestingT(t)
106         outDir := "test_output_directory"
107         result, err := getContext("testdata/ip.api.json", outDir)
108         Expect(err).ShouldNot(HaveOccurred())
109         Expect(result).ToNot(BeNil())
110         Expect(result.outputFile)
111         Expect(result.outputFile).To(BeEquivalentTo(outDir + "/ip/ip.ba.go"))
112 }
113
114 func TestReadJson(t *testing.T) {
115         RegisterTestingT(t)
116         inputData, err := readFile("testdata/af_packet.api.json")
117         Expect(err).ShouldNot(HaveOccurred())
118         result, err := parseJSON(inputData)
119         Expect(err).ShouldNot(HaveOccurred())
120         Expect(result).ToNot(BeNil())
121         Expect(result.Len()).To(BeEquivalentTo(5))
122 }
123
124 func TestReadJsonError(t *testing.T) {
125         RegisterTestingT(t)
126         inputData, err := readFile("testdata/input-read-json-error.json")
127         Expect(err).ShouldNot(HaveOccurred())
128         result, err := parseJSON(inputData)
129         Expect(err).Should(HaveOccurred())
130         Expect(result).To(BeNil())
131 }
132
133 func TestGeneratePackage(t *testing.T) {
134         RegisterTestingT(t)
135         // prepare context
136         testCtx := new(context)
137         testCtx.packageName = "test-package-name"
138
139         // prepare input/output output files
140         inputData, err := readFile("testdata/ip.api.json")
141         Expect(err).ShouldNot(HaveOccurred())
142         testCtx.inputBuff = bytes.NewBuffer(inputData)
143         jsonRoot, err := parseJSON(inputData)
144         Expect(err).ShouldNot(HaveOccurred())
145         testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
146         Expect(err).ShouldNot(HaveOccurred())
147         outDir := "test_output_directory"
148         outFile, err := os.Create(outDir)
149         Expect(err).ShouldNot(HaveOccurred())
150         defer os.RemoveAll(outDir)
151
152         // prepare writer
153         writer := bufio.NewWriter(outFile)
154         Expect(writer.Buffered()).To(BeZero())
155         err = generatePackage(testCtx, writer)
156         Expect(err).ShouldNot(HaveOccurred())
157 }
158
159 func TestGenerateMessageType(t *testing.T) {
160         RegisterTestingT(t)
161         // prepare context
162         testCtx := new(context)
163         testCtx.packageName = "test-package-name"
164
165         // prepare input/output output files
166         inputData, err := readFile("testdata/ip.api.json")
167         Expect(err).ShouldNot(HaveOccurred())
168         testCtx.inputBuff = bytes.NewBuffer(inputData)
169         jsonRoot, err := parseJSON(inputData)
170         Expect(err).ShouldNot(HaveOccurred())
171         outDir := "test_output_directory"
172         outFile, err := os.Create(outDir)
173         Expect(err).ShouldNot(HaveOccurred())
174         testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
175         Expect(err).ShouldNot(HaveOccurred())
176         defer os.RemoveAll(outDir)
177
178         // prepare writer
179         writer := bufio.NewWriter(outFile)
180
181         for _, msg := range testCtx.packageData.Messages {
182                 generateMessage(testCtx, writer, &msg)
183                 Expect(writer.Buffered()).ToNot(BeZero())
184         }
185 }
186
187 /*func TestGenerateMessageName(t *testing.T) {
188         RegisterTestingT(t)
189         // prepare context
190         testCtx := new(context)
191         testCtx.packageName = "test-package-name"
192
193         // prepare input/output output files
194         inputData, err := readFile("testdata/ip.api.json")
195         Expect(err).ShouldNot(HaveOccurred())
196         testCtx.inputBuff = bytes.NewBuffer(inputData)
197         inFile, _ := parseJSON(inputData)
198         outDir := "test_output_directory"
199         outFile, err := os.Create(outDir)
200         Expect(err).ShouldNot(HaveOccurred())
201         defer os.RemoveAll(outDir)
202
203         // prepare writer
204         writer := bufio.NewWriter(outFile)
205
206         types := inFile.Map("types")
207         Expect(types.Len()).To(BeEquivalentTo(1))
208         for i := 0; i < types.Len(); i++ {
209                 typ := types.At(i)
210                 Expect(writer.Buffered()).To(BeZero())
211                 err := generateMessage(testCtx, writer, typ, false)
212                 Expect(err).ShouldNot(HaveOccurred())
213                 Expect(writer.Buffered()).ToNot(BeZero())
214
215         }
216 }
217
218 func TestGenerateMessageFieldTypes(t *testing.T) {
219         // expected results according to acl.api.json in testdata
220         expectedTypes := []string{
221                 "\tIsPermit uint8",
222                 "\tIsIpv6 uint8",
223                 "\tSrcIPAddr []byte     `struc:\"[16]byte\"`",
224                 "\tSrcIPPrefixLen uint8",
225                 "\tDstIPAddr []byte     `struc:\"[16]byte\"`",
226                 "\tDstIPPrefixLen uint8",
227                 "\tProto uint8",
228                 "\tSrcportOrIcmptypeFirst uint16",
229                 "\tSrcportOrIcmptypeLast uint16",
230                 "\tDstportOrIcmpcodeFirst uint16",
231                 "\tDstportOrIcmpcodeLast uint16",
232                 "\tTCPFlagsMask uint8",
233                 "\tTCPFlagsValue uint8"}
234         RegisterTestingT(t)
235         // prepare context
236         testCtx := new(context)
237         testCtx.packageName = "test-package-name"
238
239         // prepare input/output output files
240         inputData, err := readFile("testdata/acl.api.json")
241         Expect(err).ShouldNot(HaveOccurred())
242         inFile, err := parseJSON(inputData)
243         Expect(err).ShouldNot(HaveOccurred())
244         Expect(inFile).ToNot(BeNil())
245
246         // test types
247         types := inFile.Map("types")
248         fields := make([]string, 0)
249         for i := 0; i < types.Len(); i++ {
250                 for j := 0; j < types.At(i).Len(); j++ {
251                         field := types.At(i).At(j)
252                         if field.GetType() == jsongo.TypeArray {
253                                 err := processMessageField(testCtx, &fields, field, false)
254                                 Expect(err).ShouldNot(HaveOccurred())
255                                 Expect(fields[j-1]).To(BeEquivalentTo(expectedTypes[j-1]))
256                         }
257                 }
258         }
259 }
260
261 func TestGenerateMessageFieldMessages(t *testing.T) {
262         // expected results according to acl.api.json in testdata
263         expectedFields := []string{"\tMajor uint32", "\tMinor uint32", "\tRetval int32",
264                 "\tVpePid uint32", "\tACLIndex uint32", "\tTag []byte   `struc:\"[64]byte\"`",
265                 "\tCount uint32"}
266         RegisterTestingT(t)
267         // prepare context
268         testCtx := new(context)
269         testCtx.packageName = "test-package-name"
270
271         // prepare input/output output files
272         inputData, err := readFile("testdata/acl.api.json")
273         Expect(err).ShouldNot(HaveOccurred())
274         inFile, err := parseJSON(inputData)
275         Expect(err).ShouldNot(HaveOccurred())
276         Expect(inFile).ToNot(BeNil())
277
278         // test message fields
279         messages := inFile.Map("messages")
280         customIndex := 0
281         fields := make([]string, 0)
282         for i := 0; i < messages.Len(); i++ {
283                 for j := 0; j < messages.At(i).Len(); j++ {
284                         field := messages.At(i).At(j)
285                         if field.GetType() == jsongo.TypeArray {
286                                 specificFieldName := field.At(1).Get().(string)
287                                 if specificFieldName == "crc" || specificFieldName == "_vl_msg_id" ||
288                                         specificFieldName == "client_index" || specificFieldName == "context" {
289                                         continue
290                                 }
291                                 err := processMessageField(testCtx, &fields, field, false)
292                                 Expect(err).ShouldNot(HaveOccurred())
293                                 Expect(fields[customIndex]).To(BeEquivalentTo(expectedFields[customIndex]))
294                                 customIndex++
295                                 if customIndex >= len(expectedFields) {
296                                         // there is too much fields now for one UT...
297                                         return
298                                 }
299                         }
300                 }
301         }
302 }
303
304 func TestGeneratePackageHeader(t *testing.T) {
305         RegisterTestingT(t)
306         // prepare context
307         testCtx := new(context)
308         testCtx.packageName = "test-package-name"
309
310         // prepare input/output output files
311         inputData, err := readFile("testdata/acl.api.json")
312         Expect(err).ShouldNot(HaveOccurred())
313         inFile, err := parseJSON(inputData)
314         Expect(err).ShouldNot(HaveOccurred())
315         outDir := "test_output_directory"
316         outFile, err := os.Create(outDir)
317         Expect(err).ShouldNot(HaveOccurred())
318         defer os.RemoveAll(outDir)
319         // prepare writer
320         writer := bufio.NewWriter(outFile)
321         Expect(writer.Buffered()).To(BeZero())
322         generateHeader(testCtx, writer, inFile)
323         Expect(writer.Buffered()).ToNot(BeZero())
324 }
325
326 func TestGenerateMessageCommentType(t *testing.T) {
327         RegisterTestingT(t)
328         // prepare context
329         testCtx := new(context)
330         testCtx.packageName = "test-package-name"
331         testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
332
333         outDir := "test_output_directory"
334         outFile, err := os.Create(outDir)
335         Expect(err).ShouldNot(HaveOccurred())
336         writer := bufio.NewWriter(outFile)
337         defer os.RemoveAll(outDir)
338         Expect(writer.Buffered()).To(BeZero())
339         generateMessageComment(testCtx, writer, "test-struct", "msg-name", true)
340         Expect(writer.Buffered()).ToNot(BeZero())
341 }
342
343 func TestGenerateMessageCommentMessage(t *testing.T) {
344         RegisterTestingT(t)
345         // prepare context
346         testCtx := new(context)
347         testCtx.packageName = "test-package-name"
348         testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
349
350         outDir := "test_output_directory"
351         outFile, err := os.Create(outDir)
352         Expect(err).ShouldNot(HaveOccurred())
353         writer := bufio.NewWriter(outFile)
354         defer os.RemoveAll(outDir)
355         Expect(writer.Buffered()).To(BeZero())
356         generateMessageComment(testCtx, writer, "test-struct", "msg-name", false)
357         Expect(writer.Buffered()).ToNot(BeZero())
358 }
359
360 func TestGenerateMessageNameGetter(t *testing.T) {
361         RegisterTestingT(t)
362         outDir := "test_output_directory"
363         outFile, err := os.Create(outDir)
364         Expect(err).ShouldNot(HaveOccurred())
365         writer := bufio.NewWriter(outFile)
366         defer os.RemoveAll(outDir)
367         Expect(writer.Buffered()).To(BeZero())
368         generateMessageNameGetter(writer, "test-struct", "msg-name")
369         Expect(writer.Buffered()).ToNot(BeZero())
370 }
371
372 func TestGenerateTypeNameGetter(t *testing.T) {
373         RegisterTestingT(t)
374         outDir := "test_output_directory"
375         outFile, err := os.Create(outDir)
376         Expect(err).ShouldNot(HaveOccurred())
377         writer := bufio.NewWriter(outFile)
378         defer os.RemoveAll(outDir)
379         Expect(writer.Buffered()).To(BeZero())
380         generateTypeNameGetter(writer, "test-struct", "msg-name")
381         Expect(writer.Buffered()).ToNot(BeZero())
382 }
383
384 func TestGenerateCrcGetter(t *testing.T) {
385         RegisterTestingT(t)
386         outDir := "test_output_directory"
387         outFile, err := os.Create(outDir)
388         Expect(err).ShouldNot(HaveOccurred())
389         writer := bufio.NewWriter(outFile)
390         defer os.RemoveAll(outDir)
391         Expect(writer.Buffered()).To(BeZero())
392         generateCrcGetter(writer, "test-struct", "msg-name")
393         Expect(writer.Buffered()).ToNot(BeZero())
394 }
395
396 func TestTranslateVppType(t *testing.T) {
397         RegisterTestingT(t)
398         context := new(context)
399         typesToTranslate := []string{"u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f64"}
400         expected := []string{"uint8", "int8", "uint16", "int16", "uint32", "int32", "uint64", "int64", "float64"}
401         var translated []string
402         for _, value := range typesToTranslate {
403                 translated = append(translated, convertToGoType(context, value, false))
404         }
405         for index, value := range expected {
406                 Expect(value).To(BeEquivalentTo(translated[index]))
407         }
408
409 }
410
411 func TestTranslateVppTypeArray(t *testing.T) {
412         RegisterTestingT(t)
413         context := new(context)
414         translated := convertToGoType(context, "u8", true)
415         Expect(translated).To(BeEquivalentTo("byte"))
416 }
417
418 func TestTranslateVppUnknownType(t *testing.T) {
419         defer func() {
420                 if recovery := recover(); recovery != nil {
421                         t.Logf("Recovered from panic: %v", recovery)
422                 }
423         }()
424         context := new(context)
425         convertToGoType(context, "?", false)
426 }
427
428 func TestCamelCase(t *testing.T) {
429         RegisterTestingT(t)
430         // test camel case functionality
431         expected := "allYourBaseAreBelongToUs"
432         result := camelCaseName("all_your_base_are_belong_to_us")
433         Expect(expected).To(BeEquivalentTo(result))
434         // test underscore
435         expected = "_"
436         result = camelCaseName(expected)
437         Expect(expected).To(BeEquivalentTo(result))
438         // test all lower
439         expected = "lower"
440         result = camelCaseName(expected)
441         Expect(expected).To(BeEquivalentTo(result))
442 }
443
444 func TestCommonInitialisms(t *testing.T) {
445         RegisterTestingT(t)
446
447         for key, value := range commonInitialisms {
448                 Expect(value).ShouldNot(BeFalse())
449                 Expect(key).ShouldNot(BeEmpty())
450         }
451 }
452 */