Files
adam-acs/tests/property/inventory_coverage.property.spec.ts
T
Kevin L'HereecandCopilot d1c65dbf1e chore: initial commit — AdonisJS v7 TR-069 ACS
- Docker infrastructure (Dockerfile, docker-compose.yml, genieacs-sim)
- AdonisJS v7 app with Inertia.js + Vue 3
- MongoDB integration
- CWMP/TR-069 state machine engine
- Configuration engine with compliance tracking
- Branding: ADAM ACS (favicon, navbar, locales)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-29 16:46:37 +02:00

119 lines
4.2 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import * as fc from 'fast-check'
import {
isParameterCoveredByInventory,
suggestInventoryPath,
} from '../../app/utils/inventory_coverage.js'
/**
* **Validates: Requirements 5.5**
*
* Property 9: Desired parameters require inventory coverage
* Verifies subtree prefix matching logic using random TR-069-like paths.
*/
// Arbitrary: generates a single TR-069 path segment (alphanumeric, 1-10 chars)
const segmentArb = fc.array(
fc.constantFrom(...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('')),
{ minLength: 1, maxLength: 10 }
).map((chars) => chars.join(''))
// Arbitrary: generates a TR-069-like dot-separated path with 2-5 segments (e.g. "Device.Info.Param")
const tr069PathArb = fc.array(segmentArb, { minLength: 2, maxLength: 5 }).map((segments) => segments.join('.'))
// Arbitrary: generates a subtree path (ends with dot) from a TR-069 path by removing the last segment
const subtreePathFromParamArb = tr069PathArb.map((paramPath) => {
const parts = paramPath.split('.')
parts.pop()
return { paramPath, subtreePath: parts.join('.') + '.' }
})
describe('Property 9: Inventory coverage validation', () => {
it('a parameter is always covered by its own subtree path', () => {
fc.assert(
fc.property(subtreePathFromParamArb, ({ paramPath, subtreePath }) => {
const result = isParameterCoveredByInventory(paramPath, [{ path: subtreePath }])
expect(result).toBe(true)
}),
{ numRuns: 200 }
)
})
it('suggestInventoryPath always produces a path that covers the original parameter', () => {
fc.assert(
fc.property(tr069PathArb, (paramPath) => {
const suggested = suggestInventoryPath(paramPath)
const result = isParameterCoveredByInventory(paramPath, [{ path: suggested }])
expect(result).toBe(true)
}),
{ numRuns: 200 }
)
})
it('a subtree path covers all parameters that start with it', () => {
fc.assert(
fc.property(
fc.array(segmentArb, { minLength: 1, maxLength: 3 }),
fc.array(segmentArb, { minLength: 1, maxLength: 3 }),
(prefixSegments, suffixSegments) => {
const subtreePath = prefixSegments.join('.') + '.'
const paramPath = prefixSegments.join('.') + '.' + suffixSegments.join('.')
const result = isParameterCoveredByInventory(paramPath, [{ path: subtreePath }])
expect(result).toBe(true)
}
),
{ numRuns: 200 }
)
})
it('a subtree path does NOT cover parameters that do not start with it', () => {
fc.assert(
fc.property(
fc.array(segmentArb, { minLength: 1, maxLength: 3 }),
fc.array(segmentArb, { minLength: 1, maxLength: 3 }),
segmentArb,
(prefixSegments, suffixSegments, differentFirst) => {
const subtreePath = prefixSegments.join('.') + '.'
// Build a param that does NOT start with the subtree path
// by using a different first segment
const altFirst = differentFirst + 'X' // ensure it differs
const paramPath = altFirst + '.' + suffixSegments.join('.')
// Only assert when the param truly doesn't start with the subtree
fc.pre(!paramPath.startsWith(subtreePath))
const result = isParameterCoveredByInventory(paramPath, [{ path: subtreePath }])
expect(result).toBe(false)
}
),
{ numRuns: 200 }
)
})
it('an exact path (no trailing dot) only matches the exact same string', () => {
fc.assert(
fc.property(tr069PathArb, tr069PathArb, (exactPath, otherPath) => {
// exactPath has no trailing dot, so it's an exact match inventory path
fc.pre(!exactPath.endsWith('.'))
const result = isParameterCoveredByInventory(otherPath, [{ path: exactPath }])
if (otherPath === exactPath) {
expect(result).toBe(true)
} else {
expect(result).toBe(false)
}
}),
{ numRuns: 200 }
)
})
it('empty inventory paths array means never covered', () => {
fc.assert(
fc.property(tr069PathArb, (paramPath) => {
const result = isParameterCoveredByInventory(paramPath, [])
expect(result).toBe(false)
}),
{ numRuns: 200 }
)
})
})