const Machine = require('./machine'); const specs = require('../../../generalFunctions/datasets/assetData/pumps/hydrostal/centrifugal pumps/models.json'); class MachineTester { constructor() { this.totalTests = 0; this.passedTests = 0; this.failedTests = 0; this.machineCurve = specs[0].machineCurve; } assert(condition, message) { this.totalTests++; if (condition) { console.log(`✓ PASS: ${message}`); this.passedTests++; } else { console.log(`✗ FAIL: ${message}`); this.failedTests++; } } createBaseMachineConfig(name) { return { general: { logging: { enabled: true, logLevel: "debug" }, name: name, unit: "m3/h" }, functionality: { softwareType: "machine", role: "RotationalDeviceController" }, asset: { type: "pump", subType: "Centrifugal", model: "TestModel", supplier: "Hydrostal", machineCurve: this.machineCurve }, mode: { current: "auto", allowedActions: { auto: ["execSequence", "execMovement", "statusCheck"], virtualControl: ["execMovement", "statusCheck"], fysicalControl: ["statusCheck"] }, allowedSources: { auto: ["parent", "GUI"], virtualControl: ["GUI"], fysicalControl: ["fysical"] } }, sequences: { startup: ["starting", "warmingup", "operational"], shutdown: ["stopping", "coolingdown", "idle"], emergencystop: ["emergencystop", "off"], boot: ["idle", "starting", "warmingup", "operational"] }, calculationMode: "medium" }; } async testBasicOperations() { console.log('\nTesting Basic Machine Operations...'); const machine = new Machine(this.createBaseMachineConfig("TestMachine")); try { // Test 1: Initialization this.assert( machine.currentMode === "auto", 'Machine should initialize in auto mode' ); // Test 2: Set pressure measurement machine.measurements.type("pressure").variant("measured").position("downstream").value(800); const pressure = machine.handleMeasuredPressure(); this.assert( pressure === 800, 'Should correctly handle pressure measurement' ); // Test 3: State transition await machine.state.transitionToState("idle"); this.assert( machine.state.getCurrentState() === "idle", 'Should transition to idle state' ); // Test 4: Mode change machine.setMode("virtualControl"); this.assert( machine.currentMode === "virtualControl", 'Should change mode to virtual control' ); } catch (error) { console.error('Test failed with error:', error); this.failedTests++; } } async testPredictions() { console.log('\nTesting Machine Predictions...'); const machine = new Machine(this.createBaseMachineConfig("TestMachine")); machine.measurements.type("pressure").variant("measured").position("downstream").value(800); try { // Test 1: Flow prediction const flow = machine.calcFlow(50); this.assert( flow > 0 && !isNaN(flow), 'Should calculate valid flow for control value' ); // Test 2: Power prediction const power = machine.calcPower(50); this.assert( power > 0 && !isNaN(power), 'Should calculate valid power for control value' ); // Test 3: Control prediction const ctrl = machine.calcCtrl(100); this.assert( ctrl >= 0 && ctrl <= 100, 'Should calculate valid control value for desired flow' ); } catch (error) { console.error('Test failed with error:', error); this.failedTests++; } } async testSequenceExecution() { console.log('\nTesting Machine Sequences...'); const machine = new Machine(this.createBaseMachineConfig("TestMachine")); try { // Test 1: Startup sequence await machine.handleInput("parent", "execSequence", "startup"); this.assert( machine.state.getCurrentState() === "operational", 'Should complete startup sequence' ); // Test 2: Movement after startup await machine.handleInput("parent", "execMovement", 50); this.assert( machine.state.getCurrentPosition() === 50, 'Should move to specified position' ); // Test 3: Shutdown sequence await machine.handleInput("parent", "execSequence", "shutdown"); this.assert( machine.state.getCurrentState() === "idle", 'Should complete shutdown sequence' ); // Test 4: Emergency stop await machine.handleInput("parent", "execSequence", "emergencystop"); this.assert( machine.state.getCurrentState() === "off", 'Should execute emergency stop' ); } catch (error) { console.error('Test failed with error:', error); this.failedTests++; } } async testMeasurementHandling() { console.log('\nTesting Measurement Handling...'); const machine = new Machine(this.createBaseMachineConfig("TestMachine")); try { // Test 1: Pressure measurement machine.measurements.type("pressure").variant("measured").position("downstream").value(800); machine.measurements.type("pressure").variant("measured").setUpstream(1000); const pressure = machine.handleMeasuredPressure(); this.assert( pressure === 200, 'Should calculate correct differential pressure' ); // Test 2: Flow measurement machine.measurements.type("flow").variant("measured").position("downstream").value(100); const flow = machine.handleMeasuredFlow(); this.assert( flow === 100, 'Should handle flow measurement correctly' ); // Test 3: Power measurement machine.measurements.type("power").variant("measured").setUpstream(75); const power = machine.handleMeasuredPower(); this.assert( power === 75, 'Should handle power measurement correctly' ); // Test 4: Efficiency calculation machine.calcEfficiency(); const efficiency = machine.measurements.type("efficiency").variant("measured").getDownstream(); this.assert( efficiency > 0 && !isNaN(efficiency), 'Should calculate valid efficiency' ); } catch (error) { console.error('Test failed with error:', error); this.failedTests++; } } async testCurveHandling() { console.log('\nTesting Machine Curve Handling...'); const machine = new Machine(this.createBaseMachineConfig("TestMachine")); try { // Test 1: Curve initialization const curves = machine.showCurve(); this.assert( curves.powerCurve && curves.flowCurve, 'Should properly initialize power and flow curves' ); // Test 2: Test reverse curve creation const reversedCurve = machine.reverseCurve(this.machineCurve.nq); this.assert( reversedCurve["1"].x[0] === this.machineCurve.nq["1"].y[0] && reversedCurve["1"].y[0] === this.machineCurve.nq["1"].x[0], 'Should correctly reverse x and y values in curve' ); // Test 3: Update curve dynamically const newCurve = { nq: { "1": { x: [0, 25, 50, 75, 100], y: [0, 125, 250, 375, 500] } }, np: { "1": { x: [0, 25, 50, 75, 100], y: [0, 75, 150, 225, 300] } } }; machine.updateCurve(newCurve); const updatedCurves = machine.showCurve(); this.assert( updatedCurves.flowCurve["1"].y[2] === 250, 'Should update curve with new values' ); // Test 4: Verify curve interpolation machine.measurements.type("pressure").variant("measured").position("downstream").value(800); const midpointCtrl = machine.calcCtrl(250); // Should interpolate between points const calculatedFlow = machine.calcFlow(midpointCtrl); this.assert( Math.abs(calculatedFlow - 250) < 1, // Allow small numerical error 'Should accurately interpolate between curve points' ); } catch (error) { console.error('Test failed with error:', error); this.failedTests++; } } async runAllTests() { console.log('Starting Machine Tests...\n'); await this.testBasicOperations(); await this.testPredictions(); await this.testSequenceExecution(); await this.testMeasurementHandling(); await this.testCurveHandling(); console.log('\nTest Summary:'); console.log(`Total Tests: ${this.totalTests}`); console.log(`Passed: ${this.passedTests}`); console.log(`Failed: ${this.failedTests}`); process.exit(this.failedTests > 0 ? 1 : 0); } } // Run the tests const tester = new MachineTester(); tester.runAllTests().catch(console.error);