iOS Simulator LayoutTestRelay
[WebKit-https.git] / Tools / LayoutTestRelay / LayoutTestRelay / LTPipeRelay.m
1 /*
2  * Copyright (C) 2014 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "LTPipeRelay.h"
27
28 #import <Foundation/Foundation.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 @interface LTPipeRelay ()
33 @property (readonly, strong) NSString *fifoPrefix;
34 @property (strong) NSOutputStream *standardInputPipe;
35 @property (strong) NSInputStream *standardOutputPipe;
36 @property (strong) NSInputStream *standardErrorPipe;
37
38 - (void)createFIFOs;
39 - (void)destroyFIFOs;
40 @end
41
42 @implementation LTPipeRelay
43
44 - (NSString *)inPipePath
45 {
46     return [_fifoPrefix stringByAppendingString:@"_IN"];
47 }
48
49 - (NSString *)outPipePath
50 {
51     return [_fifoPrefix stringByAppendingString:@"_OUT"];
52 }
53
54 - (NSString *)errorPipePath
55 {
56     return [_fifoPrefix stringByAppendingString:@"_ERROR"];
57 }
58
59 - (NSOutputStream *) outputStream
60 {
61     return _standardInputPipe;
62 }
63
64 - (id)initWithPrefix:(NSString *)prefix
65 {
66     if ((self = [super init])) {
67         _fifoPrefix = prefix;
68         [self destroyFIFOs];
69     }
70     return self;
71 }
72
73 - (void)setup
74 {
75     [self destroyFIFOs];
76     [self createFIFOs];
77 }
78
79 - (void)tearDown
80 {
81     [self destroyFIFOs];
82 }
83
84 -(void) connect
85 {
86     _standardInputPipe = [NSOutputStream outputStreamToFileAtPath:[self inPipePath] append:YES];
87     _standardOutputPipe = [NSInputStream inputStreamWithFileAtPath:[self outPipePath]];
88     _standardErrorPipe = [NSInputStream inputStreamWithFileAtPath:[self errorPipePath]];
89
90     [[self standardInputPipe] setDelegate:self];
91     [[self standardOutputPipe] setDelegate:self];
92     [[self standardErrorPipe] setDelegate:self];
93
94     [[self standardOutputPipe] scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
95     [[self standardErrorPipe] scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
96
97     [[self standardInputPipe] open];
98     [[self standardOutputPipe] open];
99     [[self standardErrorPipe] open];
100
101     [[self relayDelegate] didConnect];
102 }
103
104 - (void)disconnect
105 {
106     [[self standardOutputPipe] close];
107     [[self standardErrorPipe] close];
108     [[self standardInputPipe] close];
109     [[self relayDelegate] didDisconnect];
110 }
111
112 - (void)createFIFOs
113 {
114     mkfifo([[self inPipePath] UTF8String], 0666);
115     mkfifo([[self outPipePath] UTF8String], 0666);
116     mkfifo([[self errorPipePath] UTF8String], 0666);
117 }
118
119 - (void)destroyFIFOs
120 {
121     unlink([[self inPipePath] UTF8String]);
122     unlink([[self outPipePath] UTF8String]);
123     unlink([[self errorPipePath] UTF8String]);
124 }
125
126 - (void) relayStream:(NSInputStream *)stream
127 {
128     uint8_t bytes[1024];
129     NSInteger bytesRead = [stream read:bytes maxLength:1024];
130     NSData *data = [NSData dataWithBytes:bytes length:bytesRead];
131
132     if (stream == [self standardOutputPipe])
133         [[self relayDelegate] didReceiveStdoutData:data];
134     else
135         [[self relayDelegate] didReceiveStderrData:data];
136 }
137
138 - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
139 {
140     switch (eventCode) {
141     case NSStreamEventNone:
142         break;
143     case NSStreamEventHasBytesAvailable:
144         [self relayStream:(NSInputStream *)aStream];
145     case NSStreamEventHasSpaceAvailable:
146         break;
147     case NSStreamEventOpenCompleted:
148         break;
149     case NSStreamEventEndEncountered:
150         [[self relayDelegate] didCrashWithMessage:nil];
151         break;
152     case NSStreamEventErrorOccurred:
153         [[self relayDelegate] didCrashWithMessage:[[aStream streamError] description]];
154         break;
155     }
156 }
157
158 @end