blob: 45233962f70c0893adab5192c0e295ae29578f1f [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 <lib/standalone-test/standalone.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/sanitizer.h>
#include <string>
#include <zxtest/zxtest.h>
#include "data-publisher/published-data.h"
#include "helper.h"
namespace {
class MultipleProcessSvcTest : public zxtest::Test {
public:
void SetUp() final {
static zx::channel svc_stash;
static zx::channel svc_server;
static zx::channel provider_svc_server;
// Prevents multiple iterations from discarding this.
if (!svc_stash) {
svc_stash = GetSvcStash();
ASSERT_TRUE(svc_stash);
}
// Order matters, provider is stored first.
if (!provider_svc_server) {
ASSERT_NO_FATAL_FAILURE(GetStashedSvc(svc_stash.borrow(), provider_svc_server));
}
// Ours is stored second.
if (!svc_server) {
ASSERT_NO_FATAL_FAILURE(GetStashedSvc(svc_stash.borrow(), svc_server));
}
svc_stash_ = svc_stash.borrow();
svc_ = standalone::GetNsDir("/svc");
stashed_svc_ = svc_server.borrow();
provider_svc_ = provider_svc_server.borrow();
}
zx::unowned_channel svc_stash() { return svc_stash_->borrow(); }
zx::unowned_channel local_svc() { return svc_->borrow(); }
zx::unowned_channel stashed_svc() { return stashed_svc_->borrow(); }
zx::unowned_channel provider_svc() { return provider_svc_->borrow(); }
private:
zx::unowned_channel svc_stash_;
zx::unowned_channel svc_;
zx::unowned_channel stashed_svc_;
zx::unowned_channel provider_svc_;
};
TEST_F(MultipleProcessSvcTest, ProviderDataMatchesExpectations) {
bool found = false;
OnEachMessage(provider_svc(), [&](zx::unowned_channel stashed_svc, bool& keep_going) {
keep_going = false;
Message debug_msg;
ASSERT_NO_FAILURES(GetDebugDataMessage(std::move(stashed_svc), debug_msg));
DebugDataMessageView view(debug_msg);
if (view.sink() != kPublisherSinkName) {
keep_going = true;
return;
}
found = true;
// Token must be signaled with peer closed.
zx_signals_t observed = 0;
view.token()->wait_one(ZX_EVENTPAIR_PEER_CLOSED, zx::time::infinite_past(), &observed);
EXPECT_TRUE((observed & ZX_EVENTPAIR_PEER_CLOSED) != 0);
// Check vmo contents.
std::array<char, 12> actual_contents = {};
ASSERT_OK(view.vmo()->read(actual_contents.data(), 0, actual_contents.size()));
ASSERT_EQ(std::string(actual_contents.data(), actual_contents.size()), "Hello World!");
});
ASSERT_TRUE(found);
}
TEST_F(MultipleProcessSvcTest, SanitizerPublishDataShowsUpInStashedHandle) {
ASSERT_TRUE(local_svc()->is_valid());
ASSERT_TRUE(stashed_svc()->is_valid());
zx::vmo vmo;
ASSERT_OK(zx::vmo::create(124, 0, &vmo));
constexpr const char* kDataSink = "some_sink_name";
zx_koid_t vmo_koid = GetKoid(vmo.get());
zx::eventpair token_1(__sanitizer_publish_data(kDataSink, vmo.release()));
zx_koid_t token_koid = GetPeerKoid(token_1.get());
ASSERT_NE(token_koid, ZX_KOID_INVALID);
ASSERT_NE(vmo_koid, ZX_KOID_INVALID);
bool found = false;
OnEachMessage(stashed_svc(), [&](zx::unowned_channel stashed_svc, bool& keep_going) {
keep_going = false;
Message debug_msg;
ASSERT_NO_FAILURES(GetDebugDataMessage(std::move(stashed_svc), debug_msg));
DebugDataMessageView view(debug_msg);
if (view.sink() != kDataSink) {
keep_going = true;
return;
}
found = true;
ASSERT_EQ(view.sink(), kDataSink);
ASSERT_EQ(GetKoid(view.vmo()->get()), vmo_koid);
ASSERT_EQ(GetKoid(view.token()->get()), token_koid);
});
ASSERT_TRUE(found);
}
} // namespace