cue icon indicating copy to clipboard operation
cue copied to clipboard

OpenAPI missing default case when default is variable and defined using `or`

Open rycee opened this issue 4 years ago • 3 comments

What version of CUE are you using (cue version)?

$ cue version
cue version 0.4.0 linux/amd64

Does this issue reproduce with the latest release?

I believe so, 0.4.0 is listed as latest release.

What did you do?

I'm trying to use CUE as a generator of OpenAPI schemas. That is, given a description of a schema as a CUE object I use the "transform pattern" to lift it to the CUE type level. This works well in general but I've noticed some strange interaction between or and * (default value).

I've attempted to create a test that I would expect to have pass (note, I don't have testscript installed so this is handmade to the best of my ability):

exec cue def test.cue -e '{#Out: #Example}' -o openapi:-
cmp stdout stdout.golden

-- test.cue --
#Enum: {
	enum: [... string]
	default: or(enum)
}

#Lift: {
	input:  #Enum
	output: or(input.enum) | *input.default
}

#Example: (#Lift & {input: {enum: [ "a", "b"], default: "a"}}).output
-- stdout.golden --
{
    "openapi": "3.0.0",
    "info": {
        "title": "Generated by cue.",
        "version": "no version"
    },
    "paths": {},
    "components": {
        "schemas": {
            "Example": {
                "type": "string",
                "enum": [
                    "a",
                    "b"
                ],
                "default": "a"
            },
            "Out": {
                "$ref": "#/components/schemas/Example"
            }
        }
    }
}

What did you expect to see?

Given the test.cue file above I'd expect the provided output.

What did you see instead?

The output but missing the "default": "a" line.

Given the above test.cue file, I've found that the default field appears in the OpenAPI output when changing either

  • default: or(enum) to default: string OR
  • output: or(input.enum) | *input.default to output: or(input.enum) | *(input.default + "")

The second (more curious) alternative is my current work-around for this issue.

rycee avatar Aug 16 '21 10:08 rycee

@rycee thanks for the excellent repro!

Interesting. Confirmed with 0f53054d, giving the output:

> cmp stdout stdout.golden
[diff -stdout +stdout.golden]
 {
     "openapi": "3.0.0",
     "info": {
         "title": "Generated by cue.",
         "version": "no version"
     },
     "paths": {},
     "components": {
         "schemas": {
             "Example": {
                 "type": "string",
                 "enum": [
                     "a",
                     "b"
-                ]
+                ],
+                "default": "a"
             },
             "Out": {
                 "$ref": "#/components/schemas/Example"
             }
         }
     }
 }

FAIL: /tmp/testscript035794467/repro.txt/script.txt:2: stdout and stdout.golden differ

myitcv avatar Aug 16 '21 11:08 myitcv

FTR: a reduced reproducer:

#Example: "a" | "b" | *(or(["a", "b"]) & "a")

This seems to be a disjunction bug in the evaluator, similar to the other bugs marked as related to disjunction.

mpvl avatar Nov 23 '21 15:11 mpvl

This reproduces it in an evaluator test: "a" | "b" | *(("a" | "b") & "a"). The issue is that default marking is not properly propagated.

mpvl avatar Nov 23 '21 15:11 mpvl