From: sourabh_sourabh Date: Wed, 4 Jun 2025 17:22:42 +0000 (+0100) Subject: Refactor(utils): Consolidate response handling into utility functions X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=63757c351de63101e10add79941adaf530ad0202;p=cps.git Refactor(utils): Consolidate response handling into utility functions Abstracted common HTTP response validation and metric recording logic into reusable utility functions: - Added `validateAndRecordMetric` for generalized response checks and metric recording. - Introduced `processHttpResponseWithOverheadMetrics` to handle response times adjusted for known delays. - Created `validateResponseAndRecordMetric` to validate JSON response lengths and record metrics. These changes promote code reuse and maintain consistency across test scenarios. Issue-ID: CPS-2690 Change-Id: Ie4dd1075c65e87c1b48225e096b2b781b098da0f Signed-off-by: sourabh_sourabh --- diff --git a/k6-tests/ncmp/common/utils.js b/k6-tests/ncmp/common/utils.js index ca3a651b95..0c2491270f 100644 --- a/k6-tests/ncmp/common/utils.js +++ b/k6-tests/ncmp/common/utils.js @@ -146,25 +146,45 @@ function makeSummaryCsvLine(testCase, testName, unit, measurementName, currentEx } /** - * Handles the response by performing a check, logging errors if any, and recording overhead. + * Validates a response against an expected HTTP status and an optional additional check. + * If successful, records a metric value to a trend. Logs detailed error output on failure. + * + * @param {Object} response - The HTTP response object from a K6 request. + * @param {number} expectedStatus - The expected HTTP status code (e.g., 200, 202). + * @param {string} checkLabel - The label to use in the K6 `check()` for reporting. + * @param {Trend} trendMetric - A K6 `Trend` metric to which the extracted value will be added on success. + * @param {function(Object): number} metricExtractor - A function that takes the response and returns a numeric value to record (e.g., `res.timings.duration`). + * @param {function(Object): boolean} [additionalCheckValidator=() => true] - Optional function for any additional custom validation on the response. * - * @param {Object} response - The HTTP response object. - * @param {number} expectedStatus - The expected HTTP status code. - * @param {string} checkLabel - A descriptive label for the check. - * @param {number} delayMs - The predefined delay in milliseconds. - * @param {Trend} trendMetric - The Trend metric to record overhead. */ -export function handleHttpResponse(response, expectedStatus, checkLabel, delayMs, trendMetric) { +export function validateAndRecordMetric(response, expectedStatus, checkLabel, trendMetric, metricExtractor, additionalCheckValidator = () => true) { + + const isExpectedStatus = response.status === expectedStatus; + const isAdditionalCheckValid = additionalCheckValidator(response); const isSuccess = check(response, { - [checkLabel]: (responseObj) => responseObj.status === expectedStatus, + [checkLabel]: () => isExpectedStatus && isAdditionalCheckValid, }); if (isSuccess) { - const overhead = response.timings.duration - delayMs; - trendMetric.add(overhead); + trendMetric.add(metricExtractor(response)); } else { - let responseBody = JSON.parse(response.body); - console.error(`${checkLabel} failed: Error response status: ${response.status}, message: ${responseBody.message}, details: ${responseBody.details}`); + console.error(`${checkLabel} failed. Status: ${response.status}`); + if (response.body) { + try { + const responseBody = JSON.parse(response.body); + console.error(`❌ ${checkLabel} failed: Error response status: ${response.status}, message: ${responseBody.message}, details: ${responseBody.details}`); + } catch (e) { + console.error(`❌ ${checkLabel} failed: Unable to parse response body.`); + } + } } } +export function processHttpResponseWithOverheadMetrics(response, expectedStatus, checkLabel, delayMs, trendMetric) { + validateAndRecordMetric(response, expectedStatus, checkLabel, trendMetric, (res) => res.timings.duration - delayMs); +} + +export function validateResponseAndRecordMetric(response, expectedStatus, expectedJsonLength, trendMetric, checkLabel) { + validateAndRecordMetric(response, expectedStatus, checkLabel, trendMetric, (res) => res.timings.duration, (res) => res.json('#') === expectedJsonLength); +} + diff --git a/k6-tests/ncmp/ncmp-test-runner.js b/k6-tests/ncmp/ncmp-test-runner.js index a3c30d83ed..dae4df5af0 100644 --- a/k6-tests/ncmp/ncmp-test-runner.js +++ b/k6-tests/ncmp/ncmp-test-runner.js @@ -25,7 +25,8 @@ import { TOTAL_CM_HANDLES, READ_DATA_FOR_CM_HANDLE_DELAY_MS, WRITE_DATA_FOR_CM_HANDLE_DELAY_MS, makeCustomSummaryReport, makeBatchOfCmHandleIds, makeRandomBatchOfAlternateIds, LEGACY_BATCH_THROUGHPUT_TEST_BATCH_SIZE, REGISTRATION_BATCH_SIZE, - KAFKA_BOOTSTRAP_SERVERS, LEGACY_BATCH_TOPIC_NAME, CONTAINER_UP_TIME_IN_SECONDS, testConfig, handleHttpResponse + KAFKA_BOOTSTRAP_SERVERS, LEGACY_BATCH_TOPIC_NAME, CONTAINER_UP_TIME_IN_SECONDS, testConfig, processHttpResponseWithOverheadMetrics, + validateResponseAndRecordMetric } from './common/utils.js'; import { createCmHandles, deleteCmHandles, waitForAllCmHandlesToBeReady } from './common/cmhandle-crud.js'; import { executeCmHandleSearch, executeCmHandleIdSearch } from './common/search-base.js'; @@ -91,94 +92,62 @@ export function teardown() { export function passthroughReadAltIdScenario() { const response = passthroughRead(); - handleHttpResponse(response, 200, 'passthrough read with alternate Id status equals 200', - READ_DATA_FOR_CM_HANDLE_DELAY_MS, ncmpReadOverheadTrend); + processHttpResponseWithOverheadMetrics(response, 200, 'passthrough read with alternate Id status equals 200', READ_DATA_FOR_CM_HANDLE_DELAY_MS, ncmpReadOverheadTrend); } export function passthroughWriteAltIdScenario() { const response = passthroughWrite(); - handleHttpResponse(response, 201, 'passthrough write with alternate Id status equals 201', - WRITE_DATA_FOR_CM_HANDLE_DELAY_MS, ncmpWriteOverheadTrend); + processHttpResponseWithOverheadMetrics(response, 201, 'passthrough write with alternate Id status equals 201', WRITE_DATA_FOR_CM_HANDLE_DELAY_MS, ncmpWriteOverheadTrend); } export function cmHandleIdSearchNoFilterScenario() { const response = executeCmHandleIdSearch('no-filter'); - if (check(response, { 'CM handle ID no-filter search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle ID no-filter search returned the correct number of ids': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleIdSearchNoFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleIdSearchNoFilterTrend, 'CM handle ID no-filter search'); } export function cmHandleSearchNoFilterScenario() { const response = executeCmHandleSearch('no-filter'); - if (check(response, { 'CM handle no-filter search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle no-filter search returned expected CM-handles': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleSearchNoFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleSearchNoFilterTrend, 'CM handle no-filter search'); } export function cmHandleIdSearchModuleScenario() { const response = executeCmHandleIdSearch('module'); - if (check(response, { 'CM handle ID module search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle ID module search returned the correct number of ids': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleIdSearchModuleFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleIdSearchModuleFilterTrend, 'CM handle ID module search'); } export function cmHandleSearchModuleScenario() { const response = executeCmHandleSearch('module'); - if (check(response, { 'CM handle module search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle module search returned expected CM-handles': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleSearchModuleFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleSearchModuleFilterTrend, 'CM handle module search'); } export function cmHandleIdSearchPropertyScenario() { const response = executeCmHandleIdSearch('property'); - if (check(response, { 'CM handle ID property search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle ID property search returned the correct number of ids': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleIdSearchPropertyFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleIdSearchPropertyFilterTrend, 'CM handle ID property search'); } export function cmHandleSearchPropertyScenario() { const response = executeCmHandleSearch('property'); - if (check(response, { 'CM handle property search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle property search returned expected CM-handles': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleSearchPropertyFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleSearchPropertyFilterTrend, 'CM handle property search'); } export function cmHandleIdSearchCpsPathScenario() { const response = executeCmHandleIdSearch('cps-path-for-ready-cm-handles'); - if (check(response, { 'CM handle ID cps path search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle ID cps path search returned the correct number of ids': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleIdSearchCpsPathFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleIdSearchCpsPathFilterTrend, 'CM handle ID cps path search'); } export function cmHandleSearchCpsPathScenario() { const response = executeCmHandleSearch('cps-path-for-ready-cm-handles'); - if (check(response, { 'CM handle cps path search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle cps path search returned expected CM-handles': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleSearchCpsPathFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleSearchCpsPathFilterTrend, 'CM handle cps path search'); } export function cmHandleIdSearchTrustLevelScenario() { const response = executeCmHandleIdSearch('trust-level'); - if (check(response, { 'CM handle ID trust level search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle ID trust level search returned the correct number of cm handle references': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleIdSearchTrustLevelFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleIdSearchTrustLevelFilterTrend, 'CM handle ID trust level search'); } export function cmHandleSearchTrustLevelScenario() { const response = executeCmHandleSearch('trust-level'); - if (check(response, { 'CM handle trust level search status equals 200': (response) => response.status === 200 }) - && check(response, { 'CM handle trust level search returned expected CM-handles': (response) => response.json('#') === TOTAL_CM_HANDLES })) { - cmHandleSearchTrustLevelFilterTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, TOTAL_CM_HANDLES, cmHandleSearchTrustLevelFilterTrend, 'CM handle trust level search'); } export function legacyBatchProduceScenario() { @@ -189,18 +158,12 @@ export function legacyBatchProduceScenario() { export function writeDataJobLargeScenario() { const response = executeWriteDataJob(100000); - if (check(response, {'large writeDataJob response status is 200': (response) => response.status === 200}) - && check(response, {'large writeDataJob received expected number of responses': (response) => response.json('#') === EXPECTED_WRITE_RESPONSE_COUNT})) { - dcmWriteDataJobLargeTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, EXPECTED_WRITE_RESPONSE_COUNT, dcmWriteDataJobLargeTrend, 'Large writeDataJob'); } export function writeDataJobSmallScenario() { const response = executeWriteDataJob(100); - if (check(response, {'small writeDataJob response status is 200': (response) => response.status === 200}) - && check(response, {'small writeDataJob received expected number of responses': (response) => response.json('#') === EXPECTED_WRITE_RESPONSE_COUNT})) { - dcmWriteDataJobSmallTrend.add(response.timings.duration); - } + validateResponseAndRecordMetric(response, 200, EXPECTED_WRITE_RESPONSE_COUNT, dcmWriteDataJobSmallTrend, 'Small writeDataJob'); } export function produceAvcEventsScenario() { diff --git a/k6-tests/ncmp/run-all-tests.sh b/k6-tests/ncmp/run-all-tests.sh index c7197b67d2..872bd0c643 100755 --- a/k6-tests/ncmp/run-all-tests.sh +++ b/k6-tests/ncmp/run-all-tests.sh @@ -87,7 +87,7 @@ awk -v trends="$trend_declarations" ' } ' "$NCMP_RUNNER_FILE" > "$TMP_FILE" mv "$TMP_FILE" "$NCMP_RUNNER_FILE" -echo "✅ Trend declarations inserted." +echo "✅ Trend declarations inserted into [$NCMP_RUNNER_FILE]" # Update thresholds in KPI config TMP_FILE=$(mktemp)