@@ -567,4 +567,78 @@ class RepositoryPackageContainerProviderTests: XCTestCase {
567
567
}
568
568
}
569
569
}
570
+
571
+ func testRepositoryPackageContainerCache( ) throws {
572
+ // From rdar://problem/65284674
573
+ // RepositoryPackageContainer used to erroneously cache dependencies based only on version,
574
+ // storing the result of the first product filter and then continually returning it for other filters too.
575
+ // This lead to corrupt graph states.
576
+
577
+ try testWithTemporaryDirectory { temporaryDirectory in
578
+ let packageDirectory = temporaryDirectory. appending ( component: " Package " )
579
+ try localFileSystem. createDirectory ( packageDirectory)
580
+ initGitRepo ( packageDirectory)
581
+ let packageRepository = GitRepository ( path: packageDirectory)
582
+
583
+ let manifestFile = packageDirectory. appending ( component: " Package.swift " )
584
+ try localFileSystem. writeFileContents ( manifestFile, bytes: ByteString ( " // swift-tools-version:5.2 " ) )
585
+
586
+ try packageRepository. stage ( file: " Package.swift " )
587
+ try packageRepository. commit ( message: " Initialized. " )
588
+ try packageRepository. tag ( name: " 1.0.0 " )
589
+
590
+ let repositoryProvider = GitRepositoryProvider ( )
591
+ let repositoryManager = RepositoryManager (
592
+ path: packageDirectory,
593
+ provider: repositoryProvider,
594
+ delegate: nil ,
595
+ fileSystem: localFileSystem
596
+ )
597
+
598
+ let version = Version ( 1 , 0 , 0 )
599
+ let manifest = Manifest . createManifest (
600
+ name: packageDirectory. basename,
601
+ path: packageDirectory. pathString,
602
+ url: packageDirectory. pathString,
603
+ v: . v5_2,
604
+ packageKind: . root,
605
+ dependencies: [
606
+ PackageDependencyDescription (
607
+ url: " Somewhere/Dependency " ,
608
+ requirement: . exact( version) ,
609
+ productFilter: . specific( [ ] )
610
+ )
611
+ ] ,
612
+ products: [ ProductDescription ( name: " Product " , type: . library( . automatic) , targets: [ " Target " ] ) ] ,
613
+ targets: [
614
+ TargetDescription (
615
+ name: " Target " ,
616
+ dependencies: [ . product( name: " DependencyProduct " , package : " Dependency " ) ]
617
+ ) ,
618
+ ]
619
+ )
620
+ let containerProvider = RepositoryPackageContainerProvider (
621
+ repositoryManager: repositoryManager,
622
+ manifestLoader: MockManifestLoader (
623
+ manifests: [ . init( url: packageDirectory. pathString, version: Version ( 1 , 0 , 0 ) ) : manifest]
624
+ )
625
+ )
626
+
627
+ let packageReference = PackageReference ( identity: " package " , path: packageDirectory. pathString)
628
+ let container = try tsc_await { completion in
629
+ containerProvider. getContainer (
630
+ for: packageReference,
631
+ skipUpdate: false ,
632
+ completion: completion
633
+ )
634
+ }
635
+
636
+ let forNothing = try container. getDependencies ( at: version, productFilter: . specific( [ ] ) )
637
+ let forProduct = try container. getDependencies ( at: version, productFilter: . specific( [ " Product " ] ) )
638
+ #if ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION
639
+ // If the cache overlaps (incorrectly), these will be the same.
640
+ XCTAssertNotEqual ( forNothing, forProduct)
641
+ #endif
642
+ }
643
+ }
570
644
}
0 commit comments