blob: bcde111de6eef35f70924db049c7003ab159f829 [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::AllTypesTable;
using fidl::test::compatibility::Echo_EchoTableWithError_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 InitializeAllTypesTable(AllTypesTable* value, DataGenerator& gen) {
value->set_bool_member(gen.next<bool>());
value->set_int8_member(gen.next<int8_t>());
value->set_int16_member(gen.next<int16_t>());
value->set_int32_member(gen.next<int32_t>());
value->set_int64_member(gen.next<int64_t>());
value->set_uint8_member(gen.next<uint8_t>());
value->set_uint16_member(gen.next<uint16_t>());
value->set_uint32_member(gen.next<uint32_t>());
value->set_uint64_member(gen.next<uint64_t>());
value->set_float32_member(gen.next<float>());
value->set_float64_member(gen.next<double>());
value->set_enum_member(gen.choose(fidl::test::compatibility::default_enum::kOne,
fidl::test::compatibility::default_enum::kZero));
value->set_bits_member(gen.choose(fidl::test::compatibility::default_bits::kOne,
fidl::test::compatibility::default_bits::kTwo));
value->set_handle_member(gen.next<zx::handle>());
value->set_string_member(gen.next<std::string>());
value->set_struct_member(gen.next<this_is_a_struct>());
value->set_union_member(gen.next<this_is_a_union>());
std::array<uint32_t, fidl::test::compatibility::arrays_size> array;
for (size_t i = 0; i < array.size(); i++) {
array[i] = gen.next<uint32_t>();
}
value->set_array_member(array);
std::vector<uint32_t> vector;
for (size_t i = 0; i < kArbitraryVectorSize; i++) {
vector.push_back(gen.next<uint32_t>());
}
value->set_vector_member(vector);
value->set_table_member(gen.next<this_is_a_table>());
value->set_xunion_member(gen.next<this_is_a_xunion>());
}
void ExpectAllTypesTableEq(const AllTypesTable& a, const AllTypesTable& b) {
EXPECT_TRUE(fidl::Equals(a.bool_member(), b.bool_member()));
EXPECT_TRUE(fidl::Equals(a.int8_member(), b.int8_member()));
EXPECT_TRUE(fidl::Equals(a.int16_member(), b.int16_member()));
EXPECT_TRUE(fidl::Equals(a.int32_member(), b.int32_member()));
EXPECT_TRUE(fidl::Equals(a.int64_member(), b.int64_member()));
EXPECT_TRUE(fidl::Equals(a.uint8_member(), b.uint8_member()));
EXPECT_TRUE(fidl::Equals(a.uint16_member(), b.uint16_member()));
EXPECT_TRUE(fidl::Equals(a.uint32_member(), b.uint32_member()));
EXPECT_TRUE(fidl::Equals(a.uint64_member(), b.uint64_member()));
EXPECT_TRUE(fidl::Equals(a.float32_member(), b.float32_member()));
EXPECT_TRUE(fidl::Equals(a.float64_member(), b.float64_member()));
EXPECT_TRUE(fidl::Equals(a.enum_member(), b.enum_member()));
EXPECT_TRUE(fidl::Equals(a.bits_member(), b.bits_member()));
EXPECT_TRUE(HandlesEq(a.handle_member(), b.handle_member()));
EXPECT_TRUE(fidl::Equals(a.string_member(), b.string_member()));
EXPECT_TRUE(fidl::Equals(a.struct_member(), b.struct_member()));
EXPECT_TRUE(fidl::Equals(a.union_member(), b.union_member()));
EXPECT_TRUE(fidl::Equals(a.array_member(), b.array_member()));
EXPECT_TRUE(fidl::Equals(a.vector_member(), b.vector_member()));
EXPECT_TRUE(fidl::Equals(a.table_member(), b.table_member()));
EXPECT_TRUE(fidl::Equals(a.xunion_member(), b.xunion_member()));
}
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(Table, EchoTable) {
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) + " (table)"] =
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);
AllTypesTable sent;
InitializeAllTypesTable(&sent, generator);
AllTypesTable sent_clone;
sent.Clone(&sent_clone);
AllTypesTable resp_clone;
bool called_back = false;
proxy->EchoTable(std::move(sent), server_url,
[&loop, &resp_clone, &called_back](AllTypesTable resp) {
ASSERT_EQ(ZX_OK, resp.Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
ExpectAllTypesTableEq(sent_clone, resp_clone);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (table)"] =
true;
});
}
TEST(Table, EchoTableWithErrorSuccessCase) {
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) +
" (table 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);
AllTypesTable sent;
InitializeAllTypesTable(&sent, generator);
auto err = fidl::test::compatibility::default_enum::kOne;
AllTypesTable sent_clone;
sent.Clone(&sent_clone);
AllTypesTable resp_clone;
bool called_back = false;
proxy->EchoTableWithError(
std::move(sent), err, server_url, RespondWith::SUCCESS,
[&loop, &resp_clone, &called_back](Echo_EchoTableWithError_Result resp) {
ASSERT_TRUE(resp.is_response());
ASSERT_EQ(ZX_OK, resp.response().value.Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
ExpectAllTypesTableEq(sent_clone, resp_clone);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (table result success)"] = true;
});
}
TEST(Table, EchoTableWithErrorErrorCase) {
ForAllImpls(impls,
// See: https://fxbug.dev/42159920
[](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) +
" (table 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);
AllTypesTable sent;
InitializeAllTypesTable(&sent, generator);
auto err = fidl::test::compatibility::default_enum::kOne;
bool called_back = false;
proxy->EchoTableWithError(
std::move(sent), err, server_url, RespondWith::ERR,
[&loop, &err, &called_back](Echo_EchoTableWithError_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) +
" (table result error)"] = true;
});
}
TEST(Table, EchoTablePayload) {
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) + " (table)"] =
false;
fidl::test::compatibility::RequestTable sent;
sent.set_forward_to_server(server_url);
sent.set_value(42u);
fidl::test::compatibility::RequestTable sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseTable resp_clone;
bool called_back = false;
proxy->EchoTablePayload(std::move(sent), [&loop, &resp_clone, &called_back](
fidl::test::compatibility::ResponseTable resp) {
ASSERT_EQ(ZX_OK, resp.Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
EXPECT_EQ(sent_clone.has_value(), resp_clone.has_value());
EXPECT_EQ(sent_clone.value(), resp_clone.value());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (table)"] =
true;
});
}
TEST(Table, EchoTablePayloadWithErrorSuccessCase) {
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) +
" (table result success)"] = false;
fidl::test::compatibility::EchoEchoTablePayloadWithErrorRequest sent;
sent.set_forward_to_server(server_url);
sent.set_value(42u);
sent.set_result_variant(fidl::test::compatibility::RespondWith::SUCCESS);
fidl::test::compatibility::EchoEchoTablePayloadWithErrorRequest sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseTable resp_clone;
bool called_back = false;
proxy->EchoTablePayloadWithError(
std::move(sent),
[&loop, &resp_clone,
&called_back](fidl::test::compatibility::Echo_EchoTablePayloadWithError_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.has_value(), resp_clone.has_value());
EXPECT_EQ(sent_clone.value(), resp_clone.value());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) +
" (table result success)"] = true;
});
}
TEST(Table, EchoTablePayloadWithErrorErrorCase) {
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) +
" (table result success)"] = false;
fidl::test::compatibility::EchoEchoTablePayloadWithErrorRequest sent;
auto err = fidl::test::compatibility::default_enum::kOne;
sent.set_forward_to_server(server_url);
sent.set_result_err(err);
sent.set_result_variant(fidl::test::compatibility::RespondWith::ERR);
fidl::test::compatibility::EchoEchoTablePayloadWithErrorRequest sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseTable resp_clone;
bool called_back = false;
proxy->EchoTablePayloadWithError(
std::move(sent),
[&loop, &err,
&called_back](fidl::test::compatibility::Echo_EchoTablePayloadWithError_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) +
" (table result success)"] = true;
});
}
TEST(Table, EchoTablePayloadNoRetval) {
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) + " (table)"] =
false;
fidl::test::compatibility::RequestTable sent;
sent.set_forward_to_server(server_url);
sent.set_value(42u);
fidl::test::compatibility::RequestTable sent_clone;
sent.Clone(&sent_clone);
fidl::test::compatibility::ResponseTable resp_clone;
bool event_received = false;
proxy.events().OnEchoTablePayloadEvent =
[&loop, &resp_clone, &event_received](fidl::test::compatibility::ResponseTable resp) {
resp.Clone(&resp_clone);
event_received = true;
loop.Quit();
};
proxy->EchoTablePayloadNoRetVal(std::move(sent));
loop.Run();
ASSERT_TRUE(event_received);
EXPECT_EQ(sent_clone.has_value(), resp_clone.has_value());
EXPECT_EQ(sent_clone.value(), resp_clone.value());
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (table)"] =
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(Table, EchoTableRequestComposed) {
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) + " (table)"] =
false;
::fidl::test::imported::ComposedEchoTableRequestComposedRequest sent;
sent.set_value(42u);
sent.set_forward_to_server(server_url);
::fidl::test::imported::ComposedEchoTableRequestComposedRequest sent_clone;
sent.Clone(&sent_clone);
fidl::test::imported::SimpleStruct expected_resp;
expected_resp.f1 = true;
expected_resp.f2 = sent.value();
fidl::test::imported::SimpleStruct resp_clone;
bool called_back = false;
proxy->EchoTableRequestComposed(
std::move(sent),
[&loop, &resp_clone, &called_back](fidl::test::imported::SimpleStruct resp) {
ASSERT_EQ(ZX_OK, resp.Clone(&resp_clone));
called_back = true;
loop.Quit();
});
loop.Run();
ASSERT_TRUE(called_back);
EXPECT_EQ(expected_resp.f1, resp_clone.f1);
EXPECT_EQ(expected_resp.f2, resp_clone.f2);
summary[ExtractShortName(proxy_url) + " <-> " + ExtractShortName(server_url) + " (table)"] =
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;
}