1/* 2 Copyright (C) 2007-2010 Stig Brautaset. 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 are met: 6 7 * Redistributions of source code must retain the above copyright notice, this 8 list of conditions and the following disclaimer. 9 10 * Redistributions in binary form must reproduce the above copyright notice, 11 this list of conditions and the following disclaimer in the documentation 12 and/or other materials provided with the distribution. 13 14 * Neither the name of the author nor the names of its contributors may be used 15 to endorse or promote products derived from this software without specific 16 prior written permission. 17 18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE 22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#import "ErrorTest.h" 31#import <JSON/JSON.h> 32 33#define assertErrorContains(e, s) \ 34 STAssertTrue([[e localizedDescription] hasPrefix:s], @"%@", [e userInfo]) 35 36#define assertUnderlyingErrorContains(e, s) \ 37 STAssertTrue([[[[e userInfo] objectForKey:NSUnderlyingErrorKey] localizedDescription] hasPrefix:s], @"%@", [e userInfo]) 38 39#define assertUnderlyingErrorContains2(e, s) \ 40 STAssertTrue([[[[[[e userInfo] objectForKey:NSUnderlyingErrorKey] userInfo] objectForKey:NSUnderlyingErrorKey] localizedDescription] hasPrefix:s], @"%@", [e userInfo]) 41 42@implementation ErrorTest 43 44#pragma mark Generator 45 46- (void)testUnsupportedObject 47{ 48 NSError *error = nil; 49 STAssertNil([writer stringWithObject:[NSData data] error:&error], nil); 50 STAssertNotNil(error, nil); 51} 52 53- (void)testNonStringDictionaryKey 54{ 55 NSArray *keys = [NSArray arrayWithObjects:[NSNull null], 56 [NSNumber numberWithInt:1], 57 [NSArray array], 58 [NSDictionary dictionary], 59 nil]; 60 61 for (int i = 0; i < [keys count]; i++) { 62 NSError *error = nil; 63 NSDictionary *object = [NSDictionary dictionaryWithObject:@"1" forKey:[keys objectAtIndex:i]]; 64 STAssertNil([writer stringWithObject:object error:&error], nil); 65 STAssertNotNil(error, nil); 66 } 67} 68 69 70- (void)testScalar 71{ 72 NSArray *fragments = [NSArray arrayWithObjects:@"foo", @"", [NSNull null], [NSNumber numberWithInt:1], [NSNumber numberWithBool:YES], nil]; 73 for (int i = 0; i < [fragments count]; i++) { 74 NSString *fragment = [fragments objectAtIndex:i]; 75 76 // We don't check the convenience category here, like we do for parsing, 77 // because the category is explicitly on the NSArray and NSDictionary objects. 78 // STAssertNil([fragment JSONRepresentation], nil); 79 80 NSError *error = nil; 81 STAssertNil([writer stringWithObject:fragment error:&error], @"%@", fragment); 82 assertErrorContains(error, @"Not valid type for JSON"); 83 } 84} 85 86- (void)testInfinity { 87 NSArray *obj = [NSArray arrayWithObject:[NSNumber numberWithDouble:INFINITY]]; 88 NSError *error = nil; 89 STAssertNil([writer stringWithObject:obj error:&error], nil); 90 assertUnderlyingErrorContains(error, @"Infinity is not a valid number in JSON"); 91} 92 93- (void)testNegativeInfinity { 94 NSArray *obj = [NSArray arrayWithObject:[NSNumber numberWithDouble:-INFINITY]]; 95 NSError *error = nil; 96 STAssertNil([writer stringWithObject:obj error:&error], nil); 97 assertUnderlyingErrorContains(error, @"Infinity is not a valid number in JSON"); 98} 99 100- (void)testNaN { 101 NSArray *obj = [NSArray arrayWithObject:[NSDecimalNumber notANumber]]; 102 NSError *error = nil; 103 STAssertNil([writer stringWithObject:obj error:&error], nil); 104 assertUnderlyingErrorContains(error, @"NaN is not a valid number in JSON"); 105} 106 107#pragma mark Scanner 108 109- (void)testArray { 110 NSError *error; 111 112 STAssertNil([parser objectWithString:@"[1,,2]" error:&error], nil); 113 assertErrorContains(error, @"Expected value"); 114 115 STAssertNil([parser objectWithString:@"[1,,]" error:&error], nil); 116 assertErrorContains(error, @"Expected value"); 117 118 STAssertNil([parser objectWithString:@"[,1]" error:&error], nil); 119 assertErrorContains(error, @"Expected value"); 120 121 122 STAssertNil([parser objectWithString:@"[1,]" error:&error], nil); 123 assertErrorContains(error, @"Trailing comma disallowed"); 124 125 126 STAssertNil([parser objectWithString:@"[1" error:&error], nil); 127 assertErrorContains(error, @"End of input while parsing array"); 128 129 STAssertNil([parser objectWithString:@"[[]" error:&error], nil); 130 assertErrorContains(error, @"End of input while parsing array"); 131 132 // See if seemingly-valid arrays have nasty elements 133 STAssertNil([parser objectWithString:@"[+1]" error:&error], nil); 134 assertErrorContains(error, @"Expected value"); 135 assertUnderlyingErrorContains(error, @"Leading + disallowed"); 136} 137 138- (void)testObject { 139 NSError *error; 140 141 STAssertNil([parser objectWithString:@"{1" error:&error], nil); 142 assertErrorContains(error, @"Object key string expected"); 143 144 STAssertNil([parser objectWithString:@"{null" error:&error], nil); 145 assertErrorContains(error, @"Object key string expected"); 146 147 STAssertNil([parser objectWithString:@"{\"a\":1,,}" error:&error], nil); 148 assertErrorContains(error, @"Object key string expected"); 149 150 STAssertNil([parser objectWithString:@"{,\"a\":1}" error:&error], nil); 151 assertErrorContains(error, @"Object key string expected"); 152 153 154 STAssertNil([parser objectWithString:@"{\"a\"" error:&error], nil); 155 assertErrorContains(error, @"Expected ':'"); 156 157 158 STAssertNil([parser objectWithString:@"{\"a\":" error:&error], nil); 159 assertErrorContains(error, @"Object value expected"); 160 161 STAssertNil([parser objectWithString:@"{\"a\":," error:&error], nil); 162 assertErrorContains(error, @"Object value expected"); 163 164 165 STAssertNil([parser objectWithString:@"{\"a\":1,}" error:&error], nil); 166 assertErrorContains(error, @"Trailing comma disallowed"); 167 168 169 STAssertNil([parser objectWithString:@"{" error:&error], nil); 170 assertErrorContains(error, @"End of input while parsing object"); 171 172 STAssertNil([parser objectWithString:@"{\"a\":{}" error:&error], nil); 173 assertErrorContains(error, @"End of input while parsing object"); 174} 175 176- (void)testNumber { 177 NSError *error; 178 179 STAssertNil([parser objectWithString:@"[-" error:&error], nil); 180 assertUnderlyingErrorContains(error, @"No digits after initial minus"); 181 182 STAssertNil([parser objectWithString:@"[+1" error:&error], nil); 183 assertUnderlyingErrorContains(error, @"Leading + disallowed in number"); 184 185 STAssertNil([parser objectWithString:@"[01" error:&error], nil); 186 assertUnderlyingErrorContains(error, @"Leading 0 disallowed in number"); 187 188 STAssertNil([parser objectWithString:@"[0." error:&error], nil); 189 assertUnderlyingErrorContains(error, @"No digits after decimal point"); 190 191 192 STAssertNil([parser objectWithString:@"[1e" error:&error], nil); 193 assertUnderlyingErrorContains(error, @"No digits after exponent"); 194 195 STAssertNil([parser objectWithString:@"[1e-" error:&error], nil); 196 assertUnderlyingErrorContains(error, @"No digits after exponent"); 197 198 STAssertNil([parser objectWithString:@"[1e+" error:&error], nil); 199 assertUnderlyingErrorContains(error, @"No digits after exponent"); 200} 201 202- (void)testNull { 203 NSError *error; 204 205 STAssertNil([parser objectWithString:@"[nil" error:&error], nil); 206 assertUnderlyingErrorContains(error, @"Expected 'null'"); 207} 208 209- (void)testBool { 210 NSError *error; 211 212 STAssertNil([parser objectWithString:@"[truth" error:&error], nil); 213 assertUnderlyingErrorContains(error, @"Expected 'true'"); 214 215 STAssertNil([parser objectWithString:@"[fake" error:&error], nil); 216 assertUnderlyingErrorContains(error, @"Expected 'false'"); 217} 218 219- (void)testString { 220 NSError *error; 221 222 STAssertNil([parser objectWithString:@"" error:&error], nil); 223 assertErrorContains(error, @"Unexpected end of string"); 224 225 STAssertNil([parser objectWithString:@"" error:&error], nil); 226 assertErrorContains(error, @"Unexpected end of string"); 227 228 STAssertNil([parser objectWithString:@"[\"" error:&error], nil); 229 assertUnderlyingErrorContains(error, @"Unescaped control character"); 230 231 STAssertNil([parser objectWithString:@"[\"foo" error:&error], nil); 232 assertUnderlyingErrorContains(error, @"Unescaped control character"); 233 234 235 STAssertNil([parser objectWithString:@"[\"\\uD834foo\"" error:&error], nil); 236 assertUnderlyingErrorContains(error, @"Broken unicode character"); 237 assertUnderlyingErrorContains2(error, @"Missing low character"); 238 239 STAssertNil([parser objectWithString:@"[\"\\uD834\\u001E\"" error:&error], nil); 240 assertUnderlyingErrorContains(error, @"Broken unicode character"); 241 assertUnderlyingErrorContains2(error, @"Invalid low surrogate"); 242 243 STAssertNil([parser objectWithString:@"[\"\\uDD1Ef\"" error:&error], nil); 244 assertUnderlyingErrorContains(error, @"Broken unicode character"); 245 assertUnderlyingErrorContains2(error, @"Invalid high character"); 246 247 248 for (NSUInteger i = 0; i < 0x20; i++) { 249 NSString *str = [NSString stringWithFormat:@"\"[%C\"", i]; 250 STAssertNil([parser objectWithString:str error:&error], nil); 251 assertErrorContains(error, @"Unescaped control character"); 252 } 253} 254 255- (void)testObjectGarbage { 256 NSError *error; 257 258 STAssertNil([parser objectWithString:@"['1'" error:&error], nil); 259 assertUnderlyingErrorContains(error, @"Unrecognised leading character"); 260 261 STAssertNil([parser objectWithString:@"['hello'" error:&error], nil); 262 assertUnderlyingErrorContains(error, @"Unrecognised leading character"); 263 264 STAssertNil([parser objectWithString:@"[**" error:&error], nil); 265 assertUnderlyingErrorContains(error, @"Unrecognised leading character"); 266 267 STAssertNil([parser objectWithString:nil error:&error], nil); 268 assertErrorContains(error, @"Input was 'nil'"); 269} 270 271@end 272