4bec874a092be6c18da071a06d2d71c4a6e913f5
[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         "io/ioutil"
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", 1)
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", 1)
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, nil)
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, nil)
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, nil)
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, nil)
83         Expect(err).Should(HaveOccurred())
84 }
85
86 func TestGetContext(t *testing.T) {
87         RegisterTestingT(t)
88         outDir := "test_output_directory"
89         result, err := newContext("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 := newContext("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 := newContext("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 := ioutil.ReadFile("testdata/af_packet.api.json")
117         Expect(err).ShouldNot(HaveOccurred())
118         result, err := parseInputJSON(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 := ioutil.ReadFile("testdata/input-read-json-error.json")
127         Expect(err).ShouldNot(HaveOccurred())
128         result, err := parseInputJSON(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 := ioutil.ReadFile("testdata/ip.api.json")
141         Expect(err).ShouldNot(HaveOccurred())
142         jsonRoot, err := parseInputJSON(inputData)
143         Expect(err).ShouldNot(HaveOccurred())
144         testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
145         Expect(err).ShouldNot(HaveOccurred())
146         outDir := "test_output_directory"
147         outFile, err := os.Create(outDir)
148         Expect(err).ShouldNot(HaveOccurred())
149         defer os.RemoveAll(outDir)
150
151         // prepare writer
152         writer := bufio.NewWriter(outFile)
153         Expect(writer.Buffered()).To(BeZero())
154         err = generatePackage(testCtx, writer)
155         Expect(err).ShouldNot(HaveOccurred())
156 }
157
158 func TestGenerateMessageType(t *testing.T) {
159         RegisterTestingT(t)
160         // prepare context
161         testCtx := new(context)
162         testCtx.packageName = "test-package-name"
163
164         // prepare input/output output files
165         inputData, err := ioutil.ReadFile("testdata/ip.api.json")
166         Expect(err).ShouldNot(HaveOccurred())
167         jsonRoot, err := parseInputJSON(inputData)
168         Expect(err).ShouldNot(HaveOccurred())
169         outDir := "test_output_directory"
170         outFile, err := os.Create(outDir)
171         Expect(err).ShouldNot(HaveOccurred())
172         testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
173         Expect(err).ShouldNot(HaveOccurred())
174         defer os.RemoveAll(outDir)
175
176         // prepare writer
177         writer := bufio.NewWriter(outFile)
178
179         for _, msg := range testCtx.packageData.Messages {
180                 generateMessage(testCtx, writer, &msg)
181                 Expect(writer.Buffered()).ToNot(BeZero())
182         }
183 }
184
185 /*func TestGenerateMessageName(t *testing.T) {
186         RegisterTestingT(t)
187         // prepare context
188         testCtx := new(context)
189         testCtx.packageName = "test-package-name"
190
191         // prepare input/output output files
192         inputData, err := readFile("testdata/ip.api.json")
193         Expect(err).ShouldNot(HaveOccurred())
194         testCtx.inputBuff = bytes.NewBuffer(inputData)
195         inFile, _ := parseJSON(inputData)
196         outDir := "test_output_directory"
197         outFile, err := os.Create(outDir)
198         Expect(err).ShouldNot(HaveOccurred())
199         defer os.RemoveAll(outDir)
200
201         // prepare writer
202         writer := bufio.NewWriter(outFile)
203
204         types := inFile.Map("types")
205         Expect(types.Len()).To(BeEquivalentTo(1))
206         for i := 0; i < types.Len(); i++ {
207                 typ := types.At(i)
208                 Expect(writer.Buffered()).To(BeZero())
209                 err := generateMessage(testCtx, writer, typ, false)
210                 Expect(err).ShouldNot(HaveOccurred())
211                 Expect(writer.Buffered()).ToNot(BeZero())
212
213         }
214 }
215
216 func TestGenerateMessageFieldTypes(t *testing.T) {
217         // expected results according to acl.api.json in testdata
218         expectedTypes := []string{
219                 "\tIsPermit uint8",
220                 "\tIsIpv6 uint8",
221                 "\tSrcIPAddr []byte     `struc:\"[16]byte\"`",
222                 "\tSrcIPPrefixLen uint8",
223                 "\tDstIPAddr []byte     `struc:\"[16]byte\"`",
224                 "\tDstIPPrefixLen uint8",
225                 "\tProto uint8",
226                 "\tSrcportOrIcmptypeFirst uint16",
227                 "\tSrcportOrIcmptypeLast uint16",
228                 "\tDstportOrIcmpcodeFirst uint16",
229                 "\tDstportOrIcmpcodeLast uint16",
230                 "\tTCPFlagsMask uint8",
231                 "\tTCPFlagsValue uint8"}
232         RegisterTestingT(t)
233         // prepare context
234         testCtx := new(context)
235         testCtx.packageName = "test-package-name"
236
237         // prepare input/output output files
238         inputData, err := readFile("testdata/acl.api.json")
239         Expect(err).ShouldNot(HaveOccurred())
240         inFile, err := parseJSON(inputData)
241         Expect(err).ShouldNot(HaveOccurred())
242         Expect(inFile).ToNot(BeNil())
243
244         // test types
245         types := inFile.Map("types")
246         fields := make([]string, 0)
247         for i := 0; i < types.Len(); i++ {
248                 for j := 0; j < types.At(i).Len(); j++ {
249                         field := types.At(i).At(j)
250                         if field.GetType() == jsongo.TypeArray {
251                                 err := processMessageField(testCtx, &fields, field, false)
252                                 Expect(err).ShouldNot(HaveOccurred())
253                                 Expect(fields[j-1]).To(BeEquivalentTo(expectedTypes[j-1]))
254                         }
255                 }
256         }
257 }
258
259 func TestGenerateMessageFieldMessages(t *testing.T) {
260         // expected results according to acl.api.json in testdata
261         expectedFields := []string{"\tMajor uint32", "\tMinor uint32", "\tRetval int32",
262                 "\tVpePid uint32", "\tACLIndex uint32", "\tTag []byte   `struc:\"[64]byte\"`",
263                 "\tCount uint32"}
264         RegisterTestingT(t)
265         // prepare context
266         testCtx := new(context)
267         testCtx.packageName = "test-package-name"
268
269         // prepare input/output output files
270         inputData, err := readFile("testdata/acl.api.json")
271         Expect(err).ShouldNot(HaveOccurred())
272         inFile, err := parseJSON(inputData)
273         Expect(err).ShouldNot(HaveOccurred())
274         Expect(inFile).ToNot(BeNil())
275
276         // test message fields
277         messages := inFile.Map("messages")
278         customIndex := 0
279         fields := make([]string, 0)
280         for i := 0; i < messages.Len(); i++ {
281                 for j := 0; j < messages.At(i).Len(); j++ {
282                         field := messages.At(i).At(j)
283                         if field.GetType() == jsongo.TypeArray {
284                                 specificFieldName := field.At(1).Get().(string)
285                                 if specificFieldName == "crc" || specificFieldName == "_vl_msg_id" ||
286                                         specificFieldName == "client_index" || specificFieldName == "context" {
287                                         continue
288                                 }
289                                 err := processMessageField(testCtx, &fields, field, false)
290                                 Expect(err).ShouldNot(HaveOccurred())
291                                 Expect(fields[customIndex]).To(BeEquivalentTo(expectedFields[customIndex]))
292                                 customIndex++
293                                 if customIndex >= len(expectedFields) {
294                                         // there is too much fields now for one UT...
295                                         return
296                                 }
297                         }
298                 }
299         }
300 }
301
302 func TestGeneratePackageHeader(t *testing.T) {
303         RegisterTestingT(t)
304         // prepare context
305         testCtx := new(context)
306         testCtx.packageName = "test-package-name"
307
308         // prepare input/output output files
309         inputData, err := readFile("testdata/acl.api.json")
310         Expect(err).ShouldNot(HaveOccurred())
311         inFile, err := parseJSON(inputData)
312         Expect(err).ShouldNot(HaveOccurred())
313         outDir := "test_output_directory"
314         outFile, err := os.Create(outDir)
315         Expect(err).ShouldNot(HaveOccurred())
316         defer os.RemoveAll(outDir)
317         // prepare writer
318         writer := bufio.NewWriter(outFile)
319         Expect(writer.Buffered()).To(BeZero())
320         generateHeader(testCtx, writer, inFile)
321         Expect(writer.Buffered()).ToNot(BeZero())
322 }
323
324 func TestGenerateMessageCommentType(t *testing.T) {
325         RegisterTestingT(t)
326         // prepare context
327         testCtx := new(context)
328         testCtx.packageName = "test-package-name"
329         testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
330
331         outDir := "test_output_directory"
332         outFile, err := os.Create(outDir)
333         Expect(err).ShouldNot(HaveOccurred())
334         writer := bufio.NewWriter(outFile)
335         defer os.RemoveAll(outDir)
336         Expect(writer.Buffered()).To(BeZero())
337         generateMessageComment(testCtx, writer, "test-struct", "msg-name", true)
338         Expect(writer.Buffered()).ToNot(BeZero())
339 }
340
341 func TestGenerateMessageCommentMessage(t *testing.T) {
342         RegisterTestingT(t)
343         // prepare context
344         testCtx := new(context)
345         testCtx.packageName = "test-package-name"
346         testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
347
348         outDir := "test_output_directory"
349         outFile, err := os.Create(outDir)
350         Expect(err).ShouldNot(HaveOccurred())
351         writer := bufio.NewWriter(outFile)
352         defer os.RemoveAll(outDir)
353         Expect(writer.Buffered()).To(BeZero())
354         generateMessageComment(testCtx, writer, "test-struct", "msg-name", false)
355         Expect(writer.Buffered()).ToNot(BeZero())
356 }
357
358 func TestGenerateMessageNameGetter(t *testing.T) {
359         RegisterTestingT(t)
360         outDir := "test_output_directory"
361         outFile, err := os.Create(outDir)
362         Expect(err).ShouldNot(HaveOccurred())
363         writer := bufio.NewWriter(outFile)
364         defer os.RemoveAll(outDir)
365         Expect(writer.Buffered()).To(BeZero())
366         generateMessageNameGetter(writer, "test-struct", "msg-name")
367         Expect(writer.Buffered()).ToNot(BeZero())
368 }
369
370 func TestGenerateTypeNameGetter(t *testing.T) {
371         RegisterTestingT(t)
372         outDir := "test_output_directory"
373         outFile, err := os.Create(outDir)
374         Expect(err).ShouldNot(HaveOccurred())
375         writer := bufio.NewWriter(outFile)
376         defer os.RemoveAll(outDir)
377         Expect(writer.Buffered()).To(BeZero())
378         generateTypeNameGetter(writer, "test-struct", "msg-name")
379         Expect(writer.Buffered()).ToNot(BeZero())
380 }
381
382 func TestGenerateCrcGetter(t *testing.T) {
383         RegisterTestingT(t)
384         outDir := "test_output_directory"
385         outFile, err := os.Create(outDir)
386         Expect(err).ShouldNot(HaveOccurred())
387         writer := bufio.NewWriter(outFile)
388         defer os.RemoveAll(outDir)
389         Expect(writer.Buffered()).To(BeZero())
390         generateCrcGetter(writer, "test-struct", "msg-name")
391         Expect(writer.Buffered()).ToNot(BeZero())
392 }
393
394 func TestTranslateVppType(t *testing.T) {
395         RegisterTestingT(t)
396         context := new(context)
397         typesToTranslate := []string{"u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f64"}
398         expected := []string{"uint8", "int8", "uint16", "int16", "uint32", "int32", "uint64", "int64", "float64"}
399         var translated []string
400         for _, value := range typesToTranslate {
401                 translated = append(translated, convertToGoType(context, value, false))
402         }
403         for index, value := range expected {
404                 Expect(value).To(BeEquivalentTo(translated[index]))
405         }
406
407 }
408
409 func TestTranslateVppTypeArray(t *testing.T) {
410         RegisterTestingT(t)
411         context := new(context)
412         translated := convertToGoType(context, "u8", true)
413         Expect(translated).To(BeEquivalentTo("byte"))
414 }
415
416 func TestTranslateVppUnknownType(t *testing.T) {
417         defer func() {
418                 if recovery := recover(); recovery != nil {
419                         t.Logf("Recovered from panic: %v", recovery)
420                 }
421         }()
422         context := new(context)
423         convertToGoType(context, "?", false)
424 }
425
426 func TestCamelCase(t *testing.T) {
427         RegisterTestingT(t)
428         // test camel case functionality
429         expected := "allYourBaseAreBelongToUs"
430         result := camelCaseName("all_your_base_are_belong_to_us")
431         Expect(expected).To(BeEquivalentTo(result))
432         // test underscore
433         expected = "_"
434         result = camelCaseName(expected)
435         Expect(expected).To(BeEquivalentTo(result))
436         // test all lower
437         expected = "lower"
438         result = camelCaseName(expected)
439         Expect(expected).To(BeEquivalentTo(result))
440 }
441
442 func TestCommonInitialisms(t *testing.T) {
443         RegisterTestingT(t)
444
445         for key, value := range commonInitialisms {
446                 Expect(value).ShouldNot(BeFalse())
447                 Expect(key).ShouldNot(BeEmpty())
448         }
449 }
450 */