Skip to content

Commit

Permalink
test: add runtime testing for Go models (#1484)
Browse files Browse the repository at this point in the history
* Added runtime testing for Go models

* Added Runtime Testing for Golang

---------

Co-authored-by: Devansh Bhatt <devanshbhatt@Devanshs-MacBook-Air.local>
Co-authored-by: Jonas Lagoni <jonas-lt@live.dk>
  • Loading branch information
3 people authored Aug 28, 2023
1 parent 387768e commit 3ebc6b2
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 0 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/runtime-go-testing.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 13 additions & 0 deletions test/runtime/runtime-go.spec.ts
Original file line number Diff line number Diff line change
@@ -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);
})

15 changes: 15 additions & 0 deletions test/runtime/runtime-go.ts
Original file line number Diff line number Diff line change
@@ -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"}
)
1 change: 1 addition & 0 deletions test/runtime/runtime-go/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
10 changes: 10 additions & 0 deletions test/runtime/runtime-go/README.md
Original file line number Diff line number Diff line change
@@ -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.
64 changes: 64 additions & 0 deletions test/runtime/runtime-go/Test_Go/Test_Address.go
Original file line number Diff line number Diff line change
@@ -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")
}
}
117 changes: 117 additions & 0 deletions test/runtime/runtime-go/Test_Go/Test_Marshall_Address.go
Original file line number Diff line number Diff line change
@@ -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)
})
}
3 changes: 3 additions & 0 deletions test/runtime/runtime-go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module runtimego

go 1.20

0 comments on commit 3ebc6b2

Please sign in to comment.