ASIHTTPRequestTests.m
75.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
//
// ASIHTTPRequestTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 01/08/2008.
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import "ASIHTTPRequestTests.h"
#import "ASIHTTPRequest.h"
#import "ASINetworkQueue.h"
#import "ASIFormDataRequest.h"
#import <SystemConfiguration/SystemConfiguration.h>
// Used for subclass test
@interface ASIHTTPRequestSubclass : ASIHTTPRequest {}
@end
@implementation ASIHTTPRequestSubclass;
// For testing exceptions are caught
- (void)startRequest
{
[[NSException exceptionWithName:@"Test Exception" reason:@"Test Reason" userInfo:nil] raise];
}
@end
@implementation ASIHTTPRequestTests
- (void)testBasicDownload
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *html = [request responseString];
GHAssertNotNil(html,@"Basic synchronous request failed");
// Check we're getting the correct response headers
NSString *pingBackHeader = [[request responseHeaders] objectForKey:@"X-Pingback"];
BOOL success = [pingBackHeader isEqualToString:@"http://allseeing-i.com/Ping-Back"];
GHAssertTrue(success,@"Failed to populate response headers");
// Check we're getting back the correct status code
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/a-page-that-does-not-exist"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = ([request responseStatusCode] == 404);
GHAssertTrue(success,@"Didn't get correct status code");
// Check data is as expected
NSRange notFound = NSMakeRange(NSNotFound, 0);
success = !NSEqualRanges([html rangeOfString:@"All-Seeing Interactive"],notFound);
GHAssertTrue(success,@"Failed to download the correct data");
// Attempt to grab from bad url
url = [[[NSURL alloc] initWithString:@""] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = [[request error] code] == ASIInternalErrorWhileBuildingRequestType;
GHAssertTrue(success,@"Failed to generate an error for a bad host");
request = [[[ASIHTTPRequest alloc] initWithURL:nil] autorelease];
[request startSynchronous];
success = [[request error] code] == ASIUnableToCreateRequestErrorType;
GHAssertTrue(success,@"Failed to generate an error for a bad host");
}
- (void)testCancel
{
// We run this test on the main thread because otherwise we can't depend on the delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(runCancelTest) withObject:nil waitUntilDone:YES];
}
- (void)runCancelTest
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
[request startAsynchronous];
[request cancel];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
GHAssertNotNil([request error],@"Failed to cancel the request");
// Test cancelling a redirected request works
// This test is probably unreliable on very slow or very fast connections, as it depends on being able to complete the first request (but not the second) in under 2 seconds
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cancel_redirect"]];
[request startAsynchronous];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
[request cancel];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
BOOL success = ([[[request url] absoluteString] isEqualToString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel.txt"]);
GHAssertTrue(success, @"Request did not redirect quickly enough, cannot proceed with test");
GHAssertNotNil([request error],@"Failed to cancel the request");
success = [request totalBytesRead] < 7900198;
GHAssertTrue(success, @"Downloaded the whole of the response even though we should have cancelled by now");
}
- (void)testDelegateMethods
{
// We run this test on the main thread because otherwise we can't depend on the delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(performDelegateMethodsTest) withObject:nil waitUntilDone:YES];
}
- (void)performDelegateMethodsTest
{
started = NO;
finished = NO;
failed = NO;
// Test default delegate methods
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setDelegate:self];
[request startSynchronous];
// Hacky, but this test won't run on the main thread, we have to hope the delegate methods will be called in this time
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
GHAssertTrue(started,@"Failed to call the delegate method when the request started");
GHAssertTrue(receivedResponseHeaders,@"Failed to call the delegate method when the request started");
GHAssertTrue(finished,@"Failed to call the delegate method when the request finished");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
[request setDelegate:self];
[request setTimeOutSeconds:0.01];
[request startSynchronous];
GHAssertTrue(failed,@"Failed to call the delegate method when the request failed");
started = NO;
finished = NO;
failed = NO;
receivedResponseHeaders = NO;
// Test custom delegate methods
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setDelegate:self];
[request setDidStartSelector:@selector(delegateTestStarted:)];
[request setDidReceiveResponseHeadersSelector:@selector(delegateTestResponseHeaders:)];
[request setDidFinishSelector:@selector(delegateTestFinished:)];
[request startSynchronous];
GHAssertTrue(started,@"Failed to call the delegate method when the request started");
GHAssertTrue(finished,@"Failed to call the delegate method when the request finished");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
[request setDidFailSelector:@selector(delegateTestFailed:)];
[request setDelegate:self];
[request setTimeOutSeconds:0.01];
[request startSynchronous];
GHAssertTrue(failed,@"Failed to call the delegate method when the request failed");
}
- (void)requestStarted:(ASIHTTPRequest *)request
{
started = YES;
}
- (void)requestReceivedResponseHeaders:(ASIHTTPRequest *)request
{
GHAssertNotNil([request responseHeaders],@"Called requestReceivedResponseHeaders: when we have no headers");
receivedResponseHeaders = YES;
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
finished = YES;
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
failed = YES;
}
- (void)delegateTestStarted:(ASIHTTPRequest *)request
{
started = YES;
}
- (void)delegateTestResponseHeaders:(ASIHTTPRequest *)request
{
GHAssertNotNil([request responseHeaders],@"Called delegateTestResponseHeaders: when we have no headers");
receivedResponseHeaders = YES;
}
- (void)delegateTestFinished:(ASIHTTPRequest *)request
{
finished = YES;
}
- (void)delegateTestFailed:(ASIHTTPRequest *)request
{
failed = YES;
}
- (void)testConditionalGET
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request startSynchronous];
BOOL success = ([request responseStatusCode] == 200);
GHAssertTrue(success, @"Failed to download file, cannot proceed with this test");
success = ([[request responseData] length] > 0);
GHAssertTrue(success, @"Response length is 0, this shouldn't happen");
NSString *etag = [[request responseHeaders] objectForKey:@"Etag"];
NSString *lastModified = [[request responseHeaders] objectForKey:@"Last-Modified"];
GHAssertNotNil(etag, @"Response didn't return an etag");
GHAssertNotNil(lastModified, @"Response didn't return a last modified date");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request addRequestHeader:@"If-Modified-Since" value:lastModified];
[request addRequestHeader:@"If-None-Match" value:etag];
[request startSynchronous];
success = ([request responseStatusCode] == 304);
GHAssertTrue(success, @"Got wrong status code");
success = ([[request responseData] length] == 0);
GHAssertTrue(success, @"Response length is not 0, this shouldn't happen");
}
- (void)testException
{
ASIHTTPRequestSubclass *request = [ASIHTTPRequestSubclass requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request startSynchronous];
NSError *error = [request error];
GHAssertNotNil(error,@"Failed to generate an error for an exception");
BOOL success = [[[error userInfo] objectForKey:NSLocalizedDescriptionKey] isEqualToString:@"Test Exception"];
GHAssertTrue(success, @"Generated wrong error for exception");
}
- (void)testCharacterEncoding
{
NSArray *IANAEncodings = [NSArray arrayWithObjects:@"UTF-8",@"US-ASCII",@"ISO-8859-1",@"UTF-16",nil];
NSUInteger NSStringEncodings[] = {NSUTF8StringEncoding,NSASCIIStringEncoding,NSISOLatin1StringEncoding,NSUnicodeStringEncoding};
NSUInteger i;
for (i=0; i<[IANAEncodings count]; i++) {
NSURL *url = [[[NSURL alloc] initWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/%@",[IANAEncodings objectAtIndex:i]]] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
BOOL success = [request responseEncoding] == NSStringEncodings[i];
GHAssertTrue(success,[NSString stringWithFormat:@"Failed to use the correct text encoding for %@i",[IANAEncodings objectAtIndex:i]]);
}
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/Something-else"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDefaultResponseEncoding:NSWindowsCP1251StringEncoding];
[request startSynchronous];
BOOL success = [request responseEncoding] == [request defaultResponseEncoding];
GHAssertTrue(success,[NSString stringWithFormat:@"Failed to use the default string encoding"]);
// Will return a Content-Type header with charset in the middle of the value (Fix contributed by Roman Busyghin)
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/utf-16-with-type-header"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = [request responseEncoding] == NSUnicodeStringEncoding;
GHAssertTrue(success,[NSString stringWithFormat:@"Failed to parse the content type header correctly"]);
}
- (void)testTimeOut
{
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setTimeOutSeconds:0.0001]; //It's pretty unlikely we will be able to grab the data this quickly, so the request should timeout
[request startSynchronous];
BOOL success = [[request error] code] == ASIRequestTimedOutErrorType;
GHAssertTrue(success,@"Timeout didn't generate the correct error");
[ASIHTTPRequest setDefaultTimeOutSeconds:0.0001];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = [[request error] code] == ASIRequestTimedOutErrorType;
GHAssertTrue(success,@"Failed to change the default timeout");
[ASIHTTPRequest setDefaultTimeOutSeconds:10];
}
// Test fix for a bug that might have caused timeouts when posting data
- (void)testTimeOutWithoutDownloadDelegate
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28young_readers_edition%29.txt"]];
[request setTimeOutSeconds:5];
[request setShowAccurateProgress:NO];
[request setPostBody:[NSMutableData dataWithData:[@"Small Body" dataUsingEncoding:NSUTF8StringEncoding]]];
[request startSynchronous];
GHAssertNil([request error],@"Generated an error (most likely a timeout) - this test might fail on high latency connections");
}
- (void)testRequestMethod
{
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/request-method"] autorelease];
NSArray *methods = [[[NSArray alloc] initWithObjects:@"GET",@"POST",@"PUT",@"DELETE", nil] autorelease];
for (NSString *method in methods) {
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setRequestMethod:method];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:method];
GHAssertTrue(success,@"Failed to set the request method correctly");
}
// Test to ensure we don't change the request method when we have an unrecognised method already set
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setRequestMethod:@"FINK"];
[request appendPostData:[@"King" dataUsingEncoding:NSUTF8StringEncoding]];
[request buildPostBody];
BOOL success = [[request requestMethod] isEqualToString:@"FINK"];
GHAssertTrue(success,@"Erroneously changed request method");
}
- (void)testHTTPVersion
{
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/http-version"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:@"HTTP/1.1"];
GHAssertTrue(success,@"Wrong HTTP version used (May fail when using a proxy that changes the HTTP version!)");
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseHTTPVersionOne:YES];
[request startSynchronous];
success = [[request responseString] isEqualToString:@"HTTP/1.0"];
GHAssertTrue(success,@"Wrong HTTP version used (May fail when using a proxy that changes the HTTP version!)");
}
- (void)testUserAgent
{
// defaultUserAgentString will be nil if we haven't set a Bundle Name or Bundle Display Name
if ([ASIHTTPRequest defaultUserAgentString]) {
// Returns the user agent it received in the response body
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/user-agent"]];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:[ASIHTTPRequest defaultUserAgentString]];
GHAssertTrue(success,@"Failed to set the correct user agent");
}
// Now test specifying a custom user agent
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/user-agent"]];
[request addRequestHeader:@"User-Agent" value:@"Ferdinand Fuzzworth's Magic Tent of Mystery"];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:@"Ferdinand Fuzzworth's Magic Tent of Mystery"];
GHAssertTrue(success,@"Failed to set the correct user agent");
}
- (void)testAutomaticRedirection
{
ASIHTTPRequest *request;
ASIFormDataRequest *request2;
BOOL success;
unsigned int i;
for (i=301; i<308; i++) {
if (i > 304 && i < 307) {
continue;
}
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/%hi",i]];
request = [ASIHTTPRequest requestWithURL:url];
[request setShouldRedirect:NO];
[request startSynchronous];
if (i == 304) { // 304s will not contain a body, as per rfc2616. Will test 304 handling in a future test when we have etag support
continue;
}
success = [[request responseString] isEqualToString:[NSString stringWithFormat:@"Non-redirected content with %hi status code",i]];
GHAssertTrue(success,[NSString stringWithFormat:@"Got the wrong content when not redirecting after a %hi",i]);
request2 = [ASIFormDataRequest requestWithURL:url];
[request2 setPostValue:@"Giant Monkey" forKey:@"lookbehindyou"];
[request2 startSynchronous];
NSString *method = @"GET";
if (i>304) {
method = @"POST";
}
NSString *expectedString = [NSString stringWithFormat:@"Redirected as %@ after a %hi status code",method,i];
if (i>304) {
expectedString = [NSString stringWithFormat:@"%@\r\nWatch out for the Giant Monkey!",expectedString];
}
success = [[request2 responseString] isEqualToString:expectedString];
GHAssertTrue(success,[NSString stringWithFormat:@"Got the wrong content when redirecting after a %hi",i]);
success = ([request2 responseStatusCode] == 200);
GHAssertTrue(success,@"Got the wrong status code (expected 200)");
}
// Test RFC 2616 behaviour
for (i=301; i<303; i++) {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/%hi",i]];
request2 = [ASIFormDataRequest requestWithURL:url];
[request2 setPostValue:@"Giant Monkey" forKey:@"lookbehindyou"];
[request2 setShouldUseRFC2616RedirectBehaviour:YES];
[request2 startSynchronous];
success = ([request2 responseStatusCode] == 200);
GHAssertTrue(success,@"Got the wrong status code (expected 200)");
if (i == 303) {
success = ([request2 postLength] == 0 && ![request2 postBody] && [[request2 requestMethod] isEqualToString:@"GET"]);
GHAssertTrue(success,@"Failed to reset request to GET on 303 redirect");
success = [[request2 responseString] isEqualToString:[NSString stringWithFormat:@"Redirected as GET after a %hi status code",i]];
GHAssertTrue(success,@"Failed to dump the post body on 303 redirect");
} else {
success = ([request2 postLength] > 0 || ![request2 postBody] || ![[request2 requestMethod] isEqualToString:@"POST"]);
GHAssertTrue(success,@"Failed to use the same request method and body for a redirect when using rfc2616 behaviour");
success = ([[request2 responseString] isEqualToString:[NSString stringWithFormat:@"Redirected as POST after a %hi status code\r\nWatch out for the Giant Monkey!",i]]);
GHAssertTrue(success,@"Failed to send the correct post body on redirect");
}
}
// Ensure the file contains only the body of the last request (after redirects) when downloading to a file
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/301"]];
NSString *path = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"test.txt"];
[request setDownloadDestinationPath:path];
[request startSynchronous];
NSString *result = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
success = [result isEqualToString:@"Redirected as GET after a 301 status code"];
GHAssertTrue(success,@"Failed to store just the body of the file request on redirect");
success = ([request originalURL] != [request url]);
GHAssertTrue(success,@"Failed to update request url on redirection");
success = ([[[request originalURL] absoluteString] isEqualToString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/301"]);
GHAssertTrue(success,@"Failed to preserve original url");
// Ensure user agent is preserved
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/301"]];
[request addRequestHeader:@"User-Agent" value:@"test"];
[request startSynchronous];
success = ([[[request requestHeaders] objectForKey:@"User-Agent"] isEqualToString:@"test"]);
GHAssertTrue(success,@"Failed to preserve original user agent on redirect");
}
// Using a persistent connection for HTTP 305-307 would cause crashes on the redirect, not really sure why
// Since 305 (use proxy) wasn't properly supported anyway, 306 is unused, and clients are supposed to confirm redirects for 307, I've simply removed automatic redirect for these codes
- (void)test30xCrash
{
int i;
for (i=305; i<308; i++) {
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/%hi",i]]];
[request setPostValue:@"foo" forKey:@"eep"];
[request setShouldRedirect:NO];
[request startSynchronous];
request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect/%hi",i]]];
[request setPostValue:@"foo" forKey:@"eep"];
[request startSynchronous];
}
}
- (void)testResumeChecksContentRangeHeader
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/no_resume"];
NSString *temporaryPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.temp"];
[@"" writeToFile:temporaryPath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.txt"];
// Download part of a large file that is returned after a redirect
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setTemporaryFileDownloadPath:temporaryPath];
[request setDownloadDestinationPath:downloadPath];
[request setAllowResumeForFileDownloads:YES];
[request setAllowCompressedResponse:NO];
[request setShouldAttemptPersistentConnection:NO];
[request startAsynchronous];
// Cancel the request as soon as it has downloaded 64KB
while (1) {
sleep(0.5);
if ([request totalBytesRead] > 32*1024) {
[request cancel];
break;
}
}
NSNumber *fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:temporaryPath error:NULL] objectForKey:NSFileSize];
unsigned long long partialFileSize = [fileSize unsignedLongLongValue];
BOOL success = (partialFileSize < 1036935);
GHAssertTrue(success,@"Downloaded whole file too quickly, cannot proceed with this test");
// Resume the download
request = [ASIHTTPRequest requestWithURL:url];
[request setTemporaryFileDownloadPath:temporaryPath];
[request setDownloadDestinationPath:downloadPath];
[request setAllowResumeForFileDownloads:YES];
[request setAllowCompressedResponse:NO];
[request buildRequestHeaders];
success = ([request partialDownloadSize] == partialFileSize);
GHAssertTrue(success,@"Failed to obtain correct partial dowload size");
[request startAsynchronous];
while (1) {
sleep(0.5);
if ([request isFinished]) {
break;
}
}
GHAssertNil([request error],@"Request failed, cannot proceed with this test");
success = (![[request responseHeaders] objectForKey:@"Content-Range"]);
GHAssertTrue(success,@"Got range header back, cannot proceed with this test");
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:downloadPath error:NULL];
fileSize = [attributes objectForKey:NSFileSize];
success = ([fileSize intValue] == 1036935);
GHAssertTrue(success,@"Downloaded file has wrong length");
success = ([request partialDownloadSize] == 0);
GHAssertTrue(success,@"Failed to reset download size");
}
- (void)testRedirectedResume
{
[self performSelectorOnMainThread:@selector(runRedirectedResume) withObject:nil waitUntilDone:YES];
}
- (void)runRedirectedResume
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect_resume"];
NSString *temporaryPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.temp"];
[@"" writeToFile:temporaryPath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"foo.txt"];
// Download part of a large file that is returned after a redirect
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setTemporaryFileDownloadPath:temporaryPath];
[request setDownloadDestinationPath:downloadPath];
[request setAllowResumeForFileDownloads:YES];
[request setAllowCompressedResponse:NO];
[request startAsynchronous];
// Cancel the request as soon as it has downloaded 64KB
while (1) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
if ([request totalBytesRead] > 32*1024) {
[request cancel];
break;
}
}
NSNumber *fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:temporaryPath error:NULL] objectForKey:NSFileSize];
unsigned long long partialFileSize = [fileSize unsignedLongLongValue];
BOOL success = (partialFileSize < 1036935);
GHAssertTrue(success,@"Downloaded whole file too quickly, cannot proceed with this test");
// Resume the download synchronously
request = [ASIHTTPRequest requestWithURL:url];
[request setTemporaryFileDownloadPath:temporaryPath];
[request setDownloadDestinationPath:downloadPath];
[request setAllowResumeForFileDownloads:YES];
[request setAllowCompressedResponse:NO];
[request startSynchronous];
fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:downloadPath error:NULL] objectForKey:NSFileSize];
success = ([fileSize intValue] == 1036935);
GHAssertTrue(success,@"Downloaded file has wrong length");
success = [[[request requestHeaders] objectForKey:@"Range"] isEqualToString:[NSString stringWithFormat:@"bytes=%llu-",partialFileSize]];
GHAssertTrue(success,@"Restarted download when we should have resumed, or asked for the wrong segment of the file");
}
- (void)testUploadContentLength
{
//This url will return the contents of the Content-Length request header
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-length"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setPostBody:[NSMutableData dataWithLength:1024*32]];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"%hu",(1024*32)]]);
GHAssertTrue(success,@"Sent wrong content length");
}
- (void)testDownloadContentLength
{
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/i/logo.png"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
BOOL success = ([request contentLength] == 27872);
GHAssertTrue(success,@"Got wrong content length");
}
- (void)testFileDownload
{
NSString *path = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testimage.png"];
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/i/logo.png"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadDestinationPath:path];
[request startSynchronous];
#if TARGET_OS_IPHONE
UIImage *image = [[[UIImage alloc] initWithContentsOfFile:path] autorelease];
#else
NSImage *image = [[[NSImage alloc] initWithContentsOfFile:path] autorelease];
#endif
GHAssertNotNil(image,@"Failed to download data to a file");
}
- (void)testCompressedResponseDownloadToFile
{
NSString *path = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile"];
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/first"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadDestinationPath:path];
[request startSynchronous];
NSString *tempPath = [request temporaryFileDownloadPath];
GHAssertNil(tempPath,@"Failed to clean up temporary download file");
//BOOL success = (![[NSFileManager defaultManager] fileExistsAtPath:tempPath]);
//GHAssertTrue(success,@"Failed to remove file from temporary location");
BOOL success = [[NSString stringWithContentsOfURL:[NSURL fileURLWithPath:path] encoding:NSUTF8StringEncoding error:NULL] isEqualToString:@"This is the expected content for the first string"];
GHAssertTrue(success,@"Failed to download data to a file");
}
- (void)testDownloadProgress
{
// We run tests that measure progress on the main thread because otherwise we can't depend on the progress delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(performDownloadProgressTest) withObject:nil waitUntilDone:YES];
}
- (void)performDownloadProgressTest
{
progress = 0;
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/i/logo.png"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadProgressDelegate:self];
[request startSynchronous];
BOOL success = (progress == 1.0);
GHAssertTrue(success,@"Failed to properly increment download progress %f != 1.0",progress);
progress = 0;
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel.txt"]];
[request setDownloadProgressDelegate:self];
[request startAsynchronous];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
success = (progress != 1.0);
GHAssertTrue(success,@"Downloaded too quickly, cannot proceed with test");
success = (progress > 0);
GHAssertTrue(success,@"Either downloaded too slowly, or progress is not being correctly updated");
}
- (void)testUploadProgress
{
// We run tests that measure progress on the main thread because otherwise we can't depend on the progress delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(performUploadProgressTest) withObject:nil waitUntilDone:YES];
}
- (void)performUploadProgressTest
{
progress = 0;
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ignore"]] autorelease];
[request setPostBody:(NSMutableData *)[@"This is the request body" dataUsingEncoding:NSUTF8StringEncoding]];
[request setUploadProgressDelegate:self];
[request startSynchronous];
BOOL success = (progress == 1.0);
GHAssertTrue(success,@"Failed to properly increment upload progress %f != 1.0",progress);
}
- (void)testPostBodyStreamedFromDisk
{
// We run tests that measure progress on the main thread because otherwise we can't depend on the progress delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(performPostBodyStreamedFromDiskTest) withObject:nil waitUntilDone:YES];
}
- (void)performPostBodyStreamedFromDiskTest
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/print_request_body"];
NSString *requestBody = @"This is the request body";
NSString *requestContentPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
[[requestBody dataUsingEncoding:NSUTF8StringEncoding] writeToFile:requestContentPath atomically:NO];
// Test using a user-specified file as the request body (useful for PUT)
progress = 0;
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setRequestMethod:@"PUT"];
[request setShouldStreamPostDataFromDisk:YES];
[request setUploadProgressDelegate:self];
[request setPostBodyFilePath:requestContentPath];
[request startSynchronous];
BOOL success = (progress == 1.0);
GHAssertTrue(success,@"Failed to properly increment upload progress %f != 1.0",progress);
success = [[request responseString] isEqualToString:requestBody];
GHAssertTrue(success,@"Failed upload the correct request body");
// Test building a request body by appending data
progress = 0;
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setShouldStreamPostDataFromDisk:YES];
[request setRequestMethod:@"PUT"];
[request setUploadProgressDelegate:self];
[request appendPostDataFromFile:requestContentPath];
[request startSynchronous];
success = (progress == 1.0);
GHAssertTrue(success,@"Failed to properly increment upload progress %f != 1.0",progress);
success = [[request responseString] isEqualToString:requestBody];
GHAssertTrue(success,@"Failed upload the correct request body");
}
- (void)testCookies
{
BOOL success;
// Set setting a cookie
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/set_cookie"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:YES];
[request startSynchronous];
NSString *html = [request responseString];
success = [html isEqualToString:@"I have set a cookie"];
GHAssertTrue(success,@"Failed to set a cookie");
// Test a cookie is stored in responseCookies
NSArray *cookies = [request responseCookies];
GHAssertNotNil(cookies,@"Failed to store cookie data in responseCookies");
// Test the cookie contains the correct data
NSHTTPCookie *cookie = nil;
BOOL foundCookie = NO;
for (cookie in cookies) {
if ([[cookie name] isEqualToString:@"ASIHTTPRequestTestCookie"]) {
foundCookie = YES;
success = [[cookie value] isEqualToString:@"This+is+the+value"];
GHAssertTrue(success,@"Failed to store the correct value for a cookie");
success = [[cookie domain] isEqualToString:@"allseeing-i.com"];
GHAssertTrue(success,@"Failed to store the correct domain for a cookie");
success = [[cookie path] isEqualToString:@"/ASIHTTPRequest/tests"];
GHAssertTrue(success,@"Failed to store the correct path for a cookie");
break;
}
}
GHAssertTrue(foundCookie,@"Failed store a particular cookie - can't continue with the rest of the tests");
if (!foundCookie) {
return;
}
// Test a cookie is presented when manually added to the request
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"I have 'This is the value' as the value of 'ASIHTTPRequestTestCookie'"];
GHAssertTrue(success,@"Cookie not presented to the server with cookie persistence OFF");
// Test a cookie is presented from the persistent store
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:YES];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"I have 'This is the value' as the value of 'ASIHTTPRequestTestCookie'"];
GHAssertTrue(success,@"Cookie not presented to the server with cookie persistence ON");
// Test removing a cookie
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/remove_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"I have removed a cookie"];
GHAssertTrue(success,@"Failed to remove a cookie");
// Test making sure cookie was properly removed
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"No cookie exists"];
GHAssertTrue(success,@"Cookie presented to the server when it should have been removed");
// Test setting a custom cookie works
NSDictionary *cookieProperties = [[[NSMutableDictionary alloc] init] autorelease];
// We'll add a line break to our cookie value to test it gets correctly encoded
[cookieProperties setValue:@"Test%0D%0AValue" forKey:NSHTTPCookieValue];
[cookieProperties setValue:@"ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName];
[cookieProperties setValue:@"allseeing-i.com" forKey:NSHTTPCookieDomain];
[cookieProperties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60*4] forKey:NSHTTPCookieExpires];
[cookieProperties setValue:@"/ASIHTTPRequest/tests" forKey:NSHTTPCookiePath];
cookie = [[[NSHTTPCookie alloc] initWithProperties:cookieProperties] autorelease];
GHAssertNotNil(cookie,@"Failed to create a cookie - cookie value was not correctly encoded?");
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"I have 'Test\r\nValue' as the value of 'ASIHTTPRequestTestCookie'"];
GHAssertTrue(success,@"Custom cookie not presented to the server with cookie persistence OFF");
// Test removing all cookies works
[ASIHTTPRequest clearSession];
NSArray *sessionCookies = [ASIHTTPRequest sessionCookies];
success = ([sessionCookies count] == 0);
GHAssertTrue(success,@"Cookies not removed");
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:YES];
[request startSynchronous];
html = [request responseString];
success = [html isEqualToString:@"No cookie exists"];
GHAssertTrue(success,@"Cookie presented to the server when it should have been removed");
// Test fetching cookies for a relative url - fixes a problem where urls created with URLWithString:relativeToURL: wouldn't always read cookies from the persistent store
[ASIHTTPRequest clearSession];
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/set_cookie"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:YES];
[request setUseSessionPersistence:NO];
[request startSynchronous];
NSURL *originalURL = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/"];
url = [NSURL URLWithString:@"read_cookie" relativeToURL:originalURL];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseCookiePersistence:YES];
[request setUseSessionPersistence:NO];
[request startSynchronous];
html = [request responseString];
NSLog(@"%@",html);
success = [html isEqualToString:@"I have 'This is the value' as the value of 'ASIHTTPRequestTestCookie'"];
GHAssertTrue(success,@"Custom cookie not presented to the server with cookie persistence OFF");
}
// Test fix for a crash if you tried to remove credentials that didn't exist
- (void)testRemoveCredentialsFromKeychain
{
[ASIHTTPRequest removeCredentialsForHost:@"apple.com" port:0 protocol:@"http" realm:@"Nothing to see here"];
[ASIHTTPRequest removeCredentialsForProxy:@"apple.com" port:0 realm:@"Nothing to see here"];
}
- (void)testBasicAuthentication
{
[ASIHTTPRequest removeCredentialsForHost:@"allseeing-i.com" port:0 protocol:@"http" realm:@"SECRET_STUFF"];
[ASIHTTPRequest clearSession];
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"];
ASIHTTPRequest *request;
BOOL success;
NSError *err;
// Test authentication needed when no credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to generate permission denied error with no credentials");
// Test wrong credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request setUsername:@"wrong"];
[request setPassword:@"wrong"];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to generate permission denied error with wrong credentials");
// Test correct credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:YES];
[request setShouldPresentCredentialsBeforeChallenge:NO];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to supply correct username and password");
// Ensure credentials are not reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:NO];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Reused credentials when we shouldn't have");
// Ensure credentials stored in the session are reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to reuse credentials");
[ASIHTTPRequest clearSession];
// Ensure credentials stored in the session were wiped
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to clear credentials");
// Ensure credentials stored in the keychain are reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:YES];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to use stored credentials");
[ASIHTTPRequest removeCredentialsForHost:@"allseeing-i.com" port:0 protocol:@"http" realm:@"SECRET_STUFF"];
// Ensure credentials stored in the keychain were wiped
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:YES];
[request setUseSessionPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to clear credentials");
// Tests shouldPresentCredentialsBeforeChallenge with credentials stored in the session
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request startSynchronous];
success = [request authenticationRetryCount] == 0;
GHAssertTrue(success,@"Didn't supply credentials before being asked for them when talking to the same server with shouldPresentCredentialsBeforeChallenge == YES");
// Ensure credentials stored in the session were not presented to the server before it asked for them
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setShouldPresentCredentialsBeforeChallenge:NO];
[request startSynchronous];
success = [request authenticationRetryCount] == 1;
GHAssertTrue(success,@"Supplied session credentials before being asked for them");
[ASIHTTPRequest clearSession];
// Test credentials set on the request are sent before the server asks for them
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:NO];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request setShouldPresentCredentialsBeforeChallenge:YES];
[request startSynchronous];
success = [request authenticationRetryCount] == 0;
GHAssertTrue(success,@"Didn't supply credentials before being asked for them, even though they were set on the request and shouldPresentCredentialsBeforeChallenge == YES");
// Test credentials set on the request aren't sent before the server asks for them
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:NO];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request setShouldPresentCredentialsBeforeChallenge:NO];
[request startSynchronous];
success = [request authenticationRetryCount] == 1;
GHAssertTrue(success,@"Supplied request credentials before being asked for them");
// Test credentials presented before a challenge are stored in the session store
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request setShouldPresentCredentialsBeforeChallenge:YES];
[request startSynchronous];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to use stored credentials");
// Ok, now let's test on a different server to sanity check that the credentials from out previous requests are not being used
url = [NSURL URLWithString:@"https://selfsigned.allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:NO];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Reused credentials when we shouldn't have");
}
- (void)testDigestAuthentication
{
[ASIHTTPRequest removeCredentialsForHost:@"allseeing-i.com" port:0 protocol:@"http" realm:@"Keep out"];
[ASIHTTPRequest clearSession];
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/digest-authentication"] autorelease];
ASIHTTPRequest *request;
BOOL success;
NSError *err;
// Test authentication needed when no credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to generate permission denied error with no credentials");
// Test wrong credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request setUsername:@"wrong"];
[request setPassword:@"wrong"];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to generate permission denied error with wrong credentials");
// Test correct credentials supplied
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:YES];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to supply correct username and password");
// Ensure credentials are not reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:NO];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Reused credentials when we shouldn't have");
// Ensure credentials stored in the session are reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to reuse credentials");
[ASIHTTPRequest clearSession];
// Ensure credentials stored in the session were wiped
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to clear credentials");
// Ensure credentials stored in the keychain are reused
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:YES];
[request startSynchronous];
err = [request error];
GHAssertNil(err,@"Failed to reuse credentials");
[ASIHTTPRequest removeCredentialsForHost:@"allseeing-i.com" port:0 protocol:@"http" realm:@"Keep out"];
// Ensure credentials stored in the keychain were wiped
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistence:YES];
[request setUseSessionPersistence:NO];
[request startSynchronous];
success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to clear credentials");
// Test credentials set on the request are sent before the server asks for them
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseSessionPersistence:YES];
[request setShouldPresentCredentialsBeforeChallenge:YES];
[request startSynchronous];
success = [request authenticationRetryCount] == 0;
GHAssertTrue(success,@"Didn't supply credentials before being asked for them, even though they were set in the session and shouldPresentCredentialsBeforeChallenge == YES");
}
- (void)testNTLMHandshake
{
// This test connects to a script that masquerades as an NTLM server
// It tests that the handshake seems sane, but doesn't actually authenticate
[ASIHTTPRequest clearSession];
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/pretend-ntlm-handshake"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUseKeychainPersistence:NO];
[request setUseSessionPersistence:NO];
[request startSynchronous];
BOOL success = [[request error] code] == ASIAuthenticationErrorType;
GHAssertTrue(success,@"Failed to generate permission denied error with no credentials");
request = [ASIHTTPRequest requestWithURL:url];
[request setUseSessionPersistence:YES];
[request setUseKeychainPersistence:NO];
[request setUsername:@"king"];
[request setPassword:@"fink"];
[request setDomain:@"Castle.Kingdom"];
[request startSynchronous];
GHAssertNil([request error],@"Got an error when credentials were supplied");
// NSProcessInfo returns a lower case string for host name, while CFNetwork will send a mixed case string for host name, so we'll compare by lowercasing everything
NSString *hostName = [[NSProcessInfo processInfo] hostName];
NSString *expectedResponse = [[NSString stringWithFormat:@"You are %@ from %@/%@",@"king",@"Castle.Kingdom",hostName] lowercaseString];
success = [[[request responseString] lowercaseString] isEqualToString:expectedResponse];
GHAssertTrue(success,@"Failed to send credentials correctly? (Expected: '%@', got '%@')",expectedResponse,[[request responseString] lowercaseString]);
}
- (void)testCompressedResponse
{
// allseeing-i.com does not gzip png images
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/i/logo.png"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
NSString *encoding = [[request responseHeaders] objectForKey:@"Content-Encoding"];
BOOL success = (!encoding || [encoding rangeOfString:@"gzip"].location != NSNotFound);
GHAssertTrue(success,@"Got incorrect request headers from server");
success = ([request rawResponseData] == [request responseData]);
GHAssertTrue(success,@"Attempted to uncompress data that was not compressed");
url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/first"] autorelease];
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = ([request rawResponseData] != [request responseData]);
GHAssertTrue(success,@"Uncompressed data is the same as compressed data");
success = [[request responseString] isEqualToString:@"This is the expected content for the first string"];
GHAssertTrue(success,@"Failed to decompress data correctly?");
}
- (void)testPartialFetch
{
// We run tests that measure progress on the main thread because otherwise we can't depend on the progress delegate being notified before we need to test it's working
[self performSelectorOnMainThread:@selector(performPartialFetchTest) withObject:nil waitUntilDone:YES];
}
- (void)performPartialFetchTest
{
NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
NSString *tempPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"tempfile.txt"];
NSString *partialContent = @"This file should be exactly 163 bytes long when encoded as UTF8, Unix line breaks with no BOM.\n";
[partialContent writeToFile:tempPath atomically:NO encoding:NSASCIIStringEncoding error:nil];
progress = 0;
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/test_partial_download.txt"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadDestinationPath:downloadPath];
[request setTemporaryFileDownloadPath:tempPath];
[request setAllowResumeForFileDownloads:YES];
[request setDownloadProgressDelegate:self];
[request startSynchronous];
BOOL success = ([request contentLength] == 68);
GHAssertTrue(success,@"Failed to download a segment of the data");
NSString *content = [NSString stringWithContentsOfFile:downloadPath encoding:NSUTF8StringEncoding error:NULL];
NSString *newPartialContent = [content substringFromIndex:95];
success = ([newPartialContent isEqualToString:@"This is the content we ought to be getting if we start from byte 95."]);
GHAssertTrue(success,@"Failed to append the correct data to the end of the file?");
success = (progress == 1.0);
GHAssertTrue(success,@"Failed to correctly display increment progress for a partial download");
}
// The '000' is to ensure this test runs first, as another test may connect to https://selfsigned.allseeing-i.com and accept the certificate
- (void)test000SSL
{
NSURL *url = [NSURL URLWithString:@"https://selfsigned.allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an error for a self-signed certificate (Will fail on the second run in the same session!)");
// Just for testing the request generated a custom error description - don't do this! You should look at the domain / code of the underlyingError in your own programs.
BOOL success = ([[[request error] localizedDescription] isEqualToString:@"A connection failure occurred: SSL problem (possibly a bad/expired/self-signed certificate)"]);
GHAssertTrue(success,@"Generated the wrong error for a self signed cert");
// Turn off certificate validation, and try again
request = [ASIHTTPRequest requestWithURL:url];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
GHAssertNil([request error],@"Failed to accept a self-signed certificate");
}
- (void)testRedirectPreservesSession
{
// Remove any old session cookies
[ASIHTTPRequest clearSession];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/session_redirect"]];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:@"Take me to your leader"];
GHAssertTrue(success,@"Failed to redirect preserving session cookies");
}
- (void)testTooMuchRedirection
{
// This url will simply send a 302 redirect back to itself
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/one_infinite_loop"]];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an error when redirection occurs too many times");
BOOL success = ([[request error] code] == ASITooMuchRedirectionErrorType);
GHAssertTrue(success,@"Generated the wrong error for a redirection loop");
}
- (void)testRedirectToNewDomain
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect_to_new_domain"]];
[request startSynchronous];
BOOL success = [[[request url] absoluteString] isEqualToString:@"http://www.apple.com/"];
GHAssertTrue(success,@"Failed to redirect to a different domain");
}
// Ensure request method changes to get
- (void)test303Redirect
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect_303"]];
[request setRequestMethod:@"PUT"];
[request appendPostData:[@"Fuzzy" dataUsingEncoding:NSUTF8StringEncoding]];
[request startSynchronous];
BOOL success = [[[request url] absoluteString] isEqualToString:@"http://allseeing-i.com/ASIHTTPRequest/tests/request-method"];
GHAssertTrue(success,@"Failed to redirect to correct location");
success = [[request responseString] isEqualToString:@"GET"];
GHAssertTrue(success,@"Failed to use GET on new URL");
}
- (void)testCompression
{
NSString *content = @"This is the test content. This is the test content. This is the test content. This is the test content.";
// Test in memory compression / decompression
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
NSData *compressedData = [ASIHTTPRequest compressData:data];
NSData *uncompressedData = [ASIHTTPRequest uncompressZippedData:compressedData];
NSString *newContent = [[[NSString alloc] initWithBytes:[uncompressedData bytes] length:[uncompressedData length] encoding:NSUTF8StringEncoding] autorelease];
BOOL success = [newContent isEqualToString:content];
GHAssertTrue(success,@"Failed compress or decompress the correct data");
// Test file to file compression / decompression
NSString *basePath = [self filePathForTemporaryTestFiles];
NSString *sourcePath = [basePath stringByAppendingPathComponent:@"text.txt"];
NSString *destPath = [basePath stringByAppendingPathComponent:@"text.txt.compressed"];
NSString *newPath = [basePath stringByAppendingPathComponent:@"text2.txt"];
[content writeToFile:sourcePath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
[ASIHTTPRequest compressDataFromFile:sourcePath toFile:destPath];
[ASIHTTPRequest uncompressZippedDataFromFile:destPath toFile:newPath];
success = [[NSString stringWithContentsOfFile:newPath encoding:NSUTF8StringEncoding error:NULL] isEqualToString:content];
GHAssertTrue(success,@"Failed compress or decompress the correct data");
// Test compressed body
// Body is deflated by ASIHTTPRequest, sent, inflated by the server, printed, deflated by mod_deflate, response is inflated by ASIHTTPRequest
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/compressed_post_body"]];
[request setRequestMethod:@"PUT"];
[request setShouldCompressRequestBody:YES];
[request appendPostData:data];
[request startSynchronous];
success = [[request responseString] isEqualToString:content];
GHAssertTrue(success,@"Failed to compress the body, or server failed to decompress it");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/compressed_post_body"]];
[request setRequestMethod:@"PUT"];
[request setShouldCompressRequestBody:YES];
[request setShouldStreamPostDataFromDisk:YES];
[request setUploadProgressDelegate:self];
[request setPostBodyFilePath:sourcePath];
[request startSynchronous];
success = [[request responseString] isEqualToString:content];
GHAssertTrue(success,@"Failed to compress the body, or server failed to decompress it");
}
// Ensure class convenience constructor returns an instance of our subclass
- (void)testSubclass
{
ASIHTTPRequestSubclass *instance = [ASIHTTPRequestSubclass requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
BOOL success = [instance isKindOfClass:[ASIHTTPRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
}
- (void)testThrottlingDownloadBandwidth
{
[ASIHTTPRequest setMaxBandwidthPerSecond:0];
// This content is around 128KB in size, and it won't be gzipped, so it should take more than 8 seconds to download at 14.5KB / second
// We'll test first without throttling
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
NSDate *date = [NSDate date];
[request startSynchronous];
NSTimeInterval interval =[date timeIntervalSinceNow];
BOOL success = (interval > -7);
GHAssertTrue(success,@"Downloaded the file too slowly - either this is a bug, or your internet connection is too slow to run this test (must be able to download 128KB in less than 7 seconds, without throttling)");
// Now we'll test with throttling
[ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
date = [NSDate date];
[request startSynchronous];
[ASIHTTPRequest setMaxBandwidthPerSecond:0];
interval =[date timeIntervalSinceNow];
success = (interval < -7);
GHAssertTrue(success,@"Failed to throttle download");
GHAssertNil([request error],@"Request generated an error - timeout?");
}
- (void)testThrottlingUploadBandwidth
{
[ASIHTTPRequest setMaxBandwidthPerSecond:0];
// Create a 64KB request body
NSData *data = [[[NSMutableData alloc] initWithLength:64*1024] autorelease];
// We'll test first without throttling
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ignore"]];
[request appendPostData:data];
NSDate *date = [NSDate date];
[request startSynchronous];
NSTimeInterval interval =[date timeIntervalSinceNow];
BOOL success = (interval > -3);
GHAssertTrue(success,@"Uploaded the data too slowly - either this is a bug, or your internet connection is too slow to run this test (must be able to upload 64KB in less than 3 seconds, without throttling)");
// Now we'll test with throttling
[ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ignore"]];
[request appendPostData:data];
date = [NSDate date];
[request startSynchronous];
[ASIHTTPRequest setMaxBandwidthPerSecond:0];
interval =[date timeIntervalSinceNow];
success = (interval < -3);
GHAssertTrue(success,@"Failed to throttle upload");
GHAssertNil([request error],@"Request generated an error - timeout?");
}
- (void)testFetchToInvalidPath
{
// Test gzipped content
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setDownloadDestinationPath:@"/an/invalid/location.html"];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an authentication when attempting to write to an invalid location");
//Test non-gzipped content
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request setDownloadDestinationPath:@"/an/invalid/location.png"];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an authentication when attempting to write to an invalid location");
}
- (void)testResponseStatusMessage
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/the-meaning-of-life"]];
[request startSynchronous];
BOOL success = [[request responseStatusMessage] isEqualToString:@"HTTP/1.0 404 Not Found"];
GHAssertTrue(success,@"Got wrong response status message");
}
- (void)testAsynchronous
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/first"]];
[request setUserInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:@"RequestNumber"]];
[request setDidFailSelector:@selector(asyncFail:)];
[request setDidFinishSelector:@selector(asyncSuccess:)];
[request setDelegate:self];
[request startAsynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/second"]];
[request setUserInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:2] forKey:@"RequestNumber"]];
[request setDidFailSelector:@selector(asyncFail:)];
[request setDidFinishSelector:@selector(asyncSuccess:)];
[request setDelegate:self];
[request startAsynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/third"]];
[request setUserInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:3] forKey:@"RequestNumber"]];
[request setDidFailSelector:@selector(asyncFail:)];
[request setDidFinishSelector:@selector(asyncSuccess:)];
[request setDelegate:self];
[request startAsynchronous];
request = [ASIHTTPRequest requestWithURL:nil];
[request setUserInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:4] forKey:@"RequestNumber"]];
[request setDidFailSelector:@selector(asyncFail:)];
[request setDidFinishSelector:@selector(asyncSuccess:)];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)asyncFail:(ASIHTTPRequest *)request
{
int requestNumber = [[[request userInfo] objectForKey:@"RequestNumber"] intValue];
BOOL success = (requestNumber == 4);
GHAssertTrue(success,@"Wrong request failed");
}
- (void)asyncSuccess:(ASIHTTPRequest *)request
{
int requestNumber = [[[request userInfo] objectForKey:@"RequestNumber"] intValue];
BOOL success = (requestNumber != 4);
GHAssertTrue(success,@"Request succeeded when it should have failed");
switch (requestNumber) {
case 1:
success = [[request responseString] isEqualToString:@"This is the expected content for the first string"];
break;
case 2:
success = [[request responseString] isEqualToString:@"This is the expected content for the second string"];
break;
case 3:
success = [[request responseString] isEqualToString:@"This is the expected content for the third string"];
break;
}
GHAssertTrue(success,@"Got wrong request content - very bad!");
}
// Will be called on Mac OS
- (void)setDoubleValue:(double)newProgress;
{
progress = (float)newProgress;
}
// Will be called on iPhone OS
- (void)setProgress:(float)newProgress;
{
progress = newProgress;
}
#if TARGET_OS_IPHONE
- (void)testReachability
{
#if REACHABILITY_20_API
NSLog(@"Using Reachability 2.0 API");
#else
NSLog(@"Using Reachability 1.5 API");
#endif
if ([ASIHTTPRequest isNetworkReachableViaWWAN]) {
NSLog(@"Connected via WWAN");
} else {
NSLog(@"Not connected via WWAN");
}
}
#endif
- (void)testAutomaticRetry
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setTimeOutSeconds:0.001];
[request setNumberOfTimesToRetryOnTimeout:5];
[request startSynchronous];
GHAssertNotNil([request error],@"Request failed to timeout, cannot proceed with test");
BOOL success = ([request retryCount] == 5);
GHAssertTrue(success,@"Request failed to retry on timeout");
}
- (void)testCopy
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
ASIHTTPRequest *request2 = [request copy];
[pool release];
GHAssertNotNil(request2,@"Failed to create a copy");
BOOL success = ([request2 retainCount] == 1);
GHAssertTrue(success,@"Failed to create a retained copy");
[request2 release];
}
- (void)testCloseConnection
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/close-connection"]];
[request startSynchronous];
BOOL success = ![request connectionCanBeReused];
GHAssertTrue(success,@"Should not be able to re-use a request sent with Connection:close");
// Ensure we close the connection when authentication is needed
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://asi/ASIHTTPRequest/tests/close-connection-auth-needed"]];
[request startSynchronous];
success = ![request connectionCanBeReused];
GHAssertTrue(success,@"Should not be able to re-use a request sent with Connection:close");
}
- (void)testPersistentConnectionTimeout
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
BOOL success = ([request persistentConnectionTimeoutSeconds] == 60);
GHAssertTrue(success,@"Request failed to default to 60 seconds for connection timeout");
[request startSynchronous];
NSNumber *connectionId = [request connectionID];
success = ([request persistentConnectionTimeoutSeconds] == 2);
GHAssertTrue(success,@"Request failed to use time out set by server");
// Wait 3 seconds - connection should have timed out
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request startSynchronous];
success = ([[request connectionID] intValue] != [connectionId intValue]);
GHAssertTrue(success,@"Reused a connection that should have timed out");
}
- (void)testRemoveUploadProgress
{
[self performSelectorOnMainThread:@selector(runRemoveUploadProgressTest) withObject:nil waitUntilDone:YES];
}
- (void)runRemoveUploadProgressTest
{
progress = 0;
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
NSData *data = [[[NSMutableData alloc] initWithLength:64*1024] autorelease];
[request appendPostData:data];
[request setRequestMethod:@"POST"];
[request setUploadProgressDelegate:self];
[request startSynchronous];
BOOL success = (progress == 1.0);
GHAssertTrue(success,@"Failed to set upload progress, cannot proceed with test");
[request removeUploadProgressSoFar];
success = (progress == 0);
GHAssertTrue(success,@"Failed to set upload progress, cannot proceed with test");
}
- (void)testMimeType
{
NSString *text = @"This is my content";
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
[[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
BOOL success = ([[ASIHTTPRequest mimeTypeForFileAtPath:filePath] isEqualToString:@"text/plain"]);
GHAssertTrue(success,@"Failed to detect the mime type for a file");
filePath = @"/nowhere";
success = (![ASIHTTPRequest mimeTypeForFileAtPath:filePath]);
GHAssertTrue(success,@"Returned a mime type for a non-existent file");
filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile"];
[[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
success = ([[ASIHTTPRequest mimeTypeForFileAtPath:filePath] isEqualToString:@"application/octet-stream"]);
GHAssertTrue(success,@"Failed to return the default mime type when a file has no extension");
}
- (void)testDelegateResponseDataHandling
{
[self setResponseData:[NSMutableData dataWithLength:0]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28young_readers_edition%29.txt"]];
[request setDelegate:self];
[request setDidReceiveDataSelector:@selector(theTestRequest:didReceiveData:)];
[request setDidFinishSelector:@selector(theTestRequestFinished:)];
[request startAsynchronous];
}
- (void)theTestRequestFinished:(ASIHTTPRequest *)request
{
ASIHTTPRequest *request2 = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28young_readers_edition%29.txt"]];
[request2 startSynchronous];
NSString *firstResponse = [[[NSString alloc] initWithBytes:[[self responseData] bytes] length:[[self responseData] length] encoding:[request responseEncoding]] autorelease];
BOOL success = [[request2 responseString] isEqualToString:firstResponse];
GHAssertTrue(success,@"Failed to correctly download and store the response using a delegate");
}
- (void)theTestRequest:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
{
[[self responseData] appendData:data];
}
- (void)testNilPortCredentialsMatching
{
// Test for http://github.com/pokeb/asi-http-request/issues#issue/39
[ASIHTTPRequest clearSession];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com:80/ASIHTTPRequest/tests/basic-authentication"]];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"]];
[request startSynchronous];
// Now let's test the other way around
[ASIHTTPRequest clearSession];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com:/ASIHTTPRequest/tests/basic-authentication"]];
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com:80/ASIHTTPRequest/tests/basic-authentication"]];
[request startSynchronous];
}
- (void)testRFC1123DateParsing
{
unsigned dateUnits = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit;
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
[calendar setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSString *dateString = @"Thu, 19 Nov 1981 08:52:01 GMT";
NSDate *date = [ASIHTTPRequest dateFromRFC1123String:dateString];
NSDateComponents *components = [calendar components:dateUnits fromDate:date];
BOOL success = ([components year] == 1981 && [components month] == 11 && [components day] == 19 && [components weekday] == 5 && [components hour] == 8 && [components minute] == 52 && [components second] == 1);
GHAssertTrue(success,@"Failed to parse an RFC1123 date correctly");
dateString = @"4 May 2010 00:59 CET";
date = [ASIHTTPRequest dateFromRFC1123String:dateString];
components = [calendar components:dateUnits fromDate:date];
success = ([components year] == 2010 && [components month] == 5 && [components day] == 3 && [components hour] == 23 && [components minute] == 59);
GHAssertTrue(success,@"Failed to parse an RFC1123 date correctly");
}
- (void)testAccurateProgressFallback
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setAllowCompressedResponse:NO]; // A bit hacky - my server will send a chunked response (without content length) when we don't specify that we accept gzip
[request startSynchronous];
BOOL success = ([request showAccurateProgress] == NO);
GHAssertTrue(success,@"Request failed to fall back to simple progress");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/redirect_resume"]];
[request startSynchronous];
success = ([request showAccurateProgress] == YES);
GHAssertTrue(success,@"Request fell back to simple progress when redirecting");
}
// Because of they way I implemented the server part of this test, I'm afraid you won't be able to run it yourself
- (void)testResumeWithAutomaticTimeoutRetry
{
printf("\nSkipping testResumeWithAutomaticTimeoutRetry - ");
return;
// Get the first part of the response
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/resume-with-timeout"]];
[request setAllowCompressedResponse:NO];
[request startSynchronous];
NSString *partialPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"partial.txt"];
[[request responseString] writeToFile:partialPath atomically:NO encoding:NSUTF8StringEncoding error:NULL];
NSString *completePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"complete.txt"];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/resume-with-timeout-finish"]];
[request setAllowCompressedResponse:NO];
[request setAllowResumeForFileDownloads:YES];
[request setTemporaryFileDownloadPath:partialPath];
[request setDownloadDestinationPath:completePath];
[request setNumberOfTimesToRetryOnTimeout:1];
[request startSynchronous];
NSString *expectedOutput = @"";
char i;
for (i=0; i<3; i++) {
char *s;
s = (char *)malloc(1024*128);
memset(s, i+49, 1024*128);
expectedOutput = [expectedOutput stringByAppendingString:[[[NSString alloc] initWithBytes:s length:1024*128 encoding:NSUTF8StringEncoding] autorelease]];
expectedOutput = [expectedOutput stringByAppendingString:@"\r\n"];
free(s);
}
BOOL success = [expectedOutput isEqualToString:[NSString stringWithContentsOfFile:completePath encoding:NSUTF8StringEncoding error:NULL]];
GHAssertTrue(success, @"Failed to send the correct Range headers to the server when resuming after a timeout");
}
@synthesize responseData;
@end