namespace InferenceEngine {
namespace details {
+// helper for adding creators with a specific exception
+#define REQUIRED_IE_CONVERSION_CREATOR(type_name, ie_type_name)\
+ addSpecificCreator({type_name}, [](const std::shared_ptr<::ngraph::Node>& node,\
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {\
+ THROW_IE_EXCEPTION << type_name << " operation has a form that is not supported. " << node->get_friendly_name()\
+ << " should be converted to " << ie_type_name << " operation.";\
+ return nullptr;\
+ });\
+
/**
* @brief Creator for CNNLayer from nGraph op
*/
class CNNLayerCreator : public ::ngraph::AttributeVisitor {
public:
using CreatorFor = std::function<CNNLayerPtr(const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> param)>;
+ const std::map<std::string, std::string>& param)>;
explicit CNNLayerCreator(const std::shared_ptr<::ngraph::Node>& node);
CNNLayerPtr create();
} else if (auto a = ::ngraph::as_type<::ngraph::AttributeAdapter<::ngraph::Strides>>(&adapter)) {
auto shape = static_cast<::ngraph::Strides&>(*a);
params[name] = joinVec(shape);
+ } else if (auto a = ::ngraph::as_type<::ngraph::AttributeAdapter<std::vector<size_t>>>(& adapter)) {
+ auto data = a->get();
+ params[name] = joinVec(data);
} else {
THROW_IE_EXCEPTION << "Error converting ngraph to CNN network. "
"Attribute adapter can not be found for " << name << " parameter";
InferenceEngine::details::CNNLayerCreator::CNNLayerCreator(const std::shared_ptr<::ngraph::Node>& node): node(node) {
addSpecificCreator({"Parameter"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Input",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<CNNLayer>(attrs);
// TODO - Remove "GreaterEq" once ngraph transitions to GreaterEqual
addSpecificCreator({"Eltwise", "Subtract", "Power", "Maximum", "Divide", "Greater", "GreaterEqual", "FloorMod", "LogicalOr", "LogicalAnd", "LogicalXor",
"GreaterEq", "Less", "LessEqual", "Equal", "NotEqual", "Multiply", "Add"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Eltwise",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<EltwiseLayer>(attrs);
return res;
});
addSpecificCreator({"Concat"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<ConcatLayer>(attrs);
return res;
});
addSpecificCreator({"AvgPool", "MaxPool"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Pooling",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<PoolingLayer>(attrs);
return res;
});
addSpecificCreator({"Select"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<SelectLayer>(attrs);
return res;
});
addSpecificCreator({"BinaryConvolution"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<BinaryConvolutionLayer>(attrs);
});
addSpecificCreator({"SpaceToBatch"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<SpaceToBatchLayer>(attrs);
});
addSpecificCreator({"BatchToSpace"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<BatchToSpaceLayer>(attrs);
});
addSpecificCreator({"Assign"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Memory",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<CNNLayer>(attrs);
});
addSpecificCreator({"ReadValue"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Memory",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<CNNLayer>(attrs);
});
addSpecificCreator({"DepthToSpace"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<DepthToSpaceLayer>(attrs);
});
addSpecificCreator({"SpaceToDepth"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<SpaceToDepthLayer>(attrs);
return res;
});
- addSpecificCreator({"RNNCell"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
- THROW_IE_EXCEPTION << "RNNCell operation has a form that is not supported." << node->get_friendly_name()
- << " should be converted to RNNCellIE operation";
- return nullptr;
- });
-
- addSpecificCreator({"GRUCell"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
- THROW_IE_EXCEPTION << "GRUCell operation has a form that is not supported." << node->get_friendly_name()
- << " should be converted to GRUCellIE operation";
- return nullptr;
- });
-
addSpecificCreator({"RNNCellIE"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "RNNCell",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<RNNCell>(attrs);
});
addSpecificCreator({"GRUCellIE"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "GRUCell",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<GRUCell>(attrs);
});
addSpecificCreator({"ScatterElementsUpdate"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<ScatterElementsUpdateLayer>(attrs);
});
addSpecificCreator({"ScatterUpdate"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(),
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<ScatterUpdateLayer>(attrs);
});
addSpecificCreator({"StaticShapeTopK"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "TopK",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<TopKLayer>(attrs);
});
addSpecificCreator({"Transpose"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Permute",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<InferenceEngine::CNNLayer>(attrs);
});
addSpecificCreator({"SwishIE"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "Swish",
details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<InferenceEngine::CNNLayer>(attrs);
});
- addSpecificCreator({"PriorBox"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
- // Todo (itikhono): replace the message after supporting constants as outputs in plugins
-// THROW_IE_EXCEPTION << "PriorBox operation has a form that is not supported." << node->get_friendly_name()
-// << " should be replaced by constant during constant folding.";
- THROW_IE_EXCEPTION << "PriorBox operation has a form that is not supported." << node->get_friendly_name()
- << " should be converted to PriorBoxIE operation";
- return nullptr;
- });
-
- addSpecificCreator({"PriorBoxClustered"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
- // Todo (itikhono): replace the message after supporting constants as outputs in plugins
-// THROW_IE_EXCEPTION << "PriorBoxClustered operation has a form that is not supported." << node->get_friendly_name()
-// << " should be replaced by constant during constant folding.";
- THROW_IE_EXCEPTION << "PriorBoxClustered operation has a form that is not supported." << node->get_friendly_name()
- << " should be converted to PriorBoxClusteredIE operation";
- return nullptr;
- });
-
addSpecificCreator({"NonMaxSuppressionIE"}, [](const std::shared_ptr<::ngraph::Node>& node,
- const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "NonMaxSuppression", details::convertPrecision(node->get_output_element_type(0))};
auto res = std::make_shared<InferenceEngine::NonMaxSuppressionLayer>(attrs);
res->params = params;
return res;
});
+ REQUIRED_IE_CONVERSION_CREATOR("Broadcast", "Tile");
+ REQUIRED_IE_CONVERSION_CREATOR("Interpolate", "Interp");
+ REQUIRED_IE_CONVERSION_CREATOR("NormalizeL2", "NormalizeIE");
+ REQUIRED_IE_CONVERSION_CREATOR("GroupConvolution", "ConvolutionIE");
+ REQUIRED_IE_CONVERSION_CREATOR("ConvolutionBackpropData", "DeconvolutionIE");
+ REQUIRED_IE_CONVERSION_CREATOR("GroupConvolutionBackpropData", "DeconvolutionIE");
+
+ addSpecificCreator({ "Convolution", "Gather", "GatherTree", "GRUCell", "GRUSequence", "HardSigmoid",
+ "LRN", "LSTMCell", "LSTMSequence", "NonMaxSuppression", "RNNCell", "RNNSequence", "OneHot",
+ "Pad", "PriorBoxClustered", "PriorBox", "Proposal", "Selu", "Swish", "Tile", "TopK"},
+ [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string>& params)
+ -> CNNLayerPtr {
+ const std::string& type_name = node->get_type_name();
+ THROW_IE_EXCEPTION << type_name << " operation has a form that is not supported. " << node->get_friendly_name()
+ << " should be converted to " << type_name + "IE operation.";
+ return nullptr;
+ });
+
addSpecificCreator({"ReduceMin", "ReduceMax", "ReduceMean", "ReduceProd", "ReduceSum", "ReduceL1", "ReduceL2"},
- [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), node->description(), details::convertPrecision(node->get_output_element_type(0))};
auto reduce_node = std::dynamic_pointer_cast<ngraph::op::util::ArithmeticReductionKeepDims>(node);
auto res = std::make_shared<InferenceEngine::ReduceLayer>(attrs);
return res;
});
- addSpecificCreator({"ReduceLogicalAnd"}, [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ addSpecificCreator({"ReduceLogicalAnd"}, [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "ReduceAnd", details::convertPrecision(node->get_output_element_type(0))};
auto reduce_node = std::dynamic_pointer_cast<ngraph::op::util::LogicalReductionKeepDims>(node);
auto res = std::make_shared<InferenceEngine::ReduceLayer>(attrs);
return res;
});
- addSpecificCreator({"ReduceLogicalOr"}, [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string> params) -> CNNLayerPtr {
+ addSpecificCreator({"ReduceLogicalOr"}, [](const std::shared_ptr<::ngraph::Node>& node, const std::map<std::string, std::string>& params) -> CNNLayerPtr {
LayerParams attrs = {node->get_friendly_name(), "ReduceOr", details::convertPrecision(node->get_output_element_type(0))};
auto reduce_node = std::dynamic_pointer_cast<ngraph::op::util::LogicalReductionKeepDims>(node);
auto res = std::make_shared<InferenceEngine::ReduceLayer>(attrs);
std::make_shared<Builder::NodeConverter<::ngraph::op::Atan>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::AvgPool>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::BatchNormInference>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::v1::Broadcast>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Clamp>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Concat>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Constant>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Floor>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Ceiling>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::GatherIE>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::v1::GatherTree>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::GatherTreeIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Interp>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::Interpolate>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Log>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::LRN>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::LRN_IE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::MVN>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::FullyConnected>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::Maximum>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::Minimum>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::Multiply>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::v1::NonMaxSuppression>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::NormalizeL2>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::NormalizeIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::OneHotIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::PRelu>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::PadIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::Power>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::PowerIE>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::PriorBox>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::PriorBoxClustered>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::PriorBoxClusteredIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::PriorBoxIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::ProposalIE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::Unsqueeze>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::TensorIterator>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::LSTMCellIE>>(),
- std::make_shared<Builder::NodeConverter<::ngraph::op::HardSigmoid>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::HardSigmoid_IE>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::LogicalNot>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::ShuffleChannels>>(),
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset1.hpp>
+#include <ngraph/opsets/opset4.hpp>
#include <ngraph_ops/convolution_ie.hpp>
#include <transformations/init_node_info.hpp>
+#include <legacy/convert_function_to_cnn_network.hpp>
using namespace testing;
using namespace InferenceEngine;
FAIL();
}
}
+
+TEST(ConvertFunctionToCNNNetworkTests, OpsShouldBeConvertedToIERepresentation) {
+ ngraph::NodeVector should_converted_to_ie = {
+ std::make_shared<ngraph::opset4::Broadcast>(),
+ std::make_shared<ngraph::opset4::Convolution>(),
+ std::make_shared<ngraph::opset4::ConvolutionBackpropData>(),
+ std::make_shared<ngraph::opset4::Gather>(),
+ std::make_shared<ngraph::opset4::GatherTree>(),
+ std::make_shared<ngraph::opset4::GroupConvolution>(),
+ std::make_shared<ngraph::opset4::GroupConvolutionBackpropData>(),
+ std::make_shared<ngraph::opset4::GRUCell>(),
+ // std::make_shared<ngraph::opset4::GRUSequence>(), todo: enable after GRUSequence support
+ std::make_shared<ngraph::opset4::HardSigmoid>(),
+ std::make_shared<ngraph::opset4::Interpolate>(),
+ std::make_shared<ngraph::opset4::LRN>(),
+ std::make_shared<ngraph::opset4::LSTMCell>(),
+ // std::make_shared<ngraph::opset4::LSTMSequence>(), todo: enable after LSTMSequence support
+ std::make_shared<ngraph::opset4::NonMaxSuppression>(),
+ std::make_shared<ngraph::opset4::NormalizeL2>(),
+ std::make_shared<ngraph::opset4::RNNCell>(),
+ // std::make_shared<ngraph::opset4::RNNSequence>(), todo: enable after RNNSequence support
+ std::make_shared<ngraph::opset4::OneHot>(),
+ std::make_shared<ngraph::opset4::Pad>(),
+ std::make_shared<ngraph::opset4::PriorBoxClustered>(),
+ std::make_shared<ngraph::opset4::PriorBox>(),
+ std::make_shared<ngraph::opset4::Proposal>(),
+ std::make_shared<ngraph::opset4::Selu>(),
+ std::make_shared<ngraph::opset4::Swish>(),
+ std::make_shared<ngraph::opset4::Tile>(),
+ std::make_shared<ngraph::opset4::TopK>(),
+ };
+
+ // create simple ngraph function Parameter -> Result
+ std::shared_ptr<ngraph::Function> f;
+ auto param = std::make_shared<ngraph::opset4::Parameter>(ngraph::element::f32, ngraph::Shape{});
+ auto res = std::make_shared<ngraph::opset4::Result>(param);
+ f = std::make_shared<ngraph::Function>(ngraph::ResultVector{res}, ngraph::ParameterVector{param});
+ InferenceEngine::CNNNetwork nGraphImpl(f);
+
+ for (const auto& ngraph_node : should_converted_to_ie) {
+ // add node without inputs to the ngraph function
+ ngraph_node->set_output_type(0, ngraph::element::f32, ngraph::Shape{});
+ res->input(0).replace_source_output(ngraph_node->output(0));
+
+ EXPECT_THROW(InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl, true),
+ InferenceEngine::details::InferenceEngineException)
+ << "failed node: " << ngraph_node->get_type_name() << std::endl;
+ try {
+ InferenceEngine::details::convertFunctionToICNNNetwork(f, nGraphImpl, true);
+ } catch (InferenceEngine::details::InferenceEngineException &err) {
+ std::string type_name = ngraph_node->get_type_name();
+
+ std::map<std::string, std::string> exceptions = { {"Broadcast", "Tile"}, {"Interpolate", "Interp"},
+ {"NormalizeL2", "NormalizeIE"},
+ {"GroupConvolution", "ConvolutionIE"},
+ {"ConvolutionBackpropData", "DeconvolutionIE"},
+ {"GroupConvolutionBackpropData", "DeconvolutionIE"},
+ };
+ std::string type_name_ie = type_name + "IE";
+ if (exceptions[type_name].empty()) {
+ type_name_ie = type_name + "IE";
+ } else {
+ type_name_ie = exceptions[type_name];
+ }
+ std::string expected_error_message = type_name + " operation has a form that is not supported. "
+ + ngraph_node->get_friendly_name() + " should be converted to " + type_name_ie + " operation.";
+ std::string real_message = err.what();
+ bool is_messages_match = real_message.find(expected_error_message) != std::string::npos;
+ EXPECT_TRUE(is_messages_match) << "failed node: " << type_name << std::endl
+ << "Exception massage: " << err.what() << std::endl
+ << "Expected message: " << expected_error_message << std:: endl;
+ } catch (...) {
+ FAIL() << "ERROR: Unexpected exception thrown: " << std::current_exception << std::endl;
+ }
+ }
+}
\ No newline at end of file