1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "snapshot/mac/system_snapshot_mac.h"
16 
17 #include <sys/time.h>
18 
19 #include <string>
20 
21 #include "build/build_config.h"
22 #include "gtest/gtest.h"
23 #include "snapshot/mac/process_reader_mac.h"
24 #include "test/errors.h"
25 #include "util/mac/mac_util.h"
26 
27 namespace crashpad {
28 namespace test {
29 namespace {
30 
31 // SystemSnapshotMac objects would be cumbersome to construct in each test that
32 // requires one, because of the repetitive and mechanical work necessary to set
33 // up a ProcessReaderMac and timeval, along with the checks to verify that these
34 // operations succeed. This test fixture class handles the initialization work
35 // so that individual tests don’t have to.
36 class SystemSnapshotMacTest : public testing::Test {
37  public:
SystemSnapshotMacTest()38   SystemSnapshotMacTest()
39       : Test(),
40         process_reader_(),
41         snapshot_time_(),
42         system_snapshot_() {
43   }
44 
system_snapshot() const45   const internal::SystemSnapshotMac& system_snapshot() const {
46     return system_snapshot_;
47   }
48 
49   // testing::Test:
SetUp()50   void SetUp() override {
51     ASSERT_TRUE(process_reader_.Initialize(mach_task_self()));
52     ASSERT_EQ(gettimeofday(&snapshot_time_, nullptr), 0)
53         << ErrnoMessage("gettimeofday");
54     system_snapshot_.Initialize(&process_reader_, &snapshot_time_);
55   }
56 
57  private:
58   ProcessReaderMac process_reader_;
59   timeval snapshot_time_;
60   internal::SystemSnapshotMac system_snapshot_;
61 
62   DISALLOW_COPY_AND_ASSIGN(SystemSnapshotMacTest);
63 };
64 
TEST_F(SystemSnapshotMacTest,GetCPUArchitecture)65 TEST_F(SystemSnapshotMacTest, GetCPUArchitecture) {
66   CPUArchitecture cpu_architecture = system_snapshot().GetCPUArchitecture();
67 
68 #if defined(ARCH_CPU_X86)
69   EXPECT_EQ(cpu_architecture, kCPUArchitectureX86);
70 #elif defined(ARCH_CPU_X86_64)
71   EXPECT_EQ(cpu_architecture, kCPUArchitectureX86_64);
72 #elif defined(ARCH_CPU_ARM64)
73   EXPECT_EQ(cpu_architecture, kCPUArchitectureARM64);
74 #else
75 #error port to your architecture
76 #endif
77 }
78 
TEST_F(SystemSnapshotMacTest,CPUCount)79 TEST_F(SystemSnapshotMacTest, CPUCount) {
80   EXPECT_GE(system_snapshot().CPUCount(), 1);
81 }
82 
TEST_F(SystemSnapshotMacTest,CPUVendor)83 TEST_F(SystemSnapshotMacTest, CPUVendor) {
84   std::string cpu_vendor = system_snapshot().CPUVendor();
85 
86 #if defined(ARCH_CPU_X86_FAMILY)
87   // Apple has only shipped Intel x86-family CPUs, but here’s a small nod to the
88   // “Hackintosh” crowd.
89   if (cpu_vendor != "GenuineIntel" && cpu_vendor != "AuthenticAMD") {
90     FAIL() << "cpu_vendor " << cpu_vendor;
91   }
92 #elif defined(ARCH_CPU_ARM64)
93   EXPECT_EQ(cpu_vendor, "Apple processor");
94 #else
95 #error port to your architecture
96 #endif
97 }
98 
99 #if defined(ARCH_CPU_X86_FAMILY)
100 
TEST_F(SystemSnapshotMacTest,CPUX86SupportsDAZ)101 TEST_F(SystemSnapshotMacTest, CPUX86SupportsDAZ) {
102   // All x86-family CPUs that Apple is known to have shipped should support DAZ.
103   EXPECT_TRUE(system_snapshot().CPUX86SupportsDAZ());
104 }
105 
106 #endif
107 
TEST_F(SystemSnapshotMacTest,GetOperatingSystem)108 TEST_F(SystemSnapshotMacTest, GetOperatingSystem) {
109   EXPECT_EQ(system_snapshot().GetOperatingSystem(),
110             SystemSnapshot::kOperatingSystemMacOSX);
111 }
112 
TEST_F(SystemSnapshotMacTest,OSVersion)113 TEST_F(SystemSnapshotMacTest, OSVersion) {
114   int major;
115   int minor;
116   int bugfix;
117   std::string build;
118   system_snapshot().OSVersion(&major, &minor, &bugfix, &build);
119 
120   const int macos_version_number = MacOSVersionNumber();
121   EXPECT_EQ(major * 1'00'00 + minor * 1'00 +
122                 (macos_version_number >= 10'13'04 ? bugfix : 0),
123             macos_version_number);
124   EXPECT_FALSE(build.empty());
125 }
126 
TEST_F(SystemSnapshotMacTest,OSVersionFull)127 TEST_F(SystemSnapshotMacTest, OSVersionFull) {
128   EXPECT_FALSE(system_snapshot().OSVersionFull().empty());
129 }
130 
TEST_F(SystemSnapshotMacTest,MachineDescription)131 TEST_F(SystemSnapshotMacTest, MachineDescription) {
132   EXPECT_FALSE(system_snapshot().MachineDescription().empty());
133 }
134 
TEST_F(SystemSnapshotMacTest,NXEnabled)135 TEST_F(SystemSnapshotMacTest, NXEnabled) {
136   // Assume NX will always be enabled, as it was always enabled by default on
137   // all supported versions of macOS.
138   EXPECT_TRUE(system_snapshot().NXEnabled());
139 }
140 
141 }  // namespace
142 }  // namespace test
143 }  // namespace crashpad
144