From d0aea4d1a038ef10374168ca957acc51aec65067 Mon Sep 17 00:00:00 2001 From: frantuma Date: Thu, 25 Jan 2024 14:28:57 +0100 Subject: [PATCH] test 3735 --- .../services/validation/validation-service.ts | 2 + .../fixtures/validation/oas/issue3735.json | 1 + packages/apidom-ls/test/validate.ts | 53 ++++++++++++-- .../dereference/dereference-apidom-failure.ts | 73 +++++++++++++++++++ .../ticket-3735/fixtures/dereferenced.json | 17 +++++ .../ticket-3735/fixtures/root.json | 1 + 6 files changed, 141 insertions(+), 6 deletions(-) create mode 100644 packages/apidom-ls/test/fixtures/validation/oas/issue3735.json create mode 100644 packages/apidom-reference/test/dereference/dereference-apidom-failure.ts create mode 100644 packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/dereferenced.json create mode 100644 packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/root.json diff --git a/packages/apidom-ls/src/services/validation/validation-service.ts b/packages/apidom-ls/src/services/validation/validation-service.ts index 27b767c7c5..c3119a5cfd 100644 --- a/packages/apidom-ls/src/services/validation/validation-service.ts +++ b/packages/apidom-ls/src/services/validation/validation-service.ts @@ -181,6 +181,7 @@ export class DefaultValidationService implements ValidationService { nameSpace: ContentLanguage, validationContext?: ValidationContext, ): Promise { + console.log('validateReferencesConcurrent'); const SharedReferenceSet = stampit(ReferenceSet, { statics: { refs: [], @@ -325,6 +326,7 @@ export class DefaultValidationService implements ValidationService { nameSpace: ContentLanguage, validationContext?: ValidationContext, ): Promise { + console.log('validateReferencesSequential'); const diagnostics: Diagnostic[] = []; const pointersMap: Record = {}; diff --git a/packages/apidom-ls/test/fixtures/validation/oas/issue3735.json b/packages/apidom-ls/test/fixtures/validation/oas/issue3735.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/apidom-ls/test/fixtures/validation/oas/issue3735.json @@ -0,0 +1 @@ +{} diff --git a/packages/apidom-ls/test/validate.ts b/packages/apidom-ls/test/validate.ts index 58502e3573..a32001d14c 100644 --- a/packages/apidom-ls/test/validate.ts +++ b/packages/apidom-ls/test/validate.ts @@ -2,21 +2,30 @@ import fs from 'node:fs'; import path from 'node:path'; import { assert } from 'chai'; import { TextDocument } from 'vscode-languageserver-textdocument'; -import { Diagnostic, DiagnosticSeverity, CodeAction } from 'vscode-languageserver-types'; +import { CodeAction, Diagnostic, DiagnosticSeverity } from 'vscode-languageserver-types'; import getLanguageService from '../src/apidom-language-service'; import { LanguageService, LanguageServiceContext, + ReferenceValidationMode, ValidationContext, } from '../src/apidom-language-types'; import { metadata } from './metadata'; -import { OpenAPi31JsonSchemaValidationProvider } from '../src/services/validation/providers/openapi-31-json-schema-validation-provider'; -import { Asyncapi20JsonSchemaValidationProvider } from '../src/services/validation/providers/asyncapi-20-json-schema-validation-provider'; -import { Asyncapi21JsonSchemaValidationProvider } from '../src/services/validation/providers/asyncapi-21-json-schema-validation-provider'; -import { Asyncapi22JsonSchemaValidationProvider } from '../src/services/validation/providers/asyncapi-22-json-schema-validation-provider'; +import { + OpenAPi31JsonSchemaValidationProvider, +} from '../src/services/validation/providers/openapi-31-json-schema-validation-provider'; +import { + Asyncapi20JsonSchemaValidationProvider, +} from '../src/services/validation/providers/asyncapi-20-json-schema-validation-provider'; +import { + Asyncapi21JsonSchemaValidationProvider, +} from '../src/services/validation/providers/asyncapi-21-json-schema-validation-provider'; +import { + Asyncapi22JsonSchemaValidationProvider, +} from '../src/services/validation/providers/asyncapi-22-json-schema-validation-provider'; import openapiSchemaJson30 from '../src/services/validation/json-schema/open-api-30/openapi-schema-idea-draft7.json'; -import { logPerformance, logLevel } from './test-utils'; +import { logLevel, logPerformance } from './test-utils'; const specOpenapiSimple = fs .readFileSync(path.join(__dirname, 'fixtures', 'ajv-simple-api.json')) @@ -3755,4 +3764,36 @@ describe('apidom-ls-validate', function () { languageService.terminate(); }); + + it.only('openapi / json - validation should not go into infinite loop - issue #3735', async function () { + const validationContext: ValidationContext = { + comments: DiagnosticSeverity.Error, + referenceValidationMode: ReferenceValidationMode.APIDOM_INDIRECT, + referenceValidationSequentialProcessing: true, + maxNumberOfProblems: 100, + relatedInformation: false, + }; + + const spec = fs + .readFileSync(path.join(__dirname, 'fixtures', 'validation', 'oas', 'issue3735.json')) + .toString(); + const doc: TextDocument = TextDocument.create('foo://bar/issue3735.yaml', 'json', 0, spec); + + const languageService: LanguageService = getLanguageService(contextNoSchema); + + const result = await languageService.doValidation(doc, validationContext); + const expected: Diagnostic[] = [ + { + range: { start: { line: 36, character: 8 }, end: { line: 36, character: 13 } }, + message: 'Schema does not include any Schema Object keywords', + severity: 4, + code: 10072, + source: 'apilint', + }, + ]; + console.log(JSON.stringify(result, null, 2)); + // assert.deepEqual(result, expected as Diagnostic[]); + + languageService.terminate(); + }); }); diff --git a/packages/apidom-reference/test/dereference/dereference-apidom-failure.ts b/packages/apidom-reference/test/dereference/dereference-apidom-failure.ts new file mode 100644 index 0000000000..b50ee504f8 --- /dev/null +++ b/packages/apidom-reference/test/dereference/dereference-apidom-failure.ts @@ -0,0 +1,73 @@ +import path from 'node:path'; +import { + toValue, + traverse, + Element, + ObjectElement, + isObjectElement, +} from '@swagger-api/apidom-core'; +import { mediaTypes } from '@swagger-api/apidom-ns-openapi-3-0'; + +import { dereferenceApiDOM, parse, Reference, ReferenceSet } from '../../src'; + +const isObject = (element: Element): element is ObjectElement => { + return isObjectElement(element); +}; + +describe.only('dereferenceApiDOM', function () { + const fixturePath = path.join(__dirname, 'strategies', 'openapi-3-0', 'ticket-3735', 'fixtures'); + const rootFilePath = path.join(fixturePath, 'root.json'); + // const expected = loadJsonFile(path.join(fixturePath, 'dereferenced.json')); + + context('given the spec', function () { + specify('should dereference an ApiDOM fragment with no errors', async function () { + const baseURI = 'https://smartbear.com/'; + + const refElements: Element[] = []; + const result = await parse(rootFilePath, { + parse: { mediaType: mediaTypes.latest('json') }, + }); + const { api } = result; + const collectRefs = (element: Element) => { + if ( + toValue(element.getMetaProperty('referenced-element', '')).length > 0 && + isObject(element) && + element.hasKey('$ref') + ) { + refElements.push(element); + } + }; + traverse(collectRefs, api!); + + const apiReference = Reference({ uri: baseURI, value: result }); + let fragmentId = 0; + const refSet = ReferenceSet({ refs: [apiReference] }); + + for (const refEl of refElements) { + // @ts-ignore + refSet.rootRef = null; + fragmentId += 1; + const referenceElementReference = Reference({ + uri: `${baseURI}#reference${fragmentId}`, + value: refEl, + }); + refSet.add(referenceElementReference); + try { + // eslint-disable-next-line no-await-in-loop + await dereferenceApiDOM(refEl, { + resolve: { + baseURI: `${baseURI}#reference${fragmentId}`, + external: !toValue((refEl as ObjectElement).get('$ref')).startsWith('#'), + }, + parse: { + mediaType: mediaTypes.latest('json'), + }, + dereference: { refSet }, + }); + } catch (ex) { + console.log(ex); + } + } + }); + }); +}); diff --git a/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/dereferenced.json b/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/dereferenced.json new file mode 100644 index 0000000000..e54e11a0aa --- /dev/null +++ b/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/dereferenced.json @@ -0,0 +1,17 @@ +[ + { + "openapi": "3.0.3", + "components": { + "examples": { + "example1": { + "description": "example1 description", + "value": 1 + }, + "example2": { + "description": "example1 description", + "value": 1 + } + } + } + } +] diff --git a/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/root.json b/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/root.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/apidom-reference/test/dereference/strategies/openapi-3-0/ticket-3735/fixtures/root.json @@ -0,0 +1 @@ +{}