Skip to content

Commit

Permalink
tests for models for C-libcurl generator (OpenAPITools#5699)
Browse files Browse the repository at this point in the history
* First try to generate unit tests for the models of the C-libcurl client. Models into models are not supported yet.

* Added unit tests for the modules of the C-libcurl client to the git repository.

* Support for objects having other objects as properties, for the C-libcurl client generator

* Proper formatting of generated code
  • Loading branch information
michelealbano authored and michaelpro1 committed May 7, 2020
1 parent dc54dfc commit 6a7fe88
Show file tree
Hide file tree
Showing 15 changed files with 580 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public CLibcurlClientCodegen() {
embeddedTemplateDir = templateDir = "C-libcurl";

// TODO add auto-generated test files
//modelTestTemplateFiles.put("model_test.mustache", ".c");
modelTestTemplateFiles.put("model_test.mustache", ".c");
//apiTestTemplateFiles.put("api_test.mustache", ".c");

// default HIDE_GENERATION_TIMESTAMP to true
Expand Down Expand Up @@ -321,6 +321,104 @@ public String toDefaultValue(Schema p) {
return null;
}

@Override
public String toExampleValue(Schema schema) {
String example = super.toExampleValue(schema);

if (ModelUtils.isNullType(schema) && null != example) {
// The 'null' type is allowed in OAS 3.1 and above. It is not supported by OAS 3.0.x,
// though this tooling supports it.
return "NULL";
}
// correct "'"s into "'"s after toString()
if (ModelUtils.isStringSchema(schema) && schema.getDefault() != null) {
example = (String) schema.getDefault();
}
if (StringUtils.isNotBlank(example) && !"null".equals(example)) {
if (ModelUtils.isStringSchema(schema)) {
example = "\"" + example + "\"";
}
return example;
}

if (schema.getEnum() != null && !schema.getEnum().isEmpty()) {
// Enum case:
example = schema.getEnum().get(0).toString();
/* if (ModelUtils.isStringSchema(schema)) {
example = "'" + escapeText(example) + "'";
}*/
if (null == example)
LOGGER.warn("Empty enum. Cannot built an example!");

return example;
} else if (null != schema.get$ref()) {
// $ref case:
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
String ref = ModelUtils.getSimpleRef(schema.get$ref());
if (allDefinitions != null) {
Schema refSchema = allDefinitions.get(ref);
if (null == refSchema) {
return "None";
} else {
String refTitle = refSchema.getTitle();
if (StringUtils.isBlank(refTitle) || "null".equals(refTitle)) {
refSchema.setTitle(ref);
}
return toExampleValue(refSchema);
}
} else {
LOGGER.warn("allDefinitions not defined in toExampleValue!\n");
}
}
if (ModelUtils.isDateSchema(schema)) {
example = "\"2013-10-20\"";
return example;
} else if (ModelUtils.isDateTimeSchema(schema)) {
example = "\"2013-10-20T19:20:30+01:00\"";
return example;
} else if (ModelUtils.isBinarySchema(schema)) {
example = "bytes(b'blah')";
return example;
} else if (ModelUtils.isByteArraySchema(schema)) {
example = "YQ==";
} else if (ModelUtils.isStringSchema(schema)) {
// a BigDecimal:
if ("Number".equalsIgnoreCase(schema.getFormat())) {return "1";}
if (StringUtils.isNotBlank(schema.getPattern())) return "'a'"; // I cheat here, since it would be too complicated to generate a string from a regexp
int len = 0;
if (null != schema.getMinLength()) len = schema.getMinLength().intValue();
if (len < 1) len = 1;
example = "";
for (int i=0;i<len;i++) example += i;
} else if (ModelUtils.isIntegerSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "56";
} else if (ModelUtils.isNumberSchema(schema)) {
if (schema.getMinimum() != null)
example = schema.getMinimum().toString();
else
example = "1.337";
} else if (ModelUtils.isBooleanSchema(schema)) {
example = "1";
} else if (ModelUtils.isArraySchema(schema)) {
example = "list_create()";
} else if (ModelUtils.isMapSchema(schema)) {
example = "list_create()";
} else if (ModelUtils.isObjectSchema(schema)) {
return null; // models are managed at moustache level
} else {
LOGGER.warn("Type " + schema.getType() + " not handled properly in toExampleValue");
}

if (ModelUtils.isStringSchema(schema)) {
example = "\"" + escapeText(example) + "\"";
}

return example;
}

@Override
public String getSchemaType(Schema schema) {
String openAPIType = super.getSchemaType(schema);
Expand Down Expand Up @@ -431,7 +529,7 @@ public String toApiTestFilename(String name) {

@Override
public String toModelTestFilename(String name) {
return ("test_" + toModelFilename(name)).replaceAll("_", "-");
return ("test_" + toModelFilename(name));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct {{classname}}_t {{classname}}_t;

{{#imports}}
#include "{{{.}}}.h"
{{/imports}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,74 @@
{{#models}}
{{#model}}
#ifndef {{classFilename}}_TEST
#define {{classFilename}}_TEST

// the following is to include only the main from the first c file
#ifndef TEST_MAIN
#define TEST_MAIN
#define {{classFilename}}_MAIN
#endif // TEST_MAIN

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "cJSON.h"
{{#imports}}{{{import}}}
{{/imports}}
#include <stdbool.h>
#include "../external/cJSON.h"

#include "../model/{{classFilename}}.h"
{{classname}}_t* instantiate_{{classname}}(int include_optional);

{{#vars}}{{#isModel}}{{#isEnum}}
// it is enum. Work in Progress
{{/isEnum}}{{^isEnum}}#include "test_{{{dataType}}}.c"
{{/isEnum}}{{/isModel}}{{/vars}}

{{classname}}_t* instantiate_{{classname}}(int include_optional) {
{{classname}}_t* {{classname}} = NULL;
if (include_optional) {
{{classname}} = {{classname}}_create(
{{#vars}} {{#isEnum}}{{^isContainer}}{{#example}}{{projectName}}_{{classVarName}}_{{enumName}}_{{{.}}}{{/example}}{{/isContainer}}{{#isContainer}}{{#example}}{{{.}}}{{/example}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{#example}}{{{.}}}{{/example}}{{/isEnum}}{{^example}}{{#isModel}}{{#isEnum}}// enum {{datatypeWithEnum}}_e Work in Progress
{{/isEnum}}{{^isEnum}} // false, not to have infinite recursion
instantiate_{{{dataType}}}(0){{/isEnum}}{{/isModel}}{{^isModel}}0{{/isModel}}{{/example}}{{#hasMore}},{{/hasMore}}
{{/vars}}
);
} else {
{{classname}} = {{classname}}_create(
{{#vars}} {{#isEnum}}{{^isContainer}}{{#example}}{{projectName}}_{{classVarName}}_{{enumName}}_{{{.}}}{{/example}}{{/isContainer}}{{#isContainer}}{{#example}}{{{.}}}{{/example}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{#example}}{{{.}}}{{/example}}{{/isEnum}}{{^example}}{{#isModel}}{{#isEnum}}// enum {{datatypeWithEnum}}_e Work in Progress
{{/isEnum}}{{^isEnum}}NULL{{/isEnum}}{{/isModel}}{{^isModel}}0{{/isModel}}{{/example}}{{#hasMore}},{{/hasMore}}
{{/vars}}
);
}

return {{classname}};
}


#ifdef {{classFilename}}_MAIN

void test_{{classname}}(int include_optional) {
{{classname}}_t* {{classname}}_1 = instantiate_{{classname}}(include_optional);

cJSON* json{{classname}}_1 = {{classname}}_convertToJSON({{classname}}_1);
printf("{{classname}} :\n%s\n", cJSON_Print(json{{classname}}_1));
{{classname}}_t* {{classname}}_2 = {{classname}}_parseFromJSON(json{{classname}}_1);
cJSON* json{{classname}}_2 = {{classname}}_convertToJSON({{classname}}_2);
printf("repeating {{classname}}:\n%s\n", cJSON_Print(json{{classname}}_2));
}

int main() {
printf("Hello world \n");
{{#models}}
{{#model}}
test_{{classname}}(1);
test_{{classname}}(0);
{{/model}}
{{/models}}

printf("Hello world \n");
return 0;
}

#endif // {{classFilename}}_MAIN
#endif // {{classFilename}}_TEST
{{/model}}
{{/models}}
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/api_response.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct api_response_t api_response_t;




typedef struct api_response_t {
Expand Down
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/category.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct category_t category_t;




typedef struct category_t {
Expand Down
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/order.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct order_t order_t;


// Enum STATUS for order

typedef enum { openapi_petstore_order_STATUS_NULL = 0, openapi_petstore_order_STATUS_placed, openapi_petstore_order_STATUS_approved, openapi_petstore_order_STATUS_delivered } openapi_petstore_order_STATUS_e;
Expand Down
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/pet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "../external/cJSON.h"
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct pet_t pet_t;

#include "category.h"
#include "tag.h"

Expand Down
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/tag.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct tag_t tag_t;




typedef struct tag_t {
Expand Down
3 changes: 3 additions & 0 deletions samples/client/petstore/c/model/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
#include "../include/list.h"
#include "../include/keyValuePair.h"

typedef struct user_t user_t;




typedef struct user_t {
Expand Down
62 changes: 62 additions & 0 deletions samples/client/petstore/c/unit-test/test_api_response.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#ifndef api_response_TEST
#define api_response_TEST

// the following is to include only the main from the first c file
#ifndef TEST_MAIN
#define TEST_MAIN
#define api_response_MAIN
#endif // TEST_MAIN

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include "../external/cJSON.h"

#include "../model/api_response.h"
api_response_t* instantiate_api_response(int include_optional);



api_response_t* instantiate_api_response(int include_optional) {
api_response_t* api_response = NULL;
if (include_optional) {
api_response = api_response_create(
56,
"0",
"0"
);
} else {
api_response = api_response_create(
56,
"0",
"0"
);
}

return api_response;
}


#ifdef api_response_MAIN

void test_api_response(int include_optional) {
api_response_t* api_response_1 = instantiate_api_response(include_optional);

cJSON* jsonapi_response_1 = api_response_convertToJSON(api_response_1);
printf("api_response :\n%s\n", cJSON_Print(jsonapi_response_1));
api_response_t* api_response_2 = api_response_parseFromJSON(jsonapi_response_1);
cJSON* jsonapi_response_2 = api_response_convertToJSON(api_response_2);
printf("repeating api_response:\n%s\n", cJSON_Print(jsonapi_response_2));
}

int main() {
test_api_response(1);
test_api_response(0);

printf("Hello world \n");
return 0;
}

#endif // api_response_MAIN
#endif // api_response_TEST
60 changes: 60 additions & 0 deletions samples/client/petstore/c/unit-test/test_category.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef category_TEST
#define category_TEST

// the following is to include only the main from the first c file
#ifndef TEST_MAIN
#define TEST_MAIN
#define category_MAIN
#endif // TEST_MAIN

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include "../external/cJSON.h"

#include "../model/category.h"
category_t* instantiate_category(int include_optional);



category_t* instantiate_category(int include_optional) {
category_t* category = NULL;
if (include_optional) {
category = category_create(
56,
"0"
);
} else {
category = category_create(
56,
"0"
);
}

return category;
}


#ifdef category_MAIN

void test_category(int include_optional) {
category_t* category_1 = instantiate_category(include_optional);

cJSON* jsoncategory_1 = category_convertToJSON(category_1);
printf("category :\n%s\n", cJSON_Print(jsoncategory_1));
category_t* category_2 = category_parseFromJSON(jsoncategory_1);
cJSON* jsoncategory_2 = category_convertToJSON(category_2);
printf("repeating category:\n%s\n", cJSON_Print(jsoncategory_2));
}

int main() {
test_category(1);
test_category(0);

printf("Hello world \n");
return 0;
}

#endif // category_MAIN
#endif // category_TEST
Loading

0 comments on commit 6a7fe88

Please sign in to comment.