Refactor and enhance tests for call graph extractors and connection management

- Updated JavaScriptCallGraphExtractorTests to improve naming conventions and test cases for Azure Functions, CLI commands, and socket handling.
- Modified NodeCallGraphExtractorTests to correctly assert exceptions for null inputs.
- Enhanced WitnessModalComponent tests in Angular to use Jasmine spies and improved assertions for path visualization and signature verification.
- Added ConnectionState property for tracking connection establishment time in Router.Common.
- Implemented validation for HelloPayload in ConnectionManager to ensure required fields are present.
- Introduced RabbitMqContainerFixture method for restarting RabbitMQ container during tests.
- Added integration tests for RabbitMq to verify connection recovery after broker restarts.
- Created new BinaryCallGraphExtractorTests, GoCallGraphExtractorTests, and PythonCallGraphExtractorTests for comprehensive coverage of binary, Go, and Python call graph extraction functionalities.
- Developed ConnectionManagerTests to validate connection handling, including rejection of invalid hello messages and proper cleanup on client disconnects.
This commit is contained in:
master
2025-12-19 18:49:36 +02:00
parent 8779e9226f
commit 91f3610b9d
18 changed files with 1119 additions and 69 deletions

View File

@@ -7,6 +7,7 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { signal } from '@angular/core';
import { of } from 'rxjs';
import { WitnessModalComponent } from './witness-modal.component';
import {
@@ -19,7 +20,7 @@ import { WitnessMockClient } from '../../core/api/witness.client';
describe('WitnessModalComponent', () => {
let component: WitnessModalComponent;
let fixture: ComponentFixture<WitnessModalComponent>;
let mockWitnessClient: jest.Mocked<WitnessMockClient>;
let mockWitnessClient: jasmine.SpyObj<WitnessMockClient>;
const mockWitness: ReachabilityWitness = {
witnessId: 'witness-001',
@@ -64,24 +65,24 @@ describe('WitnessModalComponent', () => {
evidence: {
callGraphHash: 'blake3:a1b2c3d4e5f6',
surfaceHash: 'sha256:9f8e7d6c5b4a',
analysisMethod: 'static',
},
signature: {
keyId: 'attestor-stellaops-ed25519',
algorithm: 'ed25519',
signatureValue: 'base64-signature-value',
signedAt: '2025-12-18T10:30:00Z',
signature: 'base64-signature-value',
},
observedAt: '2025-12-18T10:30:00Z',
};
beforeEach(async () => {
mockWitnessClient = {
verifySignature: jest.fn(),
getWitnessById: jest.fn(),
getWitnessForVulnerability: jest.fn(),
listWitnessesByScan: jest.fn(),
exportWitness: jest.fn(),
} as unknown as jest.Mocked<WitnessMockClient>;
mockWitnessClient = jasmine.createSpyObj('WitnessMockClient', [
'verifyWitness',
'getWitness',
'getWitnessesForVuln',
'listWitnesses',
'downloadWitnessJson',
]);
await TestBed.configureTestingModule({
imports: [WitnessModalComponent],
@@ -120,7 +121,7 @@ describe('WitnessModalComponent', () => {
it('should show path visualization for reachable vulns', () => {
expect(component.pathData()).toBeDefined();
expect(component.pathData()?.steps.length).toBeGreaterThan(0);
expect(component.pathData()?.callPath.length).toBeGreaterThan(0);
});
});
@@ -159,28 +160,30 @@ describe('WitnessModalComponent', () => {
it('should verify signature on button click', async () => {
const mockResult: WitnessVerificationResult = {
witnessId: 'witness-001',
verified: true,
keyId: 'attestor-stellaops-ed25519',
algorithm: 'ed25519',
message: 'Signature valid',
verifiedAt: '2025-12-18T10:30:00Z',
};
mockWitnessClient.verifySignature.mockReturnValue(Promise.resolve(mockResult));
mockWitnessClient.verifyWitness.and.returnValue(of(mockResult));
await component.verifySignature();
expect(mockWitnessClient.verifySignature).toHaveBeenCalledWith(mockWitness);
expect(mockWitnessClient.verifyWitness).toHaveBeenCalled();
expect(component.verificationResult()).toEqual(mockResult);
});
it('should handle verification failure', async () => {
const failedResult: WitnessVerificationResult = {
witnessId: 'witness-001',
verified: false,
keyId: 'attestor-stellaops-ed25519',
algorithm: 'ed25519',
message: 'Invalid signature',
verifiedAt: '2025-12-18T10:30:00Z',
error: 'Signature mismatch',
};
mockWitnessClient.verifySignature.mockReturnValue(Promise.resolve(failedResult));
mockWitnessClient.verifyWitness.and.returnValue(of(failedResult));
await component.verifySignature();
@@ -199,15 +202,15 @@ describe('WitnessModalComponent', () => {
it('should generate JSON download', () => {
// Mock URL.createObjectURL and document.createElement
const mockUrl = 'blob:mock-url';
global.URL.createObjectURL = jest.fn().mockReturnValue(mockUrl);
global.URL.revokeObjectURL = jest.fn();
spyOn(URL, 'createObjectURL').and.returnValue(mockUrl);
spyOn(URL, 'revokeObjectURL');
const mockAnchor = {
href: '',
download: '',
click: jest.fn(),
click: jasmine.createSpy('click'),
};
jest.spyOn(document, 'createElement').mockReturnValue(mockAnchor as unknown as HTMLAnchorElement);
spyOn(document, 'createElement').and.returnValue(mockAnchor as unknown as HTMLAnchorElement);
component.downloadJson();
@@ -225,20 +228,18 @@ describe('WitnessModalComponent', () => {
});
it('should copy witness ID to clipboard', async () => {
const mockClipboard = {
writeText: jest.fn().mockResolvedValue(undefined),
};
Object.assign(navigator, { clipboard: mockClipboard });
const writeTextSpy = jasmine.createSpy('writeText').and.returnValue(Promise.resolve(undefined));
Object.assign(navigator, { clipboard: { writeText: writeTextSpy } });
await component.copyWitnessId();
expect(mockClipboard.writeText).toHaveBeenCalledWith('witness-001');
expect(writeTextSpy).toHaveBeenCalledWith('witness-001');
});
});
describe('modal behavior', () => {
it('should emit close event on backdrop click', () => {
const closeSpy = jest.fn();
const closeSpy = jasmine.createSpy('close');
component.close.subscribe(closeSpy);
fixture.componentRef.setInput('witness', mockWitness);
@@ -252,7 +253,7 @@ describe('WitnessModalComponent', () => {
});
it('should not emit close when clicking modal content', () => {
const closeSpy = jest.fn();
const closeSpy = jasmine.createSpy('close');
component.close.subscribe(closeSpy);
fixture.componentRef.setInput('witness', mockWitness);
@@ -278,7 +279,7 @@ describe('WitnessModalComponent', () => {
expect(pathData?.entrypoint).toBeDefined();
expect(pathData?.entrypoint?.symbol).toBe('UserController.getUser');
expect(pathData?.sink?.symbol).toBe('JsonParser.parse');
expect(pathData?.steps.length).toBe(3);
expect(pathData?.callPath.length).toBe(3);
});
it('should include gates in path data', () => {