Index: util/mac/mac_util_test.mm |
diff --git a/util/mac/mac_util_test.mm b/util/mac/mac_util_test.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5c1366fb53b2bbb60b47c4ce5e98d22345f5c030 |
--- /dev/null |
+++ b/util/mac/mac_util_test.mm |
@@ -0,0 +1,149 @@ |
+// 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 "util/mac/mac_util.h" |
+ |
+#import <Foundation/Foundation.h> |
+#include <stdlib.h> |
+ |
+#include <string> |
+ |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/strings/stringprintf.h" |
+#include "gtest/gtest.h" |
+ |
+#ifdef __GLIBCXX__ |
+// When C++ exceptions are disabled, libstdc++ from GCC 4.2 defines |try| and |
+// |catch| so as to allow exception-expecting C++ code to build properly when |
+// language support for exceptions is not present. These macros interfere with |
+// the use of |@try| and |@catch| in Objective-C files such as this one. |
+// Undefine these macros here, after everything has been #included, since there |
+// will be no C++ uses and only Objective-C uses from this point on. |
+#undef try |
+#undef catch |
+#endif |
+ |
+namespace { |
+ |
+using namespace crashpad; |
+ |
+// Runs /usr/bin/sw_vers with a single argument, |argument|, and places the |
+// command’s standard output into |output| after stripping the trailing newline. |
+// Fatal gtest assertions report tool failures, which the caller should check |
+// for with testing::Test::HasFatalFailure(). |
+void SwVers(NSString* argument, std::string* output) { |
+ @autoreleasepool { |
+ base::scoped_nsobject<NSPipe> pipe([[NSPipe alloc] init]); |
+ base::scoped_nsobject<NSTask> task([[NSTask alloc] init]); |
+ [task setStandardOutput:pipe]; |
+ [task setLaunchPath:@"/usr/bin/sw_vers"]; |
+ [task setArguments:@[ argument ]]; |
+ |
+ @try { |
+ [task launch]; |
+ } |
+ @catch (NSException* exception) { |
+ FAIL() << [[exception name] UTF8String] << ": " |
+ << [[exception reason] UTF8String]; |
+ } |
+ |
+ NSData* data = [[pipe fileHandleForReading] readDataToEndOfFile]; |
+ [task waitUntilExit]; |
+ |
+ ASSERT_EQ(NSTaskTerminationReasonExit, [task terminationReason]); |
+ ASSERT_EQ(EXIT_SUCCESS, [task terminationStatus]); |
+ |
+ output->assign(reinterpret_cast<const char*>([data bytes]), [data length]); |
+ |
+ EXPECT_EQ('\n', output->at(output->size() - 1)); |
+ output->resize(output->size() - 1); |
+ } |
+} |
+ |
+TEST(MacUtil, MacOSXVersion) { |
+ int major; |
+ int minor; |
+ int bugfix; |
+ std::string build; |
+ bool server; |
+ std::string version_string; |
+ ASSERT_TRUE( |
+ MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string)); |
+ |
+ std::string version; |
+ if (bugfix) { |
+ version = base::StringPrintf("%d.%d.%d", major, minor, bugfix); |
+ } else { |
+ // 10.x.0 releases report their version string as simply 10.x. |
+ version = base::StringPrintf("%d.%d", major, minor); |
+ } |
+ |
+ std::string expected_product_version; |
+ SwVers(@"-productVersion", &expected_product_version); |
+ if (Test::HasFatalFailure()) { |
+ return; |
+ } |
+ |
+ EXPECT_EQ(expected_product_version, version); |
+ |
+ std::string expected_build_version; |
+ SwVers(@"-buildVersion", &expected_build_version); |
+ if (Test::HasFatalFailure()) { |
+ return; |
+ } |
+ |
+ EXPECT_EQ(expected_build_version, build); |
+ |
+ std::string expected_product_name; |
+ SwVers(@"-productName", &expected_product_name); |
+ if (Test::HasFatalFailure()) { |
+ return; |
+ } |
+ |
+ // Look for a space after the product name in the complete version string. |
+ expected_product_name += ' '; |
+ EXPECT_EQ(0u, version_string.find(expected_product_name)); |
+} |
+ |
+TEST(MacUtil, MacOSXMinorVersion) { |
+ // Make sure that MacOSXMinorVersion() and MacOSXVersion() agree. The two have |
+ // their own distinct implementations, and the latter was checked against |
+ // sw_vers above. |
+ int major; |
+ int minor; |
+ int bugfix; |
+ std::string build; |
+ bool server; |
+ std::string version_string; |
+ ASSERT_TRUE( |
+ MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string)); |
+ |
+ EXPECT_EQ(minor, MacOSXMinorVersion()); |
+} |
+ |
+TEST(MacUtil, MacModelAndBoard) { |
+ // There’s not much that can be done to test these, so just make sure they’re |
+ // not empty. The model could be compared against the parsed output of |
+ // “system_profiler SPHardwareDataType”, but the board doesn’t show up |
+ // anywhere other than the I/O Registry, and that’s exactly how |
+ // MacModelAndBoard() gets the data, so it wouldn’t be a very useful test. |
+ std::string model; |
+ std::string board; |
+ MacModelAndBoard(&model, &board); |
+ |
+ EXPECT_FALSE(model.empty()); |
+ EXPECT_FALSE(board.empty()); |
+} |
+ |
+} // namespace |