| package main |
| |
| import ( |
| "io/ioutil" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "strings" |
| "testing" |
| ) |
| |
| func testCompiler(t *testing.T, inputFile string, referenceFile string, expectErrors bool) { |
| textFile := strings.Replace(filepath.Base(inputFile), filepath.Ext(inputFile), ".text", 1) |
| errorsFile := strings.Replace(filepath.Base(inputFile), filepath.Ext(inputFile), ".errors", 1) |
| // remove any preexisting output files |
| os.Remove(textFile) |
| os.Remove(errorsFile) |
| // run the compiler |
| var err error |
| var cmd = exec.Command( |
| "gnostic", |
| inputFile, |
| "--text-out=.", |
| "--errors-out=.", |
| "--resolve-refs") |
| //t.Log(cmd.Args) |
| err = cmd.Run() |
| if err != nil && !expectErrors { |
| t.Logf("Compile failed: %+v", err) |
| t.FailNow() |
| } |
| // verify the output against a reference |
| var outputFile string |
| if expectErrors { |
| outputFile = errorsFile |
| } else { |
| outputFile = textFile |
| } |
| err = exec.Command("diff", outputFile, referenceFile).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(textFile) |
| os.Remove(errorsFile) |
| } |
| } |
| |
| func testNormal(t *testing.T, inputFile string, referenceFile string) { |
| testCompiler(t, inputFile, referenceFile, false) |
| } |
| |
| func testErrors(t *testing.T, inputFile string, referenceFile string) { |
| testCompiler(t, inputFile, referenceFile, true) |
| } |
| |
| func TestPetstoreJSON(t *testing.T) { |
| testNormal(t, |
| "examples/v2.0/json/petstore.json", |
| "test/v2.0/petstore.text") |
| } |
| |
| func TestPetstoreYAML(t *testing.T) { |
| testNormal(t, |
| "examples/v2.0/yaml/petstore.yaml", |
| "test/v2.0/petstore.text") |
| } |
| |
| func TestSeparateYAML(t *testing.T) { |
| testNormal(t, |
| "examples/v2.0/yaml/petstore-separate/spec/swagger.yaml", |
| "test/v2.0/yaml/petstore-separate/spec/swagger.text") |
| } |
| |
| func TestSeparateJSON(t *testing.T) { |
| testNormal(t, |
| "examples/v2.0/json/petstore-separate/spec/swagger.json", |
| "test/v2.0/yaml/petstore-separate/spec/swagger.text") // yaml and json results should be identical |
| } |
| |
| func TestRemotePetstoreJSON(t *testing.T) { |
| testNormal(t, |
| "https://raw.githubusercontent.com/googleapis/openapi-compiler/master/examples/v2.0/json/petstore.json", |
| "test/v2.0/petstore.text") |
| } |
| |
| func TestRemotePetstoreYAML(t *testing.T) { |
| testNormal(t, |
| "https://raw.githubusercontent.com/googleapis/openapi-compiler/master/examples/v2.0/yaml/petstore.yaml", |
| "test/v2.0/petstore.text") |
| } |
| |
| func TestRemoteSeparateYAML(t *testing.T) { |
| testNormal(t, |
| "https://raw.githubusercontent.com/googleapis/openapi-compiler/master/examples/v2.0/yaml/petstore-separate/spec/swagger.yaml", |
| "test/v2.0/yaml/petstore-separate/spec/swagger.text") |
| } |
| |
| func TestRemoteSeparateJSON(t *testing.T) { |
| testNormal(t, |
| "https://raw.githubusercontent.com/googleapis/openapi-compiler/master/examples/v2.0/json/petstore-separate/spec/swagger.json", |
| "test/v2.0/yaml/petstore-separate/spec/swagger.text") |
| } |
| |
| func TestErrorBadProperties(t *testing.T) { |
| testErrors(t, |
| "examples/errors/petstore-badproperties.yaml", |
| "test/errors/petstore-badproperties.errors") |
| } |
| |
| func TestErrorUnresolvedRefs(t *testing.T) { |
| testErrors(t, |
| "examples/errors/petstore-unresolvedrefs.yaml", |
| "test/errors/petstore-unresolvedrefs.errors") |
| } |
| |
| func TestErrorMissingVersion(t *testing.T) { |
| testErrors(t, |
| "examples/errors/petstore-missingversion.yaml", |
| "test/errors/petstore-missingversion.errors") |
| } |
| |
| func testPlugin(t *testing.T, plugin string, inputFile string, outputFile string, referenceFile string) { |
| // remove any preexisting output files |
| os.Remove(outputFile) |
| // run the compiler |
| var err error |
| output, err := exec.Command( |
| "gnostic", |
| "--"+plugin+"-out=-", |
| inputFile).Output() |
| if err != nil { |
| t.Logf("Compile failed: %+v", err) |
| t.FailNow() |
| } |
| _ = ioutil.WriteFile(outputFile, output, 0644) |
| err = exec.Command("diff", outputFile, referenceFile).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(outputFile) |
| } |
| } |
| |
| func TestSamplePluginWithPetstore(t *testing.T) { |
| testPlugin(t, |
| "summary", |
| "examples/v2.0/yaml/petstore.yaml", |
| "sample-petstore.out", |
| "test/v2.0/yaml/sample-petstore.out") |
| } |
| |
| func TestErrorInvalidPluginInvocations(t *testing.T) { |
| var err error |
| output, err := exec.Command( |
| "gnostic", |
| "examples/v2.0/yaml/petstore.yaml", |
| "--errors-out=-", |
| "--plugin-out=foo=bar,:abc", |
| "--plugin-out=,foo=bar:abc", |
| "--plugin-out=foo=:abc", |
| "--plugin-out==bar:abc", |
| "--plugin-out=,,:abc", |
| "--plugin-out=foo=bar=baz:abc", |
| ).Output() |
| if err == nil { |
| t.Logf("Invalid invocations were accepted") |
| t.FailNow() |
| } |
| outputFile := "invalid-plugin-invocation.errors" |
| _ = ioutil.WriteFile(outputFile, output, 0644) |
| err = exec.Command("diff", outputFile, "test/errors/invalid-plugin-invocation.errors").Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(outputFile) |
| } |
| } |
| |
| func TestValidPluginInvocations(t *testing.T) { |
| var err error |
| output, err := exec.Command( |
| "gnostic", |
| "examples/v2.0/yaml/petstore.yaml", |
| "--errors-out=-", |
| // verify an invocation with no parameters |
| "--summary-out=!", // "!" indicates that no output should be generated |
| // verify single pair of parameters |
| "--summary-out=a=b:!", |
| // verify multiple parameters |
| "--summary-out=a=b,c=123,xyz=alphabetagammadelta:!", |
| // verify that special characters / . - _ can be included in parameter keys and values |
| "--summary-out=a/b/c=x/y/z:!", |
| "--summary-out=a.b.c=x.y.z:!", |
| "--summary-out=a-b-c=x-y-z:!", |
| "--summary-out=a_b_c=x_y_z:!", |
| ).Output() |
| if len(output) != 0 { |
| t.Logf("Valid invocations generated invalid errors\n%s", string(output)) |
| t.FailNow() |
| } |
| if err != nil { |
| t.Logf("Valid invocations were not accepted") |
| t.FailNow() |
| } |
| } |
| |
| func TestExtensionHandlerWithLibraryExample(t *testing.T) { |
| outputFile := "library-example-with-ext.text.out" |
| inputFile := "test/library-example-with-ext.json" |
| referenceFile := "test/library-example-with-ext.text.out" |
| |
| os.Remove(outputFile) |
| // run the compiler |
| var err error |
| |
| command := exec.Command( |
| "gnostic", |
| "--x-sampleone", |
| "--x-sampletwo", |
| "--text-out="+outputFile, |
| "--resolve-refs", |
| inputFile) |
| |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Compile failed for command %v: %+v", command, err) |
| t.FailNow() |
| } |
| //_ = ioutil.WriteFile(outputFile, output, 0644) |
| err = exec.Command("diff", outputFile, referenceFile).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(outputFile) |
| } |
| } |
| |
| func TestJSONOutput(t *testing.T) { |
| inputFile := "test/library-example-with-ext.json" |
| |
| textFile := "sample.text" |
| jsonFile := "sample.json" |
| textFile2 := "sample2.text" |
| jsonFile2 := "sample2.json" |
| |
| os.Remove(textFile) |
| os.Remove(jsonFile) |
| os.Remove(textFile2) |
| os.Remove(jsonFile2) |
| |
| var err error |
| |
| // Run the compiler once. |
| command := exec.Command( |
| "gnostic", |
| "--text-out="+textFile, |
| "--json-out="+jsonFile, |
| inputFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Compile failed for command %v: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Run the compiler again, this time on the generated output. |
| command = exec.Command( |
| "gnostic", |
| "--text-out="+textFile2, |
| "--json-out="+jsonFile2, |
| jsonFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Compile failed for command %v: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Verify that both models have the same internal representation. |
| err = exec.Command("diff", textFile, textFile2).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(textFile) |
| os.Remove(jsonFile) |
| os.Remove(textFile2) |
| os.Remove(jsonFile2) |
| } |
| } |
| |
| func TestYAMLOutput(t *testing.T) { |
| inputFile := "test/library-example-with-ext.json" |
| |
| textFile := "sample.text" |
| yamlFile := "sample.yaml" |
| textFile2 := "sample2.text" |
| yamlFile2 := "sample2.yaml" |
| |
| os.Remove(textFile) |
| os.Remove(yamlFile) |
| os.Remove(textFile2) |
| os.Remove(yamlFile2) |
| |
| var err error |
| |
| // Run the compiler once. |
| command := exec.Command( |
| "gnostic", |
| "--text-out="+textFile, |
| "--yaml-out="+yamlFile, |
| inputFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Compile failed for command %v: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Run the compiler again, this time on the generated output. |
| command = exec.Command( |
| "gnostic", |
| "--text-out="+textFile2, |
| "--yaml-out="+yamlFile2, |
| yamlFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Compile failed for command %v: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Verify that both models have the same internal representation. |
| err = exec.Command("diff", textFile, textFile2).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } else { |
| // if the test succeeded, clean up |
| os.Remove(textFile) |
| os.Remove(yamlFile) |
| os.Remove(textFile2) |
| os.Remove(yamlFile2) |
| } |
| } |
| |
| func testBuilder(version string, t *testing.T) { |
| var err error |
| |
| pbFile := "petstore-" + version + ".pb" |
| yamlFile := "petstore.yaml" |
| jsonFile := "petstore.json" |
| textFile := "petstore.text" |
| textReference := "test/" + version + ".0/petstore.text" |
| |
| os.Remove(pbFile) |
| os.Remove(textFile) |
| os.Remove(yamlFile) |
| os.Remove(jsonFile) |
| |
| // Generate petstore.pb. |
| command := exec.Command( |
| "petstore-builder", |
| "--"+version) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Command %v failed: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Convert petstore.pb to yaml and json. |
| command = exec.Command( |
| "gnostic", |
| pbFile, |
| "--json-out="+jsonFile, |
| "--yaml-out="+yamlFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Command %v failed: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Read petstore.yaml, resolve references, and export text. |
| command = exec.Command( |
| "gnostic", |
| yamlFile, |
| "--resolve-refs", |
| "--text-out="+textFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Command %v failed: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Verify that the generated text matches our reference. |
| err = exec.Command("diff", textFile, textReference).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } |
| |
| // Read petstore.json, resolve references, and export text. |
| command = exec.Command( |
| "gnostic", |
| jsonFile, |
| "--resolve-refs", |
| "--text-out="+textFile) |
| _, err = command.Output() |
| if err != nil { |
| t.Logf("Command %v failed: %+v", command, err) |
| t.FailNow() |
| } |
| |
| // Verify that the generated text matches our reference. |
| err = exec.Command("diff", textFile, textReference).Run() |
| if err != nil { |
| t.Logf("Diff failed: %+v", err) |
| t.FailNow() |
| } |
| |
| // if the test succeeded, clean up |
| os.Remove(pbFile) |
| os.Remove(textFile) |
| os.Remove(yamlFile) |
| os.Remove(jsonFile) |
| } |
| |
| func TestBuilderV2(t *testing.T) { |
| testBuilder("v2", t) |
| } |
| |
| func TestBuilderV3(t *testing.T) { |
| testBuilder("v3", t) |
| } |
| |
| // OpenAPI 3.0 tests |
| |
| func TestPetstoreYAML_30(t *testing.T) { |
| testNormal(t, |
| "examples/v3.0/yaml/petstore.yaml", |
| "test/v3.0/petstore.text") |
| } |
| |
| func TestPetstoreJSON_30(t *testing.T) { |
| testNormal(t, |
| "examples/v3.0/json/petstore.json", |
| "test/v3.0/petstore.text") |
| } |