From 1057c99ca375a6b53ca079cede47fe2e9dce4d8b Mon Sep 17 00:00:00 2001 From: dmaclach Date: Thu, 3 Jan 2019 08:22:28 -0800 Subject: Add GTMTimeUtils (#229) Utilities for relatively common desire to know the launch time of an app, or the boot time of a device. --- Foundation/GTMTimeUtils.h | 35 +++++++++++++++++++++ Foundation/GTMTimeUtils.m | 72 +++++++++++++++++++++++++++++++++++++++++++ Foundation/GTMTimeUtilsTest.m | 45 +++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 Foundation/GTMTimeUtils.h create mode 100644 Foundation/GTMTimeUtils.m create mode 100644 Foundation/GTMTimeUtilsTest.m (limited to 'Foundation') diff --git a/Foundation/GTMTimeUtils.h b/Foundation/GTMTimeUtils.h new file mode 100644 index 0000000..9b49532 --- /dev/null +++ b/Foundation/GTMTimeUtils.h @@ -0,0 +1,35 @@ +// +// GTMTimeUtils.h +// +// Copyright 2018 Google LLC +// +// 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. +// + +#import + +// Return the date that the app was launched. +NSDate *GTMAppLaunchDate(void); + +// Return the date that the device was started. Note on the simulator that this +// returns the date that the computer was started, not the simulator. +NSDate *GTMBootDate(void); + +// Convert a timeval to NSTimeInterval. +NSTimeInterval GTMTimeValToNSTimeInterval(struct timeval time); + +// Timeval versions of the functions above if timevals are a more useful +// structure to work with. +struct timeval GTMBootTimeRelativeTo1970(void); +struct timeval GTMAppLaunchTimeRelativeTo1970(void); + diff --git a/Foundation/GTMTimeUtils.m b/Foundation/GTMTimeUtils.m new file mode 100644 index 0000000..2b551e4 --- /dev/null +++ b/Foundation/GTMTimeUtils.m @@ -0,0 +1,72 @@ +// +// GTMTimeUtils.m +// +// Copyright 2018 Google LLC +// +// 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. +// + +#import "GTMTimeUtils.h" + +#include + +#import "GTMDefines.h" + +NSTimeInterval GTMTimeValToNSTimeInterval(struct timeval time) { + return time.tv_sec + (time.tv_usec / (double)USEC_PER_SEC); +} + +struct timeval GTMBootTimeRelativeTo1970(void) { + struct timeval bootTime = { 0, 0 }; + int mib[2] = { CTL_KERN, KERN_BOOTTIME }; + size_t bootTimeSize = sizeof(bootTime); + if (sysctl(mib, 2, &bootTime, &bootTimeSize, NULL, 0) != 0) { + _GTMDevAssert(errno == 0, @"sysctl error - %d", errno); + struct timeval invalid = { 0, 0 }; + return invalid; + } + return bootTime; +} + +struct timeval GTMAppLaunchTimeRelativeTo1970(void) { + id_t pid = getpid(); + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid }; + const size_t mibSize = sizeof(mib) / sizeof(mib[0]); + size_t infoSize = 0; + + // Get initial size of KERN_PROC data structure. + if (sysctl(mib, mibSize, NULL, &infoSize, NULL, 0) != 0) { + _GTMDevAssert(errno == 0, @"sysctl error - %d", errno); + struct timeval invalid = { 0, 0 }; + return invalid; + } + struct kinfo_proc info; + if (sysctl(mib, mibSize, &info, &infoSize, NULL, 0) != 0) { + _GTMDevAssert(errno == 0, @"sysctl error - %d", errno); + struct timeval invalid = { 0, 0 }; + return invalid; + } + return info.kp_proc.p_starttime; +} + +NSDate *GTMAppLaunchDate() { + NSTimeInterval ti = + GTMTimeValToNSTimeInterval(GTMAppLaunchTimeRelativeTo1970()); + return [NSDate dateWithTimeIntervalSince1970:ti]; +} + +NSDate *GTMBootDate() { + NSTimeInterval ti = + GTMTimeValToNSTimeInterval(GTMBootTimeRelativeTo1970()); + return [NSDate dateWithTimeIntervalSince1970:ti]; +} diff --git a/Foundation/GTMTimeUtilsTest.m b/Foundation/GTMTimeUtilsTest.m new file mode 100644 index 0000000..471cad0 --- /dev/null +++ b/Foundation/GTMTimeUtilsTest.m @@ -0,0 +1,45 @@ +// +// GTMTimeUtilsTest.m +// +// Copyright 2018 Google LLC +// +// 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. +// + +#import "GTMSenTestCase.h" +#import "GTMTimeUtils.h" + +@interface GTMTimeUtilsTest : GTMTestCase +@end + +@implementation GTMTimeUtilsTest + +- (void)testAppLaunchDate { + // Basic test to verify that "now" is after appLaunch. + NSDate *now = [NSDate date]; + NSDate *appLaunch = GTMAppLaunchDate(); + + XCTAssertEqual([now compare:appLaunch], NSOrderedDescending, + @"now: %@ appLaunch: %@", now, appLaunch); +} + +- (void)testBootDate { + // Basic test to verify that appLaunch occurred after boot. + NSDate *appLaunch = GTMAppLaunchDate(); + NSDate *boot = GTMBootDate(); + + XCTAssertEqual([appLaunch compare:boot], NSOrderedDescending, + @"appLaunch: %@ boot: %@", appLaunch, boot); +} + +@end -- cgit v1.2.3