diff --git a/.github/workflows/runtime-go-testing.yml b/.github/workflows/runtime-go-testing.yml new file mode 100644 index 0000000000..b1ac3df3e6 --- /dev/null +++ b/.github/workflows/runtime-go-testing.yml @@ -0,0 +1,32 @@ +name: Runtime Testing Go Models +on: + push: + pull_request: + types: [opened, reopened, synchronize, ready_for_review] + paths: + - 'src/generators/go/**' + - 'test/runtime/runtime-go/**' + - test/runtime/**go** + +jobs: + test: + name: Runtime testing Go Models + if: "github.event.pull_request.draft == false &&!((github.actor == 'asyncapi-bot' && startsWith(github.event.pull_request.title, 'ci: update global workflows')) || (github.actor == 'asyncapi-bot' && startsWith(github.event.pull_request.title, 'chore(release):')) || (github.actor == 'allcontributors' && startsWith(github.event.pull_request.title, 'docs: add')))" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 14 + - name: Build Library + run: npm install && npm run build:prod + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: 1.20 + -name: Generate Go Models + run: npm run generate:runtime:go + -name: Run runtime Tests + run: npm run test:runtime:go \ No newline at end of file diff --git a/package.json b/package.json index b76b431b97..6e1e6671a1 100644 --- a/package.json +++ b/package.json @@ -100,6 +100,8 @@ "test:blackbox:java": "cross-env CI=true jest ./test/blackbox/blackbox-java.spec.ts", "test:runtime:java": "cross-env CI=true jest ./test/runtime/runtime-java.spec.ts", "generate:runtime:java": "cross-env CI=true ts-node ./test/runtime/runtime-java.ts", + "test:runtime:go": "cross-env CI=true jest ./test/runtime/runtime-go.spec.ts", + "generate:runtime:go": "cross-env CI=true ts-node ./test/runtime/runtime-go.ts", "test:runtime:cplusplus": "cross-env CI=true jest ./test/runtime/runtime-cplusplus.spec.ts", "generate:runtime:cplusplus": "cross-env CI=true ts-node ./test/runtime/runtime-cplusplus.ts", "test:runtime:kotlin": "cross-env CI=true jest ./test/runtime/runtime-kotlin.spec.ts", diff --git a/test/runtime/runtime-go.spec.ts b/test/runtime/runtime-go.spec.ts new file mode 100644 index 0000000000..1110d0be1f --- /dev/null +++ b/test/runtime/runtime-go.spec.ts @@ -0,0 +1,13 @@ +import { execCommand } from "../blackbox/utils/Utils"; +import path from 'path'; + +jest.setTimeout(50000); + +test('Go runtime testing', async () => { + const compileCommand = `cd ${path.resolve( + __dirname, + './runtime-go' + )} && go test`; + await execCommand(compileCommand); +}) + diff --git a/test/runtime/runtime-go.ts b/test/runtime/runtime-go.ts new file mode 100644 index 0000000000..4416138de5 --- /dev/null +++ b/test/runtime/runtime-go.ts @@ -0,0 +1,15 @@ +import {GoFileGenerator, GO_DEFAULT_PRESET} from "../../src"; +import path from "path"; +import input from "./generic-input.json"; + + +const generator = new GoFileGenerator({ + presets : [GO_DEFAULT_PRESET], + +}) + +generator.generateToFiles( + input, + path.resolve(__dirname,'./runtime-go'), + {packageName : "runtimego"} +) \ No newline at end of file diff --git a/test/runtime/runtime-go/.gitignore b/test/runtime/runtime-go/.gitignore new file mode 100644 index 0000000000..c41cc9e35e --- /dev/null +++ b/test/runtime/runtime-go/.gitignore @@ -0,0 +1 @@ +/target \ No newline at end of file diff --git a/test/runtime/runtime-go/README.md b/test/runtime/runtime-go/README.md new file mode 100644 index 0000000000..9d0e447b7c --- /dev/null +++ b/test/runtime/runtime-go/README.md @@ -0,0 +1,10 @@ +# Modelina Go Runtime Project + +This is the Modelina Go runtime project that is used to test the Go-generated code from Modelina at +runtime to ensure that everything works as expected. + +Here is how it works: +- The models are first generated during the build phase of the project, by running the root npm script +`npm run generate:runtime:go`. These models are pre-defined with the [generic input](../generic-input.json) +- The tests are manually added and changed +- When the project is tested, it tests the generated models at runtime for semantic errors. \ No newline at end of file diff --git a/test/runtime/runtime-go/Test_Go/Test_Address.go b/test/runtime/runtime-go/Test_Go/Test_Address.go new file mode 100644 index 0000000000..58a16751f3 --- /dev/null +++ b/test/runtime/runtime-go/Test_Go/Test_Address.go @@ -0,0 +1,64 @@ +package Test_Go + +import ( + "encoding/json" + runtimego "runtimego/target" + "testing" +) + +func TestShouldbeAbleToSerializeModel(t *testing.T) { + nestedobj := runtimego.NestedObject{ + Test: "test", + } + address := runtimego.Address{ + StreetName: "Test Address 2", + HouseNumber: 2, + Marriage: true, + Members: 2, + ArrayType: []interface{}{2, "test"}, + NestedObject: &nestedobj, + AdditionalProperties: nil, + } + + jsonBytes, err := json.Marshal(address) + + if err != nil { + t.Fatalf("Failed to serialize Address to JSON: %v", err) + } + jsonStr := string(jsonBytes) + + if jsonStr == "" { + t.Errorf("Serialize JSON is empty") + } +} + +func TestShouldNotContainAdditionalPropertiesWhenSerialized(t *testing.T) { + nestedobj := runtimego.NestedObject{ + Test: "test", + } + address := runtimego.Address{ + StreetName: "Test Address 2", + HouseNumber: 2.0, + Marriage: true, + Members: 2, + ArrayType: []interface{}{2, "test"}, + NestedObject: &nestedobj, + AdditionalProperties: nil, + } + + jsonBytes, err := json.Marshal(address) + + if err != nil { + t.Fatalf("Failed to serialize Address to JSON: %v", err) + } + + var JsonObject map[string]interface{} + + if err := json.Unmarshal(jsonBytes, &JsonObject); err != nil { + t.Fatalf("Failed to deserialize JSON: %v", err) + } + + if _, found := JsonObject["AdditionalProperties"]; found { + t.Errorf("Serialize JSON contains 'Additional Properties' key") + } +} diff --git a/test/runtime/runtime-go/Test_Go/Test_Marshall_Address.go b/test/runtime/runtime-go/Test_Go/Test_Marshall_Address.go new file mode 100644 index 0000000000..f255280108 --- /dev/null +++ b/test/runtime/runtime-go/Test_Go/Test_Marshall_Address.go @@ -0,0 +1,117 @@ +package Test_Go + +import ( + "encoding/json" + runtimego "runtimego/target" + "testing" +) + +func Test(expected string, address runtimego.Address, t *testing.T) { + // Marshalling Test + serialized, err := json.Marshal(address) + if err != nil { + t.Errorf("Failed to serialize Address to JSON: %v", err) + } + + serializedStr := string(serialized) + if serializedStr != expected { + t.Errorf("Expected marshalled JSON: %s, but got: %s", expected, serialized) + } + + // Unmarshalling Test + var newAddress runtimego.Address + if err := json.Unmarshal([]byte(expected), &newAddress); err != nil { + t.Fatalf("Failed to unmarshal JSON: %v", err) + } + reSerialized, err := json.Marshal(newAddress) + if err != nil { + t.Fatalf("Failed to marshal Address: %v", err) + } + reSerializedStr := string(reSerialized) + + if serializedStr != reSerializedStr { + t.Errorf("Serialized JSON after unmarshalling does not match: %s", reSerializedStr) + } +} + +func TestAddressMarshalling(t *testing.T) { + + // Testing Address with Required Properties + + t.Run("required properties", func(t *testing.T) { + address := runtimego.Address{ + StreetName: "test", + HouseNumber: 1, + ArrayType: []interface{}{1, "test"}, + } + expected := "{\"street_name\": \"test\",\"house_number\": 1,\"array_type\": [1,\"test\"]}" + + Test(expected, address, t) + }) + + // Testing Address with Marriage + + t.Run("marriage", func(t *testing.T) { + address := runtimego.Address{ + StreetName: "test", + HouseNumber: 1, + Marriage: true, + ArrayType: []interface{}{1, "test"}, + } + expected := "{\"street_name\": \"test\",\"house_number\": 1,\"marriage\": true,\"array_type\": [1,\"test\"]}" + + Test(expected, address, t) + + }) + + // Testing Address with Members + + t.Run("members", func(t *testing.T) { + address := runtimego.Address{ + StreetName: "test", + HouseNumber: 1, + ArrayType: []interface{}{1, "test"}, + Members: 2, + } + expected := "{\"street_name\": \"test\",\"house_number\": 1,\"members\": 2,\"array_type\": [1,\"test\"]}" + + Test(expected, address, t) + }) + + // Testing Address with Nested Object + + t.Run("nestedObject", func(t *testing.T) { + nestedObj := runtimego.NestedObject{ + Test: "test", + } + address := runtimego.Address{ + StreetName: "test", + HouseNumber: 1, + ArrayType: []interface{}{1, "test"}, + NestedObject: &nestedObj, + } + expected := "{\"street_name\": \"test\",\"house_number\": 1,\"array_type\": [1,\"test\"],\"nestedObject\": {\"test\": \"test\"}}" + + Test(expected, address, t) + }) + + // Testing Address Full Model + + t.Run("full model", func(t *testing.T) { + nestedObj := runtimego.NestedObject{ + Test: "test", + } + address := runtimego.Address{ + StreetName: "test", + HouseNumber: 1, + Marriage: true, + Members: 2, + ArrayType: []interface{}{1, "test"}, + NestedObject: &nestedObj, + AdditionalProperties: nil, + } + expected := "{\"street_name\": \"test\",\"house_number\": 1,\"marriage\": true,\"members\": 2,\"array_type\": [1,\"test\"],\"nestedObject\": {\"test\": \"test\"}}" + + Test(expected, address, t) + }) +} diff --git a/test/runtime/runtime-go/go.mod b/test/runtime/runtime-go/go.mod new file mode 100644 index 0000000000..f03497dded --- /dev/null +++ b/test/runtime/runtime-go/go.mod @@ -0,0 +1,3 @@ +module runtimego + +go 1.20