1 // Copyright (c) 2017 Cisco and/or its affiliates.
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:
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
22 . "github.com/onsi/gomega"
25 func TestGetInputFiles(t *testing.T) {
27 result, err := getInputFiles("testdata")
28 Expect(err).ShouldNot(HaveOccurred())
29 Expect(result).To(HaveLen(3))
30 for _, file := range result {
31 Expect(file).To(BeAnExistingFile())
35 func TestGetInputFilesError(t *testing.T) {
37 result, err := getInputFiles("nonexisting_directory")
38 Expect(err).Should(HaveOccurred())
39 Expect(result).To(BeNil())
42 func TestGenerateFromFile(t *testing.T) {
44 outDir := "test_output_directory"
45 // remove directory created during test
46 defer os.RemoveAll(outDir)
47 err := generateFromFile("testdata/acl.api.json", outDir)
48 Expect(err).ShouldNot(HaveOccurred())
49 fileInfo, err := os.Stat(outDir + "/acl/acl.ba.go")
50 Expect(err).ShouldNot(HaveOccurred())
51 Expect(fileInfo.IsDir()).To(BeFalse())
52 Expect(fileInfo.Name()).To(BeEquivalentTo("acl.ba.go"))
55 func TestGenerateFromFileInputError(t *testing.T) {
57 outDir := "test_output_directory"
58 err := generateFromFile("testdata/nonexisting.json", outDir)
59 Expect(err).Should(HaveOccurred())
60 Expect(err.Error()).To(ContainSubstring("invalid input file name"))
63 func TestGenerateFromFileReadJsonError(t *testing.T) {
65 outDir := "test_output_directory"
66 err := generateFromFile("testdata/input-read-json-error.json", outDir)
67 Expect(err).Should(HaveOccurred())
68 Expect(err.Error()).To(ContainSubstring("invalid input file name"))
71 func TestGenerateFromFileGeneratePackageError(t *testing.T) {
73 outDir := "test_output_directory"
74 // generate package throws panic, recover after it
76 if recovery := recover(); recovery != nil {
77 t.Logf("Recovered from panic: %v", recovery)
81 err := generateFromFile("testdata/input-generate-error.json", outDir)
82 Expect(err).Should(HaveOccurred())
85 func TestGetContext(t *testing.T) {
87 outDir := "test_output_directory"
88 result, err := getContext("testdata/af_packet.api.json", outDir)
89 Expect(err).ShouldNot(HaveOccurred())
90 Expect(result).ToNot(BeNil())
91 Expect(result.outputFile).To(BeEquivalentTo(outDir + "/af_packet/af_packet.ba.go"))
94 func TestGetContextNoJsonFile(t *testing.T) {
96 outDir := "test_output_directory"
97 result, err := getContext("testdata/input.txt", outDir)
98 Expect(err).Should(HaveOccurred())
99 Expect(err.Error()).To(ContainSubstring("invalid input file name"))
100 Expect(result).To(BeNil())
103 func TestGetContextInterfaceJson(t *testing.T) {
105 outDir := "test_output_directory"
106 result, err := getContext("testdata/ip.api.json", outDir)
107 Expect(err).ShouldNot(HaveOccurred())
108 Expect(result).ToNot(BeNil())
109 Expect(result.outputFile)
110 Expect(result.outputFile).To(BeEquivalentTo(outDir + "/ip/ip.ba.go"))
113 func TestReadJson(t *testing.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))
123 func TestReadJsonError(t *testing.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())
132 func TestGeneratePackage(t *testing.T) {
135 testCtx := new(context)
136 testCtx.packageName = "test-package-name"
138 // prepare input/output output files
139 inputData, err := readFile("testdata/ip.api.json")
140 Expect(err).ShouldNot(HaveOccurred())
141 jsonRoot, err := parseJSON(inputData)
142 Expect(err).ShouldNot(HaveOccurred())
143 testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
144 Expect(err).ShouldNot(HaveOccurred())
145 outDir := "test_output_directory"
146 outFile, err := os.Create(outDir)
147 Expect(err).ShouldNot(HaveOccurred())
148 defer os.RemoveAll(outDir)
151 writer := bufio.NewWriter(outFile)
152 Expect(writer.Buffered()).To(BeZero())
153 err = generatePackage(testCtx, writer)
154 Expect(err).ShouldNot(HaveOccurred())
157 func TestGenerateMessageType(t *testing.T) {
160 testCtx := new(context)
161 testCtx.packageName = "test-package-name"
163 // prepare input/output output files
164 inputData, err := readFile("testdata/ip.api.json")
165 Expect(err).ShouldNot(HaveOccurred())
166 jsonRoot, err := parseJSON(inputData)
167 Expect(err).ShouldNot(HaveOccurred())
168 outDir := "test_output_directory"
169 outFile, err := os.Create(outDir)
170 Expect(err).ShouldNot(HaveOccurred())
171 testCtx.packageData, err = parsePackage(testCtx, jsonRoot)
172 Expect(err).ShouldNot(HaveOccurred())
173 defer os.RemoveAll(outDir)
176 writer := bufio.NewWriter(outFile)
178 for _, msg := range testCtx.packageData.Messages {
179 generateMessage(testCtx, writer, &msg)
180 Expect(writer.Buffered()).ToNot(BeZero())
184 /*func TestGenerateMessageName(t *testing.T) {
187 testCtx := new(context)
188 testCtx.packageName = "test-package-name"
190 // prepare input/output output files
191 inputData, err := readFile("testdata/ip.api.json")
192 Expect(err).ShouldNot(HaveOccurred())
193 testCtx.inputBuff = bytes.NewBuffer(inputData)
194 inFile, _ := parseJSON(inputData)
195 outDir := "test_output_directory"
196 outFile, err := os.Create(outDir)
197 Expect(err).ShouldNot(HaveOccurred())
198 defer os.RemoveAll(outDir)
201 writer := bufio.NewWriter(outFile)
203 types := inFile.Map("types")
204 Expect(types.Len()).To(BeEquivalentTo(1))
205 for i := 0; i < types.Len(); i++ {
207 Expect(writer.Buffered()).To(BeZero())
208 err := generateMessage(testCtx, writer, typ, false)
209 Expect(err).ShouldNot(HaveOccurred())
210 Expect(writer.Buffered()).ToNot(BeZero())
215 func TestGenerateMessageFieldTypes(t *testing.T) {
216 // expected results according to acl.api.json in testdata
217 expectedTypes := []string{
220 "\tSrcIPAddr []byte `struc:\"[16]byte\"`",
221 "\tSrcIPPrefixLen uint8",
222 "\tDstIPAddr []byte `struc:\"[16]byte\"`",
223 "\tDstIPPrefixLen uint8",
225 "\tSrcportOrIcmptypeFirst uint16",
226 "\tSrcportOrIcmptypeLast uint16",
227 "\tDstportOrIcmpcodeFirst uint16",
228 "\tDstportOrIcmpcodeLast uint16",
229 "\tTCPFlagsMask uint8",
230 "\tTCPFlagsValue uint8"}
233 testCtx := new(context)
234 testCtx.packageName = "test-package-name"
236 // prepare input/output output files
237 inputData, err := readFile("testdata/acl.api.json")
238 Expect(err).ShouldNot(HaveOccurred())
239 inFile, err := parseJSON(inputData)
240 Expect(err).ShouldNot(HaveOccurred())
241 Expect(inFile).ToNot(BeNil())
244 types := inFile.Map("types")
245 fields := make([]string, 0)
246 for i := 0; i < types.Len(); i++ {
247 for j := 0; j < types.At(i).Len(); j++ {
248 field := types.At(i).At(j)
249 if field.GetType() == jsongo.TypeArray {
250 err := processMessageField(testCtx, &fields, field, false)
251 Expect(err).ShouldNot(HaveOccurred())
252 Expect(fields[j-1]).To(BeEquivalentTo(expectedTypes[j-1]))
258 func TestGenerateMessageFieldMessages(t *testing.T) {
259 // expected results according to acl.api.json in testdata
260 expectedFields := []string{"\tMajor uint32", "\tMinor uint32", "\tRetval int32",
261 "\tVpePid uint32", "\tACLIndex uint32", "\tTag []byte `struc:\"[64]byte\"`",
265 testCtx := new(context)
266 testCtx.packageName = "test-package-name"
268 // prepare input/output output files
269 inputData, err := readFile("testdata/acl.api.json")
270 Expect(err).ShouldNot(HaveOccurred())
271 inFile, err := parseJSON(inputData)
272 Expect(err).ShouldNot(HaveOccurred())
273 Expect(inFile).ToNot(BeNil())
275 // test message fields
276 messages := inFile.Map("messages")
278 fields := make([]string, 0)
279 for i := 0; i < messages.Len(); i++ {
280 for j := 0; j < messages.At(i).Len(); j++ {
281 field := messages.At(i).At(j)
282 if field.GetType() == jsongo.TypeArray {
283 specificFieldName := field.At(1).Get().(string)
284 if specificFieldName == "crc" || specificFieldName == "_vl_msg_id" ||
285 specificFieldName == "client_index" || specificFieldName == "context" {
288 err := processMessageField(testCtx, &fields, field, false)
289 Expect(err).ShouldNot(HaveOccurred())
290 Expect(fields[customIndex]).To(BeEquivalentTo(expectedFields[customIndex]))
292 if customIndex >= len(expectedFields) {
293 // there is too much fields now for one UT...
301 func TestGeneratePackageHeader(t *testing.T) {
304 testCtx := new(context)
305 testCtx.packageName = "test-package-name"
307 // prepare input/output output files
308 inputData, err := readFile("testdata/acl.api.json")
309 Expect(err).ShouldNot(HaveOccurred())
310 inFile, err := parseJSON(inputData)
311 Expect(err).ShouldNot(HaveOccurred())
312 outDir := "test_output_directory"
313 outFile, err := os.Create(outDir)
314 Expect(err).ShouldNot(HaveOccurred())
315 defer os.RemoveAll(outDir)
317 writer := bufio.NewWriter(outFile)
318 Expect(writer.Buffered()).To(BeZero())
319 generateHeader(testCtx, writer, inFile)
320 Expect(writer.Buffered()).ToNot(BeZero())
323 func TestGenerateMessageCommentType(t *testing.T) {
326 testCtx := new(context)
327 testCtx.packageName = "test-package-name"
328 testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
330 outDir := "test_output_directory"
331 outFile, err := os.Create(outDir)
332 Expect(err).ShouldNot(HaveOccurred())
333 writer := bufio.NewWriter(outFile)
334 defer os.RemoveAll(outDir)
335 Expect(writer.Buffered()).To(BeZero())
336 generateMessageComment(testCtx, writer, "test-struct", "msg-name", true)
337 Expect(writer.Buffered()).ToNot(BeZero())
340 func TestGenerateMessageCommentMessage(t *testing.T) {
343 testCtx := new(context)
344 testCtx.packageName = "test-package-name"
345 testCtx.inputBuff = bytes.NewBuffer([]byte("test content"))
347 outDir := "test_output_directory"
348 outFile, err := os.Create(outDir)
349 Expect(err).ShouldNot(HaveOccurred())
350 writer := bufio.NewWriter(outFile)
351 defer os.RemoveAll(outDir)
352 Expect(writer.Buffered()).To(BeZero())
353 generateMessageComment(testCtx, writer, "test-struct", "msg-name", false)
354 Expect(writer.Buffered()).ToNot(BeZero())
357 func TestGenerateMessageNameGetter(t *testing.T) {
359 outDir := "test_output_directory"
360 outFile, err := os.Create(outDir)
361 Expect(err).ShouldNot(HaveOccurred())
362 writer := bufio.NewWriter(outFile)
363 defer os.RemoveAll(outDir)
364 Expect(writer.Buffered()).To(BeZero())
365 generateMessageNameGetter(writer, "test-struct", "msg-name")
366 Expect(writer.Buffered()).ToNot(BeZero())
369 func TestGenerateTypeNameGetter(t *testing.T) {
371 outDir := "test_output_directory"
372 outFile, err := os.Create(outDir)
373 Expect(err).ShouldNot(HaveOccurred())
374 writer := bufio.NewWriter(outFile)
375 defer os.RemoveAll(outDir)
376 Expect(writer.Buffered()).To(BeZero())
377 generateTypeNameGetter(writer, "test-struct", "msg-name")
378 Expect(writer.Buffered()).ToNot(BeZero())
381 func TestGenerateCrcGetter(t *testing.T) {
383 outDir := "test_output_directory"
384 outFile, err := os.Create(outDir)
385 Expect(err).ShouldNot(HaveOccurred())
386 writer := bufio.NewWriter(outFile)
387 defer os.RemoveAll(outDir)
388 Expect(writer.Buffered()).To(BeZero())
389 generateCrcGetter(writer, "test-struct", "msg-name")
390 Expect(writer.Buffered()).ToNot(BeZero())
393 func TestTranslateVppType(t *testing.T) {
395 context := new(context)
396 typesToTranslate := []string{"u8", "i8", "u16", "i16", "u32", "i32", "u64", "i64", "f64"}
397 expected := []string{"uint8", "int8", "uint16", "int16", "uint32", "int32", "uint64", "int64", "float64"}
398 var translated []string
399 for _, value := range typesToTranslate {
400 translated = append(translated, convertToGoType(context, value, false))
402 for index, value := range expected {
403 Expect(value).To(BeEquivalentTo(translated[index]))
408 func TestTranslateVppTypeArray(t *testing.T) {
410 context := new(context)
411 translated := convertToGoType(context, "u8", true)
412 Expect(translated).To(BeEquivalentTo("byte"))
415 func TestTranslateVppUnknownType(t *testing.T) {
417 if recovery := recover(); recovery != nil {
418 t.Logf("Recovered from panic: %v", recovery)
421 context := new(context)
422 convertToGoType(context, "?", false)
425 func TestCamelCase(t *testing.T) {
427 // test camel case functionality
428 expected := "allYourBaseAreBelongToUs"
429 result := camelCaseName("all_your_base_are_belong_to_us")
430 Expect(expected).To(BeEquivalentTo(result))
433 result = camelCaseName(expected)
434 Expect(expected).To(BeEquivalentTo(result))
437 result = camelCaseName(expected)
438 Expect(expected).To(BeEquivalentTo(result))
441 func TestCommonInitialisms(t *testing.T) {
444 for key, value := range commonInitialisms {
445 Expect(value).ShouldNot(BeFalse())
446 Expect(key).ShouldNot(BeEmpty())