-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(cpp): add cpp filter for test value
- Loading branch information
1 parent
9091ce5
commit 2d5e723
Showing
5 changed files
with
315 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package filtercpp | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/apigear-io/cli/pkg/gen/filters/common" | ||
"github.com/apigear-io/cli/pkg/model" | ||
) | ||
|
||
// ToTestValueString returns the test value string for a given schema. | ||
// We intentionally ignore arrays in order to return the test value of the inner type. | ||
func ToTestValueString(prefix string, schema *model.Schema) (string, error) { | ||
if schema == nil { | ||
return "xxx", fmt.Errorf("cppTestValue schema is nil") | ||
} | ||
if schema.Module == nil { | ||
return "xxx", fmt.Errorf("cppTestValue schema module is nil") | ||
} | ||
var text string | ||
switch schema.KindType { | ||
case model.TypeString: | ||
text = "std::string(\"xyz\")" | ||
case model.TypeInt, model.TypeInt32: | ||
text = "1" | ||
case model.TypeInt64: | ||
text = "1LL" | ||
case model.TypeFloat, model.TypeFloat32: | ||
text = "1.1f" | ||
case model.TypeFloat64: | ||
text = "1.1" | ||
case model.TypeBool: | ||
text = "true" | ||
case model.TypeVoid: | ||
return ToDefaultString(prefix, schema) | ||
case model.TypeEnum: | ||
e_local := schema.LookupEnum("", schema.Type) | ||
e_imported := schema.LookupEnum(schema.Import, schema.Type) | ||
if e_local == nil && e_imported == nil { | ||
return "xxx", fmt.Errorf("cppTestValue enum not found: %s", schema.Dump()) | ||
} | ||
// if enum is local it is found both as e_local and e_imported | ||
name := e_imported.Name | ||
member := e_imported.Members[0].Name | ||
if len(e_imported.Members) > 1 { | ||
member = e_imported.Members[1].Name | ||
} | ||
if e_local == nil { | ||
moduleNamespace := common.CamelTitleCase(e_imported.Module.Name) | ||
prefix = fmt.Sprintf("%s::", moduleNamespace) | ||
} | ||
text = fmt.Sprintf("%s%sEnum::%s", prefix, name, member) | ||
// all types return deafualt value, but cannot be passed to deafult filter | ||
// due to variants with array. Here we want to return default element, not deafult empty array. | ||
case model.TypeStruct: | ||
s_local := schema.LookupStruct("", schema.Type) | ||
s_imported := schema.LookupStruct(schema.Import, schema.Type) | ||
if s_local == nil && s_imported == nil { | ||
return "xxx", fmt.Errorf("cppTestValue struct not found: %s", schema.Dump()) | ||
} | ||
// if struct is local it is found both as s_local and s_imported | ||
name := s_imported.Name | ||
if s_local == nil { | ||
moduleNamespace := common.CamelTitleCase(s_imported.Module.Name) | ||
prefix = fmt.Sprintf("%s::", moduleNamespace) | ||
} | ||
text = fmt.Sprintf("%s%s()", prefix, name) | ||
case model.TypeExtern: | ||
xe := parseCppExtern(schema) | ||
if xe.Default != "" { | ||
text = xe.Default | ||
} else { | ||
namespace_prefix := "" | ||
if xe.NameSpace != "" { | ||
namespace_prefix = fmt.Sprintf("%s::", xe.NameSpace) | ||
} | ||
text = fmt.Sprintf("%s%s()", namespace_prefix, xe.Name) | ||
} | ||
case model.TypeInterface: | ||
i_local := schema.LookupInterface("", schema.Type) | ||
i_imported := schema.LookupInterface(schema.Import, schema.Type) | ||
if i_local == nil && i_imported == nil { | ||
return "xxx", fmt.Errorf("cppTestValue interface not found: %s", schema.Dump()) | ||
} | ||
// if interface is local it is found both as s_local and s_imported | ||
name := i_imported.Name | ||
if i_local == nil { | ||
moduleNamespace := common.CamelTitleCase(i_imported.Module.Name) | ||
prefix = fmt.Sprintf("%s::", moduleNamespace) | ||
} | ||
text = fmt.Sprintf("%s%s()", prefix, name) | ||
default: | ||
return "xxx", fmt.Errorf("pyTestValue unknown schema %s", schema.Dump()) | ||
} | ||
return text, nil | ||
} | ||
|
||
func cppTestValue(prefix string, node *model.TypedNode) (string, error) { | ||
if node == nil { | ||
return "xxx", fmt.Errorf("cppTestValue node is nil") | ||
} | ||
return ToTestValueString(prefix, &node.Schema) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
package filtercpp | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
// test with all the types | ||
// properties, operation params, operation return, signal params, struct fields | ||
func TestTestValueFromIdl(t *testing.T) { | ||
t.Parallel() | ||
syss := loadTestSystems(t) | ||
var propTests = []struct { | ||
mn string | ||
in string | ||
pn string | ||
rt string | ||
}{ | ||
{"test", "Test1", "propVoid", "void"}, | ||
{"test", "Test1", "propBool", "true"}, | ||
{"test", "Test1", "propInt", "1"}, | ||
{"test", "Test1", "propInt32", "1"}, | ||
{"test", "Test1", "propInt64", "1LL"}, | ||
{"test", "Test1", "propFloat", "1.1f"}, | ||
{"test", "Test1", "propFloat32", "1.1f"}, | ||
{"test", "Test1", "propFloat64", "1.1"}, | ||
{"test", "Test1", "propString", "std::string(\"xyz\")"}, | ||
{"test", "Test1", "propBoolArray", "true"}, // all the array types return value intentionally, it may be put into empty array | ||
{"test", "Test1", "propIntArray", "1"}, | ||
{"test", "Test1", "propInt32Array", "1"}, | ||
{"test", "Test1", "propInt64Array", "1LL"}, | ||
{"test", "Test1", "propFloatArray", "1.1f"}, | ||
{"test", "Test1", "propFloat32Array", "1.1f"}, | ||
{"test", "Test1", "propFloat64Array", "1.1"}, | ||
{"test", "Test1", "propStringArray", "std::string(\"xyz\")"}, | ||
} | ||
for _, sys := range syss { | ||
for _, tt := range propTests { | ||
t.Run(tt.pn, func(t *testing.T) { | ||
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn) | ||
assert.NotNil(t, prop) | ||
r, err := cppTestValue("", prop) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.rt, r) | ||
}) | ||
} | ||
} | ||
} | ||
|
||
func TestTestValueSymbolsFromIdl(t *testing.T) { | ||
t.Parallel() | ||
syss := loadTestSystems(t) | ||
var propTests = []struct { | ||
mn string | ||
in string | ||
pn string | ||
rt string | ||
}{ | ||
{"test", "Test2", "propEnum", "Enum1::NotDefault"}, | ||
{"test", "InterfaceNamesCheck", "lowerEnumProp", "EnumLowerNames::secondValue"}, | ||
{"test", "Test2", "propStruct", "Struct1()"}, | ||
{"test", "Test2", "propInterface", "Interface1()"}, | ||
{"test", "Test2", "propEnumArray", "Enum1::NotDefault"}, | ||
{"test", "Test2", "propStructArray", "Struct1()"}, | ||
{"test", "Test2", "propInterfaceArray", "Interface1()"}, | ||
} | ||
for _, sys := range syss { | ||
for _, tt := range propTests { | ||
t.Run(tt.pn, func(t *testing.T) { | ||
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn) | ||
assert.NotNil(t, prop) | ||
r, err := cppTestValue("", prop) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.rt, r) | ||
}) | ||
} | ||
} | ||
} | ||
|
||
func TestTestValueWithErrors(t *testing.T) { | ||
t.Parallel() | ||
s, err := cppTestValue("", nil) | ||
assert.Error(t, err) | ||
assert.Equal(t, "xxx", s) | ||
} | ||
|
||
func TestTestValueFromIdlWithPrefix_makesNoDifference(t *testing.T) { | ||
t.Parallel() | ||
syss := loadTestSystems(t) | ||
var propTests = []struct { | ||
mn string | ||
in string | ||
pn string | ||
rt string | ||
}{ | ||
{"test", "Test1", "propVoid", "void"}, | ||
{"test", "Test1", "propBool", "true"}, | ||
{"test", "Test1", "propInt", "1"}, | ||
{"test", "Test1", "propInt32", "1"}, | ||
{"test", "Test1", "propInt64", "1LL"}, | ||
{"test", "Test1", "propFloat", "1.1f"}, | ||
{"test", "Test1", "propFloat32", "1.1f"}, | ||
{"test", "Test1", "propFloat64", "1.1"}, | ||
{"test", "Test1", "propString", "std::string(\"xyz\")"}, | ||
{"test", "Test1", "propBoolArray", "true"}, // all the array types return value intentionally, it may be put into empty array | ||
{"test", "Test1", "propIntArray", "1"}, | ||
{"test", "Test1", "propInt32Array", "1"}, | ||
{"test", "Test1", "propInt64Array", "1LL"}, | ||
{"test", "Test1", "propFloatArray", "1.1f"}, | ||
{"test", "Test1", "propFloat32Array", "1.1f"}, | ||
{"test", "Test1", "propFloat64Array", "1.1"}, | ||
{"test", "Test1", "propStringArray", "std::string(\"xyz\")"}, | ||
} | ||
prefix := "my_prefix::" | ||
for _, sys := range syss { | ||
for _, tt := range propTests { | ||
t.Run(tt.pn, func(t *testing.T) { | ||
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn) | ||
assert.NotNil(t, prop) | ||
r, err := cppTestValue(prefix, prop) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.rt, r) | ||
}) | ||
} | ||
} | ||
} | ||
|
||
func TestTestValueSymbolsFromIdlWithPrefix(t *testing.T) { | ||
t.Parallel() | ||
syss := loadTestSystems(t) | ||
var propTests = []struct { | ||
mn string | ||
in string | ||
pn string | ||
rt string | ||
}{ | ||
{"test", "Test2", "propEnum", "my_prefix::Enum1Enum::NotDefault"}, | ||
{"test", "Test2", "propStruct", "my_prefix::Struct1()"}, | ||
{"test", "Test2", "propInterface", "my_prefix::Interface1()"}, | ||
{"test", "Test2", "propEnumArray", "my_prefix::Enum1Enum::NotDefault"}, | ||
{"test", "Test2", "propStructArray", "my_prefix::Struct1()"}, | ||
{"test", "Test2", "propInterfaceArray", "my_prefix::Interface1()"}, | ||
} | ||
prefix := "my_prefix::" | ||
for _, sys := range syss { | ||
for _, tt := range propTests { | ||
t.Run(tt.pn, func(t *testing.T) { | ||
prop := sys.LookupProperty(tt.mn, tt.in, tt.pn) | ||
assert.NotNil(t, prop) | ||
r, err := cppTestValue(prefix, prop) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.rt, r) | ||
}) | ||
} | ||
} | ||
} | ||
|
||
func TestTestValueExterns(t *testing.T) { | ||
t.Parallel() | ||
table := []struct { | ||
module_name string | ||
interface_name string | ||
operation_name string | ||
result string | ||
}{ | ||
{"test_apigear_next", "Iface1", "prop1", "XType1()"}, | ||
{"test_apigear_next", "Iface1", "prop2", "demo::x::XType2()"}, | ||
{"test_apigear_next", "Iface1", "prop3", "demo::x::XtypeFactory::create()"}, | ||
{"test_apigear_next", "Iface1", "propList", "demo::x::XtypeFactory::create()"}, | ||
{"test_apigear_next", "Iface1", "propImportedEnum", "Test::Enum1Enum::NotDefault"}, | ||
{"test_apigear_next", "Iface1", "propImportedStruct", "Test::Struct1()"}, | ||
} | ||
syss := loadExternSystems(t) | ||
prefix := "my_prefix::" | ||
for _, sys := range syss { | ||
for _, tt := range table { | ||
t.Run(tt.operation_name, func(t *testing.T) { | ||
prop := sys.LookupProperty(tt.module_name, tt.interface_name, tt.operation_name) | ||
assert.NotNil(t, prop) | ||
r, err := cppTestValue(prefix, prop) | ||
assert.NoError(t, err) | ||
assert.Equal(t, tt.result, r) | ||
}) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters