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 8import os 9import unittest 10from Logger.Log import FatalError 11 12from Parser.DecParser import \ 13 Dec, \ 14 _DecDefine, \ 15 _DecLibraryclass, \ 16 _DecPcd, \ 17 _DecGuid, \ 18 FileContent, \ 19 _DecBase, \ 20 CleanString 21 22from Object.Parser.DecObject import _DecComments 23 24# 25# Test CleanString 26# 27class 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# 53class 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# 73class 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# 112class DataItem(_DecComments): 113 def __init__(self): 114 _DecComments.__init__(self) 115 self.String = '' 116 117class Data(_DecComments): 118 def __init__(self): 119 _DecComments.__init__(self) 120 # List of DataItem 121 self.ItemList = [] 122 123class 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 140class 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 156class 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# 228class 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# 254class 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# 283class 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# 324class DecIncludeTestCase(unittest.TestCase): 325 # 326 # Test code to be added 327 # 328 pass 329 330# 331# Test _DecGuid._ParseItem 332# 333class 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# 366class DecDecInitTestCase(unittest.TestCase): 367 def testNoDecFile(self): 368 self.assertRaises(FatalError, Dec, 'No_Such_File') 369 370class 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# 391class 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# 437class 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# 494class 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 524if __name__ == '__main__': 525 import Logger.Logger 526 Logger.Logger.Initialize() 527 unittest.main() 528 529