Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] python-experimental stackOverflow when using self-referencing data structures like GeoJson #13043

Closed
5 of 6 tasks
fbl100 opened this issue Jul 29, 2022 · 6 comments · Fixed by #13062
Closed
5 of 6 tasks

Comments

@fbl100
Copy link
Contributor

fbl100 commented Jul 29, 2022

Bug Report Checklist

  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator (example)?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

Issue 8052 fixed a bug with example values for models with circular references. The test case provided was a minimal representation of GeoJSON. While it is unclear what has changed, a full representation of the GeoJson Specification now causes an infinite recursion in python-experimental. The full GeoJson Specification "works" in the legacy generator, in that it doesn't get into an infinite loop.

openapi-generator version

6.0.1+

OpenAPI declaration file content or url

The GeoJsonGeometry used in the prior test was not exactly right and may have masked the true nature of this bug. This spec is not the full GeoJson, but it is sufficient to cause the bug. Essentially a GeoJsonGeometry is either a Point, or a GeometryCollection, and a GeometryCollection can have more GeoJsonGeometry objects. The full spec includes lines, polygons, and a few more types, but this is the minimal subset that causes the issue.

openapi: 3.0.0
info:
  version: 01.01.00
  title: APITest API documentation.
  termsOfService: http://api.apitest.com/party/tos/
servers:
  - url: https://api.apitest.com/v1
paths:
  /geojson:
    post:
      summary: Add a GeoJson Object
      operationId: post-geojson
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: string
                description: GeoJson ID
        '400':
          description: Bad Request
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/GeoJsonGeometry'
      parameters: []
components:
  schemas:
    GeoJsonGeometry:
      title: GeoJsonGeometry
      description: GeoJSON geometry
      oneOf:
        - $ref: '#/components/schemas/Point'
        - $ref: '#/components/schemas/GeometryCollection'
      discriminator:
        propertyName: type
        mapping:
          Point: '#/components/schemas/Point'
          GeometryCollection: '#/components/schemas/GeometryCollection'
      externalDocs:
        url: http://geojson.org/geojson-spec.html#geometry-objects
    Point:
      title: Point
      type: object
      description: GeoJSON geometry
      externalDocs:
        url: http://geojson.org/geojson-spec.html#id2
      properties:
        coordinates:
          title: Point3D
          type: array
          description: Point in 3D space
          externalDocs:
            url: http://geojson.org/geojson-spec.html#id2
          minItems: 2
          maxItems: 3
          items:
            type: number
            format: double
        type:
          type: string
          default: Point
      required:
        - type
    GeometryCollection:
      title: GeometryCollection
      type: object
      description: GeoJSon geometry collection
      required:
        - type
        - geometries
      externalDocs:
        url: http://geojson.org/geojson-spec.html#geometrycollection
      properties:
        type:
          type: string
          default: GeometryCollection
        geometries:
          type: array
          items:
            $ref: '#/components/schemas/GeoJsonGeometry'
Generation Details
Steps to reproduce

This test (if placed into PythonExperimentalClientTest) will recreate the bug. Note that in my testing environment, I added the GeoJson spec (above) to the prior yaml.

    @Test(description = "tests RecursiveToExample")
    public void testRecursiveToExample() throws IOException {
        final OpenAPI openAPI = TestUtils.parseFlattenSpec("src/test/resources/3_0/issue_8052_recursive_model.yaml");
        final PythonExperimentalClientCodegen codegen = new PythonExperimentalClientCodegen();
        codegen.setOpenAPI(openAPI);

        final Operation operation = openAPI.getPaths().get("/geojson").getPost();
        Schema schema = ModelUtils.getSchemaFromRequestBody(operation.getRequestBody());
        String exampleValue = codegen.toExampleValue(schema, null);

        // you never get here

    }
Related issues/PRs

#8052

Suggest a fix

I would be happy to attempt to fix it, but I could use a little guidance from @spacether. It looks like the new generator is attempting to detect cycles, and it's unclear what about the full GeoJson specification is causing the issue. Hopefully the provided yaml and test case will shed some light on this.

@fbl100 fbl100 changed the title [BUG] Description [BUG] python-experimental stackOverflow when using self-referencing data structures like GeoJson Jul 29, 2022
@spacether
Copy link
Contributor

Do you have your intelij set up so you can debug the generator? What is the stack trace? Want to sync up this week?

@fbl100
Copy link
Contributor Author

fbl100 commented Jul 31, 2022 via email

@fbl100
Copy link
Contributor Author

fbl100 commented Jul 31, 2022

This is the output from the test case I posted. I'm on commit 79c5091

java.lang.StackOverflowError
	at java.base/java.util.ArrayList.hashCode(ArrayList.java:582)
	at java.base/java.util.Collections$UnmodifiableList.hashCode(Collections.java:1319)
	at java.base/java.util.Arrays.hashCode(Arrays.java:4498)
	at java.base/java.util.Objects.hash(Objects.java:133)
	at org.openapitools.codegen.DefaultCodegen$SanitizeNameOptions.hashCode(DefaultCodegen.java:7450)
	at java.base/java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
	at com.github.benmanes.caffeine.cache.BoundedLocalCache.computeIfAbsent(BoundedLocalCache.java:2344)
	at com.github.benmanes.caffeine.cache.LocalCache.computeIfAbsent(LocalCache.java:108)
	at com.github.benmanes.caffeine.cache.LocalManualCache.get(LocalManualCache.java:62)
	at org.openapitools.codegen.DefaultCodegen.sanitizeName(DefaultCodegen.java:5938)
	at org.openapitools.codegen.DefaultCodegen.sanitizeName(DefaultCodegen.java:5907)
	at org.openapitools.codegen.DefaultCodegen.sanitizeName(DefaultCodegen.java:5886)
	at org.openapitools.codegen.languages.AbstractPythonCodegen.toVarName(AbstractPythonCodegen.java:187)
	at org.openapitools.codegen.DefaultCodegen.createDiscriminator(DefaultCodegen.java:3313)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1594)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1582)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1764)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.exampleForObjectModel(PythonExperimentalClientCodegen.java:1881)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1641)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1582)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1764)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.exampleForObjectModel(PythonExperimentalClientCodegen.java:1881)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1641)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1582)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1764)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.exampleForObjectModel(PythonExperimentalClientCodegen.java:1881)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1641)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1582)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.toExampleValueRecursive(PythonExperimentalClientCodegen.java:1764)
	at org.openapitools.codegen.languages.PythonExperimentalClientCodegen.exampleForObjectModel(PythonExperimentalClientCodegen.java:1881)

@spacether
Copy link
Contributor

spacether commented Jul 31, 2022

So it is infinitely looping in the Java layer when trying to generate an example value. My time zone is PT here and I can be reached on Slack here https://join.slack.com/t/openapi-generator/shared_invite/zt-1dluqpbf5-9DbM3xGiGjPH0hwuQvGKZg as Justin Black

@fbl100
Copy link
Contributor Author

fbl100 commented Jul 31, 2022 via email

@spacether
Copy link
Contributor

Related PR: #13109

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants