mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
Add SystemSnapshotMac and its test.
TEST=snapshot_test SystemSnapshotMac.* R=rsesek@chromium.org Review URL: https://codereview.chromium.org/626013002
This commit is contained in:
parent
bc8626f898
commit
3f81599848
@ -34,8 +34,29 @@
|
||||
'module_snapshot.h',
|
||||
'process_snapshot.h',
|
||||
'system_snapshot.h',
|
||||
'system_snapshot_mac.cc',
|
||||
'system_snapshot_mac.h',
|
||||
'thread_snapshot.h',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'snapshot_test',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'snapshot',
|
||||
'../compat/compat.gyp:compat',
|
||||
'../third_party/gtest/gtest.gyp:gtest',
|
||||
'../third_party/gtest/gtest.gyp:gtest_main',
|
||||
'../third_party/mini_chromium/mini_chromium/base/base.gyp:base',
|
||||
'../util/util.gyp:util',
|
||||
'../util/util.gyp:util_test_lib',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'system_snapshot_mac_test.cc',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
373
snapshot/system_snapshot_mac.cc
Normal file
373
snapshot/system_snapshot_mac.cc
Normal file
@ -0,0 +1,373 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "snapshot/system_snapshot_mac.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "build/build_config.h"
|
||||
#include "snapshot/cpu_context.h"
|
||||
#include "util/mac/mac_util.h"
|
||||
#include "util/mac/process_reader.h"
|
||||
#include "util/numeric/in_range_cast.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
T ReadIntSysctlByName(const char* name, T default_value) {
|
||||
T value;
|
||||
size_t value_len = sizeof(value);
|
||||
if (sysctlbyname(name, &value, &value_len, NULL, 0) != 0) {
|
||||
PLOG(WARNING) << "sysctlbyname " << name;
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T CastIntSysctlByName(const char* name, T default_value) {
|
||||
int int_value = ReadIntSysctlByName<int>(name, default_value);
|
||||
return InRangeCast<T>(int_value, default_value);
|
||||
}
|
||||
|
||||
std::string ReadStringSysctlByName(const char* name) {
|
||||
size_t buf_len;
|
||||
if (sysctlbyname(name, NULL, &buf_len, NULL, 0) != 0) {
|
||||
PLOG(WARNING) << "sysctlbyname (size) " << name;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (buf_len == 0) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string value(buf_len - 1, '\0');
|
||||
if (sysctlbyname(name, &value[0], &buf_len, NULL, 0) != 0) {
|
||||
PLOG(WARNING) << "sysctlbyname " << name;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
void CallCPUID(uint32_t leaf,
|
||||
uint32_t* eax,
|
||||
uint32_t* ebx,
|
||||
uint32_t* ecx,
|
||||
uint32_t* edx) {
|
||||
asm("cpuid"
|
||||
: "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx)
|
||||
: "a"(leaf), "b"(0), "c"(0), "d"(0));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
SystemSnapshotMac::SystemSnapshotMac()
|
||||
: SystemSnapshot(),
|
||||
os_version_full_(),
|
||||
os_version_build_(),
|
||||
process_reader_(NULL),
|
||||
snapshot_time_(NULL),
|
||||
os_version_major_(0),
|
||||
os_version_minor_(0),
|
||||
os_version_bugfix_(0),
|
||||
os_server_(false),
|
||||
initialized_() {
|
||||
}
|
||||
|
||||
SystemSnapshotMac::~SystemSnapshotMac() {
|
||||
}
|
||||
|
||||
void SystemSnapshotMac::Initialize(ProcessReader* process_reader,
|
||||
const timeval* snapshot_time) {
|
||||
INITIALIZATION_STATE_SET_INITIALIZING(initialized_);
|
||||
|
||||
process_reader_ = process_reader;
|
||||
snapshot_time_ = snapshot_time;
|
||||
|
||||
// MacOSXVersion() logs its own warnings if it can’t figure anything out. It’s
|
||||
// not fatal if this happens. The default values are reasonable.
|
||||
std::string os_version_string;
|
||||
MacOSXVersion(&os_version_major_,
|
||||
&os_version_minor_,
|
||||
&os_version_bugfix_,
|
||||
&os_version_build_,
|
||||
&os_server_,
|
||||
&os_version_string);
|
||||
|
||||
std::string uname_string;
|
||||
utsname uts;
|
||||
if (uname(&uts) != 0) {
|
||||
PLOG(WARNING) << "uname";
|
||||
} else {
|
||||
uname_string = base::StringPrintf(
|
||||
"%s %s %s %s", uts.sysname, uts.release, uts.version, uts.machine);
|
||||
}
|
||||
|
||||
if (!os_version_string.empty()) {
|
||||
if (!uname_string.empty()) {
|
||||
os_version_full_ = base::StringPrintf(
|
||||
"%s; %s", os_version_string.c_str(), uname_string.c_str());
|
||||
} else {
|
||||
os_version_full_ = os_version_string;
|
||||
}
|
||||
} else {
|
||||
os_version_full_ = uname_string;
|
||||
}
|
||||
|
||||
INITIALIZATION_STATE_SET_VALID(initialized_);
|
||||
}
|
||||
|
||||
CPUArchitecture SystemSnapshotMac::GetCPUArchitecture() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return process_reader_->Is64Bit() ? kCPUArchitectureX86_64
|
||||
: kCPUArchitectureX86;
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t SystemSnapshotMac::CPURevision() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
// machdep.cpu.family and machdep.cpu.model already take the extended family
|
||||
// and model IDs into account. See 10.9.2 xnu-2422.90.20/osfmk/i386/cpuid.c
|
||||
// cpuid_set_generic_info().
|
||||
uint16_t family = CastIntSysctlByName<uint16_t>("machdep.cpu.family", 0);
|
||||
uint8_t model = CastIntSysctlByName<uint8_t>("machdep.cpu.model", 0);
|
||||
uint8_t stepping = CastIntSysctlByName<uint8_t>("machdep.cpu.stepping", 0);
|
||||
|
||||
return (family << 16) | (model << 8) | stepping;
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t SystemSnapshotMac::CPUCount() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return CastIntSysctlByName<uint8_t>("hw.ncpu", 1);
|
||||
}
|
||||
|
||||
std::string SystemSnapshotMac::CPUVendor() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadStringSysctlByName("machdep.cpu.vendor");
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
void SystemSnapshotMac::CPUFrequency(
|
||||
uint64_t* current_hz, uint64_t* max_hz) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
*current_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency", 0);
|
||||
*max_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency_max", 0);
|
||||
}
|
||||
|
||||
uint32_t SystemSnapshotMac::CPUX86Signature() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadIntSysctlByName<uint32_t>("machdep.cpu.signature", 0);
|
||||
#else
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t SystemSnapshotMac::CPUX86Features() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadIntSysctlByName<uint64_t>("machdep.cpu.feature_bits", 0);
|
||||
#else
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t SystemSnapshotMac::CPUX86ExtendedFeatures() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
return ReadIntSysctlByName<uint64_t>("machdep.cpu.extfeature_bits", 0);
|
||||
#else
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t SystemSnapshotMac::CPUX86Leaf7Features() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
// The machdep.cpu.leaf7_feature_bits sysctl isn’t supported prior to Mac OS X
|
||||
// 10.7, so read this by calling cpuid directly.
|
||||
//
|
||||
// machdep.cpu.max_basic could be used to check whether to read the leaf, but
|
||||
// that sysctl isn’t supported prior to Mac OS X 10.6, so read the maximum
|
||||
// basic leaf by calling cpuid directly as well. All CPUs that Apple is known
|
||||
// to have shipped should support a maximum basic leaf value of at least 0xa.
|
||||
uint32_t eax, ebx, ecx, edx;
|
||||
CallCPUID(0, &eax, &ebx, &ecx, &edx);
|
||||
if (eax < 7) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CallCPUID(7, &eax, &ebx, &ecx, &edx);
|
||||
return ebx;
|
||||
#else
|
||||
NOTREACHED();
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SystemSnapshotMac::CPUX86SupportsDAZ() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
// The correct way to check for denormals-as-zeros (DAZ) support is to examine
|
||||
// mxcsr mask, which can be done with fxsave. See Intel Software Developer’s
|
||||
// Manual, Volume 1: Basic Architecture (253665-051), 11.6.3 “Checking for the
|
||||
// DAZ Flag in the MXCSR Register”. Note that since this function tests for
|
||||
// DAZ support in the CPU, it checks the mxcsr mask. Testing mxcsr would
|
||||
// indicate whether DAZ is actually enabled, which is a per-thread context
|
||||
// concern.
|
||||
//
|
||||
// All CPUs that Apple is known to have shipped should support DAZ.
|
||||
|
||||
// Test for fxsave support.
|
||||
uint64_t features = CPUX86Features();
|
||||
if (!(features & (UINT64_C(1) << 24))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call fxsave.
|
||||
CPUContextX86::Fxsave fxsave __attribute__((aligned(16))) = {};
|
||||
static_assert(sizeof(fxsave) == 512, "fxsave size");
|
||||
static_assert(offsetof(decltype(fxsave), mxcsr_mask) == 28,
|
||||
"mxcsr_mask offset");
|
||||
asm("fxsave %0" : "=m"(fxsave));
|
||||
|
||||
// Test the DAZ bit.
|
||||
return fxsave.mxcsr_mask & (1 << 6);
|
||||
#else
|
||||
NOTREACHED();
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
SystemSnapshot::OperatingSystem SystemSnapshotMac::GetOperatingSystem() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return kOperatingSystemMacOSX;
|
||||
}
|
||||
|
||||
bool SystemSnapshotMac::OSServer() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return os_server_;
|
||||
}
|
||||
|
||||
void SystemSnapshotMac::OSVersion(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
*major = os_version_major_;
|
||||
*minor = os_version_minor_;
|
||||
*bugfix = os_version_bugfix_;
|
||||
build->assign(os_version_build_);
|
||||
}
|
||||
|
||||
std::string SystemSnapshotMac::OSVersionFull() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return os_version_full_;
|
||||
}
|
||||
|
||||
std::string SystemSnapshotMac::MachineDescription() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
std::string model;
|
||||
std::string board_id;
|
||||
MacModelAndBoard(&model, &board_id);
|
||||
|
||||
if (!model.empty()) {
|
||||
if (!board_id.empty()) {
|
||||
return base::StringPrintf("%s (%s)", model.c_str(), board_id.c_str());
|
||||
}
|
||||
return model;
|
||||
}
|
||||
if (!board_id.empty()) {
|
||||
return base::StringPrintf("(%s)", board_id.c_str());
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool SystemSnapshotMac::NXEnabled() const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
return ReadIntSysctlByName<int>("kern.nx", 0);
|
||||
}
|
||||
|
||||
void SystemSnapshotMac::TimeZone(DaylightSavingTimeStatus* dst_status,
|
||||
int* standard_offset_seconds,
|
||||
int* daylight_offset_seconds,
|
||||
std::string* standard_name,
|
||||
std::string* daylight_name) const {
|
||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||
|
||||
tm local;
|
||||
localtime_r(&snapshot_time_->tv_sec, &local);
|
||||
|
||||
*standard_name = tzname[0];
|
||||
if (daylight) {
|
||||
// This assumes that the offset between standard and daylight saving time is
|
||||
// globally a constant, where a time zone’s daylight saving time is one hour
|
||||
// ahead of its standard time.
|
||||
const int kSecondsPerHour = 60 * 60;
|
||||
|
||||
*daylight_name = tzname[1];
|
||||
if (!local.tm_isdst) {
|
||||
*dst_status = kObservingStandardTime;
|
||||
*standard_offset_seconds = local.tm_gmtoff;
|
||||
*daylight_offset_seconds = local.tm_gmtoff + kSecondsPerHour;
|
||||
} else {
|
||||
*dst_status = kObservingDaylightSavingTime;
|
||||
*standard_offset_seconds = local.tm_gmtoff - kSecondsPerHour;
|
||||
*daylight_offset_seconds = local.tm_gmtoff;
|
||||
}
|
||||
} else {
|
||||
*daylight_name = tzname[0];
|
||||
*dst_status = kDoesNotObserveDaylightSavingTime;
|
||||
*standard_offset_seconds = local.tm_gmtoff;
|
||||
*daylight_offset_seconds = local.tm_gmtoff;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
104
snapshot/system_snapshot_mac.h
Normal file
104
snapshot/system_snapshot_mac.h
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef CRASHPAD_SNAPSHOT_SYSTEM_SNAPSHOT_MAC_H_
|
||||
#define CRASHPAD_SNAPSHOT_SYSTEM_SNAPSHOT_MAC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "snapshot/system_snapshot.h"
|
||||
#include "util/misc/initialization_state_dcheck.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
class ProcessReader;
|
||||
|
||||
namespace internal {
|
||||
|
||||
//! \brief A SystemSnapshot of the running system, when the system runs Mac OS
|
||||
//! X.
|
||||
class SystemSnapshotMac final : public SystemSnapshot {
|
||||
public:
|
||||
SystemSnapshotMac();
|
||||
~SystemSnapshotMac();
|
||||
|
||||
//! \brief Initializes the object.
|
||||
//!
|
||||
//! \param[in] process_reader A reader for the process being snapshotted.
|
||||
//! \n\n
|
||||
//! It seems odd that a system snapshot implementation would need a
|
||||
//! ProcessReader, but some of the information reported about the system
|
||||
//! depends on the process it’s being reported for. For example, the
|
||||
//! architecture returned by GetCPUArchitecture() should be the
|
||||
//! architecture of the process, which may be different than the native
|
||||
//! architecture of the system: an x86_64 system can run both x86_64 and
|
||||
//! 32-bit x86 processes.
|
||||
//! \param[in] snapshot_time The time of the snapshot being taken.
|
||||
//! \n\n
|
||||
//! This parameter is necessary for TimeZone() to determine whether
|
||||
//! daylight saving time was in effect at the time the snapshot was taken.
|
||||
//! Otherwise, it would need to base its determination on the current
|
||||
//! time, which may be different than the snapshot time for snapshots
|
||||
//! generated around the daylight saving transition time.
|
||||
void Initialize(ProcessReader* process_reader, const timeval* snapshot_time);
|
||||
|
||||
// SystemSnapshot:
|
||||
|
||||
virtual CPUArchitecture GetCPUArchitecture() const override;
|
||||
virtual uint32_t CPURevision() const override;
|
||||
virtual uint8_t CPUCount() const override;
|
||||
virtual std::string CPUVendor() const override;
|
||||
virtual void CPUFrequency(uint64_t* current_hz,
|
||||
uint64_t* max_hz) const override;
|
||||
virtual uint32_t CPUX86Signature() const override;
|
||||
virtual uint64_t CPUX86Features() const override;
|
||||
virtual uint64_t CPUX86ExtendedFeatures() const override;
|
||||
virtual uint32_t CPUX86Leaf7Features() const override;
|
||||
virtual bool CPUX86SupportsDAZ() const override;
|
||||
virtual OperatingSystem GetOperatingSystem() const override;
|
||||
virtual bool OSServer() const override;
|
||||
virtual void OSVersion(int* major,
|
||||
int* minor,
|
||||
int* bugfix,
|
||||
std::string* build) const override;
|
||||
virtual std::string OSVersionFull() const override;
|
||||
virtual bool NXEnabled() const override;
|
||||
virtual std::string MachineDescription() const override;
|
||||
virtual void TimeZone(DaylightSavingTimeStatus* dst_status,
|
||||
int* standard_offset_seconds,
|
||||
int* daylight_offset_seconds,
|
||||
std::string* standard_name,
|
||||
std::string* daylight_name) const override;
|
||||
|
||||
private:
|
||||
std::string os_version_full_;
|
||||
std::string os_version_build_;
|
||||
ProcessReader* process_reader_; // weak
|
||||
const timeval* snapshot_time_; // weak
|
||||
int os_version_major_;
|
||||
int os_version_minor_;
|
||||
int os_version_bugfix_;
|
||||
bool os_server_;
|
||||
InitializationStateDcheck initialized_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemSnapshotMac);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_SNAPSHOT_SYSTEM_SNAPSHOT_MAC_H_
|
130
snapshot/system_snapshot_mac_test.cc
Normal file
130
snapshot/system_snapshot_mac_test.cc
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "snapshot/system_snapshot_mac.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "build/build_config.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "util/mac/mac_util.h"
|
||||
#include "util/mac/process_reader.h"
|
||||
#include "util/test/errors.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace crashpad;
|
||||
using namespace crashpad::test;
|
||||
|
||||
// SystemSnapshotMac objects would be cumbersome to construct in each test that
|
||||
// requires one, because of the repetitive and mechanical work necessary to set
|
||||
// up a ProcessReader and timeval, along with the checks to verify that these
|
||||
// operations succeed. This test fixture class handles the initialization work
|
||||
// so that individual tests don’t have to.
|
||||
class SystemSnapshotMacTest : public testing::Test {
|
||||
public:
|
||||
SystemSnapshotMacTest()
|
||||
: Test(),
|
||||
process_reader_(),
|
||||
snapshot_time_(),
|
||||
system_snapshot_() {
|
||||
}
|
||||
|
||||
const internal::SystemSnapshotMac& system_snapshot() const {
|
||||
return system_snapshot_;
|
||||
}
|
||||
|
||||
// testing::Test:
|
||||
virtual void SetUp() override {
|
||||
ASSERT_TRUE(process_reader_.Initialize(mach_task_self()));
|
||||
ASSERT_EQ(0, gettimeofday(&snapshot_time_, NULL))
|
||||
<< ErrnoMessage("gettimeofday");
|
||||
system_snapshot_.Initialize(&process_reader_, &snapshot_time_);
|
||||
}
|
||||
|
||||
private:
|
||||
ProcessReader process_reader_;
|
||||
timeval snapshot_time_;
|
||||
internal::SystemSnapshotMac system_snapshot_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SystemSnapshotMacTest);
|
||||
};
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, GetCPUArchitecture) {
|
||||
CPUArchitecture cpu_architecture = system_snapshot().GetCPUArchitecture();
|
||||
|
||||
#if defined(ARCH_CPU_X86)
|
||||
EXPECT_EQ(kCPUArchitectureX86, cpu_architecture);
|
||||
#elif defined(ARCH_CPU_X86_64)
|
||||
EXPECT_EQ(kCPUArchitectureX86_64, cpu_architecture);
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, CPUCount) {
|
||||
EXPECT_GE(system_snapshot().CPUCount(), 1);
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, CPUVendor) {
|
||||
std::string cpu_vendor = system_snapshot().CPUVendor();
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
// Apple has only shipped Intel x86-family CPUs, but here’s a small nod to the
|
||||
// “Hackintosh” crowd.
|
||||
if (cpu_vendor != "GenuineIntel" && cpu_vendor != "AuthenticAMD") {
|
||||
FAIL() << cpu_vendor;
|
||||
}
|
||||
#else
|
||||
#error port to your architecture
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, CPUX86SupportsDAZ) {
|
||||
// All x86-family CPUs that Apple is known to have shipped should support DAZ.
|
||||
EXPECT_TRUE(system_snapshot().CPUX86SupportsDAZ());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, GetOperatingSystem) {
|
||||
EXPECT_EQ(SystemSnapshot::kOperatingSystemMacOSX,
|
||||
system_snapshot().GetOperatingSystem());
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, OSVersion) {
|
||||
int major;
|
||||
int minor;
|
||||
int bugfix;
|
||||
std::string build;
|
||||
system_snapshot().OSVersion(&major, &minor, &bugfix, &build);
|
||||
|
||||
EXPECT_EQ(10, major);
|
||||
EXPECT_EQ(MacOSXMinorVersion(), minor);
|
||||
EXPECT_FALSE(build.empty());
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, OSVersionFull) {
|
||||
EXPECT_FALSE(system_snapshot().OSVersionFull().empty());
|
||||
}
|
||||
|
||||
TEST_F(SystemSnapshotMacTest, MachineDescription) {
|
||||
EXPECT_FALSE(system_snapshot().MachineDescription().empty());
|
||||
}
|
||||
|
||||
} // namespace
|
Loading…
x
Reference in New Issue
Block a user