@@ -43,6 +43,7 @@ abstract class BaseRepositoryTests extends ArtifactoryTestsBase {
4343 protected Repository federatedRepo
4444 protected Repository remoteRepo
4545 protected Repository virtualRepo
46+ protected Repository repoForVirtual // Dedicated repo for virtual repo child
4647
4748 protected XraySettings xraySettings
4849 protected Map<String , Object > customProperties
@@ -153,10 +154,74 @@ abstract class BaseRepositoryTests extends ArtifactoryTestsBase {
153154 }
154155
155156 if (prepareVirtualRepo) {
156- RepositorySettings settings = getRepositorySettings(RepositoryTypeImpl . VIRTUAL )
157- artifactory. repositories(). create(0 , genericRepo)
157+ RepositorySettings virtualSettings = getRepositorySettings(RepositoryTypeImpl . VIRTUAL )
158158 def repos = new ArrayList<String > ()
159- repos. add(genericRepo. getKey())
159+
160+ // Create a dedicated child repo for the virtual repo
161+ // Use LOCAL settings if available, otherwise use VIRTUAL settings for package type compatibility
162+ if (prepareLocalRepo) {
163+ RepositorySettings localSettingsForVirtual = getRepositorySettings(RepositoryTypeImpl . LOCAL )
164+ // If LOCAL settings are null, use VIRTUAL settings to ensure correct package type
165+ if (localSettingsForVirtual == null ) {
166+ localSettingsForVirtual = virtualSettings
167+ }
168+ XraySettings virtualXraySettings = new XraySettingsImpl ()
169+ repoForVirtual = artifactory. repositories(). builders(). localRepositoryBuilder()
170+ .key(" $REPO_NAME_PREFIX -for-virtual-$id " )
171+ .description(" for-virtual-$id " )
172+ .notes(" notes-${ rnd.nextInt()} " )
173+ .archiveBrowsingEnabled(rnd. nextBoolean())
174+ .blackedOut(rnd. nextBoolean())
175+ .excludesPattern(" org/${ rnd.nextInt()} /**" )
176+ .includesPattern(" org/${ rnd.nextInt()} /**" )
177+ .propertySets(Collections . emptyList())
178+ .repositorySettings(localSettingsForVirtual)
179+ .xraySettings(virtualXraySettings)
180+ .customProperties(customProperties)
181+ .build()
182+ artifactory. repositories(). create(0 , repoForVirtual)
183+ repos. add(repoForVirtual. getKey())
184+ } else if (prepareRemoteRepo) {
185+ // For package types that don't support local repos (e.g., P2), create a SEPARATE remote repo
186+ RepositorySettings remoteSettingsForVirtual = getRepositorySettings(RepositoryTypeImpl . REMOTE )
187+ ContentSync contentSync = new ContentSyncImpl ()
188+ repoForVirtual = artifactory. repositories(). builders(). remoteRepositoryBuilder()
189+ .key(" $REPO_NAME_PREFIX -remote-for-virtual-$id " )
190+ .description(" remote-for-virtual-$id " )
191+ .notes(" notes-${ rnd.nextInt()} " )
192+ .allowAnyHostAuth(rnd. nextBoolean())
193+ .archiveBrowsingEnabled(rnd. nextBoolean())
194+ .assumedOfflinePeriodSecs(rnd. nextLong())
195+ .enableCookieManagement(rnd. nextBoolean())
196+ .excludesPattern(" org/${ rnd.nextInt()} /**" )
197+ .failedRetrievalCachePeriodSecs(rnd. nextInt())
198+ .hardFail(rnd. nextBoolean())
199+ .includesPattern(" org/${ rnd.nextInt()} /**" )
200+ .missedRetrievalCachePeriodSecs(rnd. nextInt())
201+ .offline(rnd. nextBoolean())
202+ .password(" password_${ rnd.nextInt()} " )
203+ .propertySets(Collections . emptyList())
204+ .retrievalCachePeriodSecs(rnd. nextInt())
205+ .shareConfiguration(rnd. nextBoolean())
206+ .socketTimeoutMillis(rnd. nextInt())
207+ .storeArtifactsLocally(ObjectUtils . defaultIfNull(storeArtifactsLocallyInRemoteRepo, rnd. nextBoolean()))
208+ .synchronizeProperties(rnd. nextBoolean())
209+ .unusedArtifactsCleanupPeriodHours(Math . abs(rnd. nextInt()))
210+ .url(remoteRepoUrl)
211+ .username(" user_${ rnd.nextInt()} " )
212+ .repositorySettings(remoteSettingsForVirtual)
213+ .xraySettings(xraySettings)
214+ .contentSync(contentSync)
215+ .customProperties(customProperties)
216+ .build()
217+ artifactory. repositories(). create(0 , repoForVirtual)
218+ repos. add(repoForVirtual. getKey())
219+ } else if (prepareGenericRepo && genericRepo != null ) {
220+ // Fallback to generic repo
221+ repoForVirtual = genericRepo
222+ artifactory. repositories(). create(0 , repoForVirtual)
223+ repos. add(repoForVirtual. getKey())
224+ }
160225
161226 virtualRepo = artifactory. repositories(). builders(). virtualRepositoryBuilder()
162227 .key(" $REPO_NAME_PREFIX -virtual-$id " )
@@ -166,17 +231,18 @@ abstract class BaseRepositoryTests extends ArtifactoryTestsBase {
166231 .excludesPattern(" org/${ rnd.nextInt()} /**" )
167232 .includesPattern(" org/${ rnd.nextInt()} /**" )
168233 .repositories(repos)
169- .repositorySettings(settings )
234+ .repositorySettings(virtualSettings )
170235 .customProperties(customProperties)
171- .defaultDeploymentRepo(repos. last())
236+ .defaultDeploymentRepo(repos. isEmpty() ? null : repos . last())
172237 .build()
173238 }
174239 }
175240
176241 @AfterMethod
177242 protected void tearDown () {
178243 // Invoking sequence is important! Delete in reverse dependency order
179- deleteRepoWithRetry(virtualRepo?. getKey()) // Delete virtual repo first (depends on generic)
244+ deleteRepoWithRetry(virtualRepo?. getKey()) // Delete virtual repo first (depends on others)
245+ deleteRepoWithRetry(repoForVirtual?. getKey()) // Delete the dedicated repo for virtual
180246 deleteRepoWithRetry(federatedRepo?. getKey())
181247 deleteRepoWithRetry(remoteRepo?. getKey())
182248 deleteRepoWithRetry(localRepo?. getKey())
0 commit comments