Add 3 regression tests for GPN-unsupported + catalog classification flow: 1) GPN fault triggers catalog + persists to DB, 2) subsequent session with same params skips GPN, 3) new param in Inform triggers catalog for unclassified only. All 814 tests pass. Build status: Success
This commit is contained in:
1 parent
a9c7bcf643
commit
e43b493eff
1 file changed
+133
@@ -265,3 +265,136 @@ describe('Two-session scenario: same device, first contact then reconnect', () =
|
||||
console.log(` Skipped: GPN test, inventory, SPV, ProvisioningCode`)
|
||||
})
|
||||
})
|
||||
|
||||
import DeviceModel from '../../../../app/models/device.js'
|
||||
|
||||
describe('GPN unsupported → catalog classification + persistence', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
it('GPN fault triggers catalog reclassification and persists to DB', async () => {
|
||||
// Simulate a Livebox 4 (tr-181) device with Inform params
|
||||
const device = new Device(new DeviceId('Sagemcom', 'F8B7FF', 'Livebox 4', 'LB4-TEST-001'))
|
||||
device.setDataModel('tr-181')
|
||||
const informParams = [
|
||||
{ Name: 'Device.DeviceInfo.HardwareVersion', Value: { _: 'v3.0' } },
|
||||
{ Name: 'Device.DeviceInfo.SoftwareVersion', Value: { _: 'SR50-5.0.0' } },
|
||||
{ Name: 'Device.ManagementServer.ConnectionRequestURL', Value: { _: 'http://cpe:7547/' } },
|
||||
{ Name: 'Device.ManagementServer.PeriodicInformInterval', Value: { _: '60' } },
|
||||
]
|
||||
device.updateFromValues(informParams)
|
||||
device.setTmpParamValues(informParams)
|
||||
// gpnStatus = 'unknown' → will attempt GPN
|
||||
|
||||
const taskQueue = new CWMPTaskQueue()
|
||||
const sm = new MainStateMachine(device, 'session-gpn-fail', taskQueue)
|
||||
|
||||
// Step 1: start → sends GPN for Device.DeviceInfo. (first unclassified path)
|
||||
const step1 = await sm.start()
|
||||
expect(step1).toContain('GetParameterNames')
|
||||
expect(sm.getCurrentStateName()).toBe('discovering-parameters')
|
||||
|
||||
// Step 2: GPN Fault → mark unsupported + catalog classify + persist
|
||||
const step2 = await sm.handleResponse(false, {
|
||||
FaultCode: 9003,
|
||||
FaultString: 'Method not supported',
|
||||
})
|
||||
|
||||
// Verify: reclassifyDeviceFromCatalog was called
|
||||
expect(vi.mocked(reclassifyDeviceFromCatalog)).toHaveBeenCalledWith(device)
|
||||
|
||||
// Verify: DeviceModel.createOrUpdate was called to persist the classification
|
||||
expect(vi.mocked(DeviceModel.createOrUpdate)).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
gpnStatus: 'unsupported',
|
||||
gpnCircuitBreaker: expect.objectContaining({ failureCount: 1 }),
|
||||
})
|
||||
)
|
||||
|
||||
// Verify: device is marked as unsupported
|
||||
expect(device.gpnStatus).toBe('unsupported')
|
||||
expect(device.gpnCircuitBreaker.failureCount).toBe(1)
|
||||
|
||||
// Verify: transitioned to critical-reads (sends GPV)
|
||||
expect(step2).toContain('GetParameterValues')
|
||||
expect(sm.getCurrentStateName()).toBe('critical-reads')
|
||||
})
|
||||
|
||||
it('subsequent session with same params skips GPN (all classified)', async () => {
|
||||
// Simulate device loaded from DB after first session (already classified)
|
||||
const device = new Device(new DeviceId('Sagemcom', 'F8B7FF', 'Livebox 4', 'LB4-TEST-001'))
|
||||
device.setDataModel('tr-181')
|
||||
device.setGpnStatus('unsupported')
|
||||
|
||||
// After catalog classification, PeriodicInformInterval is a parameter (writable)
|
||||
device.setParameter(new DeviceParameter(
|
||||
'Device.ManagementServer.PeriodicInformInterval', '300', ParameterType.UNSIGNED_INT
|
||||
))
|
||||
// Read-only params are properties
|
||||
device.setProperty(new DeviceProperty('Device.DeviceInfo.HardwareVersion', 'v3.0', ParameterType.STRING))
|
||||
device.setProperty(new DeviceProperty('Device.DeviceInfo.SoftwareVersion', 'SR50-5.0.0', ParameterType.STRING))
|
||||
device.setProperty(new DeviceProperty('Device.ManagementServer.ConnectionRequestURL', 'http://cpe:7547/', ParameterType.STRING))
|
||||
|
||||
// Inform arrives with same params (all already classified)
|
||||
const informParams = [
|
||||
{ Name: 'Device.DeviceInfo.HardwareVersion', Value: { _: 'v3.0' } },
|
||||
{ Name: 'Device.DeviceInfo.SoftwareVersion', Value: { _: 'SR50-5.0.0' } },
|
||||
{ Name: 'Device.ManagementServer.ConnectionRequestURL', Value: { _: 'http://cpe:7547/' } },
|
||||
{ Name: 'Device.ManagementServer.PeriodicInformInterval', Value: { _: '300' } },
|
||||
]
|
||||
device.updateFromValues(informParams)
|
||||
device.setTmpParamValues(informParams)
|
||||
|
||||
const taskQueue = new CWMPTaskQueue()
|
||||
const sm = new MainStateMachine(device, 'session-2', taskQueue)
|
||||
|
||||
// Start → all params classified → skip GPN → directly to critical-reads (GPV)
|
||||
const step1 = await sm.start()
|
||||
expect(step1).toContain('GetParameterValues')
|
||||
expect(step1).not.toContain('GetParameterNames')
|
||||
expect(sm.getCurrentStateName()).toBe('critical-reads')
|
||||
|
||||
// reclassifyDeviceFromCatalog should NOT have been called
|
||||
expect(vi.mocked(reclassifyDeviceFromCatalog)).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('session with NEW param in Inform (not yet in properties) triggers catalog classification', async () => {
|
||||
// Device already classified from previous session
|
||||
const device = new Device(new DeviceId('Sagemcom', 'F8B7FF', 'Livebox 4', 'LB4-TEST-001'))
|
||||
device.setDataModel('tr-181')
|
||||
device.setGpnStatus('unsupported')
|
||||
device.setGpnCircuitBreaker({ failureCount: 1, lastFailureDate: new Date(), state: 'closed', cooldownUntil: null })
|
||||
|
||||
// Existing classified params
|
||||
device.setParameter(new DeviceParameter('Device.ManagementServer.PeriodicInformInterval', '300', ParameterType.UNSIGNED_INT))
|
||||
device.setProperty(new DeviceProperty('Device.DeviceInfo.HardwareVersion', 'v3.0', ParameterType.STRING))
|
||||
device.setProperty(new DeviceProperty('Device.ManagementServer.ConnectionRequestURL', 'http://cpe:7547/', ParameterType.STRING))
|
||||
|
||||
// New Inform arrives with a NEW param that is NOT in _parameters/_properties
|
||||
// (simulating a param that wasn't in the previous Inform and wasn't stored by updateFromValues)
|
||||
const informParams = [
|
||||
{ Name: 'Device.DeviceInfo.HardwareVersion', Value: { _: 'v3.0' } },
|
||||
{ Name: 'Device.ManagementServer.ConnectionRequestURL', Value: { _: 'http://cpe:7547/' } },
|
||||
{ Name: 'Device.ManagementServer.PeriodicInformInterval', Value: { _: '300' } },
|
||||
{ Name: 'Device.WANDevice.1.ExternalIPAddress', Value: { _: '192.168.1.1' } }, // NEW - not in device yet
|
||||
]
|
||||
// Only set tmpParamValues WITHOUT updateFromValues for the new param
|
||||
device.setTmpParamValues(informParams)
|
||||
|
||||
const taskQueue = new CWMPTaskQueue()
|
||||
const sm = new MainStateMachine(device, 'session-new-param', taskQueue)
|
||||
|
||||
// Start → detects 1 unclassified param (WANDevice not in _parameters/_properties)
|
||||
// GPN unsupported → catalog classify
|
||||
const step1 = await sm.start()
|
||||
|
||||
// Should have called catalog to classify the new param
|
||||
expect(vi.mocked(reclassifyDeviceFromCatalog)).toHaveBeenCalledWith(device)
|
||||
|
||||
// Should go to critical-reads (GPV)
|
||||
expect(step1).toContain('GetParameterValues')
|
||||
expect(sm.getCurrentStateName()).toBe('critical-reads')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in new issue
Block a user