Skip to content

Commit

Permalink
Add support for 0..n args in native module callbacks (#4929)
Browse files Browse the repository at this point in the history
* Support 0..n args in native module callbacks

* Change files
  • Loading branch information
vmoroz authored and NickGerleman committed May 19, 2020
1 parent 8d0d5de commit 4b2d451
Show file tree
Hide file tree
Showing 12 changed files with 1,162 additions and 292 deletions.
@@ -0,0 +1,8 @@
{
"type": "prerelease",
"comment": "Support 0..n args in native module callbacks",
"packageName": "react-native-windows",
"email": "vmorozov@microsoft.com",
"dependentChangeType": "patch",
"date": "2020-05-17T16:26:39.781Z"
}
139 changes: 139 additions & 0 deletions vnext/Microsoft.ReactNative.Cxx.UnitTests/NativeModuleTest.cpp
Expand Up @@ -152,6 +152,21 @@ struct SimpleNativeModule {
resolve("Static Hello_2");
}

REACT_METHOD(CallbackZeroArgs)
void CallbackZeroArgs(std::function<void()> const &resolve) noexcept {
resolve();
}

REACT_METHOD(CallbackTwoArgs)
void CallbackTwoArgs(std::function<void(int, int)> const &resolve) noexcept {
resolve(1, 2);
}

REACT_METHOD(CallbackThreeArgs)
void CallbackThreeArgs(std::function<void(int, int, std::string const &)> const &resolve) noexcept {
resolve(1, 2, "Hello");
}

REACT_METHOD(DivideCallbacks)
void DivideCallbacks(
int x,
Expand Down Expand Up @@ -312,6 +327,44 @@ struct SimpleNativeModule {
reject("Goodbye");
}

REACT_METHOD(TwoCallbacksZeroArgs1)
void TwoCallbacksZeroArgs1(std::function<void()> const &resolve, std::function<void()> const & /*reject*/) noexcept {
resolve();
}

REACT_METHOD(TwoCallbacksZeroArgs2)
void TwoCallbacksZeroArgs2(std::function<void()> const & /*resolve*/, std::function<void()> const &reject) noexcept {
reject();
}

REACT_METHOD(TwoCallbacksTwoArgs1)
void TwoCallbacksTwoArgs1(
std::function<void(int, int)> const &resolve,
std::function<void(int, int)> const & /*reject*/) noexcept {
resolve(1, 2);
}

REACT_METHOD(TwoCallbacksTwoArgs2)
void TwoCallbacksTwoArgs2(
std::function<void(int, int)> const & /*resolve*/,
std::function<void(int, int)> const &reject) noexcept {
reject(1, 2);
}

REACT_METHOD(TwoCallbacksThreeArgs1)
void TwoCallbacksThreeArgs1(
std::function<void(int, int, std::string const &)> const &resolve,
std::function<void(int, int, std::string const &)> const & /*reject*/) noexcept {
resolve(1, 2, "Hello");
}

REACT_METHOD(TwoCallbacksThreeArgs2)
void TwoCallbacksThreeArgs2(
std::function<void(int, int, std::string const &)> const & /*resolve*/,
std::function<void(int, int, std::string const &)> const &reject) noexcept {
reject(1, 2, "Hello");
}

REACT_METHOD(DividePromise)
void DividePromise(int x, int y, React::ReactPromise<int> const &result) noexcept {
if (y != 0) {
Expand Down Expand Up @@ -746,6 +799,30 @@ TEST_CLASS (NativeModuleTest) {
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackZeroArgs) {
m_builderMock.Call1(L"CallbackZeroArgs", std::function<void()>([]() noexcept {}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackTwoArgs) {
m_builderMock.Call1(L"CallbackTwoArgs", std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackThreeArgs) {
m_builderMock.Call1(
L"CallbackThreeArgs",
std::function<void(int, int, std::string const &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_DivideCallbacks) {
m_builderMock.Call2(
L"DivideCallbacks",
Expand Down Expand Up @@ -990,6 +1067,68 @@ TEST_CLASS (NativeModuleTest) {
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs1) {
m_builderMock.Call2(L"TwoCallbacksZeroArgs1", std::function<void()>([]() noexcept {}), std::function<void()>([
]() noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs2) {
m_builderMock.Call2(
L"TwoCallbacksZeroArgs2",
std::function<void()>([]() noexcept { TestCheckFail(); }),
std::function<void()>([]() noexcept {}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs1) {
m_builderMock.Call2(
L"TwoCallbacksTwoArgs1",
std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}),
std::function<void(int, int)>([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs2) {
m_builderMock.Call2(
L"TwoCallbacksTwoArgs2",
std::function<void(int, int)>([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }),
std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs1) {
m_builderMock.Call2(
L"TwoCallbacksThreeArgs1",
std::function<void(int, int, const std::string &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}),
std::function<void(int, int, const std::string &)>(
[](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs2) {
m_builderMock.Call2(
L"TwoCallbacksThreeArgs2",
std::function<void(int, int, const std::string &)>(
[](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }),
std::function<void(int, int, const std::string &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_DividePromise) {
m_builderMock.Call2(
L"DividePromise",
Expand Down
Expand Up @@ -135,6 +135,18 @@ struct SimpleNativeModule2 {
resolve("Static Hello_2");
}

void CallbackZeroArgs(std::function<void()> const &resolve) noexcept {
resolve();
}

void CallbackTwoArgs(std::function<void(int, int)> const &resolve) noexcept {
resolve(1, 2);
}

void CallbackThreeArgs(std::function<void(int, int, std::string const &)> const &resolve) noexcept {
resolve(1, 2, "Hello");
}

void DivideCallbacks(
int x,
int y,
Expand Down Expand Up @@ -281,6 +293,38 @@ struct SimpleNativeModule2 {
reject("Goodbye");
}

void TwoCallbacksZeroArgs1(std::function<void()> const &resolve, std::function<void()> const & /*reject*/) noexcept {
resolve();
}

void TwoCallbacksZeroArgs2(std::function<void()> const & /*resolve*/, std::function<void()> const &reject) noexcept {
reject();
}

void TwoCallbacksTwoArgs1(
std::function<void(int, int)> const &resolve,
std::function<void(int, int)> const & /*reject*/) noexcept {
resolve(1, 2);
}

void TwoCallbacksTwoArgs2(
std::function<void(int, int)> const & /*resolve*/,
std::function<void(int, int)> const &reject) noexcept {
reject(1, 2);
}

void TwoCallbacksThreeArgs1(
std::function<void(int, int, std::string const &)> const &resolve,
std::function<void(int, int, std::string const &)> const & /*reject*/) noexcept {
resolve(1, 2, "Hello");
}

void TwoCallbacksThreeArgs2(
std::function<void(int, int, std::string const &)> const & /*resolve*/,
std::function<void(int, int, std::string const &)> const &reject) noexcept {
reject(1, 2, "Hello");
}

void DividePromise(int x, int y, React::ReactPromise<int> const &result) noexcept {
if (y != 0) {
result.Resolve(x / y);
Expand Down Expand Up @@ -535,6 +579,9 @@ void GetReactModuleInfo(SimpleNativeModule2 *, React::ReactModuleBuilder<SimpleN
&SimpleNativeModule2::StaticNegateDispatchQueueCallback, L"StaticNegateDispatchQueueCallback");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::StaticNegateFutureCallback, L"StaticNegateFutureCallback");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::StaticSayHelloCallback, L"StaticSayHelloCallback");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::CallbackZeroArgs, L"CallbackZeroArgs");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::CallbackTwoArgs, L"CallbackTwoArgs");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::CallbackThreeArgs, L"CallbackThreeArgs");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::DivideCallbacks, L"DivideCallbacks");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::NegateCallbacks, L"NegateCallbacks");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::NegateAsyncCallbacks, L"NegateAsyncCallbacks");
Expand All @@ -550,6 +597,12 @@ void GetReactModuleInfo(SimpleNativeModule2 *, React::ReactModuleBuilder<SimpleN
moduleBuilder.RegisterMethod(&SimpleNativeModule2::StaticNegateFutureCallbacks, L"StaticNegateFutureCallbacks");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::StaticResolveSayHelloCallbacks, L"StaticResolveSayHelloCallbacks");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::StaticRejectSayHelloCallbacks, L"StaticRejectSayHelloCallbacks");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksZeroArgs1, L"TwoCallbacksZeroArgs1");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksZeroArgs2, L"TwoCallbacksZeroArgs2");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksTwoArgs1, L"TwoCallbacksTwoArgs1");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksTwoArgs2, L"TwoCallbacksTwoArgs2");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksThreeArgs1, L"TwoCallbacksThreeArgs1");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::TwoCallbacksThreeArgs2, L"TwoCallbacksThreeArgs2");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::DividePromise, L"DividePromise");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::NegatePromise, L"NegatePromise");
moduleBuilder.RegisterMethod(&SimpleNativeModule2::NegateAsyncPromise, L"NegateAsyncPromise");
Expand Down Expand Up @@ -753,6 +806,30 @@ TEST_CLASS (NoAttributeNativeModuleTest) {
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackZeroArgs) {
m_builderMock.Call1(L"CallbackZeroArgs", std::function<void()>([]() noexcept {}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackTwoArgs) {
m_builderMock.Call1(L"CallbackTwoArgs", std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_CallbackThreeArgs) {
m_builderMock.Call1(
L"CallbackThreeArgs",
std::function<void(int, int, std::string const &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_DivideCallbacks) {
m_builderMock.Call2(
L"DivideCallbacks",
Expand Down Expand Up @@ -997,6 +1074,68 @@ TEST_CLASS (NoAttributeNativeModuleTest) {
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs1) {
m_builderMock.Call2(L"TwoCallbacksZeroArgs1", std::function<void()>([]() noexcept {}), std::function<void()>([
]() noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksZeroArgs2) {
m_builderMock.Call2(
L"TwoCallbacksZeroArgs2",
std::function<void()>([]() noexcept { TestCheckFail(); }),
std::function<void()>([]() noexcept {}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs1) {
m_builderMock.Call2(
L"TwoCallbacksTwoArgs1",
std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}),
std::function<void(int, int)>([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksTwoArgs2) {
m_builderMock.Call2(
L"TwoCallbacksTwoArgs2",
std::function<void(int, int)>([](int /*p1*/, int /*p2*/) noexcept { TestCheckFail(); }),
std::function<void(int, int)>([](int p1, int p2) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs1) {
m_builderMock.Call2(
L"TwoCallbacksThreeArgs1",
std::function<void(int, int, const std::string &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}),
std::function<void(int, int, const std::string &)>(
[](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }));
TestCheck(m_builderMock.IsResolveCallbackCalled());
}

TEST_METHOD(TestMethodCall_TwoCallbacksThreeArgs2) {
m_builderMock.Call2(
L"TwoCallbacksThreeArgs2",
std::function<void(int, int, const std::string &)>(
[](int /*p1*/, int /*p2*/, std::string const & /*p3*/) noexcept { TestCheckFail(); }),
std::function<void(int, int, const std::string &)>([](int p1, int p2, std::string const &p3) noexcept {
TestCheckEqual(1, p1);
TestCheckEqual(2, p2);
TestCheckEqual("Hello", p3);
}));
TestCheck(m_builderMock.IsRejectCallbackCalled());
}

TEST_METHOD(TestMethodCall_DividePromise) {
m_builderMock.Call2(
L"DividePromise",
Expand Down

0 comments on commit 4b2d451

Please sign in to comment.