@@ -2,7 +2,7 @@ import { readFileSync } from 'fs';
22import { join } from 'path' ;
33import { beforeEach , describe , expect , it } from 'vitest' ;
44import { CommunicationStyle , generateFakeTrace , TraceGenerationParameters } from '../../../src/backend/generation' ;
5- import { FakeApp } from '../../../src/backend/shared/types' ;
5+ import { FakeApp , FakeClass , FakePackage } from '../../../src/backend/shared/types' ;
66import { reconstructParentReferences } from '../../../src/backend/utils/landscape.utils' ;
77
88describe ( 'Trace Generation Integration' , ( ) => {
@@ -469,4 +469,112 @@ describe('Trace Generation Integration', () => {
469469 expect ( names1 ) . not . toEqual ( names2 ) ;
470470 } ) ;
471471 } ) ;
472+
473+ describe ( 'Single Class Landscape' , ( ) => {
474+ it ( 'should handle single class with multiple methods without hanging' , ( ) => {
475+ // Create a simple landscape with one class and two methods
476+ const rootPackage : FakePackage = {
477+ name : 'org' ,
478+ classes : [ ] ,
479+ subpackages : [ ] ,
480+ } ;
481+
482+ const appPackage : FakePackage = {
483+ name : 'testapp' ,
484+ classes : [ ] ,
485+ subpackages : [ ] ,
486+ parent : rootPackage ,
487+ } ;
488+
489+ rootPackage . subpackages . push ( appPackage ) ;
490+
491+ const testClass : FakeClass = {
492+ identifier : 'TestClass' ,
493+ methods : [ 'method1' , 'method2' ] ,
494+ parent : appPackage ,
495+ parentAppName : 'test-app' ,
496+ } ;
497+
498+ appPackage . classes . push ( testClass ) ;
499+
500+ const testApp : FakeApp = {
501+ name : 'test-app' ,
502+ rootPackages : [ rootPackage ] ,
503+ entryPoint : testClass ,
504+ classes : [ testClass ] ,
505+ packages : [ rootPackage , appPackage ] ,
506+ methods : [ 'method1' , 'method2' ] ,
507+ } ;
508+
509+ const params : TraceGenerationParameters = {
510+ duration : 1000 ,
511+ callCount : 5 ,
512+ maxConnectionDepth : 3 ,
513+ communicationStyle : CommunicationStyle . TRUE_RANDOM ,
514+ allowCyclicCalls : false ,
515+ seed : 12345 ,
516+ } ;
517+
518+ // This should complete without hanging
519+ const trace = generateFakeTrace ( [ testApp ] , params ) ;
520+
521+ // Verify trace was generated
522+ expect ( trace ) . toBeDefined ( ) ;
523+ expect ( trace . length ) . toBe ( 1 ) ;
524+ expect ( trace [ 0 ] . name ) . toContain ( 'TestClass' ) ;
525+ } ) ;
526+
527+ it ( 'should handle single class with allowCyclicCalls enabled' , ( ) => {
528+ const rootPackage : FakePackage = {
529+ name : 'org' ,
530+ classes : [ ] ,
531+ subpackages : [ ] ,
532+ } ;
533+
534+ const appPackage : FakePackage = {
535+ name : 'testapp' ,
536+ classes : [ ] ,
537+ subpackages : [ ] ,
538+ parent : rootPackage ,
539+ } ;
540+
541+ rootPackage . subpackages . push ( appPackage ) ;
542+
543+ const testClass : FakeClass = {
544+ identifier : 'TestClass' ,
545+ methods : [ 'method1' , 'method2' ] ,
546+ parent : appPackage ,
547+ parentAppName : 'test-app' ,
548+ } ;
549+
550+ appPackage . classes . push ( testClass ) ;
551+
552+ const testApp : FakeApp = {
553+ name : 'test-app' ,
554+ rootPackages : [ rootPackage ] ,
555+ entryPoint : testClass ,
556+ classes : [ testClass ] ,
557+ packages : [ rootPackage , appPackage ] ,
558+ methods : [ 'method1' , 'method2' ] ,
559+ } ;
560+
561+ const params : TraceGenerationParameters = {
562+ duration : 1000 ,
563+ callCount : 5 ,
564+ maxConnectionDepth : 3 ,
565+ communicationStyle : CommunicationStyle . TRUE_RANDOM ,
566+ allowCyclicCalls : true ,
567+ seed : 54321 ,
568+ } ;
569+
570+ const trace = generateFakeTrace ( [ testApp ] , params ) ;
571+
572+ function countSpans ( spans : any [ ] ) : number {
573+ return spans . length + spans . reduce ( ( sum , span ) => sum + countSpans ( span . children ) , 0 ) ;
574+ }
575+
576+ // With cyclic calls enabled, should generate the requested number of spans
577+ expect ( countSpans ( trace ) ) . toBe ( 6 ) ; // 1 root + 5 calls
578+ } ) ;
579+ } ) ;
472580} ) ;
0 commit comments