Commit 7ae93d70 authored by limm's avatar limm
Browse files

add tests part code

parent abaad570
Pipeline #2815 canceled with stages
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/utils/formatter.h"
#include "mmdeploy/experimental/module_adapter.h"
namespace test_module_adapter {
using mmdeploy::CreateTask;
using mmdeploy::MakeTask;
using mmdeploy::Module;
using mmdeploy::Result;
using mmdeploy::Value;
class MyModule {
public:
std::tuple<int, int> operator()(const double& a, const double& b) noexcept {
return {a + b, a - b};
}
};
Result<std::tuple<int, int> > my_func(int x, int y) { return {x + y, x - y}; }
TEST_CASE("test module adapter", "[module_adapter]") {
Value x{100, 200};
Value y;
// clang-format off
SECTION("create") {
std::unique_ptr<Module> task;
SECTION("function object") {
task = CreateTask(MyModule{});
}
SECTION("shared_ptr") {
task = CreateTask(std::make_shared<MyModule>());
}
SECTION("unique_ptr") {
task = CreateTask(std::make_shared<MyModule>());
}
SECTION("function pointer") {
task = CreateTask(my_func);
}
SECTION("lambda") {
task = CreateTask(
[](int x, int y) { return std::make_tuple(x + y, x - y); });
}
y = task->Process(x).value();
}
SECTION("make") {
SECTION("function object") {
y = MakeTask(MyModule{}).Process(x).value();
}
SECTION("shared_ptr") {
y = CreateTask(std::make_shared<MyModule>())->Process(x).value();
}
SECTION("unique_ptr") {
y = MakeTask(std::make_shared<MyModule>()).Process(x).value();
}
SECTION("function pointer") {
y = MakeTask(my_func).Process(x).value();
}
SECTION("lambda") {
auto task = MakeTask([](int x, int y) {
return std::make_tuple(x + y, x - y);
});
y = task.Process(x).value();
}
}
// clang-format on
REQUIRE(y[0].get<int>() == 300);
REQUIRE(y[1].get<int>() == -100);
}
} // namespace test_module_adapter
// Copyright (c) OpenMMLab. All rights reserved.
#include <iostream>
#include "catch.hpp"
#include "mmdeploy/core/module.h"
#include "mmdeploy/core/registry.h"
using namespace mmdeploy;
using Decoder = Module;
using DecoderCreator = Creator<Decoder>;
class ImageDecoder final : public Decoder {
public:
Result<Value> Process(const Value& input) override {
if (input.contains("image_path")) {
std::cout << "decode image whose path " << input["image_path"].get<std::string>()
<< std::endl;
} else {
std::cerr << "input error" << std::endl;
return Status(eInvalidArgument);
}
return Value();
}
};
class ImageDecoderCreator : public DecoderCreator {
public:
std::string_view name() const noexcept override { return "image"; }
int version() const noexcept override { return 2004000; }
std::unique_ptr<Decoder> Create(const Value& value) override {
ImageDecoder decoder;
return std::make_unique<ImageDecoder>(std::move(decoder));
}
};
MMDEPLOY_REGISTER_CREATOR(Decoder, ImageDecoderCreator);
namespace no_mmdeploy {
class ImageDecoder final : public Decoder {
public:
ImageDecoder() = default;
Result<Value> Process(const Value& input) override {
if (input.contains("image_content")) {
std::cout << "decode image content" << std::endl;
} else {
std::cerr << "input error" << std::endl;
return Status(eInvalidArgument);
}
return Value();
}
};
class ImageDecoderCreator : public DecoderCreator {
public:
std::string_view name() const noexcept override { return "image"; }
int version() const noexcept override { return 1003006; };
std::unique_ptr<Decoder> Create(const Value& value) override {
ImageDecoder decoder;
return std::make_unique<ImageDecoder>(std::move(decoder));
}
};
MMDEPLOY_REGISTER_CREATOR(Decoder, ImageDecoderCreator);
} // namespace no_mmdeploy
TEST_CASE("define module in global namespace", "[registry]") {
auto& registry = gRegistry<Decoder>();
std::string module_type{"image"};
SECTION("get not existing decoder") {
auto creator = registry.Get("dummy");
CHECK(creator == nullptr);
}
SECTION("get creator without specifying version") {
auto creator = registry.Get(module_type);
CHECK(creator == nullptr);
}
SECTION("get creator by providing version") {
auto creator = registry.Get(module_type, 100);
CHECK(creator == nullptr);
creator = registry.Get(module_type, 2004000);
CHECK(creator != nullptr);
auto decoder = creator->Create({});
CHECK(decoder->Process({{"image_path", "./test.jpg"}}));
auto another_creator = registry.Get(module_type, 1003006);
CHECK(another_creator != nullptr);
auto another_decoder = another_creator->Create({});
CHECK(!another_decoder->Process({{"image_path", "./test.jpg"}}));
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#include <array>
#include <vector>
#include "catch.hpp"
#include "mmdeploy/core/mpl/span.h"
using mmdeploy::Span;
TEST_CASE("test span ctors & deduction guides", "[span]") {
std::array a{1, 2, 3, 4, 5};
std::vector v{1, 2, 3, 4, 5};
int c[] = {1, 2, 3, 4, 5};
Span x = a;
Span y = x;
SECTION("ctor by it & size") { y = Span(v.begin(), v.size()); }
SECTION("ctor by first & last") { y = Span(v.begin(), v.end()); }
SECTION("ctor by vector") { y = Span(v); }
SECTION("ctor by array") { y = Span(a); }
SECTION("ctor by c-style array") { y = Span(c); }
REQUIRE(x == y);
}
TEST_CASE("test span apis", "[span]") {
int c[] = {1, 2, 3, 4, 5};
Span<int> s;
REQUIRE(s.empty());
REQUIRE(s.size() == 0);
s = c;
{
std::vector v{1, 2, 3, 4, 5};
std::vector<int> u(s.begin(), s.end());
REQUIRE(u == v);
}
{
std::vector v{5, 4, 3, 2, 1};
std::vector<int> u(s.rbegin(), s.rend());
REQUIRE(u == v);
}
REQUIRE(s.front() == 1);
REQUIRE(s.back() == 5);
REQUIRE(s.size() == 5);
REQUIRE(s.size_bytes() == 5 * sizeof(int));
for (int i = 0; i < 5; ++i) REQUIRE(s[i] == i + 1);
REQUIRE(s.data()[4] == 5);
REQUIRE(!s.empty());
int a[] = {1, 2, 3};
Span t = a;
REQUIRE(s != t);
REQUIRE(s.first(0).empty());
REQUIRE(s.first(3) == t);
REQUIRE(s.first(5) == s);
int b[] = {3, 4, 5};
t = b;
REQUIRE(s.last(0).empty());
REQUIRE(s.last(3) == t);
REQUIRE(s.last(5) == s);
int m[] = {2, 3, 4};
t = m;
REQUIRE(s.subspan(0, 0).empty());
REQUIRE(s.subspan(0, 5) == s);
REQUIRE(s.subspan(0) == s);
REQUIRE(s.subspan(1, 3) == t);
REQUIRE(s.subspan(1, 3) == s.first(4).last(3));
m[0] = 1;
REQUIRE(s.subspan(1, 3) != t);
}
// Copyright (c) OpenMMLab. All rights reserved.
#include <sstream>
#include "catch.hpp"
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/status_code.h"
namespace mmdeploy {
Result<double> sqrt(int x) {
if (x >= 0) {
return std::sqrt(x);
} else {
return Status(eInvalidArgument);
}
}
Result<double> sqrt_of_negative() {
OUTCOME_TRY(auto x, sqrt(-1));
return x;
}
TEST_CASE("test status_code", "[status_code]") {
try {
sqrt_of_negative().value();
} catch (const Exception& e) {
REQUIRE(e.code() == eInvalidArgument);
MMDEPLOY_INFO("{}", e.what());
}
auto r = sqrt_of_negative();
REQUIRE(!r);
REQUIRE(r.error() == eInvalidArgument);
MMDEPLOY_INFO("{}", r.error().message().c_str());
}
} // namespace mmdeploy
// Copyright (c) OpenMMLab. All rights reserved.
#include "catch.hpp"
#include "json.hpp"
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/operator.h"
#include "mmdeploy/core/serialization.h"
#include "mmdeploy/core/utils/formatter.h"
#include "mmdeploy/core/value.h"
using namespace mmdeploy;
TEST_CASE("test value", "[value]") {
Value a;
REQUIRE(a.type() == ValueType::kNull);
Value value(1);
REQUIRE(value.type() == ValueType::kInt);
REQUIRE(value.get<int>() == 1);
REQUIRE(value.get<float>() == 1.f);
REQUIRE(value.get<double>() == 1.);
REQUIRE(value.get<bool>() == true);
value = true;
REQUIRE(value.type() == ValueType::kBool);
REQUIRE(value.get<int>() == 1);
REQUIRE(value.get<float>() == 1.f);
REQUIRE(value.get<double>() == 1.);
REQUIRE(value.get<bool>() == true);
value = ValueType::kObject;
REQUIRE(value.is_object());
using namespace std::string_literals;
value = "I'm a string";
REQUIRE(value.type() == ValueType::kString);
REQUIRE(value.get<std::string>() == "I'm a string");
value = "I'm a string"s;
REQUIRE(value.type() == ValueType::kString);
REQUIRE(value.get<const char*>() == "I'm a string"s);
Value copy = value;
Value integer(10);
Value array{0, 1, 2, 3, 4, 5};
REQUIRE(array.is_array());
for (const auto& x : array) {
std::cout << x.get<int>() << std::endl;
}
Value object{{"hello", 100}, {"world", 200}};
REQUIRE(object.is_object());
for (auto it = object.begin(); it != object.end(); ++it) {
std::cout << it.key() << " " << (*it).get<int>() << std::endl;
}
}
TEST_CASE("test null interface for value", "[value]") {
Value v;
REQUIRE(v.is_null());
REQUIRE(v.size() == 0);
REQUIRE(v.empty());
}
TEST_CASE("test array interface for value", "[value]") {
constexpr auto N = 10;
Value v;
SECTION("init by push_back") {
for (int i = 0; i < N; ++i) {
v.push_back(i);
}
}
SECTION("init by initializer list") { v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; }
REQUIRE(v.is_array());
REQUIRE(v.size() == N);
for (int i = 0; i < N; ++i) {
REQUIRE(v[i].get<int>() == i);
}
}
TEST_CASE("test object interface for value", "[value]") {
constexpr auto N = 10;
Value v;
SECTION("init by operator[]") {
for (int i = 0; i < N; ++i) {
v[std::to_string(i)] = i;
}
}
SECTION("init by initializer list") {
v = {{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4},
{"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {"9", 9}};
}
REQUIRE(v.is_object());
REQUIRE(v.size() == N);
for (int i = 0; i < N; ++i) {
REQUIRE(v[std::to_string(i)].get<int>() == i);
}
}
// clang-format off
template <class T, ValueType e>
struct Pair{
using type = T;
static constexpr const auto value = e;
};
using PrimaryTypes =
std::tuple<
Pair<Value::Boolean, Value::kBool>,
Pair<Value::Integer, Value::kInt>,
Pair<Value::Unsigned, Value::kUInt>,
Pair<Value::Float, Value::kFloat>,
Pair<Value::String, Value::kString>,
Pair<Value::Binary, Value::kBinary>,
Pair<Value::Array , Value::kArray>,
Pair<Value::Object, Value::kObject>,
Pair<Value::Pointer, Value::kPointer>
>;
// clang-format on
TEMPLATE_LIST_TEST_CASE("test value set & get", "[value]", PrimaryTypes) {
using Type = typename TestType::type;
Type t{};
Value v = t;
REQUIRE(v.type() == TestType::value);
// copy ctor
Value u = v;
REQUIRE(u.type() == v.type());
// simple get
REQUIRE(u.get<Type>() == t);
// move ctor
Value w = std::move(v);
REQUIRE(v.type() == Value::kNull);
REQUIRE(w.type() == u.type());
REQUIRE(w.get<Type>() == u.get<Type>());
// from type enum
Value x = TestType::value;
REQUIRE(x.type() == TestType::value);
REQUIRE(x.get<Type>() == t);
}
TEST_CASE("test array interface of value", "[value]") {
Value a{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
REQUIRE(a.is_array());
REQUIRE(a.size() == 10);
REQUIRE(!a.empty());
REQUIRE(a.front().get<int>() == 0);
REQUIRE(a.back().get<int>() == 9);
REQUIRE(std::as_const(a).front().get<int>() == 0);
REQUIRE(std::as_const(a).back().get<int>() == 9);
a.push_back(10);
REQUIRE(a.back().get<int>() == 10);
REQUIRE(a[10].get<int>() == 10);
REQUIRE(std::as_const(a)[10].get<int>() == 10);
a[10] = 100;
REQUIRE(a[10].get<int>() == 100);
Value b(11);
a.push_back(b);
REQUIRE(a.back().get<int>() == 11);
// init by push back
Value c;
c.push_back(0);
REQUIRE(c.is_array());
REQUIRE(c.size() == 1);
REQUIRE(c.front().get<int>() == 0);
// init by native type
Value::Array d{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto size = d.size();
Value e = d;
REQUIRE(e.is_array());
REQUIRE(e.size() == d.size());
e = std::move(d);
REQUIRE(d.empty());
REQUIRE(e.size() == size);
// resize via ref to native type
Value f = Value::kArray;
REQUIRE(f.is_array());
f.get_ref<Value::Array&>().resize(1024);
REQUIRE(f.size() == 1024);
}
TEST_CASE("test object interface of value", "[value]") {
Value a{{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}};
REQUIRE(a.is_object());
REQUIRE(a.size() == 5);
REQUIRE(!a.empty());
REQUIRE(a.contains("0"));
REQUIRE(a.value("4", 0) == 4);
REQUIRE(a.value("5", 0) == 0);
a.update({{"6", 6}, {"7", 7}});
REQUIRE(a["6"].get<int>() == 6);
REQUIRE(a["7"].get<int>() == 7);
REQUIRE(a.find("100") == a.end());
Value b;
REQUIRE(b.is_null());
b.update({{"hello", "world"}});
REQUIRE(b.is_object());
REQUIRE(b.value<std::string>("hello", "") == "world");
Value c;
c["hello"] = "world";
REQUIRE(c.is_object());
REQUIRE(c.value<std::string>("hello", "") == "world");
}
// TODO: Pointer
TEST_CASE("test pointer of Value", "[value]") {
Value o{{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}};
Value a{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Value p{{"object", std::make_shared<Value>(std::move(o))},
{"array", std::make_shared<Value>(std::move(a))}};
REQUIRE(p.is_object());
REQUIRE(p["object"].is_pointer());
REQUIRE(p["object"].is_object());
REQUIRE(p["array"].is_array());
REQUIRE(p["array"].is_array());
MMDEPLOY_INFO("{}", p);
}
TEST_CASE("test null Value", "[value]") {
Value a;
REQUIRE(a.is_null());
REQUIRE(a.empty());
REQUIRE(a.size() == 0);
Value b = a;
REQUIRE(b.is_null());
Value c = std::move(b);
REQUIRE(b.is_null());
REQUIRE(c.is_null());
Value d = Value::kNull;
REQUIRE(d.is_null());
}
TEST_CASE("test value iterator", "[value]") {
{
Value source{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int count{};
for (auto it = source.begin(); it != source.end(); ++it) {
count += it->get<int>() == count;
}
REQUIRE(count == source.size());
}
{
const Value source{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int count{};
for (auto it = source.begin(); it != source.end(); ++it) {
count += it->get<int>() == count;
}
REQUIRE(count == source.size());
}
{
Value source{{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}};
int count{};
for (auto it = source.begin(); it != source.end(); ++it) {
if (it->get<int>() == count && it.key() == std::to_string(it->get<int>())) {
++count;
}
}
REQUIRE(count == source.size());
}
{
const Value source{{"0", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}};
int count{};
for (auto it = source.begin(); it != source.end(); ++it) {
if (it->get<int>() == count && it.key() == std::to_string(it->get<int>())) {
++count;
}
}
REQUIRE(count == source.size());
}
}
struct Meow {
int value;
};
struct Doge {
int value;
};
namespace mmdeploy {
MMDEPLOY_REGISTER_TYPE_ID(Meow, 1234);
MMDEPLOY_REGISTER_TYPE_ID(Doge, 3456);
} // namespace mmdeploy
TEST_CASE("test dynamic interface for value", "[value]") {
Value meow(Meow{100});
REQUIRE(meow.is_any());
REQUIRE(meow.is_any<Meow>());
REQUIRE_FALSE(meow.is_any<int>());
REQUIRE_FALSE(meow.is_any<Doge>());
REQUIRE(meow.get<Meow>().value == 100);
REQUIRE(meow.get_ref<Meow&>().value == 100);
REQUIRE(meow.get_ptr<Meow*>() == &meow.get_ref<Meow&>());
REQUIRE(meow.get_ptr<const Meow*>() == meow.get_ptr<Meow*>());
REQUIRE(meow.get_ptr<EraseType<Doge>*>() == nullptr);
Doge v{100};
Value doge(cast_by_erasure(v));
auto u = doge.get<EraseType<Doge>>();
REQUIRE(u.value == v.value);
REQUIRE(doge.get_ptr<Meow*>() == nullptr);
REQUIRE(doge.get_ref<EraseType<Doge>&>().value == v.value);
REQUIRE(doge.get_ptr<EraseType<Doge>*>() == &doge.get_ref<EraseType<Doge>&>());
}
// conclusion: when value contains more than 8 elements, the pointer type is faster than copying
// on a modern x86 CPU
TEST_CASE("test speed of value", "[value]") {
// constexpr auto N = 512;
constexpr auto N = 32;
constexpr auto M = N / 1;
constexpr auto K = 10;
// construct NxNxM cube
Value::Array a0(N);
for (int i = 0; i < N; ++i) {
Value::Array a1(N);
for (int j = 0; j < N; ++j) {
Value::Array a2(M);
for (int k = 0; k < M; ++k) {
a2[k] = k;
}
// a1[j] = std::move(a2);
a1[j] = make_pointer(std::move(a2));
}
a0[i] = std::move(a1);
}
Value v(std::move(a0));
auto t0 = std::chrono::high_resolution_clock::now();
for (int i = 0; i < K; ++i) {
Value t = graph::DistribAA(v).value();
}
auto t1 = std::chrono::high_resolution_clock::now();
auto dt = std::chrono::duration<double, std::milli>(t1 - t0).count();
MMDEPLOY_INFO("time = {}ms", (float)dt);
}
TEST_CASE("test ctor of value", "[value]") {
static_assert(!std::is_constructible<Value, void (*)(int)>::value, "");
static_assert(!std::is_constructible<Value, int*>::value, "");
}
//
// TEST_CASE("test logger", "[logger]") {
// MMDEPLOY_INFO("{}", DataType::kFLOAT);
// MMDEPLOY_INFO("{}", DataType::kHALF);
// MMDEPLOY_INFO("{}", DataType::kINT8);
// MMDEPLOY_INFO("{}", DataType::kINT32);
// MMDEPLOY_INFO("{}", DataType::kINT64);
// MMDEPLOY_INFO("{}", PixelFormat::kBGR);
// MMDEPLOY_INFO("{}", PixelFormat::kRGB);
// MMDEPLOY_INFO("{}", PixelFormat::kGRAYSCALE);
// MMDEPLOY_INFO("{}", PixelFormat::kNV12);
// MMDEPLOY_INFO("{}", PixelFormat::kNV21);
// MMDEPLOY_INFO("{}", PixelFormat::kBGRA);
//}
// Copyright (c) OpenMMLab. All rights reserved.
#include <chrono>
#include <iostream>
#include <thread>
#include "catch.hpp"
#include "mmdeploy/core/device.h"
using namespace mmdeploy;
using namespace framework;
using namespace std::string_literals;
TEST_CASE("test buffer", "[buffer]") {
using namespace mmdeploy;
Device device{"cpu"};
std::vector src{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f};
std::vector dst(src.size(), 0.f);
auto size_in_bytes = src.size() * sizeof(float);
Buffer buf_x(device, size_in_bytes);
Buffer buf_y(device, size_in_bytes);
REQUIRE(buf_x);
REQUIRE(buf_y);
REQUIRE(buf_x.GetSize() == size_in_bytes);
REQUIRE(buf_y.GetSize() == size_in_bytes);
SECTION("copy w/ queue API") {
// Stream stream(device);
auto stream = Stream::GetDefault(device);
Event event(device);
REQUIRE(stream);
REQUIRE(event);
REQUIRE(stream.Copy(src.data(), buf_x));
REQUIRE(stream.Copy(buf_x, buf_y));
REQUIRE(stream.Copy(buf_y, dst.data()));
REQUIRE(event.Record(stream));
REQUIRE(event.Wait());
REQUIRE(src == dst);
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#include <chrono>
#include <iostream>
#include <thread>
#include "catch.hpp"
#include "mmdeploy/core/device.h"
using namespace mmdeploy;
using namespace framework;
using namespace std::string_literals;
TEST_CASE("test cuda", "[cuda]") {
using namespace mmdeploy;
Device device{"cuda"};
REQUIRE(device.platform_id() > 0);
REQUIRE(device.device_id() == 0);
std::vector src{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f};
std::vector dst(src.size(), 0.f);
auto size_in_bytes = src.size() * sizeof(float);
Buffer buf_x(device, size_in_bytes);
Buffer buf_y(device, size_in_bytes);
REQUIRE(buf_x);
REQUIRE(buf_y);
REQUIRE(buf_x.GetSize() == size_in_bytes);
REQUIRE(buf_y.GetSize() == size_in_bytes);
SECTION("copy w/ queue API") {
// Stream stream(device);
auto stream = Stream::GetDefault(device);
Event event(device);
REQUIRE(stream);
REQUIRE(event);
REQUIRE(stream.Copy(src.data(), buf_x));
REQUIRE(stream.Copy(buf_x, buf_y));
REQUIRE(stream.Copy(buf_y, dst.data()));
REQUIRE(event.Record(stream));
REQUIRE(event.Wait());
REQUIRE(src == dst);
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#include <chrono>
#include <iostream>
#include <thread>
#include "catch.hpp"
#include "mmdeploy/core/device.h"
using namespace mmdeploy;
using namespace runtime;
using namespace std::string_literals;
TEST_CASE("test opencl", "[opencl][!shouldfail]") {
using namespace mmdeploy;
Device device{"opencl"};
REQUIRE(device.platform_id() > 0);
REQUIRE(device.device_id() == 0);
std::vector src{1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f};
std::vector dst(src.size(), 0.f);
auto size_in_bytes = src.size() * sizeof(float);
Buffer buf_x(device, size_in_bytes);
Buffer buf_y(device, size_in_bytes);
REQUIRE(buf_x);
REQUIRE(buf_y);
REQUIRE(buf_x.GetSize() == size_in_bytes);
REQUIRE(buf_y.GetSize() == size_in_bytes);
SECTION("copy w/ queue API") {
// Stream stream(device);
auto stream = Stream::GetDefault(device);
Event event(device);
REQUIRE(stream);
REQUIRE(event);
REQUIRE(stream.Copy(src.data(), buf_x));
REQUIRE(stream.Copy(buf_x, buf_y));
REQUIRE(stream.Copy(buf_y, dst.data()));
REQUIRE(event.Record(stream));
REQUIRE(event.Wait());
REQUIRE(src == dst);
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#include "catch.hpp"
#include "mmdeploy/archive/json_archive.h"
#include "mmdeploy/core/graph.h"
#include "mmdeploy/core/registry.h"
#include "mmdeploy/experimental/module_adapter.h"
using namespace mmdeploy;
namespace {
class PlusCreator : public Creator<Module> {
public:
std::string_view name() const noexcept override { return "Plus"; }
std::unique_ptr<Module> Create(const Value&) override {
return CreateTask([](int a, int b) { return a + b; });
}
};
MMDEPLOY_REGISTER_CREATOR(Module, PlusCreator);
const auto json_config1 = R"(
{
"type": "Cond",
"input": ["pred", "a", "b"],
"output": "c",
"body": {
"type": "Task",
"module": "Plus"
}
}
)"_json;
} // namespace
TEST_CASE("test Cond node", "[graph]") {
auto config = from_json<Value>(json_config1);
auto builder = graph::Builder::CreateFromConfig(config).value();
REQUIRE(builder);
auto node = builder->Build().value();
REQUIRE(node);
{
auto result = SyncWait(node->Process(Just(Value({{false}, {1}, {1}}))));
MMDEPLOY_INFO("{}", result);
}
{
auto result = SyncWait(node->Process(Just(Value({{true}, {1}, {1}}))));
MMDEPLOY_INFO("{}", result);
}
{
auto result = SyncWait(
node->Process(Just(Value({{false, false, false, false}, {1, 2, 3, 4}, {1, 3, 5, 7}}))));
MMDEPLOY_INFO("{}", result);
}
{
auto result = SyncWait(
node->Process(Just(Value({{true, true, true, true}, {1, 2, 3, 4}, {1, 3, 5, 7}}))));
MMDEPLOY_INFO("{}", result);
}
{
auto result = SyncWait(
node->Process(Just(Value({{true, false, false, true}, {1, 2, 3, 4}, {1, 3, 5, 7}}))));
MMDEPLOY_INFO("{}", result);
}
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/model_impl.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test directory model", "[.model][resource]") {
std::unique_ptr<ModelImpl> model_impl;
for (auto& entry : gRegistry<ModelImpl>().Creators()) {
if (entry->name() == "DirectoryModel") {
model_impl = entry->Create();
break;
}
}
REQUIRE(model_impl);
auto& gResource = MMDeployTestResources::Get();
auto directory_model_list = gResource.LocateModelResources("sdk_models");
REQUIRE(!directory_model_list.empty());
auto model_dir = "sdk_models/good_model";
REQUIRE(gResource.IsDir(model_dir));
auto model_path = gResource.resource_root_path() / model_dir;
REQUIRE(!model_impl->Init(model_path.string()).has_error());
REQUIRE(!model_impl->ReadFile("deploy.json").has_error());
REQUIRE(model_impl->ReadFile("not-existing-file").has_error());
model_dir = "sdk_models/bad_model";
REQUIRE(gResource.IsDir(model_dir));
model_path = gResource.resource_root_path() / model_dir;
REQUIRE(!model_impl->Init(model_path.string()).has_error());
REQUIRE(model_impl->ReadMeta().has_error());
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/model_impl.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("model constructor", "[model]") {
SECTION("default constructor") {
Model model;
REQUIRE(!model);
}
SECTION("explicit constructor with model path") {
REQUIRE_THROWS(Model{"path/to/not/existing/model"});
}
SECTION("explicit constructor with buffer") { REQUIRE_THROWS(Model{nullptr, 0}); }
}
TEST_CASE("model init", "[model]") {
auto& gResource = MMDeployTestResources::Get();
for (auto& codebase : gResource.codebases()) {
if (auto img_list = gResource.LocateImageResources(fs::path{codebase} / "images");
!img_list.empty()) {
Model model;
REQUIRE(model.Init(img_list.front()).has_error());
break;
}
}
for (auto& codebase : gResource.codebases()) {
for (auto& backend : gResource.backends()) {
if (auto model_list = gResource.LocateModelResources(fs::path{codebase} / backend);
!model_list.empty()) {
Model model;
REQUIRE(!model.Init(model_list.front()).has_error());
REQUIRE(!model.ReadFile("deploy.json").has_error());
auto const& meta = model.meta();
REQUIRE(!model.GetModelConfig(meta.models[0].name).has_error());
REQUIRE(model.GetModelConfig("not-existing-model").has_error());
break;
}
}
}
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include <fstream>
#include "mmdeploy/core/logger.h"
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/model_impl.h"
#include "test_resource.h"
using namespace std;
using namespace mmdeploy;
#if MMDEPLOY_ZIP_MODEL
TEST_CASE("test zip model", "[zip_model]") {
std::unique_ptr<ModelImpl> model_impl;
for (auto& entry : ModelRegistry::Get().ListEntries()) {
if (entry.name == "ZipModel") {
model_impl = entry.creator();
break;
}
}
REQUIRE(model_impl);
auto& gResource = MMDeployTestResources::Get();
SECTION("bad sdk model") {
auto zip_model_path = fs::path{"sdk_models"} / "not_zip_file";
REQUIRE(gResource.IsFile(zip_model_path));
auto model_path = gResource.resource_root_path() / zip_model_path;
REQUIRE(model_impl->Init(model_path.string()).has_error());
}
SECTION("bad zip buffer") {
std::vector<char> buffer(100);
REQUIRE(model_impl->Init(buffer.data(), buffer.size()).has_error());
}
SECTION("good sdk model") {
auto zip_model_path = fs::path{"sdk_models"} / "good_model.zip";
REQUIRE(gResource.IsFile(zip_model_path));
auto model_path = gResource.resource_root_path() / zip_model_path;
REQUIRE(!model_impl->Init(model_path.string()).has_error());
REQUIRE(!model_impl->ReadFile("deploy.json").has_error());
REQUIRE(model_impl->ReadFile("not-exist-file").has_error());
REQUIRE(!model_impl->ReadMeta().has_error());
ifstream ifs(model_path, std::ios::binary | std::ios::in);
REQUIRE(ifs.is_open());
string buffer((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
REQUIRE(!model_impl->Init(buffer.data(), buffer.size()).has_error());
}
}
#endif
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/net.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test ncnn net", "[.ncnn_net][resource]") {
auto& gResource = MMDeployTestResources::Get();
auto model_list = gResource.LocateModelResources(fs::path{"mmcls"} / "ncnn");
REQUIRE(!model_list.empty());
Model model(model_list.front());
REQUIRE(model);
auto backend("ncnn");
auto creator = gRegistry<Net>().Get(backend);
REQUIRE(creator);
Device device{"cpu"};
auto stream = Stream::GetDefault(device);
Value net_config{{"context", {{"device", device}, {"model", model}, {"stream", stream}}},
{"name", model.meta().models[0].name}};
auto net = creator->Create(net_config);
REQUIRE(net);
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/net.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test openvino net", "[.openvino_net][resource]") {
auto& gResource = MMDeployTestResources::Get();
auto model_list = gResource.LocateModelResources(fs::path{"mmcls"} / "openvino");
REQUIRE(!model_list.empty());
Model model(model_list.front());
REQUIRE(model);
auto backend("openvino");
auto creator = gRegistry<Net>().Get(backend);
REQUIRE(creator);
Device device{"cpu"};
auto stream = Stream::GetDefault(device);
Value net_config{{"context", {{"device", device}, {"model", model}, {"stream", stream}}},
{"name", model.meta().models[0].name}};
auto net = creator->Create(net_config);
REQUIRE(net);
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/net.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test ort net", "[.ort_net][resource]") {
auto& gResource = MMDeployTestResources::Get();
auto model_list = gResource.LocateModelResources(fs::path{"mmcls"} / "ort");
REQUIRE(!model_list.empty());
Model model(model_list.front());
REQUIRE(model);
auto backend("onnxruntime");
auto creator = gRegistry<Net>().Get(backend);
REQUIRE(creator);
Device device{"cpu"};
auto stream = Stream::GetDefault(device);
Value net_config{{"context", {{"device", device}, {"model", model}, {"stream", stream}}},
{"name", model.meta().models[0].name}};
auto net = creator->Create(net_config);
REQUIRE(net);
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/net.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test pplnn net", "[.ppl_net][resource]") {
auto& gResource = MMDeployTestResources::Get();
auto model_list = gResource.LocateModelResources(fs::path{"mmcls"} / "pplnn");
REQUIRE(!model_list.empty());
Model model(model_list.front());
REQUIRE(model);
auto backend = "pplnn";
auto creator = gRegistry<Net>().Get(backend);
REQUIRE(creator);
Device device{"cpu"};
auto stream = Stream::GetDefault(device);
// clang-format off
Value net_config{
{"context", {
{"device", device},
{"model", model},
{"stream", stream}
}
},
{"name", model.meta().models[0].name}
};
}
// Copyright (c) OpenMMLab. All rights reserved.
// clang-format off
#include "catch.hpp"
// clang-format on
#include "mmdeploy/core/model.h"
#include "mmdeploy/core/net.h"
#include "test_resource.h"
using namespace mmdeploy;
using namespace framework;
TEST_CASE("test trt net", "[.trt_net][resource]") {
auto& gResource = MMDeployTestResources::Get();
auto model_list = gResource.LocateModelResources(fs::path{"mmcls"} / "trt");
REQUIRE(!model_list.empty());
Model model(model_list.front());
REQUIRE(model);
auto backend("tensorrt");
auto creator = gRegistry<Net>().Get(backend);
REQUIRE(creator);
Device device{"cuda"};
auto stream = Stream::GetDefault(device);
Value net_config{{"context", {{"device", device}, {"model", model}, {"stream", stream}}},
{"name", model.meta().models[0].name}};
auto net = creator->Create(net_config);
REQUIRE(net);
}
// Copyright (c) OpenMMLab. All rights reserved.
#include "catch.hpp"
#include "mmdeploy/core/tensor.h"
#include "mmdeploy/preprocess/transform/transform.h"
using namespace mmdeploy;
using namespace std;
TEST_CASE("test collect constructor", "[collect]") {
Device device{"cpu"};
Stream stream{device};
Value cfg = {{"context", {{"device", device}, {"stream", stream}}}};
std::string transform_type{"Collect"};
auto creator = gRegistry<Transform>().Get(transform_type);
REQUIRE(creator != nullptr);
REQUIRE_THROWS(creator->Create(cfg));
SECTION("args with 'keys' which is not an array") {
auto _cfg = cfg;
_cfg["keys"] = "img";
REQUIRE_THROWS(creator->Create(_cfg));
}
SECTION("args with keys in array") {
auto _cfg = cfg;
_cfg["keys"] = {"img"};
auto module = creator->Create(_cfg);
REQUIRE(module != nullptr);
}
SECTION("args with meta_keys that is not an array") {
auto _cfg = cfg;
_cfg["keys"] = {"img"};
_cfg["meta_keys"] = "ori_img";
REQUIRE_THROWS(creator->Create(_cfg));
}
SECTION("args with meta_keys in array") {
auto _cfg = cfg;
_cfg["keys"] = {"img"};
_cfg["meta_keys"] = {"ori_img"};
auto module = creator->Create(_cfg);
REQUIRE(module != nullptr);
}
}
TEST_CASE("test collect", "[collect]") {
std::string transform_type{"Collect"};
vector<std::string> keys{"img"};
vector<std::string> meta_keys{"filename", "ori_filename", "ori_shape", "img_shape",
"flip", "flip_direction", "img_norm_cfg"};
Value args;
Device device{"cpu"};
Stream stream{device};
args["context"]["device"] = device;
args["context"]["stream"] = stream;
for (auto& key : keys) {
args["keys"].push_back(key);
}
for (auto& meta_key : meta_keys) {
args["meta_keys"].push_back(meta_key);
}
auto creator = gRegistry<Transform>().Get(transform_type);
REQUIRE(creator != nullptr);
auto module = creator->Create(args);
REQUIRE(module != nullptr);
Value input;
SECTION("input is empty") {
auto ret = module->Apply(input);
REQUIRE(ret.has_error());
REQUIRE(ret.error() == eInvalidArgument);
}
SECTION("input has 'ori_img' and 'attribute'") {
input["ori_img"] = Tensor{};
input["attribute"] = "this is a faked image";
auto ret = module->Apply(input);
REQUIRE(ret.has_error());
REQUIRE(ret.error() == eInvalidArgument);
}
SECTION("array input with correct keys and meta keys") {
Tensor tensor;
Value input{{"img", tensor},
{"filename", "test.jpg"},
{"ori_filename", "/the/path/of/test.jpg"},
{"ori_shape", {1000, 1000, 3}},
{"img_shape", {1, 3, 224, 224}},
{"flip", "false"},
{"flip_direction", "horizontal"},
{"img_norm_cfg",
{{"mean", {123.675, 116.28, 103.53}},
{"std", {58.395, 57.12, 57.375}},
{"to_rgb", true}}}};
auto ret = module->Apply(input);
REQUIRE(ret.has_value());
}
}
// Copyright (c) OpenMMLab. All rights reserved.
#include <fstream>
// clang-format off
#include "catch.hpp"
// clang-format on
#include "json.hpp"
#include "mmdeploy/archive/json_archive.h"
#include "mmdeploy/core/mat.h"
#include "mmdeploy/core/registry.h"
#include "mmdeploy/core/utils/formatter.h"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv_utils.h"
#include "test_resource.h"
#include "test_utils.h"
using namespace mmdeploy;
using namespace framework;
using namespace mmdeploy::test;
using namespace std;
using nlohmann::json;
static constexpr const char *gPipelineConfig = R"(
[{
"type": "LoadImageFromFile"
},
{
"type": "Resize",
"size": [
256, -1
]
},
{
"type": "CenterCrop",
"crop_size": 224
},
{
"type": "Normalize",
"mean": [
123.675,
116.28,
103.53
],
"std": [
58.395,
57.12,
57.375
],
"to_rgb": true
},
{
"type": "ImageToTensor",
"keys": [
"img"
]
},
{
"type": "Collect",
"keys": [
"img"
]
}
]
)";
TEST_CASE("transform Compose exceptional case", "[compose]") {
Value compose_cfg;
SECTION("wrong transform type") {
compose_cfg = {{"type", "Compose"}, {"transforms", {{{"type", "collect"}}}}};
}
SECTION("wrong transform parameter") {
compose_cfg = {{"type", "Compose"}, {"transforms", {{{"type", "Collect"}}}}};
}
const Device kHost{"cpu"};
Stream stream{kHost};
REQUIRE(CreateTransform(compose_cfg, kHost, stream) == nullptr);
}
TEST_CASE("transform Compose", "[compose]") {
auto gResource = MMDeployTestResources::Get();
auto img_list = gResource.LocateImageResources("transform");
REQUIRE(!img_list.empty());
auto img_path = img_list.front();
cv::Mat bgr_mat = cv::imread(img_path, cv::IMREAD_COLOR);
auto src_mat = cpu::CVMat2Mat(bgr_mat, PixelFormat::kBGR);
Value input{{"ori_img", src_mat}};
auto json = json::parse(gPipelineConfig);
auto cfg = ::mmdeploy::from_json<Value>(json);
Value compose_cfg{{"type", "Compose"}, {"transforms", cfg}};
const Device kHost{"cpu"};
Stream stream{kHost};
auto transform = CreateTransform(compose_cfg, kHost, stream);
REQUIRE(transform != nullptr);
auto res = transform->Process({{"ori_img", src_mat}});
REQUIRE(!res.has_error());
}
// Copyright (c) OpenMMLab. All rights reserved.
#include "catch.hpp"
#include "mmdeploy/core/mat.h"
#include "mmdeploy/core/utils/device_utils.h"
#include "mmdeploy/preprocess/transform/transform.h"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv_utils.h"
#include "test_resource.h"
#include "test_utils.h"
using namespace mmdeploy;
using namespace framework;
using namespace std;
using namespace mmdeploy::test;
tuple<int, int, int, int> CenterCropArea(const cv::Mat& mat, int crop_height, int crop_width) {
auto img_height = mat.rows;
auto img_width = mat.cols;
auto y1 = max(0, int(round((img_height - crop_height) / 2.)));
auto x1 = max(0, int(round((img_width - crop_width) / 2.)));
auto y2 = min(img_height, y1 + crop_height) - 1;
auto x2 = min(img_width, x1 + crop_width) - 1;
return {y1, x1, y2, x2};
}
void TestCenterCrop(const Value& cfg, const cv::Mat& mat, int crop_height, int crop_width) {
auto gResource = MMDeployTestResources::Get();
for (auto const& device_name : gResource.device_names()) {
Device device{device_name.c_str()};
Stream stream{device};
auto transform = CreateTransform(cfg, device, stream);
REQUIRE(transform != nullptr);
auto [top, left, bottom, right] = CenterCropArea(mat, crop_height, crop_width);
auto ref_mat = mmdeploy::cpu::Crop(mat, top, left, bottom, right);
auto res = transform->Process({{"img", cpu::CVMat2Tensor(mat)}});
REQUIRE(!res.has_error());
auto res_tensor = res.value()["img"].get<Tensor>();
REQUIRE(res_tensor.device() == device);
REQUIRE(Shape(res.value(), "img_shape") ==
vector<int64_t>{1, ref_mat.rows, ref_mat.cols, ref_mat.channels()});
const Device kHost{"cpu"};
auto host_tensor = MakeAvailableOnDevice(res_tensor, kHost, stream);
REQUIRE(stream.Wait());
auto res_mat = mmdeploy::cpu::Tensor2CVMat(host_tensor.value());
REQUIRE(mmdeploy::cpu::Compare(ref_mat, res_mat));
}
}
TEST_CASE("transform CenterCrop", "[crop]") {
auto gResource = MMDeployTestResources::Get();
auto img_list = gResource.LocateImageResources("transform");
REQUIRE(!img_list.empty());
auto img_path = img_list.front();
cv::Mat bgr_mat = cv::imread(img_path, cv::IMREAD_COLOR);
cv::Mat gray_mat = cv::imread(img_path, cv::IMREAD_GRAYSCALE);
cv::Mat bgr_float_mat;
cv::Mat gray_float_mat;
bgr_mat.convertTo(bgr_float_mat, CV_32FC3);
gray_mat.convertTo(gray_float_mat, CV_32FC1);
vector<cv::Mat> mats{bgr_mat, gray_mat, bgr_float_mat, gray_float_mat};
SECTION("crop_size: int; small size") {
constexpr int crop_size = 224;
Value cfg{{"type", "CenterCrop"}, {"crop_size", crop_size}};
for (auto& mat : mats) {
TestCenterCrop(cfg, mat, crop_size, crop_size);
}
}
SECTION("crop_size: int; oversize") {
constexpr int crop_size = 800;
Value cfg{{"type", "CenterCrop"}, {"crop_size", crop_size}};
for (auto& mat : mats) {
TestCenterCrop(cfg, mat, crop_size, crop_size);
}
}
SECTION("crop_size: tuple") {
constexpr int crop_height = 224;
constexpr int crop_width = 224;
Value cfg{{"type", "CenterCrop"}, {"crop_size", {crop_height, crop_width}}};
for (auto& mat : mats) {
TestCenterCrop(cfg, mat, crop_height, crop_width);
}
}
SECTION("crop_size: tuple;oversize in height") {
constexpr int crop_height = 640;
constexpr int crop_width = 224;
Value cfg{{"type", "CenterCrop"}, {"crop_size", {crop_height, crop_width}}};
for (auto& mat : mats) {
TestCenterCrop(cfg, mat, crop_height, crop_width);
}
}
SECTION("crop_size: tuple;oversize in width") {
constexpr int crop_height = 224;
constexpr int crop_width = 800;
Value cfg{{"type", "CenterCrop"}, {"crop_size", {crop_height, crop_width}}};
for (auto& mat : mats) {
TestCenterCrop(cfg, mat, crop_height, crop_width);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment