1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Exceptions; 10 using Antmicro.Renode.PlatformDescription; 11 using Antmicro.Renode.Utilities; 12 using NUnit.Framework; 13 using Antmicro.Renode.Peripherals.CPU; 14 15 namespace Antmicro.Renode.UnitTests.PlatformDescription 16 { 17 [TestFixture] 18 public class VerificationTests 19 { 20 [Test] ShouldProcessOneObject()21 public void ShouldProcessOneObject() 22 { 23 var source = @" 24 mock: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral"; 25 26 ProcessSource(source); 27 } 28 29 [Test] ShouldProcessLateAttach()30 public void ShouldProcessLateAttach() 31 { 32 var source = @" 33 mock: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 34 35 mock: @sysbus <0x0, +0x100>"; 36 37 ProcessSource(source); 38 } 39 40 [Test] ShouldProcessWithoutTypeNameInFirstEntry()41 public void ShouldProcessWithoutTypeNameInFirstEntry() 42 { 43 var source = @" 44 mock: @sysbus <0x0, 0x1000> 45 46 mock: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral"; 47 48 ProcessSource(source); 49 } 50 51 [Test] ShouldFailIfTypeIsSpecifiedSecondTime()52 public void ShouldFailIfTypeIsSpecifiedSecondTime() 53 { 54 var source = @" 55 mock: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 56 57 mock: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral"; 58 59 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 60 Assert.AreEqual(ParsingError.VariableAlreadyDeclared, exception.Error); 61 } 62 63 [Test] ShouldFailOnEmptyEntry()64 public void ShouldFailOnEmptyEntry() 65 { 66 var source = @" 67 mock:"; 68 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 69 Assert.AreEqual(ParsingError.EmptyEntry, exception.Error); 70 } 71 72 [Test] ShouldFailOnNotExistingType()73 public void ShouldFailOnNotExistingType() 74 { 75 var source = @" 76 someDevice: NotExistingType"; 77 78 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 79 Assert.AreEqual(ParsingError.TypeNotResolved, exception.Error); 80 } 81 82 [Test] ShouldFailOnRegisteringNotIPeripheral()83 public void ShouldFailOnRegisteringNotIPeripheral() 84 { 85 var source = @" 86 external: Antmicro.Renode.UnitTests.Mocks.MockExternal @ sysbus 87 "; 88 89 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 90 Assert.AreEqual(ParsingError.NoUsableRegisterInterface, exception.Error); 91 } 92 93 [Test] ShouldFailOnStringMismatch()94 public void ShouldFailOnStringMismatch() 95 { 96 var source = @" 97 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 98 Placeholder: 8 99 "; 100 101 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 102 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 103 } 104 105 [Test] ShouldFailOnNonWritableProperty()106 public void ShouldFailOnNonWritableProperty() 107 { 108 var source = @" 109 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 110 Model: ""abc"""; 111 112 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 113 Assert.AreEqual(ParsingError.PropertyNotWritable, exception.Error); 114 } 115 116 [Test] ShouldFailOnNumericEnumMismatch()117 public void ShouldFailOnNumericEnumMismatch() 118 { 119 var source = @" 120 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 121 EnumValue: ""abc"""; 122 123 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 124 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 125 } 126 127 [Test] ShouldFailOnNonExistingInlineType()128 public void ShouldFailOnNonExistingInlineType() 129 { 130 var source = @" 131 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 132 OtherCpu: new NotExistingType"; 133 134 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 135 Assert.AreEqual(ParsingError.TypeNotResolved, exception.Error); 136 } 137 138 [Test] ShouldFailOnDoubleAttribute()139 public void ShouldFailOnDoubleAttribute() 140 { 141 var source = @" 142 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 143 EnumValue: One 144 EnumValue: Two"; 145 146 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 147 Assert.AreEqual(ParsingError.PropertyOrCtorNameUsedMoreThanOnce, exception.Error); 148 149 } 150 151 [Test] ShouldFailOnNonExistingProperty()152 public void ShouldFailOnNonExistingProperty() 153 { 154 var source = @" 155 external: Antmicro.Renode.UnitTests.Mocks.MockCPU 156 NotExistingProperty: ""value"""; 157 158 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 159 Assert.AreEqual(ParsingError.PropertyDoesNotExist, exception.Error); 160 } 161 162 [Test] ShouldCheckTypeOfAReference()163 public void ShouldCheckTypeOfAReference() 164 { 165 var source = @" 166 one: Antmicro.Renode.UnitTests.Mocks.MockCPU 167 OtherCpu: two 168 169 two: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral"; 170 171 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 172 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 173 } 174 175 [Test] ShouldFailOnIncorrectInlineObjectType()176 public void ShouldFailOnIncorrectInlineObjectType() 177 { 178 var source = @" 179 one: Antmicro.Renode.UnitTests.Mocks.MockCPU 180 OtherCpu: new Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral"; 181 182 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 183 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 184 } 185 186 [Test] ShouldFailOnIncorrectPropertyTypeInNestedInlineObject()187 public void ShouldFailOnIncorrectPropertyTypeInNestedInlineObject() 188 { 189 var source = @" 190 cpu: Antmicro.Renode.UnitTests.Mocks.MockCPU 191 OtherCpu: new Antmicro.Renode.UnitTests.Mocks.MockCPU 192 OtherCpu: new Antmicro.Renode.UnitTests.Mocks.MockCPU 193 EnumValue: ""string"""; 194 195 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 196 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 197 } 198 199 [Test] ShouldFailOnNotExistingIrqDestination()200 public void ShouldFailOnNotExistingIrqDestination() 201 { 202 var source = @" 203 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 204 IRQ -> receiver@0"; 205 206 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 207 Assert.AreEqual(ParsingError.IrqDestinationDoesNotExist, exception.Error); 208 } 209 210 [Test] ShouldFailOnIrqDestinationNotBeingIrqReceiver()211 public void ShouldFailOnIrqDestinationNotBeingIrqReceiver() 212 { 213 var source = @" 214 cpu: Antmicro.Renode.UnitTests.Mocks.MockCPU 215 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 216 Irq -> cpu@0"; 217 218 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 219 Assert.AreEqual(ParsingError.IrqDestinationIsNotIrqReceiver, exception.Error); 220 } 221 222 [Test] ShouldFailOnWrongIrqArity()223 public void ShouldFailOnWrongIrqArity() 224 { 225 var source = @" 226 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 227 [Irq] -> receiver@[0,1] 228 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver"; 229 230 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 231 Assert.AreEqual(ParsingError.WrongIrqArity, exception.Error); 232 233 } 234 235 [Test] ShouldFailOnWrongIrqName()236 public void ShouldFailOnWrongIrqName() 237 { 238 var source = @" 239 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 240 Something -> receiver@0 241 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver"; 242 243 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 244 Assert.AreEqual(ParsingError.IrqSourceDoesNotExist, exception.Error); 245 } 246 247 [Test] ShouldFailOnNumberIrqSourceNotBeingNumberedGpioOutput()248 public void ShouldFailOnNumberIrqSourceNotBeingNumberedGpioOutput() 249 { 250 var source = @" 251 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 252 [0-1] -> receiver@[0-1] 253 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver"; 254 255 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 256 Assert.AreEqual(ParsingError.IrqSourceIsNotNumberedGpioOutput, exception.Error); 257 } 258 259 [Test] ShouldFailOnAmbiguousDefaultIrq()260 public void ShouldFailOnAmbiguousDefaultIrq() 261 { 262 var source = @" 263 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSenderWithTwoInterrupts 264 -> receiver@0 265 266 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver"; 267 268 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 269 Assert.AreEqual(ParsingError.AmbiguousDefaultIrqSource, exception.Error); 270 } 271 272 [Test] ShouldFailOnNoIrqWhenUsingDefaultOne()273 public void ShouldFailOnNoIrqWhenUsingDefaultOne() 274 { 275 var source = @" 276 cpu: Antmicro.Renode.UnitTests.Mocks.MockCPU 277 -> receiver@0 278 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver"; 279 280 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 281 Assert.AreEqual(ParsingError.IrqSourceDoesNotExist, exception.Error); 282 } 283 284 [Test] ShouldFailIfInterruptUsedSecondTimeInEntryAsSource()285 public void ShouldFailIfInterruptUsedSecondTimeInEntryAsSource() 286 { 287 var source = @" 288 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver 289 sender: Antmicro.Renode.UnitTests.Mocks.MockGPIOByNumberConnectorPeripheral 290 2 -> receiver@6 291 [0, 1-3, 7] -> receiver@[5-9]"; 292 293 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 294 Assert.AreEqual(ParsingError.IrqSourceUsedMoreThanOnce, exception.Error); 295 } 296 297 [Test] ShouldFailIfDefaultInterruptUsedSecondTimeInEntry()298 public void ShouldFailIfDefaultInterruptUsedSecondTimeInEntry() 299 { 300 var source = @" 301 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver 302 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 303 -> receiver@0 304 -> receiver @1"; 305 306 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 307 Assert.AreEqual(ParsingError.IrqSourceUsedMoreThanOnce, exception.Error); 308 } 309 310 [Test] ShouldFailIfTheSameIrqUsedTwiceOnceAsDefault()311 public void ShouldFailIfTheSameIrqUsedTwiceOnceAsDefault() 312 { 313 var source = @" 314 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver 315 sender: Antmicro.Renode.UnitTests.Mocks.MockIrqSender 316 -> receiver@0 317 Irq -> receiver @1"; 318 319 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 320 Assert.AreEqual(ParsingError.IrqSourceUsedMoreThanOnce, exception.Error); 321 } 322 323 [Test] ShouldFailWithMoreThanOneInitAttribute()324 public void ShouldFailWithMoreThanOneInitAttribute() 325 { 326 var source = @" 327 device: Antmicro.Renode.UnitTests.Mocks.MockCPU 328 init: 329 DoSomething 330 init add: 331 DoSomethingElse"; 332 333 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 334 Assert.AreEqual(ParsingError.MoreThanOneInitAttribute, exception.Error); 335 } 336 337 [Test] ShouldFailOnMissingReference()338 public void ShouldFailOnMissingReference() 339 { 340 var source = @" 341 device: Antmicro.Renode.UnitTests.Mocks.MockCPU 342 OtherCpu: unknown"; 343 344 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 345 Assert.AreEqual(ParsingError.MissingReference, exception.Error); 346 } 347 348 [Test] ShouldFailOnMissingReferenceInRegistrationPoint()349 public void ShouldFailOnMissingReferenceInRegistrationPoint() 350 { 351 var source = @" 352 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ sysbus regPoint"; 353 354 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 355 Assert.AreEqual(ParsingError.MissingReference, exception.Error); 356 } 357 358 [Test] ShouldFailOnWrongReferenceRegistrationPointType()359 public void ShouldFailOnWrongReferenceRegistrationPointType() 360 { 361 var source = @" 362 regPoint: Antmicro.Renode.UnitTests.Mocks.MockCPU 363 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ sysbus regPoint"; 364 365 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 366 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 367 } 368 369 [Test] ShouldFailOnWrongObjectRegistrationPointType()370 public void ShouldFailOnWrongObjectRegistrationPointType() 371 { 372 var source = @" 373 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ sysbus new Antmicro.Renode.UnitTests.Mocks.MockCPU { Placeholder: ""abc"" }"; 374 375 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 376 Assert.AreEqual(ParsingError.TypeMismatch, exception.Error); 377 } 378 379 [Test] ShouldFailOnNonConstruableRegistrationPoint()380 public void ShouldFailOnNonConstruableRegistrationPoint() 381 { 382 var source = @" 383 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ sysbus ""something"""; 384 385 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 386 Assert.AreEqual(ParsingError.NoCtorForRegistrationPoint, exception.Error); 387 } 388 389 [Test] ShouldFailOnAmbiguousConstructorForRegistrationPoint()390 public void ShouldFailOnAmbiguousConstructorForRegistrationPoint() 391 { 392 var source = @" 393 register: Antmicro.Renode.UnitTests.Mocks.AmbiguousRegister 394 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ register 1"; 395 396 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 397 Assert.AreEqual(ParsingError.AmbiguousCtorForRegistrationPoint, exception.Error); 398 } 399 400 [Test] ShouldValidateObjectValueInCtorParameter()401 public void ShouldValidateObjectValueInCtorParameter() 402 { 403 var source = @" 404 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 405 ctorParam: new NoSuchType"; 406 407 // note that this would also fail on not getting ctor, but it is important it will fail on unresolved type *earlier* 408 409 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 410 Assert.AreEqual(ParsingError.TypeNotResolved, exception.Error); 411 } 412 413 [Test] ShouldFailOnNoAvailableCtorInEntry()414 public void ShouldFailOnNoAvailableCtorInEntry() 415 { 416 var source = @" 417 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 418 ctorParam: 3"; 419 420 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 421 Assert.AreEqual(ParsingError.NoCtor, exception.Error); 422 } 423 424 [Test] ShouldFailOnAmbiguousCtorInEntry()425 public void ShouldFailOnAmbiguousCtorInEntry() 426 { 427 var source = @" 428 device: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 429 value: 3"; 430 431 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 432 Assert.AreEqual(ParsingError.AmbiguousCtor, exception.Error); 433 } 434 435 [Test] ShouldFailOnNoAvailableCtorInObjectValue()436 public void ShouldFailOnNoAvailableCtorInObjectValue() 437 { 438 var source = @" 439 peripheral: Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 440 other: new Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 441 other: new Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 442 x: 7"; 443 444 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 445 Assert.AreEqual(ParsingError.NoCtor, exception.Error); 446 } 447 448 [Test] ShouldFailOnAmbiguousCtorInObjectValue()449 public void ShouldFailOnAmbiguousCtorInObjectValue() 450 { 451 var source = @" 452 peripheral: Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 453 other: new Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 454 other: new Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithDependency 455 other: new Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral 456 value: 4"; 457 458 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 459 Assert.AreEqual(ParsingError.AmbiguousCtor, exception.Error); 460 } 461 462 [Test] ShouldFailOnAmbiguousRegistrationPoint()463 public void ShouldFailOnAmbiguousRegistrationPoint() 464 { 465 var source = @" 466 register: Antmicro.Renode.UnitTests.Mocks.AmbiguousRegister 467 regPoint: Antmicro.Renode.UnitTests.Mocks.MockRegistrationPoint 468 peripheral: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ register regPoint"; 469 470 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 471 Assert.AreEqual(ParsingError.AmbiguousRegistrationPointType, exception.Error); 472 } 473 474 [Test] ShouldFailOnAliasWithoutRegistrationInfo()475 public void ShouldFailOnAliasWithoutRegistrationInfo() 476 { 477 var source = @" 478 peripheral: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral as ""alias"""; 479 480 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 481 Assert.AreEqual(ParsingError.AliasWithoutRegistration, exception.Error); 482 } 483 484 [Test] ShouldFailOnAliasWithNoneRegistrationInfo()485 public void ShouldFailOnAliasWithNoneRegistrationInfo() 486 { 487 var source = @" 488 peripheral: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ none as ""alias"""; 489 490 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 491 Assert.AreEqual(ParsingError.AliasWithNoneRegistration, exception.Error); 492 } 493 494 [Test] ShouldFailWithConstructorAttributesWithNonCreatingEntry()495 public void ShouldFailWithConstructorAttributesWithNonCreatingEntry() 496 { 497 var source = @" 498 sysbus: 499 x: 5"; 500 501 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 502 Assert.AreEqual(ParsingError.CtorAttributesInNonCreatingEntry, exception.Error); 503 } 504 505 [Test] ShouldFailOnAmbiguousRegistree()506 public void ShouldFailOnAmbiguousRegistree() 507 { 508 var source = @" 509 register: Antmicro.Renode.UnitTests.Mocks.AmbiguousRegister 510 peripheral: Antmicro.Renode.UnitTests.Mocks.EmptyPeripheral @ register 2.0"; 511 512 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 513 Assert.AreEqual(ParsingError.AmbiguousRegistree, exception.Error); 514 } 515 516 [Test] ShouldFailOnNonPeripheralRegister()517 public void ShouldFailOnNonPeripheralRegister() 518 { 519 var source = @" 520 emptyIterestingType: Antmicro.Renode.UnitTests.Mocks.EmptyInterestingType 521 cpu: Antmicro.Renode.UnitTests.Mocks.MockCPU @ emptyIterestingType 522 "; 523 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 524 Assert.AreEqual(ParsingError.CastException, exception.Error); 525 } 526 527 [Test] ShouldFailOnNonExistingIrqSourcePin()528 public void ShouldFailOnNonExistingIrqSourcePin() 529 { 530 var source = @" 531 receiver: Antmicro.Renode.UnitTests.Mocks.MockReceiver 532 sender: Antmicro.Renode.UnitTests.Mocks.MockGPIOByNumberConnectorPeripheral 533 gpios: 2 534 2 -> receiver@1"; 535 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 536 Assert.AreEqual(ParsingError.IrqSourcePinDoesNotExist, exception.Error); 537 } 538 539 [Test] ShouldFailOnNonExistingConstructor()540 public void ShouldFailOnNonExistingConstructor() 541 { 542 var source = @" 543 p: Antmicro.Renode.UnitTests.Mocks.MockPeripheralWithProtectedConstructor @ sysbus 0x0 544 "; 545 var exception = Assert.Throws<ParsingException>(() => ProcessSource(source)); 546 Assert.AreEqual(ParsingError.NoCtor, exception.Error); 547 } 548 549 [OneTimeSetUp] Init()550 public void Init() 551 { 552 if(!Misc.TryGetRootDirectory(out var rootDir)) 553 { 554 throw new ArgumentException("Couldn't get root directory."); 555 } 556 TypeManager.Instance.Scan(rootDir); 557 } 558 ProcessSource(string source)559 private static void ProcessSource(string source) 560 { 561 var creationDriver = new CreationDriver(new Machine(), new FakeUsingResolver(), new FakeInitHandler()); 562 creationDriver.ProcessDescription(source); 563 } 564 } 565 } 566