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