blob: 25d2c3d069c39a58dff36bea8642fa3bfb57d6ab [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fidl/test/compatibility/cpp/fidl.h>
#include <fidl/test/imported/cpp/fidl.h>
#include <gtest/gtest.h>
#include <src/lib/fxl/test/test_settings.h>
#include <src/tests/fidl/compatibility/helpers.h>
#include <src/tests/fidl/compatibility/hlcpp_client_app.h>
using fidl::test::compatibility::AllTypesXunion;
using fidl::test::compatibility::Echo_EchoXunionsWithError_Result;
using fidl::test::compatibility::RespondWith;
using fidl::test::compatibility::this_is_a_struct;
using fidl::test::compatibility::this_is_a_table;
using fidl::test::compatibility::this_is_a_union;
using fidl::test::compatibility::this_is_a_xunion;
using fidl_test_compatibility_helpers::DataGenerator;
using fidl_test_compatibility_helpers::ExtractShortName;
using fidl_test_compatibility_helpers::ForAllImpls;
using fidl_test_compatibility_helpers::ForSomeImpls;
using fidl_test_compatibility_helpers::GetImplsUnderTest;
using fidl_test_compatibility_helpers::HandlesEq;
using fidl_test_compatibility_helpers::Impls;
using fidl_test_compatibility_helpers::kArbitraryVectorSize;
using fidl_test_compatibility_helpers::PrintSummary;
using fidl_test_compatibility_helpers::Summary;
namespace {
void InitializeAllTypesXunions(std::vector<AllTypesXunion>* value, DataGenerator& gen) {
for (size_t i = 1; true; i++) {
AllTypesXunion xu{};
switch (i) {
case 1:
xu.set_bool_member(gen.next<bool>());
break;
case 2:
xu.set_int8_member(gen.next<int8_t>());
break;
case 3:
xu.set_int16_member(gen.next<int16_t>());
break;
case 4:
xu.set_int32_member(gen.next<int32_t>());
break;
case 5:
xu.set_int64_member(gen.next<int64_t>());
break;
case 6:
xu.set_uint8_member(gen.next<uint8_t>());
break;
case 7:
xu.set_uint16_member(gen.next<uint16_t>());
break;
case 8:
xu.set_uint32_member(gen.next<uint32_t>());
break;
case 9:
xu.set_uint64_member(gen.next<uint64_t>());
break;
case 10:
xu.set_float32_member(gen.next<float>());
break;
case 11:
xu.set_float64_member(gen.next<double>());
break;
case 12:
xu.set_enum_member(gen.choose(fidl::test::compatibility::default_enum::kOne,
fidl::test::compatibility::default_enum::kZero));
break;
case 13:
xu.set_bits_member(gen.choose(fidl::test::compatibility::default_bits::kOne,
fidl::test::compatibility::default_bits::kTwo));
break;
case 14:
xu.set_handle_member(gen.next<zx::handle>());
break;
case 15:
xu.set_string_member(gen.next<std::string>());
break;
case 16:
xu.set_struct_member(gen.next<this_is_a_struct>());
break;
case 17:
xu.set_union_member(gen.next<this_is_a_union>());
break;
default:
EXPECT_EQ(i, 18UL);
return;
}
value->push_back(std::move(xu));
}
}
void ExpectAllTypesXunionsEq(const std::vector<AllTypesXunion>& a,
const std::vector<AllTypesXunion>& b) {
EXPECT_EQ(a.size(), b.size());
for (size_t i = 0; i < a.size(); i++) {
if (a[i].is_handle_member()) {
EXPECT_TRUE(b[i].is_handle_member());
EXPECT_TRUE(HandlesEq(a[i].handle_member(), b[i].handle_member()));
} else {
EXPECT_TRUE(fidl::Equals(a[i], b[i]));
}
}
}
class CompatibilityTest : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
protected:
void SetUp() override {
proxy_url_ = ::testing::get<0>(GetParam());
server_url_ = ::testing::get<1>(GetParam());
// The FIDL support lib requires async_get_default_dispatcher() to return
// non-null.
loop_.reset(new async::Loop(&kAsyncLoopConfigAttachToCurrentThread));
}
std::string proxy_url_;
std::string server_url_;
std::unique_ptr<async::Loop> loop_;
};
Impls impls;
Summary summary;
TEST(Union, EchoUnions) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (xunion)"] =
false;
// Using randomness to avoid having to come up with varied values by
// hand. Seed deterministically so that this function's outputs are
// predictable.
DataGenerator generator(0x1234);
std::vector<AllTypesXunion> sent;
InitializeAllTypesXunions(&sent, generator);
std::vector<AllTypesXunion> sent_clone;
fidl::Clone(sent, &sent_clone);
std::vector<AllTypesXunion> resp_clone;
bool called_back = false;
proxy->EchoXunions(std::move(sent), server_url,
[&loop, &resp_clone, &called_back](std::vector<AllTypesXunion> resp) {
ASSERT_EQ(ZX_OK, fidl::Clone(resp, &resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
ExpectAllTypesXunionsEq(sent_clone, resp_clone);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (xunion)"] =
true;
});
}
TEST(Union, EchoUnionsWithErrorSuccessCase) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (xunion result success)"] = false;
// Using randomness to avoid having to come up with varied values by
// hand. Seed deterministically so that this function's outputs are
// predictable.
DataGenerator generator(0x1234);
std::vector<AllTypesXunion> sent;
InitializeAllTypesXunions(&sent, generator);
auto err = fidl::test::compatibility::default_enum::kOne;
std::vector<AllTypesXunion> sent_clone;
fidl::Clone(sent, &sent_clone);
std::vector<AllTypesXunion> resp_clone;
bool called_back = false;
proxy->EchoXunionsWithError(
std::move(sent), err, server_url, RespondWith::SUCCESS,
[&loop, &resp_clone, &called_back](Echo_EchoXunionsWithError_Result resp) {
ASSERT_TRUE(resp.is_response());
ASSERT_EQ(ZX_OK, fidl::Clone(resp.response().value, &resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
ExpectAllTypesXunionsEq(sent_clone, resp_clone);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (xunion result success)"] = true;
});
}
TEST(Union, EchoUnionsWithErrorErrorCase) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (xunion result error)"] = false;
// Using randomness to avoid having to come up with varied values by
// hand. Seed deterministically so that this function's outputs are
// predictable.
DataGenerator generator(0xF1D7);
std::vector<AllTypesXunion> sent;
InitializeAllTypesXunions(&sent, generator);
auto err = fidl::test::compatibility::default_enum::kOne;
bool called_back = false;
proxy->EchoXunionsWithError(std::move(sent), err, server_url, RespondWith::ERR,
[&loop, &err, &called_back](Echo_EchoXunionsWithError_Result resp) {
ASSERT_TRUE(resp.is_err());
ASSERT_EQ(err, resp.err());
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (xunion result error)"] = true;
});
}
TEST(Union, EchoUnionPayload) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
false;
fidl::test::compatibility::RequestUnion sent;
sent.set_signed_({.value = -123, .forward_to_server = server_url});
fidl::test::compatibility::RequestUnion sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseUnion resp_clone;
bool called_back = false;
proxy->EchoUnionPayload(std::move(sent), [&loop, &resp_clone, &called_back](
fidl::test::compatibility::ResponseUnion resp) {
ASSERT_EQ(ZX_OK, resp.Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
EXPECT_EQ(sent_clone.is_signed_(), resp_clone.is_signed_());
EXPECT_EQ(sent_clone.signed_().value, resp_clone.signed_());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
true;
});
}
TEST(Union, EchoUnionPayloadWithErrorSuccessCase) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (union result success)"] = false;
fidl::test::compatibility::UnsignedErrorable unsigned_errorable;
unsigned_errorable.forward_to_server = server_url;
unsigned_errorable.value = 42u;
unsigned_errorable.result_variant = fidl::test::compatibility::RespondWith::SUCCESS;
auto sent = fidl::test::compatibility::EchoEchoUnionPayloadWithErrorRequest::WithUnsigned_(
std::move(unsigned_errorable));
fidl::test::compatibility::EchoEchoUnionPayloadWithErrorRequest sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseUnion resp_clone;
bool called_back = false;
proxy->EchoUnionPayloadWithError(
std::move(sent),
[&loop, &resp_clone,
&called_back](fidl::test::compatibility::Echo_EchoUnionPayloadWithError_Result resp) {
ASSERT_TRUE(resp.is_response());
ASSERT_EQ(ZX_OK, resp.response().Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
EXPECT_EQ(sent_clone.is_unsigned_(), resp_clone.is_unsigned_());
EXPECT_EQ(sent_clone.unsigned_().value, resp_clone.unsigned_());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (union result success)"] = true;
});
}
TEST(Union, EchoUnionPayloadWithErrorErrorCase) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (union result success)"] = false;
fidl::test::compatibility::SignedErrorable signed_errorable;
auto err = fidl::test::compatibility::default_enum::kOne;
signed_errorable.forward_to_server = server_url;
signed_errorable.result_err = err;
signed_errorable.result_variant = fidl::test::compatibility::RespondWith::ERR;
auto sent = fidl::test::compatibility::EchoEchoUnionPayloadWithErrorRequest::WithSigned_(
std::move(signed_errorable));
fidl::test::compatibility::EchoEchoUnionPayloadWithErrorRequest sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseUnion resp_clone;
bool called_back = false;
proxy->EchoUnionPayloadWithError(
std::move(sent),
[&loop, &err,
&called_back](fidl::test::compatibility::Echo_EchoUnionPayloadWithError_Result resp) {
ASSERT_TRUE(resp.is_err());
ASSERT_EQ(err, resp.err());
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (union result success)"] = true;
});
}
TEST(Union, EchoUnionPayloadNoRetval) {
ForAllImpls(impls, [](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
false;
fidl::test::compatibility::RequestUnion sent;
sent.set_unsigned_({.value = 42u, .forward_to_server = server_url});
fidl::test::compatibility::RequestUnion sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseUnion resp_clone;
bool event_received = false;
proxy.events().OnEchoUnionPayloadEvent =
[&loop, &resp_clone, &event_received](fidl::test::compatibility::ResponseUnion resp) {
resp.Clone(&resp_clone);
event_received = true;
loop.Quit();
};
proxy->EchoUnionPayloadNoRetVal(std::move(sent));
loop.Run();
ASSERT_TRUE(event_received);
EXPECT_EQ(sent_clone.is_unsigned_(), resp_clone.is_unsigned_());
EXPECT_EQ(sent_clone.unsigned_().value, resp_clone.unsigned_());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
true;
});
}
// TODO(https://fxbug.dev/42176858): This is an N+M case, where we only want to test each bindings
// client/server once, rather than in combination with ever other binding. Move this test case to a
// more appropriate file with other such N+M cases, once it exists.
TEST(Union, EchoUnionResponseWithErrorComposedSuccessCase) {
const auto filter = [](const std::string& proxy_url, const std::string& server_url) -> bool {
return proxy_url == server_url;
};
ForSomeImpls(
impls, filter,
[](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
false;
int64_t value = -42;
bool want_absolute_value = true;
const uint32_t err = 13;
::fidl::test::imported::Composed_EchoUnionResponseWithErrorComposed_Response resp_clone;
bool called_back = false;
proxy->EchoUnionResponseWithErrorComposed(
value, want_absolute_value, server_url, err,
fidl::test::imported::WantResponse::SUCCESS,
[&loop, &resp_clone, &called_back](
fidl::test::imported::Composed_EchoUnionResponseWithErrorComposed_Result resp) {
ASSERT_TRUE(resp.is_response());
ASSERT_EQ(ZX_OK, resp.response().Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
ASSERT_EQ(want_absolute_value, resp_clone.is_unsigned_());
EXPECT_EQ((uint64_t)std::abs(value), resp_clone.unsigned_());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
true;
});
}
// TODO(https://fxbug.dev/42176858): This is an N+M case, where we only want to test each bindings
// client/server once, rather than in combination with ever other binding. Move this test case to a
// more appropriate file with other such N+M cases, once it exists.
TEST(Union, EchoUnionResponseWithErrorComposedErrorCase) {
const auto filter = [](const std::string& proxy_url, const std::string& server_url) -> bool {
return proxy_url == server_url;
};
ForSomeImpls(
impls, filter,
[](async::Loop& loop, fidl::test::compatibility::EchoPtr& proxy,
const std::string& server_url, const std::string& proxy_url) {
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
false;
int64_t value = -42;
bool want_absolute_value = true;
const uint32_t err = 13;
bool called_back = false;
proxy->EchoUnionResponseWithErrorComposed(
value, want_absolute_value, server_url, err, fidl::test::imported::WantResponse::ERR,
[&loop, &err, &called_back](
fidl::test::imported::Composed_EchoUnionResponseWithErrorComposed_Result resp) {
ASSERT_TRUE(resp.is_err());
ASSERT_EQ(err, resp.err());
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (union)"] =
true;
});
}
} // namespace
int main(int argc, char** argv) {
if (!fxl::SetTestSettings(argc, argv)) {
return EXIT_FAILURE;
}
testing::InitGoogleTest(&argc, argv);
assert(GetImplsUnderTest(&impls));
int r = RUN_ALL_TESTS();
PrintSummary(summary);
return r;
}