blob: dac2028dc21a2aa26805c562d85e7676805fe699 [file] [log] [blame]
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "DaemonTestUtilities.h"
#if PLATFORM(MAC) || PLATFORM(IOS)
#import <mach-o/dyld.h>
#import <wtf/Vector.h>
NS_ASSUME_NONNULL_BEGIN
#if PLATFORM(IOS)
@interface NSTask : NSObject
- (instancetype)init;
- (void)launch;
- (void)waitUntilExit;
@property (nullable, copy) NSString *launchPath;
@property (nullable, copy) NSArray<NSString *> *arguments;
@property (nullable, retain) id standardOutput;
@property (readonly, getter=isRunning) BOOL running;
@end
#endif
namespace TestWebKitAPI {
static RetainPtr<NSURL> currentExecutableLocation()
{
uint32_t size { 0 };
_NSGetExecutablePath(nullptr, &size);
Vector<char> buffer;
buffer.resize(size + 1);
_NSGetExecutablePath(buffer.data(), &size);
buffer[size] = '\0';
auto pathString = adoptNS([[NSString alloc] initWithUTF8String:buffer.data()]);
return adoptNS([[NSURL alloc] initFileURLWithPath:pathString.get() isDirectory:NO]);
}
RetainPtr<NSURL> currentExecutableDirectory()
{
return [currentExecutableLocation() URLByDeletingLastPathComponent];
}
#if HAVE(OS_LAUNCHD_JOB)
void registerPlistWithLaunchD(RetainPtr<xpc_object_t>&& plist)
{
NSError *error = nil;
auto launchDJob = adoptNS([[OSLaunchdJob alloc] initWithPlist:plist.get()]);
[launchDJob submit:&error];
// In the iOS Simulator we often see the following error here:
// Error Domain=OSLaunchdErrorDomain Code=17 "File exists"
// Tests still behave as expected.
#if PLATFORM(MAC)
EXPECT_FALSE(error);
#endif
}
#else // HAVE(OS_LAUNCHD_JOB)
void registerPlistWithLaunchD(RetainPtr<NSDictionary>&& plist, NSURL *tempDir)
{
NSError *error = nil;
NSURL *plistLocation = [tempDir URLByAppendingPathComponent:@"DaemonInfo.plist"];
BOOL success = [[NSFileManager defaultManager] createDirectoryAtURL:tempDir withIntermediateDirectories:YES attributes:nil error:&error];
EXPECT_TRUE(success);
EXPECT_FALSE(error);
success = [plist writeToURL:plistLocation error:&error];
EXPECT_TRUE(success);
system([NSString stringWithFormat:@"launchctl unload %@ 2> /dev/null", plistLocation.path].fileSystemRepresentation);
system([NSString stringWithFormat:@"launchctl load %@", plistLocation.path].fileSystemRepresentation);
EXPECT_FALSE(error);
}
#endif // HAVE(OS_LAUNCHD_JOB)
static int pidOfFirstDaemonInstance(NSString *daemonExecutableName)
{
auto task = adoptNS([[NSTask alloc] init]);
task.get().launchPath = @"/bin/ps";
task.get().arguments = @[
@"-ax",
@"-o",
@"pid,comm"
];
auto taskPipe = adoptNS([[NSPipe alloc] init]);
[task setStandardOutput:taskPipe.get()];
[task launch];
auto data = adoptNS([[NSMutableData alloc] init]);
while ([task isRunning])
[data appendData:[[taskPipe fileHandleForReading] readDataToEndOfFile]];
[data appendData:[[taskPipe fileHandleForReading] readDataToEndOfFile]];
auto psString = adoptNS([[NSString alloc] initWithData:data.get() encoding:NSUTF8StringEncoding]);
NSArray<NSString *> *psEntries = [psString componentsSeparatedByString:@"\n"];
for (NSString* entry in psEntries) {
if (![entry hasSuffix:daemonExecutableName])
continue;
NSArray<NSString *> *components = [entry componentsSeparatedByString:@" "];
EXPECT_GE([components count], 2u);
return [[components firstObject] integerValue];
}
return 0;
}
void killFirstInstanceOfDaemon(NSString *daemonExecutableName)
{
auto pid = pidOfFirstDaemonInstance(daemonExecutableName);
if (!pid)
return;
auto task = adoptNS([[NSTask alloc] init]);
task.get().launchPath = @"/bin/kill";
task.get().arguments = @[
@"-9",
[@(pid) stringValue]
];
[task launch];
[task waitUntilExit];
}
} // namespace TestWebKitAPI
NS_ASSUME_NONNULL_END
#endif // PLATFORM(MAC) || PLATFORM(IOS)