GOPAQUE, // a cv::GOpaqueU (note - exactly GOpaqueU, not GOpaque<T>!)
};
+ template<typename T>
+ constexpr const char* meta_to_string() noexcept;
+ template<>
+ constexpr const char* meta_to_string<cv::GMatDesc>() noexcept { return "GMatDesc"; }
+ template<>
+ constexpr const char* meta_to_string<cv::GScalarDesc>() noexcept { return "GScalarDesc"; }
+ template<>
+ constexpr const char* meta_to_string<cv::GArrayDesc>() noexcept { return "GArrayDesc"; }
+ template<>
+ constexpr const char* meta_to_string<cv::GOpaqueDesc>() noexcept { return "GOpaqueDesc"; }
+ template<>
+ constexpr const char* meta_to_string<cv::GFrameDesc>() noexcept { return "GFrameDesc";}
+
// Describe G-API types (G-types) with traits. Mostly used by
// cv::GArg to store meta information about types passed into
// operation arguments. Please note that cv::GComputation is
template<> struct ProtoToMeta<cv::GScalar> { using type = cv::GScalarDesc; };
template<typename U> struct ProtoToMeta<cv::GArray<U> > { using type = cv::GArrayDesc; };
template<typename U> struct ProtoToMeta<cv::GOpaque<U> > { using type = cv::GOpaqueDesc; };
+ template<> struct ProtoToMeta<cv::GFrame> { using type = cv::GFrameDesc; };
template<typename T> using ProtoToMetaT = typename ProtoToMeta<T>::type;
//workaround for MSVC 19.0 bug
#include "api/gorigin.hpp"
#include "api/gproto_priv.hpp"
+#include "logger.hpp"
// FIXME: it should be a visitor!
// FIXME: Reimplement with traits?
});
}
+void cv::gimpl::proto::validate_input_meta_arg(const cv::GMetaArg& meta)
+{
+ switch (meta.index())
+ {
+ case cv::GMetaArg::index_of<cv::GMatDesc>():
+ {
+ cv::gimpl::proto::validate_input_meta(cv::util::get<GMatDesc>(meta)); //may throw
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void cv::gimpl::proto::validate_input_meta(const cv::GMatDesc& meta)
+{
+ if (meta.dims.empty())
+ {
+ if (!(meta.size.height > 0 && meta.size.width > 0))
+ {
+ cv::util::throw_error
+ (std::logic_error(
+ "Image format is invalid. Size must contain positive values"
+ ", got width: " + std::to_string(meta.size.width ) +
+ (", height: ") + std::to_string(meta.size.height)));
+ }
+
+ if (!(meta.chan > 0))
+ {
+ cv::util::throw_error
+ (std::logic_error(
+ "Image format is invalid. Channel mustn't be negative value, got channel: " +
+ std::to_string(meta.chan)));
+ }
+ }
+
+ if (!(meta.depth >= 0))
+ {
+ cv::util::throw_error
+ (std::logic_error(
+ "Image format is invalid. Depth must be positive value, got depth: " +
+ std::to_string(meta.depth)));
+ }
+ // All checks are ok
+}
+
// FIXME: Is it tested for all types?
// FIXME: Where does this validation happen??
void cv::validate_input_arg(const GRunArg& arg)
case GRunArg::index_of<cv::UMat>():
{
const auto desc = cv::descr_of(util::get<cv::UMat>(arg));
- GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of cv::UMat!"); break;
+ cv::gimpl::proto::validate_input_meta(desc); //may throw
+ break;
}
#endif // !defined(GAPI_STANDALONE)
case GRunArg::index_of<cv::Mat>():
{
const auto desc = cv::descr_of(util::get<cv::Mat>(arg));
- GAPI_Assert(desc.size.height != 0 && desc.size.width != 0 && "incorrect dimensions of Mat!"); break;
+ cv::gimpl::proto::validate_input_meta(desc); //may throw
+ break;
}
default:
// No extra handling
void cv::validate_input_args(const GRunArgs& args)
{
+ GAPI_LOG_DEBUG(nullptr, "Total count: " << args.size());
+ size_t index = 0;
for (const auto& arg : args)
{
+ GAPI_LOG_DEBUG(nullptr, "Process index: " << index);
validate_input_arg(arg);
+ index ++;
}
}
// FIXME:: GAPI_EXPORTS because of tests only!!
GAPI_EXPORTS const void* ptr (const GRunArgP &arg);
+void validate_input_meta_arg(const GMetaArg& meta);
+void validate_input_meta(const GMatDesc& meta);
+
} // proto
} // gimpl
} // cv
return false; // should never happen
};
+ GAPI_LOG_DEBUG(nullptr, "Total count: " << m_metas.size());
for (const auto meta_arg_idx : ade::util::indexed(ade::util::zip(m_metas, c_expr.m_ins)))
{
const auto &meta = std::get<0>(ade::util::value(meta_arg_idx));
const auto &proto = std::get<1>(ade::util::value(meta_arg_idx));
+ const auto index = ade::util::index(meta_arg_idx);
+ GAPI_LOG_DEBUG(nullptr, "Process index: " << index);
+
+ // check types validity
if (!meta_matches(meta, proto))
{
- const auto index = ade::util::index(meta_arg_idx);
util::throw_error(std::logic_error
("GComputation object type / metadata descriptor mismatch "
"(argument " + std::to_string(index) + ")"));
// FIXME: report what we've got and what we've expected
}
+
+ // check value consistency
+ gimpl::proto::validate_input_meta_arg(meta); //may throw
}
// All checks are ok
}
cv::gapi::GKernelPackage m_all_kernels;
cv::gapi::GNetPackage m_all_networks;
- // Patters built from transformations
+ // Patterns built from transformations
std::vector<std::unique_ptr<ade::Graph>> m_all_patterns;
{
}
};
+
+ struct GCompiledValidateMetaEmpty: public ::testing::Test
+ {
+ cv::GMat in;
+ cv::GScalar scale;
+ cv::GComputation m_ucc;
+
+ G_API_OP(GReturn42, <cv::GOpaque<int>(cv::GMat)>, "org.opencv.test.return_42")
+ {
+ static GOpaqueDesc outMeta(cv::GMatDesc /* in */) { return cv::empty_gopaque_desc(); }
+ };
+
+ GAPI_OCV_KERNEL(GOCVReturn42, GReturn42)
+ {
+ static void run(const cv::Mat &/* in */, int &out)
+ {
+ out = 42;
+ }
+ };
+
+ GCompiledValidateMetaEmpty() : m_ucc(cv::GIn(in),
+ cv::GOut(GReturn42::on(in)))
+ {
+ }
+ };
} // anonymous namespace
TEST_F(GCompiledValidateMetaTyped, ValidMeta)
EXPECT_THROW(f(cv::gin(in1, sc), cv::gout(out1, out2)), std::logic_error);
}
+TEST_F(GCompiledValidateMetaEmpty, InvalidMatMetaCompile)
+{
+ EXPECT_THROW(m_ucc.compile(cv::empty_gmat_desc(),
+ cv::empty_scalar_desc()),
+ std::logic_error);
+}
+
+TEST_F(GCompiledValidateMetaEmpty, InvalidMatMetaApply)
+{
+ cv::Mat emptyIn;
+ int out {};
+ const auto pkg = cv::gapi::kernels<GCompiledValidateMetaEmpty::GOCVReturn42>();
+
+ EXPECT_THROW(m_ucc.apply(cv::gin(emptyIn), cv::gout(out), cv::compile_args(pkg)),
+ std::logic_error);
+}
+
+TEST_F(GCompiledValidateMetaEmpty, ValidInvalidMatMetasApply)
+{
+ int out {};
+ const auto pkg = cv::gapi::kernels<GCompiledValidateMetaEmpty::GOCVReturn42>();
+
+ cv::Mat nonEmptyMat = cv::Mat::eye(cv::Size(64,32), CV_8UC1);
+ m_ucc.apply(cv::gin(nonEmptyMat), cv::gout(out), cv::compile_args(pkg));
+ EXPECT_EQ(out, 42);
+
+ cv::Mat emptyIn;
+ EXPECT_THROW(m_ucc.apply(cv::gin(emptyIn), cv::gout(out), cv::compile_args(pkg)),
+ std::logic_error);
+
+ out = 0;
+ m_ucc.apply(cv::gin(nonEmptyMat), cv::gout(out), cv::compile_args(pkg));
+ EXPECT_EQ(out, 42);
+}
} // namespace opencv_test