From dd89ede423a3df636f243468fdcabae812e0a2c7 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 11 Aug 2023 14:01:36 +0200 Subject: [PATCH] backend-app-api: add test for circular module dependency check Signed-off-by: Patrik Oldsberg --- .../src/wiring/BackendInitializer.test.ts | 44 +++++++++++++++++++ .../src/wiring/BackendInitializer.ts | 4 +- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index b625db31c9..ba637b7b5b 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -250,4 +250,48 @@ describe('BackendInitializer', () => { "Module 'mod' for plugin 'test' is already registered", ); }); + + it('should reject modules with circular dependencies', async () => { + const extA = createExtensionPoint({ id: 'a' }); + const extB = createExtensionPoint({ id: 'b' }); + const init = new BackendInitializer( + new ServiceRegistry([ + rootLifecycleServiceFactory(), + createServiceFactory({ + service: coreServices.rootLogger, + deps: {}, + factory: () => new MockLogger(), + })(), + ]), + ); + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modA', + register(reg) { + reg.registerExtensionPoint(extA, 'a'); + reg.registerInit({ + deps: { ext: extB }, + async init() {}, + }); + }, + })(), + ); + init.add( + createBackendModule({ + pluginId: 'test', + moduleId: 'modB', + register(reg) { + reg.registerExtensionPoint(extB, 'b'); + reg.registerInit({ + deps: { ext: extA }, + async init() {}, + }); + }, + })(), + ); + await expect(init.start()).rejects.toThrow( + "Circular dependency detected for modules of plugin 'test', 'modA' -> 'modB' -> 'modA'", + ); + }); }); diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index ce84c2be0f..fe3120713e 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -26,7 +26,7 @@ import { EnumerableServiceHolder, ServiceOrExtensionPoint } from './types'; // Direct internal import to avoid duplication // eslint-disable-next-line @backstage/no-forbidden-package-imports import { InternalBackendFeature } from '@backstage/backend-plugin-api/src/wiring/types'; -import { ForwardedError, InputError } from '@backstage/errors'; +import { ForwardedError, ConflictError } from '@backstage/errors'; import { featureDiscoveryServiceRef } from '@backstage/backend-plugin-api/alpha'; import { DependencyTree } from '../lib/DependencyTree'; @@ -225,7 +225,7 @@ export class BackendInitializer { ); const circular = tree.detectCircularDependency(); if (circular) { - throw new InputError( + throw new ConflictError( `Circular dependency detected for modules of plugin '${pluginId}', '${circular.join( "' -> '", )}'`,