attr { key: "my_float" value { f: 0.001 } }
attr { key: "my_int" value { i: 111 } }
}
-node {
- name: "output/relu"
- op: "Relu"
- input: "my/customOp/000"
- attr { key: "T" value { type: DT_FLOAT } }
-}
);
// clang-format on
moco::tf::ModelSignature signature;
{
signature.add_input(moco::tf::TensorName("input1", 0));
- signature.add_output(moco::tf::TensorName("output/relu", 0));
+ signature.add_output(moco::tf::TensorName("my/customOp/000", 0));
signature.add_customop("new_custom_op");
signature.dtype("my/customOp/000", loco::DataType::FLOAT32);
signature.shape("my/customOp/000", {1, 2});
moco::tf::Importer importer(®istry);
std::unique_ptr<loco::Graph> graph = importer.import(signature, graph_def);
- // Convert graph to hold only Canonical dialect
- moco::tf::Canonicalizer canonicalizer;
- canonicalizer.canonicalize(graph.get());
-
- // Cannonicalized graph may look like the following:
- //
- // loco node : Pull -----customOp - Relu - Push
- // |
- // ConstGen--+
- //
- // 1. Checking other nodes linked to/from custom op
+ // what to test:
+ // - there should exist COpCall
+ // - two input nodes should exist and not be nullptr
+ // - attributes should match
+
auto *customop = moco::tf::test::find_first_node_bytype<locoex::COpCall>(graph.get());
+ ASSERT_NE(customop, nullptr);
- // check inputs and next node
ASSERT_EQ(customop->arity(), 2);
loco::Node *input_0 = customop->arg(0);
loco::Node *input_1 = customop->arg(1);
- auto next_nodes = loco::succs(customop);
-
- ASSERT_EQ(next_nodes.size(), 1);
- loco::Node *next_node = *next_nodes.begin();
- ASSERT_NE(next_node, nullptr);
-
- ASSERT_TRUE(dynamic_cast<loco::Pull *>(input_0) and dynamic_cast<loco::ConstGen *>(input_1));
- ASSERT_TRUE(dynamic_cast<loco::ReLU *>(next_node));
+ ASSERT_NE(input_0, nullptr);
+ ASSERT_NE(input_1, nullptr);
- // test 2.
- // attrs inside COpCall
auto f_attr = customop->attr<locoex::COpAttrType::Float>("my_float");
ASSERT_FLOAT_EQ(f_attr->val(), 0.001);
ASSERT_TRUE(f_attr->type() == locoex::COpAttrType::Float);