]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/UnitTest/DecParserUnitTest.py
BaseTools: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / BaseTools / Source / Python / UPT / UnitTest / DecParserUnitTest.py
1 ## @file
2 # This file contain unit test for DecParser
3 #
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 import os
9 import unittest
10 from Logger.Log import FatalError
11
12 from Parser.DecParser import \
13 Dec, \
14 _DecDefine, \
15 _DecLibraryclass, \
16 _DecPcd, \
17 _DecGuid, \
18 FileContent, \
19 _DecBase, \
20 CleanString
21
22 from Object.Parser.DecObject import _DecComments
23
24 #
25 # Test CleanString
26 #
27 class CleanStringTestCase(unittest.TestCase):
28 def testCleanString(self):
29 Line, Comment = CleanString('')
30 self.assertEqual(Line, '')
31 self.assertEqual(Comment, '')
32
33 Line, Comment = CleanString('line without comment')
34 self.assertEqual(Line, 'line without comment')
35 self.assertEqual(Comment, '')
36
37 Line, Comment = CleanString('# pure comment')
38 self.assertEqual(Line, '')
39 self.assertEqual(Comment, '# pure comment')
40
41 Line, Comment = CleanString('line # and comment')
42 self.assertEqual(Line, 'line')
43 self.assertEqual(Comment, '# and comment')
44
45 def testCleanStringCpp(self):
46 Line, Comment = CleanString('line // and comment', AllowCppStyleComment = True)
47 self.assertEqual(Line, 'line')
48 self.assertEqual(Comment, '# and comment')
49
50 #
51 # Test _DecBase._MacroParser function
52 #
53 class MacroParserTestCase(unittest.TestCase):
54 def setUp(self):
55 self.dec = _DecBase(FileContent('dummy', []))
56
57 def testCorrectMacro(self):
58 self.dec._MacroParser('DEFINE MACRO1 = test1')
59 self.failIf('MACRO1' not in self.dec._LocalMacro)
60 self.assertEqual(self.dec._LocalMacro['MACRO1'], 'test1')
61
62 def testErrorMacro1(self):
63 # Raise fatal error, macro name must be upper case letter
64 self.assertRaises(FatalError, self.dec._MacroParser, 'DEFINE not_upper_case = test2')
65
66 def testErrorMacro2(self):
67 # No macro name given
68 self.assertRaises(FatalError, self.dec._MacroParser, 'DEFINE ')
69
70 #
71 # Test _DecBase._TryBackSlash function
72 #
73 class TryBackSlashTestCase(unittest.TestCase):
74 def setUp(self):
75 Content = [
76 # Right case
77 'test no backslash',
78
79 'test with backslash \\',
80 'continue second line',
81
82 # Do not precede with whitespace
83 '\\',
84
85 # Empty line after backlash is not allowed
86 'line with backslash \\',
87 ''
88 ]
89 self.dec = _DecBase(FileContent('dummy', Content))
90
91 def testBackSlash(self):
92 #
93 # Right case, assert return values
94 #
95 ConcatLine, CommentList = self.dec._TryBackSlash(self.dec._RawData.GetNextLine(), [])
96 self.assertEqual(ConcatLine, 'test no backslash')
97 self.assertEqual(CommentList, [])
98
99 ConcatLine, CommentList = self.dec._TryBackSlash(self.dec._RawData.GetNextLine(), [])
100 self.assertEqual(CommentList, [])
101 self.assertEqual(ConcatLine, 'test with backslash continue second line')
102
103 #
104 # Error cases, assert raise exception
105 #
106 self.assertRaises(FatalError, self.dec._TryBackSlash, self.dec._RawData.GetNextLine(), [])
107 self.assertRaises(FatalError, self.dec._TryBackSlash, self.dec._RawData.GetNextLine(), [])
108
109 #
110 # Test _DecBase.Parse function
111 #
112 class DataItem(_DecComments):
113 def __init__(self):
114 _DecComments.__init__(self)
115 self.String = ''
116
117 class Data(_DecComments):
118 def __init__(self):
119 _DecComments.__init__(self)
120 # List of DataItem
121 self.ItemList = []
122
123 class TestInner(_DecBase):
124 def __init__(self, RawData):
125 _DecBase.__init__(self, RawData)
126 self.ItemObject = Data()
127
128 def _StopCurrentParsing(self, Line):
129 return Line == '[TOP]'
130
131 def _ParseItem(self):
132 Item = DataItem()
133 Item.String = self._RawData.CurrentLine
134 self.ItemObject.ItemList.append(Item)
135 return Item
136
137 def _TailCommentStrategy(self, Comment):
138 return Comment.find('@comment') != -1
139
140 class TestTop(_DecBase):
141 def __init__(self, RawData):
142 _DecBase.__init__(self, RawData)
143 # List of Data
144 self.ItemObject = []
145
146 # Top parser
147 def _StopCurrentParsing(self, Line):
148 return False
149
150 def _ParseItem(self):
151 TestParser = TestInner(self._RawData)
152 TestParser.Parse()
153 self.ItemObject.append(TestParser.ItemObject)
154 return TestParser.ItemObject
155
156 class ParseTestCase(unittest.TestCase):
157 def setUp(self):
158 pass
159
160 def testParse(self):
161 Content = \
162 '''# Top comment
163 [TOP]
164 # sub1 head comment
165 (test item has both head and tail comment) # sub1 tail comment
166 # sub2 head comment
167 (test item has head and special tail comment)
168 # @comment test TailCommentStrategy branch
169
170 (test item has no comment)
171
172 # test NextLine branch
173 [TOP]
174 sub-item
175 '''
176 dec = TestTop(FileContent('dummy', Content.splitlines()))
177 dec.Parse()
178
179 # Two sections
180 self.assertEqual(len(dec.ItemObject), 2)
181
182 data = dec.ItemObject[0]
183 self.assertEqual(data._HeadComment[0][0], '# Top comment')
184 self.assertEqual(data._HeadComment[0][1], 1)
185
186 # 3 subitems
187 self.assertEqual(len(data.ItemList), 3)
188
189 dataitem = data.ItemList[0]
190 self.assertEqual(dataitem.String, '(test item has both head and tail comment)')
191 # Comment content
192 self.assertEqual(dataitem._HeadComment[0][0], '# sub1 head comment')
193 self.assertEqual(dataitem._TailComment[0][0], '# sub1 tail comment')
194 # Comment line number
195 self.assertEqual(dataitem._HeadComment[0][1], 3)
196 self.assertEqual(dataitem._TailComment[0][1], 4)
197
198 dataitem = data.ItemList[1]
199 self.assertEqual(dataitem.String, '(test item has head and special tail comment)')
200 # Comment content
201 self.assertEqual(dataitem._HeadComment[0][0], '# sub2 head comment')
202 self.assertEqual(dataitem._TailComment[0][0], '# @comment test TailCommentStrategy branch')
203 # Comment line number
204 self.assertEqual(dataitem._HeadComment[0][1], 5)
205 self.assertEqual(dataitem._TailComment[0][1], 7)
206
207 dataitem = data.ItemList[2]
208 self.assertEqual(dataitem.String, '(test item has no comment)')
209 # Comment content
210 self.assertEqual(dataitem._HeadComment, [])
211 self.assertEqual(dataitem._TailComment, [])
212
213 data = dec.ItemObject[1]
214 self.assertEqual(data._HeadComment[0][0], '# test NextLine branch')
215 self.assertEqual(data._HeadComment[0][1], 11)
216
217 # 1 subitems
218 self.assertEqual(len(data.ItemList), 1)
219
220 dataitem = data.ItemList[0]
221 self.assertEqual(dataitem.String, 'sub-item')
222 self.assertEqual(dataitem._HeadComment, [])
223 self.assertEqual(dataitem._TailComment, [])
224
225 #
226 # Test _DecDefine._ParseItem
227 #
228 class DecDefineTestCase(unittest.TestCase):
229 def GetObj(self, Content):
230 Obj = _DecDefine(FileContent('dummy', Content.splitlines()))
231 Obj._RawData.CurrentLine = Obj._RawData.GetNextLine()
232 return Obj
233
234 def testDecDefine(self):
235 item = self.GetObj('PACKAGE_NAME = MdePkg')._ParseItem()
236 self.assertEqual(item.Key, 'PACKAGE_NAME')
237 self.assertEqual(item.Value, 'MdePkg')
238
239 def testDecDefine1(self):
240 obj = self.GetObj('PACKAGE_NAME')
241 self.assertRaises(FatalError, obj._ParseItem)
242
243 def testDecDefine2(self):
244 obj = self.GetObj('unknown_key = ')
245 self.assertRaises(FatalError, obj._ParseItem)
246
247 def testDecDefine3(self):
248 obj = self.GetObj('PACKAGE_NAME = ')
249 self.assertRaises(FatalError, obj._ParseItem)
250
251 #
252 # Test _DecLibraryclass._ParseItem
253 #
254 class DecLibraryTestCase(unittest.TestCase):
255 def GetObj(self, Content):
256 Obj = _DecLibraryclass(FileContent('dummy', Content.splitlines()))
257 Obj._RawData.CurrentLine = Obj._RawData.GetNextLine()
258 return Obj
259
260 def testNoInc(self):
261 obj = self.GetObj('UefiRuntimeLib')
262 self.assertRaises(FatalError, obj._ParseItem)
263
264 def testEmpty(self):
265 obj = self.GetObj(' | ')
266 self.assertRaises(FatalError, obj._ParseItem)
267
268 def testLibclassNaming(self):
269 obj = self.GetObj('lowercase_efiRuntimeLib|Include/Library/UefiRuntimeLib.h')
270 self.assertRaises(FatalError, obj._ParseItem)
271
272 def testLibclassExt(self):
273 obj = self.GetObj('RuntimeLib|Include/Library/UefiRuntimeLib.no_h')
274 self.assertRaises(FatalError, obj._ParseItem)
275
276 def testLibclassRelative(self):
277 obj = self.GetObj('RuntimeLib|Include/../UefiRuntimeLib.h')
278 self.assertRaises(FatalError, obj._ParseItem)
279
280 #
281 # Test _DecPcd._ParseItem
282 #
283 class DecPcdTestCase(unittest.TestCase):
284 def GetObj(self, Content):
285 Obj = _DecPcd(FileContent('dummy', Content.splitlines()))
286 Obj._RawData.CurrentLine = Obj._RawData.GetNextLine()
287 Obj._RawData.CurrentScope = [('PcdsFeatureFlag'.upper(), 'COMMON')]
288 return Obj
289
290 def testOK(self):
291 item = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d')._ParseItem()
292 self.assertEqual(item.TokenSpaceGuidCName, 'gEfiMdePkgTokenSpaceGuid')
293 self.assertEqual(item.TokenCName, 'PcdComponentNameDisable')
294 self.assertEqual(item.DefaultValue, 'FALSE')
295 self.assertEqual(item.DatumType, 'BOOLEAN')
296 self.assertEqual(item.TokenValue, '0x0000000d')
297
298 def testNoCvar(self):
299 obj = self.GetObj('123ai.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d')
300 self.assertRaises(FatalError, obj._ParseItem)
301
302 def testSplit(self):
303 obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable FALSE|BOOLEAN|0x0000000d')
304 self.assertRaises(FatalError, obj._ParseItem)
305
306 obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|BOOLEAN|0x0000000d | abc')
307 self.assertRaises(FatalError, obj._ParseItem)
308
309 def testUnknownType(self):
310 obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|FALSE|unknown|0x0000000d')
311 self.assertRaises(FatalError, obj._ParseItem)
312
313 def testVoid(self):
314 obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|abc|VOID*|0x0000000d')
315 self.assertRaises(FatalError, obj._ParseItem)
316
317 def testUINT(self):
318 obj = self.GetObj('gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable|0xabc|UINT8|0x0000000d')
319 self.assertRaises(FatalError, obj._ParseItem)
320
321 #
322 # Test _DecInclude._ParseItem
323 #
324 class DecIncludeTestCase(unittest.TestCase):
325 #
326 # Test code to be added
327 #
328 pass
329
330 #
331 # Test _DecGuid._ParseItem
332 #
333 class DecGuidTestCase(unittest.TestCase):
334 def GetObj(self, Content):
335 Obj = _DecGuid(FileContent('dummy', Content.splitlines()))
336 Obj._RawData.CurrentLine = Obj._RawData.GetNextLine()
337 Obj._RawData.CurrentScope = [('guids'.upper(), 'COMMON')]
338 return Obj
339
340 def testCValue(self):
341 item = self.GetObj('gEfiIpSecProtocolGuid={ 0xdfb386f7, 0xe100, 0x43ad,'
342 ' {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 }}')._ParseItem()
343 self.assertEqual(item.GuidCName, 'gEfiIpSecProtocolGuid')
344 self.assertEqual(item.GuidCValue, '{ 0xdfb386f7, 0xe100, 0x43ad, {0x9c, 0x9a, 0xed, 0x90, 0xd0, 0x8a, 0x5e, 0x12 }}')
345
346 def testGuidString(self):
347 item = self.GetObj('gEfiIpSecProtocolGuid=1E73767F-8F52-4603-AEB4-F29B510B6766')._ParseItem()
348 self.assertEqual(item.GuidCName, 'gEfiIpSecProtocolGuid')
349 self.assertEqual(item.GuidCValue, '1E73767F-8F52-4603-AEB4-F29B510B6766')
350
351 def testNoValue1(self):
352 obj = self.GetObj('gEfiIpSecProtocolGuid')
353 self.assertRaises(FatalError, obj._ParseItem)
354
355 def testNoValue2(self):
356 obj = self.GetObj('gEfiIpSecProtocolGuid=')
357 self.assertRaises(FatalError, obj._ParseItem)
358
359 def testNoName(self):
360 obj = self.GetObj('=')
361 self.assertRaises(FatalError, obj._ParseItem)
362
363 #
364 # Test Dec.__init__
365 #
366 class DecDecInitTestCase(unittest.TestCase):
367 def testNoDecFile(self):
368 self.assertRaises(FatalError, Dec, 'No_Such_File')
369
370 class TmpFile:
371 def __init__(self, File):
372 self.File = File
373
374 def Write(self, Content):
375 try:
376 FileObj = open(self.File, 'w')
377 FileObj.write(Content)
378 FileObj.close()
379 except:
380 pass
381
382 def Remove(self):
383 try:
384 os.remove(self.File)
385 except:
386 pass
387
388 #
389 # Test Dec._UserExtentionSectionParser
390 #
391 class DecUESectionTestCase(unittest.TestCase):
392 def setUp(self):
393 self.File = TmpFile('test.dec')
394 self.File.Write(
395 '''[userextensions.intel."myid"]
396 [userextensions.intel."myid".IA32]
397 [userextensions.intel."myid".IA32,]
398 [userextensions.intel."myid]
399 '''
400 )
401
402 def tearDown(self):
403 self.File.Remove()
404
405 def testUserExtentionHeader(self):
406 dec = Dec('test.dec', False)
407
408 # OK: [userextensions.intel."myid"]
409 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
410 dec._UserExtentionSectionParser()
411 self.assertEqual(len(dec._RawData.CurrentScope), 1)
412 self.assertEqual(dec._RawData.CurrentScope[0][0], 'userextensions'.upper())
413 self.assertEqual(dec._RawData.CurrentScope[0][1], 'intel')
414 self.assertEqual(dec._RawData.CurrentScope[0][2], '"myid"')
415 self.assertEqual(dec._RawData.CurrentScope[0][3], 'COMMON')
416
417 # OK: [userextensions.intel."myid".IA32]
418 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
419 dec._UserExtentionSectionParser()
420 self.assertEqual(len(dec._RawData.CurrentScope), 1)
421 self.assertEqual(dec._RawData.CurrentScope[0][0], 'userextensions'.upper())
422 self.assertEqual(dec._RawData.CurrentScope[0][1], 'intel')
423 self.assertEqual(dec._RawData.CurrentScope[0][2], '"myid"')
424 self.assertEqual(dec._RawData.CurrentScope[0][3], 'IA32')
425
426 # Fail: [userextensions.intel."myid".IA32,]
427 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
428 self.assertRaises(FatalError, dec._UserExtentionSectionParser)
429
430 # Fail: [userextensions.intel."myid]
431 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
432 self.assertRaises(FatalError, dec._UserExtentionSectionParser)
433
434 #
435 # Test Dec._SectionHeaderParser
436 #
437 class DecSectionTestCase(unittest.TestCase):
438 def setUp(self):
439 self.File = TmpFile('test.dec')
440 self.File.Write(
441 '''[no section start or end
442 [,] # empty sub-section
443 [unknow_section_name]
444 [Includes.IA32.other] # no third one
445 [PcdsFeatureFlag, PcdsFixedAtBuild] # feature flag PCD must not be in the same section of other types of PCD
446 [Includes.IA32, Includes.IA32]
447 [Includes, Includes.IA32] # common cannot be with other arch
448 [Includes.IA32, PcdsFeatureFlag] # different section name
449 ''' )
450
451 def tearDown(self):
452 self.File.Remove()
453
454 def testSectionHeader(self):
455 dec = Dec('test.dec', False)
456 # [no section start or end
457 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
458 self.assertRaises(FatalError, dec._SectionHeaderParser)
459
460 #[,] # empty sub-section
461 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
462 self.assertRaises(FatalError, dec._SectionHeaderParser)
463
464 # [unknow_section_name]
465 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
466 self.assertRaises(FatalError, dec._SectionHeaderParser)
467
468 # [Includes.IA32.other] # no third one
469 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
470 self.assertRaises(FatalError, dec._SectionHeaderParser)
471
472 # [PcdsFeatureFlag, PcdsFixedAtBuild]
473 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
474 self.assertRaises(FatalError, dec._SectionHeaderParser)
475
476 # [Includes.IA32, Includes.IA32]
477 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
478 dec._SectionHeaderParser()
479 self.assertEqual(len(dec._RawData.CurrentScope), 1)
480 self.assertEqual(dec._RawData.CurrentScope[0][0], 'Includes'.upper())
481 self.assertEqual(dec._RawData.CurrentScope[0][1], 'IA32')
482
483 # [Includes, Includes.IA32] # common cannot be with other arch
484 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
485 self.assertRaises(FatalError, dec._SectionHeaderParser)
486
487 # [Includes.IA32, PcdsFeatureFlag] # different section name not allowed
488 dec._RawData.CurrentLine = CleanString(dec._RawData.GetNextLine())[0]
489 self.assertRaises(FatalError, dec._SectionHeaderParser)
490
491 #
492 # Test Dec._ParseDecComment
493 #
494 class DecDecCommentTestCase(unittest.TestCase):
495 def testDecHeadComment(self):
496 File = TmpFile('test.dec')
497 File.Write(
498 '''# abc
499 ##''')
500 dec = Dec('test.dec', False)
501 dec.ParseDecComment()
502 self.assertEqual(len(dec._HeadComment), 2)
503 self.assertEqual(dec._HeadComment[0][0], '# abc')
504 self.assertEqual(dec._HeadComment[0][1], 1)
505 self.assertEqual(dec._HeadComment[1][0], '##')
506 self.assertEqual(dec._HeadComment[1][1], 2)
507 File.Remove()
508
509 def testNoDoubleComment(self):
510 File = TmpFile('test.dec')
511 File.Write(
512 '''# abc
513 #
514 [section_start]''')
515 dec = Dec('test.dec', False)
516 dec.ParseDecComment()
517 self.assertEqual(len(dec._HeadComment), 2)
518 self.assertEqual(dec._HeadComment[0][0], '# abc')
519 self.assertEqual(dec._HeadComment[0][1], 1)
520 self.assertEqual(dec._HeadComment[1][0], '#')
521 self.assertEqual(dec._HeadComment[1][1], 2)
522 File.Remove()
523
524 if __name__ == '__main__':
525 import Logger.Logger
526 Logger.Logger.Initialize()
527 unittest.main()
528