blob: ad29bb991b458bb0ab7858c62c5d54e1cfa35ff2 [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 "diagnostics/diagnosticsd/mojo_test_utils.h"
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>
#include <mojo/public/c/system/buffer.h>
#include <mojo/public/c/system/types.h>
namespace diagnostics {
namespace {
// Creates an abstract socket with a unique address.
base::ScopedFD CreateAbstractSocket() {
// Use autobind feature to avoid having to supply a unique socket address.
const socklen_t kAddrlen = sizeof(sa_family_t);
base::ScopedFD fd(
HANDLE_EINTR(socket(AF_UNIX, SOCK_STREAM, 0 /* protocol */)));
if (!fd.is_valid())
return base::ScopedFD();
sockaddr_un socket_address;
memset(&socket_address, 0, sizeof(sockaddr_un));
socket_address.sun_family = AF_UNIX;
if (HANDLE_EINTR(bind(fd.get(),
reinterpret_cast<const sockaddr*>(&socket_address),
kAddrlen)) < 0) {
return base::ScopedFD();
}
return fd;
}
// Returns the device ID and inode which the given file descriptor points to.
bool GetFdInfo(int fd, uint64_t* device_id, uint64_t* inode) {
struct stat fd_stat;
if (HANDLE_EINTR(fstat(fd, &fd_stat)) < 0) {
PLOG(ERROR) << "fstat failed for file descriptor " << fd;
return false;
}
*device_id = fd_stat.st_dev;
*inode = fd_stat.st_ino;
return true;
}
} // namespace
FakeMojoFdGenerator::FakeMojoFdGenerator() : fd_(CreateAbstractSocket()) {
CHECK(fd_.is_valid());
}
FakeMojoFdGenerator::~FakeMojoFdGenerator() = default;
base::ScopedFD FakeMojoFdGenerator::MakeFd() const {
return base::ScopedFD(HANDLE_EINTR(dup(fd_.get())));
}
bool FakeMojoFdGenerator::IsDuplicateFd(int another_fd) const {
uint64_t own_device_id = 0;
uint64_t own_inode = 0;
uint64_t another_device_id = 0;
uint64_t another_inode = 0;
if (!GetFdInfo(fd_.get(), &own_device_id, &own_inode) ||
!GetFdInfo(another_fd, &another_device_id, &another_inode)) {
return false;
}
return own_device_id == another_device_id && own_inode == another_inode;
}
namespace helper {
std::unique_ptr<mojo::ScopedSharedBufferHandle> WriteToSharedBuffer(
const std::string& content) {
std::unique_ptr<mojo::ScopedSharedBufferHandle> buffer =
std::make_unique<mojo::ScopedSharedBufferHandle>();
*buffer = mojo::SharedBufferHandle::Create(content.length());
if (!(*buffer)->is_valid()) {
return nullptr;
}
mojo::ScopedSharedBufferMapping mapping = (*buffer)->Map(content.length());
if (!mapping) {
return nullptr;
}
memcpy(mapping.get(), static_cast<const void*>(content.c_str()),
content.length());
return buffer;
}
} // namespace helper
} // namespace diagnostics