PageRenderTime 119ms CodeModel.GetById 35ms app.highlight 79ms RepoModel.GetById 1ms app.codeStats 0ms

/core/externals/update-engine/externals/google-toolbox-for-mac/Foundation/GTMScriptRunnerTest.m

http://macfuse.googlecode.com/
Objective C | 471 lines | 325 code | 82 blank | 64 comment | 3 complexity | c87e05d04f4825b37c4da570c4822882 MD5 | raw file
  1//
  2//  GTMScriptRunnerTest.m
  3//
  4//  Copyright 2007-2008 Google Inc.
  5//
  6//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
  7//  use this file except in compliance with the License.  You may obtain a copy
  8//  of the License at
  9// 
 10//  http://www.apache.org/licenses/LICENSE-2.0
 11// 
 12//  Unless required by applicable law or agreed to in writing, software
 13//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 14//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
 15//  License for the specific language governing permissions and limitations under
 16//  the License.
 17//
 18
 19#import <sys/types.h>
 20#import <unistd.h>
 21#import "GTMSenTestCase.h"
 22#import "GTMScriptRunner.h"
 23#import "GTMUnitTestDevLog.h"
 24
 25@interface GTMScriptRunnerTest : GTMTestCase {
 26 @private 
 27  NSString *shScript_;
 28  NSString *perlScript_;
 29  NSString *shOutputScript_;
 30}
 31@end
 32
 33@interface GTMScriptRunnerTest (PrivateMethods)
 34- (void)helperTestBourneShellUsingScriptRunner:(GTMScriptRunner *)sr;
 35@end
 36
 37@implementation GTMScriptRunnerTest
 38
 39- (void)setUp {
 40  shScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_%d_%d_sh", geteuid(), getpid()];
 41  [@"#!/bin/sh\n"
 42   @"i=1\n"
 43   @"if [ -n \"$1\" ]; then\n"
 44   @"  i=$1\n"
 45   @"fi\n"
 46   @"echo $i\n"
 47   writeToFile:shScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil];
 48  
 49  perlScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_%d_%d_pl", geteuid(), getpid()];
 50  [@"#!/usr/bin/perl\n"
 51   @"use strict;\n"
 52   @"my $i = 1;\n"
 53   @"if (defined $ARGV[0]) {\n"
 54   @"  $i = $ARGV[0];\n"
 55   @"}\n"
 56   @"print \"$i\n\"\n"
 57   writeToFile:perlScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil];
 58
 59  shOutputScript_ = [NSString stringWithFormat:@"/tmp/script_runner_unittest_err_%d_%d_sh", geteuid(), getpid()];
 60  [@"#!/bin/sh\n"
 61   @"if [ \"err\" = \"$1\" ]; then\n"
 62   @"  echo \" on err \" > /dev/stderr\n"
 63   @"else\n"
 64   @"  echo \" on out \"\n"
 65   @"fi\n"
 66   writeToFile:shOutputScript_ atomically:YES encoding:NSUTF8StringEncoding error:nil];
 67}
 68
 69- (void)tearDown {
 70  const char *path = [shScript_ fileSystemRepresentation];
 71  if (path) {
 72    unlink(path);
 73  }
 74  path = [perlScript_ fileSystemRepresentation];
 75  if (path) {
 76    unlink(path);
 77  }
 78  path = [shOutputScript_ fileSystemRepresentation];
 79  if (path) {
 80    unlink(path);
 81  }
 82}
 83
 84- (void)testShCommands {
 85  GTMScriptRunner *sr = [GTMScriptRunner runner];
 86  [self helperTestBourneShellUsingScriptRunner:sr];
 87}
 88
 89- (void)testBashCommands {
 90  GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash];
 91  [self helperTestBourneShellUsingScriptRunner:sr];
 92}
 93
 94- (void)testZshCommands {
 95  GTMScriptRunner *sr = [GTMScriptRunner runnerWithInterpreter:@"/bin/zsh"];
 96  [self helperTestBourneShellUsingScriptRunner:sr];
 97}
 98
 99- (void)testBcCommands {
100  GTMScriptRunner *sr = [GTMScriptRunner runnerWithInterpreter:@"/usr/bin/bc"
101                                                    withArgs:[NSArray arrayWithObject:@"-lq"]];
102  STAssertNotNil(sr, @"Script runner must not be nil");
103  NSString *output = nil;
104  
105  // Simple expression (NOTE that bc requires that commands end with a newline)
106  output = [sr run:@"1 + 2\n"];
107  STAssertEqualObjects(output, @"3", @"output should equal '3'");
108  
109  // Simple expression with variables and multiple statements
110  output = [sr run:@"i=1; i+2\n"];
111  STAssertEqualObjects(output, @"3", @"output should equal '3'");
112  
113  // Simple expression with base conversion
114  output = [sr run:@"obase=2; 2^5\n"];
115  STAssertEqualObjects(output, @"100000", @"output should equal '100000'");
116  
117  // Simple expression with sine and cosine functions
118  output = [sr run:@"scale=3;s(0)+c(0)\n"];
119  STAssertEqualObjects(output, @"1.000", @"output should equal '1.000'");
120}
121
122- (void)testPerlCommands {
123  GTMScriptRunner *sr = [GTMScriptRunner runnerWithPerl];
124  STAssertNotNil(sr, @"Script runner must not be nil");
125  NSString *output = nil;
126  
127  // Simple print
128  output = [sr run:@"print 'hi'"];
129  STAssertEqualObjects(output, @"hi", @"output should equal 'hi'");
130  
131  // Simple print x4
132  output = [sr run:@"print 'A'x4"];
133  STAssertEqualObjects(output, @"AAAA", @"output should equal 'AAAA'");
134  
135  // Simple perl-y stuff
136  output = [sr run:@"my $i=0; until ($i++==41){} print $i"];
137  STAssertEqualObjects(output, @"42", @"output should equal '42'");
138}
139
140- (void)testPythonCommands {
141  GTMScriptRunner *sr = [GTMScriptRunner runnerWithPython];
142  STAssertNotNil(sr, @"Script runner must not be nil");
143  NSString *output = nil;
144  
145  // Simple print
146  output = [sr run:@"print 'hi'"];
147  STAssertEqualObjects(output, @"hi", @"output should equal 'hi'");
148  
149  // Simple python expression
150  output = [sr run:@"print '-'.join(['a', 'b', 'c'])"];
151  STAssertEqualObjects(output, @"a-b-c", @"output should equal 'a-b-c'");
152}
153
154- (void)testBashScript {
155  GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash];
156  STAssertNotNil(sr, @"Script runner must not be nil");
157  NSString *output = nil;
158  
159  // Simple sh script
160  output = [sr runScript:shScript_];
161  STAssertEqualObjects(output, @"1", @"output should equal '1'");
162  
163  // Simple sh script with 1 command line argument
164  output = [sr runScript:shScript_ withArgs:[NSArray arrayWithObject:@"2"]];
165  STAssertEqualObjects(output, @"2", @"output should equal '2'");
166}
167
168- (void)testPerlScript {
169  GTMScriptRunner *sr = [GTMScriptRunner runnerWithPerl];
170  STAssertNotNil(sr, @"Script runner must not be nil");
171  NSString *output = nil;
172  
173  // Simple Perl script
174  output = [sr runScript:perlScript_];
175  STAssertEqualObjects(output, @"1", @"output should equal '1'");
176  
177  // Simple perl script with 1 command line argument
178  output = [sr runScript:perlScript_ withArgs:[NSArray arrayWithObject:@"2"]];
179  STAssertEqualObjects(output, @"2", @"output should equal '2'");
180}
181
182- (void)testEnvironment {
183  GTMScriptRunner *sr = [GTMScriptRunner runner];
184  STAssertNotNil(sr, @"Script runner must not be nil");
185  NSString *output = nil;
186  NSString *error = nil;
187  STAssertNil([sr environment], @"should start w/ empty env");
188  
189  output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
190  int numVars = [output intValue];
191  STAssertGreaterThan(numVars, 0, 
192                      @"numVars should be positive. StdErr %@", error);
193  // By default the environment is wiped clean, however shells often add a few
194  // of their own env vars after things have been wiped. For example, sh will 
195  // add about 3 env vars (PWD, _, and SHLVL).
196  STAssertLessThan(numVars, 5, @"Our env should be almost empty");
197  
198  NSDictionary *newEnv = [NSDictionary dictionaryWithObject:@"bar"
199                                                     forKey:@"foo"];
200  [sr setEnvironment:newEnv];
201  output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
202  STAssertEquals([output intValue], numVars + 1,
203               @"should have one more env var now. StdErr %@", error);
204  
205  [sr setEnvironment:nil];
206  output = [sr run:@"/usr/bin/env | wc -l" standardError:&error];
207  STAssertEquals([output intValue], numVars,
208               @"should be back down to %d vars. StdErr:%@", numVars, error);
209  
210  NSMutableDictionary *currVars 
211    = [[[[NSProcessInfo processInfo] environment] mutableCopy] autorelease];
212  
213  // When debugging a release build _ was not in the processInfo environment
214  // causing the assert below to fail. Not sure why, but it appeared
215  // to be harmless, and easy to account for.
216  [currVars setObject:@"/usr/bin/env" forKey:@"_"];
217  [sr setEnvironment:currVars];
218  
219  output = [sr run:@"/usr/bin/env | /usr/bin/sort" standardError:&error];
220  NSArray *lineArray = [output componentsSeparatedByString:@"\n"];
221  STAssertEquals([lineArray count], [currVars count],
222                 @"StdErr:%@\nCurrentEnvironment:\n%@\nExpected environment:\n%@", 
223                 error, output, currVars);
224}
225
226- (void)testDescription {
227  // make sure description doesn't choke
228  GTMScriptRunner *sr = [GTMScriptRunner runner];
229  STAssertNotNil(sr, @"Script runner must not be nil");
230  STAssertGreaterThan([[sr description] length], (NSUInteger)10,
231                      @"expected a description of at least 10 chars");
232}
233
234- (void)testRunCommandOutputHandling {
235  // Test whitespace trimming & stdout vs. stderr w/ run command api
236  
237  GTMScriptRunner *sr = [GTMScriptRunner runnerWithBash];
238  STAssertNotNil(sr, @"Script runner must not be nil");
239  NSString *output = nil;
240  NSString *err = nil;
241  
242  // w/o whitespace trimming
243  {
244    [sr setTrimsWhitespace:NO];
245    STAssertFalse([sr trimsWhitespace], @"setTrimsWhitespace to NO failed");
246    
247    // test stdout
248    output = [sr run:@"echo \" on out \"" standardError:&err];
249    STAssertEqualObjects(output, @" on out \n", @"failed to get stdout output");
250    STAssertNil(err, @"stderr should have been empty");
251    
252    // test stderr
253    output = [sr run:@"echo \" on err \" > /dev/stderr" standardError:&err];
254    STAssertNil(output, @"stdout should have been empty");
255    STAssertEqualObjects(err, @" on err \n", nil);
256  }
257  
258  // w/ whitespace trimming
259  {
260    [sr setTrimsWhitespace:YES];
261    STAssertTrue([sr trimsWhitespace], @"setTrimsWhitespace to YES failed");
262    
263    // test stdout
264    output = [sr run:@"echo \" on out \"" standardError:&err];
265    STAssertEqualObjects(output, @"on out", @"failed to get stdout output");
266    STAssertNil(err, @"stderr should have been empty");
267    
268    // test stderr
269    output = [sr run:@"echo \" on err \" > /dev/stderr" standardError:&err];
270    STAssertNil(output, @"stdout should have been empty");
271    STAssertEqualObjects(err, @"on err", nil);
272  }
273}
274
275- (void)testScriptOutputHandling {
276  // Test whitespace trimming & stdout vs. stderr w/ script api
277
278  GTMScriptRunner *sr = [GTMScriptRunner runner];
279  STAssertNotNil(sr, @"Script runner must not be nil");
280  NSString *output = nil;
281  NSString *err = nil;
282
283  // w/o whitespace trimming
284  {
285    [sr setTrimsWhitespace:NO];
286    STAssertFalse([sr trimsWhitespace], @"setTrimsWhitespace to NO failed");
287  
288    // test stdout
289    output = [sr runScript:shOutputScript_
290                  withArgs:[NSArray arrayWithObject:@"out"]
291             standardError:&err];
292    STAssertEqualObjects(output, @" on out \n", nil);
293    STAssertNil(err, @"stderr should have been empty");
294    
295    // test stderr
296    output = [sr runScript:shOutputScript_
297                  withArgs:[NSArray arrayWithObject:@"err"]
298             standardError:&err];
299    STAssertNil(output, @"stdout should have been empty");
300    STAssertEqualObjects(err, @" on err \n", nil);
301  }
302  
303  // w/ whitespace trimming
304  {
305    [sr setTrimsWhitespace:YES];
306    STAssertTrue([sr trimsWhitespace], @"setTrimsWhitespace to YES failed");
307    
308    // test stdout
309    output = [sr runScript:shOutputScript_
310                  withArgs:[NSArray arrayWithObject:@"out"]
311             standardError:&err];
312    STAssertEqualObjects(output, @"on out", nil);
313    STAssertNil(err, @"stderr should have been empty");
314    
315    // test stderr
316    output = [sr runScript:shOutputScript_
317                  withArgs:[NSArray arrayWithObject:@"err"]
318             standardError:&err];
319    STAssertNil(output, @"stdout should have been empty");
320    STAssertEqualObjects(err, @"on err", nil);
321  }
322}
323
324- (void)testBadRunCommandInput {
325  GTMScriptRunner *sr = [GTMScriptRunner runner];
326  STAssertNotNil(sr, @"Script runner must not be nil");
327  NSString *err = nil;
328  
329  STAssertNil([sr run:nil standardError:&err], nil);
330  STAssertNil(err, nil);
331}
332
333- (void)testBadScriptInput {
334  GTMScriptRunner *sr = [GTMScriptRunner runner];
335  STAssertNotNil(sr, @"Script runner must not be nil");
336  NSString *err = nil;
337  
338  STAssertNil([sr runScript:nil withArgs:nil standardError:&err], nil);
339  STAssertNil(err, nil);
340  STAssertNil([sr runScript:@"/path/that/does/not/exists/foo/bar/baz"
341                   withArgs:nil standardError:&err], nil);
342  STAssertNotNil(err,
343                 @"should have gotten something about the path not existing");
344}
345
346- (void)testBadCmdInterpreter {
347  GTMScriptRunner *sr =
348    [GTMScriptRunner runnerWithInterpreter:@"/path/that/does/not/exists/interpreter"];
349  STAssertNotNil(sr, @"Script runner must not be nil");
350  NSString *err = nil;
351  
352  STAssertNil([sr run:nil standardError:&err], nil);
353  STAssertNil(err, nil);
354  [GTMUnitTestDevLog expectString:@"Failed to launch interpreter "
355   "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"];
356  STAssertNil([sr run:@"ls /" standardError:&err], nil);
357  STAssertNil(err, nil);
358}
359
360- (void)testBadScriptInterpreter {
361  GTMScriptRunner *sr =
362    [GTMScriptRunner runnerWithInterpreter:@"/path/that/does/not/exists/interpreter"];
363  STAssertNotNil(sr, @"Script runner must not be nil");
364  NSString *err = nil;
365  
366  [GTMUnitTestDevLog expectString:@"Failed to launch interpreter "
367   "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"];
368  STAssertNil([sr runScript:shScript_ withArgs:nil standardError:&err], nil);
369  STAssertNil(err, nil);
370  [GTMUnitTestDevLog expectString:@"Failed to launch interpreter "
371   "'/path/that/does/not/exists/interpreter' due to: launch path not accessible"];
372  STAssertNil([sr runScript:@"/path/that/does/not/exists/foo/bar/baz"
373                   withArgs:nil standardError:&err], nil);
374  STAssertNil(err, nil);
375}
376
377- (void)testLargeOutput {
378  // These tests cover the issues found in
379  //   http://code.google.com/p/google-toolbox-for-mac/issues/detail?id=25
380
381  GTMScriptRunner *sr = [GTMScriptRunner runnerWithPython];
382  STAssertNotNil(sr, @"Script runner must not be nil");
383  NSString *output = nil, *err = nil, *cmd = nil;
384  
385  #define GENERATOR_FORMAT_STR \
386    @"import sys\n" \
387    @"block  = '.' * 512\n" \
388    @"for x in [%@]:\n" \
389    @"  to_where = x[0]\n" \
390    @"  how_many = int(x[1:])\n" \
391    @"  for x in xrange(0, how_many):\n" \
392    @"    if to_where in [ 'o', 'b' ]:\n" \
393    @"      sys.stdout.write(block)\n" \
394    @"    if to_where in [ 'e', 'b' ]:\n" \
395    @"      sys.stderr.write(block)\n"
396    
397  // Make sure we get both blocks
398  cmd = [NSString stringWithFormat:GENERATOR_FORMAT_STR, @"'b1'"];
399  STAssertNotNil(cmd, nil);
400  output = [sr run:cmd standardError:&err];
401  STAssertEquals([output length], (NSUInteger)512, nil);
402  STAssertEquals([err length], (NSUInteger)512, nil);
403  
404  // Test a large amount of data on only one connections at a time.
405  cmd = [NSString stringWithFormat:GENERATOR_FORMAT_STR, @"'b1', 'o200'"];
406  STAssertNotNil(cmd, nil);
407  output = [sr run:cmd standardError:&err];
408  STAssertEquals([output length], (NSUInteger)(512 + 512*200), nil);
409  STAssertEquals([err length], (NSUInteger)512, nil);
410
411  cmd = [NSString stringWithFormat:GENERATOR_FORMAT_STR, @"'b1', 'e200'"];
412  STAssertNotNil(cmd, nil);
413  output = [sr run:cmd standardError:&err];
414  STAssertEquals([output length], (NSUInteger)512, nil);
415  STAssertEquals([err length], (NSUInteger)(512 + 512*200), nil);
416
417  // Now send a large amount down both to make sure we spool it all in.
418  cmd = [NSString stringWithFormat:GENERATOR_FORMAT_STR, @"'b200'"];
419  STAssertNotNil(cmd, nil);
420  output = [sr run:cmd standardError:&err];
421  STAssertEquals([output length], (NSUInteger)(512*200), nil);
422  STAssertEquals([err length], (NSUInteger)(512*200), nil);
423}
424
425
426@end
427
428@implementation GTMScriptRunnerTest (PrivateMethods)
429
430- (void)helperTestBourneShellUsingScriptRunner:(GTMScriptRunner *)sr {
431  STAssertNotNil(sr, @"Script runner must not be nil");
432  NSString *output = nil;
433  
434  // Simple command
435  output = [sr run:@"ls /etc/passwd"];
436  STAssertEqualObjects(output, @"/etc/passwd", @"output should equal '/etc/passwd'");
437  
438  // Simple command pipe-line
439  output = [sr run:@"ls /etc/ | grep passwd | tail -1"];
440  STAssertEqualObjects(output, @"passwd", @"output should equal 'passwd'");
441  
442  // Simple pipe-line with quotes and awk variables
443  output = [sr run:@"ps jaxww | awk '{print $2}' | sort -nr | tail -2 | head -1"];
444  STAssertEqualObjects(output, @"1", @"output should equal '1'");
445  
446  // Simple shell loop with variables
447  output = [sr run:@"i=0; while [ $i -lt 100 ]; do i=$((i+1)); done; echo $i"];
448  STAssertEqualObjects(output, @"100", @"output should equal '100'");
449  
450  // Simple command with newlines
451  output = [sr run:@"i=1\necho $i"];
452  STAssertEqualObjects(output, @"1", @"output should equal '1'");
453  
454  // Simple full shell script
455  output = [sr run:@"#!/bin/sh\ni=1\necho $i\n"];
456  STAssertEqualObjects(output, @"1", @"output should equal '1'");
457  
458  NSString *err = nil;
459  
460  // Test getting standard error with no stdout
461  output = [sr run:@"ls /etc/does-not-exist" standardError:&err];
462  STAssertNil(output, @"output should be nil due to expected error");
463  STAssertEqualObjects(err, @"ls: /etc/does-not-exist: No such file or directory", @"");
464  
465  // Test getting standard output along with some standard error
466  output = [sr run:@"ls /etc/does-not-exist /etc/passwd" standardError:&err];
467  STAssertEqualObjects(output, @"/etc/passwd", @"");
468  STAssertEqualObjects(err, @"ls: /etc/does-not-exist: No such file or directory", @"");
469}
470
471@end